mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	vendor: update github.com/opencontainers/runc
when the systemd cgroup manager is used, controllers not handled by systemd are created manually afterwards. libcontainer didn't correctly cleanup these cgroups that were leaked on cgroup v1. Closes: https://github.com/kubernetes/kubernetes/issues/92766 Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
		
							
								
								
									
										6
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								go.mod
									
									
									
									
									
								
							@@ -77,7 +77,7 @@ require (
 | 
			
		||||
	github.com/onsi/ginkgo v1.11.0
 | 
			
		||||
	github.com/onsi/gomega v1.7.0
 | 
			
		||||
	github.com/opencontainers/go-digest v1.0.0-rc1
 | 
			
		||||
	github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657
 | 
			
		||||
	github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb
 | 
			
		||||
	github.com/opencontainers/selinux v1.5.2
 | 
			
		||||
	github.com/pkg/errors v0.9.1
 | 
			
		||||
	github.com/pmezard/go-difflib v1.0.0
 | 
			
		||||
@@ -195,7 +195,7 @@ replace (
 | 
			
		||||
	github.com/chzyer/logex => github.com/chzyer/logex v1.1.10
 | 
			
		||||
	github.com/chzyer/readline => github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
 | 
			
		||||
	github.com/chzyer/test => github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1
 | 
			
		||||
	github.com/cilium/ebpf => github.com/cilium/ebpf v0.0.0-20200601085316-9f1617e5c574
 | 
			
		||||
	github.com/cilium/ebpf => github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775
 | 
			
		||||
	github.com/clusterhq/flocker-go => github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313
 | 
			
		||||
	github.com/cockroachdb/datadriven => github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa
 | 
			
		||||
	github.com/codegangsta/negroni => github.com/codegangsta/negroni v1.0.0
 | 
			
		||||
@@ -362,7 +362,7 @@ replace (
 | 
			
		||||
	github.com/onsi/gomega => github.com/onsi/gomega v1.7.0
 | 
			
		||||
	github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0-rc1
 | 
			
		||||
	github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.1
 | 
			
		||||
	github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657
 | 
			
		||||
	github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb
 | 
			
		||||
	github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2
 | 
			
		||||
	github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.5.2
 | 
			
		||||
	github.com/pelletier/go-toml => github.com/pelletier/go-toml v1.2.0
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								go.sum
									
									
									
									
									
								
							@@ -83,8 +83,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
 | 
			
		||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
 | 
			
		||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 | 
			
		||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 | 
			
		||||
github.com/cilium/ebpf v0.0.0-20200601085316-9f1617e5c574 h1:G4qUgaciePbY+xCMxxseQhAet478x7qDMdYj3yJgsps=
 | 
			
		||||
github.com/cilium/ebpf v0.0.0-20200601085316-9f1617e5c574/go.mod h1:XT+cAw5wfvsodedcijoh1l9cf7v1x9FlFB/3VmF/O8s=
 | 
			
		||||
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775 h1:cHzBGGVew0ezFsq2grfy2RsB8hO/eNyBgOLHBCqfR1U=
 | 
			
		||||
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
 | 
			
		||||
github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 h1:eIHD9GNM3Hp7kcRW5mvcz7WTR3ETeoYYKwpgA04kaXE=
 | 
			
		||||
github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0=
 | 
			
		||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=
 | 
			
		||||
@@ -370,8 +370,8 @@ github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2i
 | 
			
		||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
 | 
			
		||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
 | 
			
		||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
 | 
			
		||||
github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657 h1:MIcmh4kMszKK3ub+n11fdkhlqF2vrNKMR0a+/zLm+Xs=
 | 
			
		||||
github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657/go.mod h1:3Sm6Dt7OT8z88EbdQqqcRN2oCT54jbi72tT/HqgflT8=
 | 
			
		||||
github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb h1:LcPVE5u4oaqw8ffPbJew0lUxZC7faM5t52PgU4px1xY=
 | 
			
		||||
github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb/go.mod h1:ZuXhqlr4EiRYgDrBDNfSbE4+n9JX4+V107NwAmF7sZA=
 | 
			
		||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2 h1:9mv9SC7GWmRWE0J/+oD8w3GsN2KYGKtg6uwLN7hfP5E=
 | 
			
		||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 | 
			
		||||
github.com/opencontainers/selinux v1.5.2 h1:F6DgIsjgBIcDksLW4D5RG9bXok6oqZ3nvMwj4ZoFu/Q=
 | 
			
		||||
@@ -449,6 +449,7 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV
 | 
			
		||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
 | 
			
		||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 | 
			
		||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 | 
			
		||||
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
 | 
			
		||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 | 
			
		||||
github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=
 | 
			
		||||
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -23,7 +23,6 @@ go_library(
 | 
			
		||||
        "//vendor/github.com/cilium/ebpf/internal:go_default_library",
 | 
			
		||||
        "//vendor/github.com/cilium/ebpf/internal/btf:go_default_library",
 | 
			
		||||
        "//vendor/github.com/cilium/ebpf/internal/unix:go_default_library",
 | 
			
		||||
        "//vendor/golang.org/x/xerrors:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/github.com/cilium/ebpf/abi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/cilium/ebpf/abi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -3,14 +3,13 @@ package ebpf
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MapABI are the attributes of a Map which are available across all supported kernels.
 | 
			
		||||
@@ -35,7 +34,7 @@ func newMapABIFromSpec(spec *MapSpec) *MapABI {
 | 
			
		||||
func newMapABIFromFd(fd *internal.FD) (string, *MapABI, error) {
 | 
			
		||||
	info, err := bpfGetMapInfoByFD(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if xerrors.Is(err, syscall.EINVAL) {
 | 
			
		||||
		if errors.Is(err, syscall.EINVAL) {
 | 
			
		||||
			abi, err := newMapABIFromProc(fd)
 | 
			
		||||
			return "", abi, err
 | 
			
		||||
		}
 | 
			
		||||
@@ -98,7 +97,7 @@ func newProgramABIFromSpec(spec *ProgramSpec) *ProgramABI {
 | 
			
		||||
func newProgramABIFromFd(fd *internal.FD) (string, *ProgramABI, error) {
 | 
			
		||||
	info, err := bpfGetProgInfoByFD(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if xerrors.Is(err, syscall.EINVAL) {
 | 
			
		||||
		if errors.Is(err, syscall.EINVAL) {
 | 
			
		||||
			return newProgramABIFromProc(fd)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -127,7 +126,7 @@ func newProgramABIFromProc(fd *internal.FD) (string, *ProgramABI, error) {
 | 
			
		||||
		"prog_type": &abi.Type,
 | 
			
		||||
		"prog_tag":  &name,
 | 
			
		||||
	})
 | 
			
		||||
	if xerrors.Is(err, errMissingFields) {
 | 
			
		||||
	if errors.Is(err, errMissingFields) {
 | 
			
		||||
		return "", nil, &internal.UnsupportedFeatureError{
 | 
			
		||||
			Name:           "reading ABI from /proc/self/fdinfo",
 | 
			
		||||
			MinimumVersion: internal.Version{4, 11, 0},
 | 
			
		||||
@@ -153,12 +152,12 @@ func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error {
 | 
			
		||||
	defer fh.Close()
 | 
			
		||||
 | 
			
		||||
	if err := scanFdInfoReader(fh, fields); err != nil {
 | 
			
		||||
		return xerrors.Errorf("%s: %w", fh.Name(), err)
 | 
			
		||||
		return fmt.Errorf("%s: %w", fh.Name(), err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var errMissingFields = xerrors.New("missing fields")
 | 
			
		||||
var errMissingFields = errors.New("missing fields")
 | 
			
		||||
 | 
			
		||||
func scanFdInfoReader(r io.Reader, fields map[string]interface{}) error {
 | 
			
		||||
	var (
 | 
			
		||||
@@ -179,7 +178,7 @@ func scanFdInfoReader(r io.Reader, fields map[string]interface{}) error {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if n, err := fmt.Fscanln(bytes.NewReader(parts[1]), field); err != nil || n != 1 {
 | 
			
		||||
			return xerrors.Errorf("can't parse field %s: %v", name, err)
 | 
			
		||||
			return fmt.Errorf("can't parse field %s: %v", name, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		scanned++
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/asm/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/asm/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -20,7 +20,6 @@ go_library(
 | 
			
		||||
    importmap = "k8s.io/kubernetes/vendor/github.com/cilium/ebpf/asm",
 | 
			
		||||
    importpath = "github.com/cilium/ebpf/asm",
 | 
			
		||||
    visibility = ["//visibility:public"],
 | 
			
		||||
    deps = ["//vendor/golang.org/x/xerrors:go_default_library"],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
filegroup(
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								vendor/github.com/cilium/ebpf/asm/instruction.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/cilium/ebpf/asm/instruction.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -2,12 +2,11 @@ package asm
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"math"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// InstructionSize is the size of a BPF instruction in bytes
 | 
			
		||||
@@ -43,7 +42,7 @@ func (ins *Instruction) Unmarshal(r io.Reader, bo binary.ByteOrder) (uint64, err
 | 
			
		||||
	ins.Constant = int64(bi.Constant)
 | 
			
		||||
	ins.Dst, ins.Src, err = bi.Registers.Unmarshal(bo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, xerrors.Errorf("can't unmarshal registers: %s", err)
 | 
			
		||||
		return 0, fmt.Errorf("can't unmarshal registers: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !bi.OpCode.isDWordLoad() {
 | 
			
		||||
@@ -53,10 +52,10 @@ func (ins *Instruction) Unmarshal(r io.Reader, bo binary.ByteOrder) (uint64, err
 | 
			
		||||
	var bi2 bpfInstruction
 | 
			
		||||
	if err := binary.Read(r, bo, &bi2); err != nil {
 | 
			
		||||
		// No Wrap, to avoid io.EOF clash
 | 
			
		||||
		return 0, xerrors.New("64bit immediate is missing second half")
 | 
			
		||||
		return 0, errors.New("64bit immediate is missing second half")
 | 
			
		||||
	}
 | 
			
		||||
	if bi2.OpCode != 0 || bi2.Offset != 0 || bi2.Registers != 0 {
 | 
			
		||||
		return 0, xerrors.New("64bit immediate has non-zero fields")
 | 
			
		||||
		return 0, errors.New("64bit immediate has non-zero fields")
 | 
			
		||||
	}
 | 
			
		||||
	ins.Constant = int64(uint64(uint32(bi2.Constant))<<32 | uint64(uint32(bi.Constant)))
 | 
			
		||||
 | 
			
		||||
@@ -66,7 +65,7 @@ func (ins *Instruction) Unmarshal(r io.Reader, bo binary.ByteOrder) (uint64, err
 | 
			
		||||
// Marshal encodes a BPF instruction.
 | 
			
		||||
func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error) {
 | 
			
		||||
	if ins.OpCode == InvalidOpCode {
 | 
			
		||||
		return 0, xerrors.New("invalid opcode")
 | 
			
		||||
		return 0, errors.New("invalid opcode")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	isDWordLoad := ins.OpCode.isDWordLoad()
 | 
			
		||||
@@ -79,7 +78,7 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error)
 | 
			
		||||
 | 
			
		||||
	regs, err := newBPFRegisters(ins.Dst, ins.Src, bo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, xerrors.Errorf("can't marshal registers: %s", err)
 | 
			
		||||
		return 0, fmt.Errorf("can't marshal registers: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bpfi := bpfInstruction{
 | 
			
		||||
@@ -113,11 +112,11 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error)
 | 
			
		||||
// Returns an error if the instruction doesn't load a map.
 | 
			
		||||
func (ins *Instruction) RewriteMapPtr(fd int) error {
 | 
			
		||||
	if !ins.OpCode.isDWordLoad() {
 | 
			
		||||
		return xerrors.Errorf("%s is not a 64 bit load", ins.OpCode)
 | 
			
		||||
		return fmt.Errorf("%s is not a 64 bit load", ins.OpCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ins.Src != PseudoMapFD && ins.Src != PseudoMapValue {
 | 
			
		||||
		return xerrors.New("not a load from a map")
 | 
			
		||||
		return errors.New("not a load from a map")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Preserve the offset value for direct map loads.
 | 
			
		||||
@@ -136,11 +135,11 @@ func (ins *Instruction) mapPtr() uint32 {
 | 
			
		||||
// Returns an error if the instruction is not a direct load.
 | 
			
		||||
func (ins *Instruction) RewriteMapOffset(offset uint32) error {
 | 
			
		||||
	if !ins.OpCode.isDWordLoad() {
 | 
			
		||||
		return xerrors.Errorf("%s is not a 64 bit load", ins.OpCode)
 | 
			
		||||
		return fmt.Errorf("%s is not a 64 bit load", ins.OpCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ins.Src != PseudoMapValue {
 | 
			
		||||
		return xerrors.New("not a direct load from a map")
 | 
			
		||||
		return errors.New("not a direct load from a map")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fd := uint64(ins.Constant) & math.MaxUint32
 | 
			
		||||
@@ -251,7 +250,7 @@ func (insns Instructions) String() string {
 | 
			
		||||
// Returns an error if the symbol isn't used, see IsUnreferencedSymbol.
 | 
			
		||||
func (insns Instructions) RewriteMapPtr(symbol string, fd int) error {
 | 
			
		||||
	if symbol == "" {
 | 
			
		||||
		return xerrors.New("empty symbol")
 | 
			
		||||
		return errors.New("empty symbol")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	found := false
 | 
			
		||||
@@ -286,7 +285,7 @@ func (insns Instructions) SymbolOffsets() (map[string]int, error) {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if _, ok := offsets[ins.Symbol]; ok {
 | 
			
		||||
			return nil, xerrors.Errorf("duplicate symbol %s", ins.Symbol)
 | 
			
		||||
			return nil, fmt.Errorf("duplicate symbol %s", ins.Symbol)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		offsets[ins.Symbol] = i
 | 
			
		||||
@@ -324,7 +323,7 @@ func (insns Instructions) marshalledOffsets() (map[string]int, error) {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if _, ok := symbols[ins.Symbol]; ok {
 | 
			
		||||
			return nil, xerrors.Errorf("duplicate symbol %s", ins.Symbol)
 | 
			
		||||
			return nil, fmt.Errorf("duplicate symbol %s", ins.Symbol)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		symbols[ins.Symbol] = currentPos
 | 
			
		||||
@@ -405,7 +404,7 @@ func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error {
 | 
			
		||||
			// Rewrite bpf to bpf call
 | 
			
		||||
			offset, ok := absoluteOffsets[ins.Reference]
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return xerrors.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference)
 | 
			
		||||
				return fmt.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ins.Constant = int64(offset - num - 1)
 | 
			
		||||
@@ -414,7 +413,7 @@ func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error {
 | 
			
		||||
			// Rewrite jump to label
 | 
			
		||||
			offset, ok := absoluteOffsets[ins.Reference]
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return xerrors.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference)
 | 
			
		||||
				return fmt.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ins.Offset = int16(offset - num - 1)
 | 
			
		||||
@@ -422,7 +421,7 @@ func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error {
 | 
			
		||||
 | 
			
		||||
		n, err := ins.Marshal(w, bo)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return xerrors.Errorf("instruction %d: %w", i, err)
 | 
			
		||||
			return fmt.Errorf("instruction %d: %w", i, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		num += int(n / InstructionSize)
 | 
			
		||||
@@ -446,7 +445,7 @@ func newBPFRegisters(dst, src Register, bo binary.ByteOrder) (bpfRegisters, erro
 | 
			
		||||
	case binary.BigEndian:
 | 
			
		||||
		return bpfRegisters((dst << 4) | (src & 0xF)), nil
 | 
			
		||||
	default:
 | 
			
		||||
		return 0, xerrors.Errorf("unrecognized ByteOrder %T", bo)
 | 
			
		||||
		return 0, fmt.Errorf("unrecognized ByteOrder %T", bo)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -457,7 +456,7 @@ func (r bpfRegisters) Unmarshal(bo binary.ByteOrder) (dst, src Register, err err
 | 
			
		||||
	case binary.BigEndian:
 | 
			
		||||
		return Register(r >> 4), Register(r & 0xf), nil
 | 
			
		||||
	default:
 | 
			
		||||
		return 0, 0, xerrors.Errorf("unrecognized ByteOrder %T", bo)
 | 
			
		||||
		return 0, 0, fmt.Errorf("unrecognized ByteOrder %T", bo)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								vendor/github.com/cilium/ebpf/collection.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/cilium/ebpf/collection.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,12 +1,13 @@
 | 
			
		||||
package ebpf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/asm"
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CollectionOptions control loading a collection into the kernel.
 | 
			
		||||
@@ -64,12 +65,12 @@ func (cs *CollectionSpec) RewriteMaps(maps map[string]*Map) error {
 | 
			
		||||
				// Not all programs need to use the map
 | 
			
		||||
 | 
			
		||||
			default:
 | 
			
		||||
				return xerrors.Errorf("program %s: %w", progName, err)
 | 
			
		||||
				return fmt.Errorf("program %s: %w", progName, err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !seen {
 | 
			
		||||
			return xerrors.Errorf("map %s not referenced by any programs", symbol)
 | 
			
		||||
			return fmt.Errorf("map %s not referenced by any programs", symbol)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Prevent NewCollection from creating rewritten maps
 | 
			
		||||
@@ -96,21 +97,21 @@ func (cs *CollectionSpec) RewriteMaps(maps map[string]*Map) error {
 | 
			
		||||
func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error {
 | 
			
		||||
	rodata := cs.Maps[".rodata"]
 | 
			
		||||
	if rodata == nil {
 | 
			
		||||
		return xerrors.New("missing .rodata section")
 | 
			
		||||
		return errors.New("missing .rodata section")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if rodata.BTF == nil {
 | 
			
		||||
		return xerrors.New(".rodata section has no BTF")
 | 
			
		||||
		return errors.New(".rodata section has no BTF")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if n := len(rodata.Contents); n != 1 {
 | 
			
		||||
		return xerrors.Errorf("expected one key in .rodata, found %d", n)
 | 
			
		||||
		return fmt.Errorf("expected one key in .rodata, found %d", n)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	kv := rodata.Contents[0]
 | 
			
		||||
	value, ok := kv.Value.([]byte)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return xerrors.Errorf("first value in .rodata is %T not []byte", kv.Value)
 | 
			
		||||
		return fmt.Errorf("first value in .rodata is %T not []byte", kv.Value)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf := make([]byte, len(value))
 | 
			
		||||
@@ -185,14 +186,14 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (col
 | 
			
		||||
		var handle *btf.Handle
 | 
			
		||||
		if mapSpec.BTF != nil {
 | 
			
		||||
			handle, err = loadBTF(btf.MapSpec(mapSpec.BTF))
 | 
			
		||||
			if err != nil && !xerrors.Is(err, btf.ErrNotSupported) {
 | 
			
		||||
			if err != nil && !errors.Is(err, btf.ErrNotSupported) {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m, err := newMapWithBTF(mapSpec, handle)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("map %s: %w", mapName, err)
 | 
			
		||||
			return nil, fmt.Errorf("map %s: %w", mapName, err)
 | 
			
		||||
		}
 | 
			
		||||
		maps[mapName] = m
 | 
			
		||||
	}
 | 
			
		||||
@@ -216,29 +217,29 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (col
 | 
			
		||||
 | 
			
		||||
			m := maps[ins.Reference]
 | 
			
		||||
			if m == nil {
 | 
			
		||||
				return nil, xerrors.Errorf("program %s: missing map %s", progName, ins.Reference)
 | 
			
		||||
				return nil, fmt.Errorf("program %s: missing map %s", progName, ins.Reference)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			fd := m.FD()
 | 
			
		||||
			if fd < 0 {
 | 
			
		||||
				return nil, xerrors.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd)
 | 
			
		||||
				return nil, fmt.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd)
 | 
			
		||||
			}
 | 
			
		||||
			if err := ins.RewriteMapPtr(m.FD()); err != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("progam %s: map %s: %w", progName, ins.Reference, err)
 | 
			
		||||
				return nil, fmt.Errorf("progam %s: map %s: %w", progName, ins.Reference, err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var handle *btf.Handle
 | 
			
		||||
		if progSpec.BTF != nil {
 | 
			
		||||
			handle, err = loadBTF(btf.ProgramSpec(progSpec.BTF))
 | 
			
		||||
			if err != nil && !xerrors.Is(err, btf.ErrNotSupported) {
 | 
			
		||||
			if err != nil && !errors.Is(err, btf.ErrNotSupported) {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		prog, err := newProgramWithBTF(progSpec, handle, opts.Programs)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("program %s: %w", progName, err)
 | 
			
		||||
			return nil, fmt.Errorf("program %s: %w", progName, err)
 | 
			
		||||
		}
 | 
			
		||||
		progs[progName] = prog
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										364
									
								
								vendor/github.com/cilium/ebpf/elf_reader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										364
									
								
								vendor/github.com/cilium/ebpf/elf_reader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -4,6 +4,8 @@ import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"debug/elf"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"math"
 | 
			
		||||
	"os"
 | 
			
		||||
@@ -13,8 +15,6 @@ import (
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type elfCode struct {
 | 
			
		||||
@@ -35,7 +35,7 @@ func LoadCollectionSpec(file string) (*CollectionSpec, error) {
 | 
			
		||||
 | 
			
		||||
	spec, err := LoadCollectionSpecFromReader(f)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("file %s: %w", file, err)
 | 
			
		||||
		return nil, fmt.Errorf("file %s: %w", file, err)
 | 
			
		||||
	}
 | 
			
		||||
	return spec, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -50,7 +50,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
 | 
			
		||||
 | 
			
		||||
	symbols, err := f.Symbols()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("load symbols: %v", err)
 | 
			
		||||
		return nil, fmt.Errorf("load symbols: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ec := &elfCode{f, symbols, symbolsPerSection(symbols), "", 0}
 | 
			
		||||
@@ -79,13 +79,13 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
 | 
			
		||||
			dataSections[elf.SectionIndex(i)] = sec
 | 
			
		||||
		case sec.Type == elf.SHT_REL:
 | 
			
		||||
			if int(sec.Info) >= len(ec.Sections) {
 | 
			
		||||
				return nil, xerrors.Errorf("found relocation section %v for missing section %v", i, sec.Info)
 | 
			
		||||
				return nil, fmt.Errorf("found relocation section %v for missing section %v", i, sec.Info)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Store relocations under the section index of the target
 | 
			
		||||
			idx := elf.SectionIndex(sec.Info)
 | 
			
		||||
			if relSections[idx] != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("section %d has multiple relocation sections", sec.Info)
 | 
			
		||||
				return nil, fmt.Errorf("section %d has multiple relocation sections", sec.Info)
 | 
			
		||||
			}
 | 
			
		||||
			relSections[idx] = sec
 | 
			
		||||
		case sec.Type == elf.SHT_PROGBITS && (sec.Flags&elf.SHF_EXECINSTR) != 0 && sec.Size > 0:
 | 
			
		||||
@@ -95,44 +95,52 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
 | 
			
		||||
 | 
			
		||||
	ec.license, err = loadLicense(licenseSection)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("load license: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("load license: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ec.version, err = loadVersion(versionSection, ec.ByteOrder)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("load version: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("load version: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	btfSpec, err := btf.LoadSpecFromReader(rd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("load BTF: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("load BTF: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	relocations, referencedSections, err := ec.loadRelocations(relSections)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("load relocations: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	maps := make(map[string]*MapSpec)
 | 
			
		||||
	if err := ec.loadMaps(maps, mapSections); err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("load maps: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("load maps: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(btfMaps) > 0 {
 | 
			
		||||
		if err := ec.loadBTFMaps(maps, btfMaps, btfSpec); err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("load BTF maps: %w", err)
 | 
			
		||||
			return nil, fmt.Errorf("load BTF maps: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(dataSections) > 0 {
 | 
			
		||||
		if err := ec.loadDataSections(maps, dataSections, btfSpec); err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("load data sections: %w", err)
 | 
			
		||||
		for idx := range dataSections {
 | 
			
		||||
			if !referencedSections[idx] {
 | 
			
		||||
				// Prune data sections which are not referenced by any
 | 
			
		||||
				// instructions.
 | 
			
		||||
				delete(dataSections, idx)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	relocations, err := ec.loadRelocations(relSections)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("load relocations: %w", err)
 | 
			
		||||
		if err := ec.loadDataSections(maps, dataSections, btfSpec); err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("load data sections: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	progs, err := ec.loadPrograms(progSections, relocations, btfSpec)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("load programs: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("load programs: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &CollectionSpec{maps, progs}, nil
 | 
			
		||||
@@ -140,11 +148,12 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
 | 
			
		||||
 | 
			
		||||
func loadLicense(sec *elf.Section) (string, error) {
 | 
			
		||||
	if sec == nil {
 | 
			
		||||
		return "", xerrors.New("missing license section")
 | 
			
		||||
		return "", nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := sec.Data()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", xerrors.Errorf("section %s: %v", sec.Name, err)
 | 
			
		||||
		return "", fmt.Errorf("section %s: %v", sec.Name, err)
 | 
			
		||||
	}
 | 
			
		||||
	return string(bytes.TrimRight(data, "\000")), nil
 | 
			
		||||
}
 | 
			
		||||
@@ -156,12 +165,12 @@ func loadVersion(sec *elf.Section, bo binary.ByteOrder) (uint32, error) {
 | 
			
		||||
 | 
			
		||||
	var version uint32
 | 
			
		||||
	if err := binary.Read(sec.Open(), bo, &version); err != nil {
 | 
			
		||||
		return 0, xerrors.Errorf("section %s: %v", sec.Name, err)
 | 
			
		||||
		return 0, fmt.Errorf("section %s: %v", sec.Name, err)
 | 
			
		||||
	}
 | 
			
		||||
	return version, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section, relocations map[elf.SectionIndex]map[uint64]elf.Symbol, btf *btf.Spec) (map[string]*ProgramSpec, error) {
 | 
			
		||||
func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section, relocations map[elf.SectionIndex]map[uint64]elf.Symbol, btfSpec *btf.Spec) (map[string]*ProgramSpec, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		progs []*ProgramSpec
 | 
			
		||||
		libs  []*ProgramSpec
 | 
			
		||||
@@ -170,35 +179,36 @@ func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section,
 | 
			
		||||
	for idx, sec := range progSections {
 | 
			
		||||
		syms := ec.symbolsPerSection[idx]
 | 
			
		||||
		if len(syms) == 0 {
 | 
			
		||||
			return nil, xerrors.Errorf("section %v: missing symbols", sec.Name)
 | 
			
		||||
			return nil, fmt.Errorf("section %v: missing symbols", sec.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		funcSym, ok := syms[0]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, xerrors.Errorf("section %v: no label at start", sec.Name)
 | 
			
		||||
			return nil, fmt.Errorf("section %v: no label at start", sec.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		insns, length, err := ec.loadInstructions(sec, syms, relocations[idx])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("program %s: can't unmarshal instructions: %w", funcSym.Name, err)
 | 
			
		||||
			return nil, fmt.Errorf("program %s: can't unmarshal instructions: %w", funcSym.Name, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		progType, attachType := getProgType(sec.Name)
 | 
			
		||||
		progType, attachType, attachTo := getProgType(sec.Name)
 | 
			
		||||
 | 
			
		||||
		spec := &ProgramSpec{
 | 
			
		||||
			Name:          funcSym.Name,
 | 
			
		||||
			Type:          progType,
 | 
			
		||||
			AttachType:    attachType,
 | 
			
		||||
			AttachTo:      attachTo,
 | 
			
		||||
			License:       ec.license,
 | 
			
		||||
			KernelVersion: ec.version,
 | 
			
		||||
			Instructions:  insns,
 | 
			
		||||
			ByteOrder:     ec.ByteOrder,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if btf != nil {
 | 
			
		||||
			spec.BTF, err = btf.Program(sec.Name, length)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("BTF for section %s (program %s): %w", sec.Name, funcSym.Name, err)
 | 
			
		||||
		if btfSpec != nil {
 | 
			
		||||
			spec.BTF, err = btfSpec.Program(sec.Name, length)
 | 
			
		||||
			if err != nil && !errors.Is(err, btf.ErrNoExtendedInfo) {
 | 
			
		||||
				return nil, fmt.Errorf("program %s: %w", funcSym.Name, err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -216,7 +226,7 @@ func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section,
 | 
			
		||||
	for _, prog := range progs {
 | 
			
		||||
		err := link(prog, libs)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("program %s: %w", prog.Name, err)
 | 
			
		||||
			return nil, fmt.Errorf("program %s: %w", prog.Name, err)
 | 
			
		||||
		}
 | 
			
		||||
		res[prog.Name] = prog
 | 
			
		||||
	}
 | 
			
		||||
@@ -237,14 +247,14 @@ func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations m
 | 
			
		||||
			return insns, offset, nil
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, 0, xerrors.Errorf("offset %d: %w", offset, err)
 | 
			
		||||
			return nil, 0, fmt.Errorf("offset %d: %w", offset, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ins.Symbol = symbols[offset].Name
 | 
			
		||||
 | 
			
		||||
		if rel, ok := relocations[offset]; ok {
 | 
			
		||||
			if err = ec.relocateInstruction(&ins, rel); err != nil {
 | 
			
		||||
				return nil, 0, xerrors.Errorf("offset %d: can't relocate instruction: %w", offset, err)
 | 
			
		||||
				return nil, 0, fmt.Errorf("offset %d: can't relocate instruction: %w", offset, err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -265,7 +275,7 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err
 | 
			
		||||
		// from the section itself.
 | 
			
		||||
		idx := int(rel.Section)
 | 
			
		||||
		if idx > len(ec.Sections) {
 | 
			
		||||
			return xerrors.New("out-of-bounds section index")
 | 
			
		||||
			return errors.New("out-of-bounds section index")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		name = ec.Sections[idx].Name
 | 
			
		||||
@@ -285,7 +295,7 @@ outer:
 | 
			
		||||
			// section. Weirdly, the offset of the real symbol in the
 | 
			
		||||
			// section is encoded in the instruction stream.
 | 
			
		||||
			if bind != elf.STB_LOCAL {
 | 
			
		||||
				return xerrors.Errorf("direct load: %s: unsupported relocation %s", name, bind)
 | 
			
		||||
				return fmt.Errorf("direct load: %s: unsupported relocation %s", name, bind)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// For some reason, clang encodes the offset of the symbol its
 | 
			
		||||
@@ -307,13 +317,13 @@ outer:
 | 
			
		||||
 | 
			
		||||
		case elf.STT_OBJECT:
 | 
			
		||||
			if bind != elf.STB_GLOBAL {
 | 
			
		||||
				return xerrors.Errorf("load: %s: unsupported binding: %s", name, bind)
 | 
			
		||||
				return fmt.Errorf("load: %s: unsupported binding: %s", name, bind)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ins.Src = asm.PseudoMapFD
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			return xerrors.Errorf("load: %s: unsupported relocation: %s", name, typ)
 | 
			
		||||
			return fmt.Errorf("load: %s: unsupported relocation: %s", name, typ)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Mark the instruction as needing an update when creating the
 | 
			
		||||
@@ -324,18 +334,18 @@ outer:
 | 
			
		||||
 | 
			
		||||
	case ins.OpCode.JumpOp() == asm.Call:
 | 
			
		||||
		if ins.Src != asm.PseudoCall {
 | 
			
		||||
			return xerrors.Errorf("call: %s: incorrect source register", name)
 | 
			
		||||
			return fmt.Errorf("call: %s: incorrect source register", name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch typ {
 | 
			
		||||
		case elf.STT_NOTYPE, elf.STT_FUNC:
 | 
			
		||||
			if bind != elf.STB_GLOBAL {
 | 
			
		||||
				return xerrors.Errorf("call: %s: unsupported binding: %s", name, bind)
 | 
			
		||||
				return fmt.Errorf("call: %s: unsupported binding: %s", name, bind)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case elf.STT_SECTION:
 | 
			
		||||
			if bind != elf.STB_LOCAL {
 | 
			
		||||
				return xerrors.Errorf("call: %s: unsupported binding: %s", name, bind)
 | 
			
		||||
				return fmt.Errorf("call: %s: unsupported binding: %s", name, bind)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// The function we want to call is in the indicated section,
 | 
			
		||||
@@ -344,23 +354,23 @@ outer:
 | 
			
		||||
			// A value of -1 references the first instruction in the section.
 | 
			
		||||
			offset := int64(int32(ins.Constant)+1) * asm.InstructionSize
 | 
			
		||||
			if offset < 0 {
 | 
			
		||||
				return xerrors.Errorf("call: %s: invalid offset %d", name, offset)
 | 
			
		||||
				return fmt.Errorf("call: %s: invalid offset %d", name, offset)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			sym, ok := ec.symbolsPerSection[rel.Section][uint64(offset)]
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return xerrors.Errorf("call: %s: no symbol at offset %d", name, offset)
 | 
			
		||||
				return fmt.Errorf("call: %s: no symbol at offset %d", name, offset)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ins.Constant = -1
 | 
			
		||||
			name = sym.Name
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			return xerrors.Errorf("call: %s: invalid symbol type %s", name, typ)
 | 
			
		||||
			return fmt.Errorf("call: %s: invalid symbol type %s", name, typ)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		return xerrors.Errorf("relocation for unsupported instruction: %s", ins.OpCode)
 | 
			
		||||
		return fmt.Errorf("relocation for unsupported instruction: %s", ins.OpCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ins.Reference = name
 | 
			
		||||
@@ -371,11 +381,11 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio
 | 
			
		||||
	for idx, sec := range mapSections {
 | 
			
		||||
		syms := ec.symbolsPerSection[idx]
 | 
			
		||||
		if len(syms) == 0 {
 | 
			
		||||
			return xerrors.Errorf("section %v: no symbols", sec.Name)
 | 
			
		||||
			return fmt.Errorf("section %v: no symbols", sec.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if sec.Size%uint64(len(syms)) != 0 {
 | 
			
		||||
			return xerrors.Errorf("section %v: map descriptors are not of equal size", sec.Name)
 | 
			
		||||
			return fmt.Errorf("section %v: map descriptors are not of equal size", sec.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var (
 | 
			
		||||
@@ -385,11 +395,11 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio
 | 
			
		||||
		for i, offset := 0, uint64(0); i < len(syms); i, offset = i+1, offset+size {
 | 
			
		||||
			mapSym, ok := syms[offset]
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return xerrors.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset)
 | 
			
		||||
				return fmt.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if maps[mapSym.Name] != nil {
 | 
			
		||||
				return xerrors.Errorf("section %v: map %v already exists", sec.Name, mapSym)
 | 
			
		||||
				return fmt.Errorf("section %v: map %v already exists", sec.Name, mapSym)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			lr := io.LimitReader(r, int64(size))
 | 
			
		||||
@@ -399,19 +409,19 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio
 | 
			
		||||
			}
 | 
			
		||||
			switch {
 | 
			
		||||
			case binary.Read(lr, ec.ByteOrder, &spec.Type) != nil:
 | 
			
		||||
				return xerrors.Errorf("map %v: missing type", mapSym)
 | 
			
		||||
				return fmt.Errorf("map %v: missing type", mapSym)
 | 
			
		||||
			case binary.Read(lr, ec.ByteOrder, &spec.KeySize) != nil:
 | 
			
		||||
				return xerrors.Errorf("map %v: missing key size", mapSym)
 | 
			
		||||
				return fmt.Errorf("map %v: missing key size", mapSym)
 | 
			
		||||
			case binary.Read(lr, ec.ByteOrder, &spec.ValueSize) != nil:
 | 
			
		||||
				return xerrors.Errorf("map %v: missing value size", mapSym)
 | 
			
		||||
				return fmt.Errorf("map %v: missing value size", mapSym)
 | 
			
		||||
			case binary.Read(lr, ec.ByteOrder, &spec.MaxEntries) != nil:
 | 
			
		||||
				return xerrors.Errorf("map %v: missing max entries", mapSym)
 | 
			
		||||
				return fmt.Errorf("map %v: missing max entries", mapSym)
 | 
			
		||||
			case binary.Read(lr, ec.ByteOrder, &spec.Flags) != nil:
 | 
			
		||||
				return xerrors.Errorf("map %v: missing flags", mapSym)
 | 
			
		||||
				return fmt.Errorf("map %v: missing flags", mapSym)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil {
 | 
			
		||||
				return xerrors.Errorf("map %v: unknown and non-zero fields in definition", mapSym)
 | 
			
		||||
				return fmt.Errorf("map %v: unknown and non-zero fields in definition", mapSym)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			maps[mapSym.Name] = &spec
 | 
			
		||||
@@ -423,84 +433,116 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio
 | 
			
		||||
 | 
			
		||||
func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec, mapSections map[elf.SectionIndex]*elf.Section, spec *btf.Spec) error {
 | 
			
		||||
	if spec == nil {
 | 
			
		||||
		return xerrors.Errorf("missing BTF")
 | 
			
		||||
		return fmt.Errorf("missing BTF")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for idx, sec := range mapSections {
 | 
			
		||||
		syms := ec.symbolsPerSection[idx]
 | 
			
		||||
		if len(syms) == 0 {
 | 
			
		||||
			return xerrors.Errorf("section %v: no symbols", sec.Name)
 | 
			
		||||
			return fmt.Errorf("section %v: no symbols", sec.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, sym := range syms {
 | 
			
		||||
			name := sym.Name
 | 
			
		||||
			if maps[name] != nil {
 | 
			
		||||
				return xerrors.Errorf("section %v: map %v already exists", sec.Name, sym)
 | 
			
		||||
				return fmt.Errorf("section %v: map %v already exists", sec.Name, sym)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			btfMap, btfMapMembers, err := spec.Map(name)
 | 
			
		||||
			mapSpec, err := mapSpecFromBTF(spec, name)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return xerrors.Errorf("map %v: can't get BTF: %w", name, err)
 | 
			
		||||
				return fmt.Errorf("map %v: %w", name, err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			spec, err := mapSpecFromBTF(btfMap, btfMapMembers)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return xerrors.Errorf("map %v: %w", name, err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			maps[name] = spec
 | 
			
		||||
			maps[name] = mapSpec
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func mapSpecFromBTF(btfMap *btf.Map, btfMapMembers []btf.Member) (*MapSpec, error) {
 | 
			
		||||
func mapSpecFromBTF(spec *btf.Spec, name string) (*MapSpec, error) {
 | 
			
		||||
	btfMap, btfMapMembers, err := spec.Map(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("can't get BTF: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	keyType := btf.MapKey(btfMap)
 | 
			
		||||
	size, err := btf.Sizeof(keyType)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("can't get size of BTF key: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	keySize := uint32(size)
 | 
			
		||||
 | 
			
		||||
	valueType := btf.MapValue(btfMap)
 | 
			
		||||
	size, err = btf.Sizeof(valueType)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("can't get size of BTF value: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	valueSize := uint32(size)
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		mapType, flags, maxEntries uint32
 | 
			
		||||
		err                        error
 | 
			
		||||
	)
 | 
			
		||||
	for _, member := range btfMapMembers {
 | 
			
		||||
		switch member.Name {
 | 
			
		||||
		case "type":
 | 
			
		||||
			mapType, err = uintFromBTF(member.Type)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("can't get type: %w", err)
 | 
			
		||||
				return nil, fmt.Errorf("can't get type: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case "map_flags":
 | 
			
		||||
			flags, err = uintFromBTF(member.Type)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("can't get BTF map flags: %w", err)
 | 
			
		||||
				return nil, fmt.Errorf("can't get BTF map flags: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case "max_entries":
 | 
			
		||||
			maxEntries, err = uintFromBTF(member.Type)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("can't get BTF map max entries: %w", err)
 | 
			
		||||
				return nil, fmt.Errorf("can't get BTF map max entries: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case "key":
 | 
			
		||||
		case "value":
 | 
			
		||||
		case "key_size":
 | 
			
		||||
			if _, isVoid := keyType.(*btf.Void); !isVoid {
 | 
			
		||||
				return nil, errors.New("both key and key_size given")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			keySize, err = uintFromBTF(member.Type)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, fmt.Errorf("can't get BTF key size: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case "value_size":
 | 
			
		||||
			if _, isVoid := valueType.(*btf.Void); !isVoid {
 | 
			
		||||
				return nil, errors.New("both value and value_size given")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			valueSize, err = uintFromBTF(member.Type)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, fmt.Errorf("can't get BTF value size: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case "pinning":
 | 
			
		||||
			pinning, err := uintFromBTF(member.Type)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, fmt.Errorf("can't get pinning: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if pinning != 0 {
 | 
			
		||||
				return nil, fmt.Errorf("'pinning' attribute not supported: %w", ErrNotSupported)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case "key", "value":
 | 
			
		||||
		default:
 | 
			
		||||
			return nil, xerrors.Errorf("unrecognized field %s in BTF map definition", member.Name)
 | 
			
		||||
			return nil, fmt.Errorf("unrecognized field %s in BTF map definition", member.Name)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	keySize, err := btf.Sizeof(btf.MapKey(btfMap))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't get size of BTF key: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	valueSize, err := btf.Sizeof(btf.MapValue(btfMap))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't get size of BTF value: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &MapSpec{
 | 
			
		||||
		Type:       MapType(mapType),
 | 
			
		||||
		KeySize:    uint32(keySize),
 | 
			
		||||
		ValueSize:  uint32(valueSize),
 | 
			
		||||
		KeySize:    keySize,
 | 
			
		||||
		ValueSize:  valueSize,
 | 
			
		||||
		MaxEntries: maxEntries,
 | 
			
		||||
		Flags:      flags,
 | 
			
		||||
		BTF:        btfMap,
 | 
			
		||||
@@ -512,12 +554,12 @@ func mapSpecFromBTF(btfMap *btf.Map, btfMapMembers []btf.Member) (*MapSpec, erro
 | 
			
		||||
func uintFromBTF(typ btf.Type) (uint32, error) {
 | 
			
		||||
	ptr, ok := typ.(*btf.Pointer)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return 0, xerrors.Errorf("not a pointer: %v", typ)
 | 
			
		||||
		return 0, fmt.Errorf("not a pointer: %v", typ)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	arr, ok := ptr.Target.(*btf.Array)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return 0, xerrors.Errorf("not a pointer to array: %v", typ)
 | 
			
		||||
		return 0, fmt.Errorf("not a pointer to array: %v", typ)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return arr.Nelems, nil
 | 
			
		||||
@@ -525,7 +567,7 @@ func uintFromBTF(typ btf.Type) (uint32, error) {
 | 
			
		||||
 | 
			
		||||
func (ec *elfCode) loadDataSections(maps map[string]*MapSpec, dataSections map[elf.SectionIndex]*elf.Section, spec *btf.Spec) error {
 | 
			
		||||
	if spec == nil {
 | 
			
		||||
		return xerrors.New("data sections require BTF, make sure all consts are marked as static")
 | 
			
		||||
		return errors.New("data sections require BTF, make sure all consts are marked as static")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, sec := range dataSections {
 | 
			
		||||
@@ -536,11 +578,11 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec, dataSections map[e
 | 
			
		||||
 | 
			
		||||
		data, err := sec.Data()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return xerrors.Errorf("data section %s: can't get contents: %w", sec.Name, err)
 | 
			
		||||
			return fmt.Errorf("data section %s: can't get contents: %w", sec.Name, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if uint64(len(data)) > math.MaxUint32 {
 | 
			
		||||
			return xerrors.Errorf("data section %s: contents exceed maximum size", sec.Name)
 | 
			
		||||
			return fmt.Errorf("data section %s: contents exceed maximum size", sec.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		mapSpec := &MapSpec{
 | 
			
		||||
@@ -567,91 +609,79 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec, dataSections map[e
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getProgType(v string) (ProgramType, AttachType) {
 | 
			
		||||
	types := map[string]ProgramType{
 | 
			
		||||
		// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c#n3568
 | 
			
		||||
		"socket":          SocketFilter,
 | 
			
		||||
		"seccomp":         SocketFilter,
 | 
			
		||||
		"kprobe/":         Kprobe,
 | 
			
		||||
		"uprobe/":         Kprobe,
 | 
			
		||||
		"kretprobe/":      Kprobe,
 | 
			
		||||
		"uretprobe/":      Kprobe,
 | 
			
		||||
		"tracepoint/":     TracePoint,
 | 
			
		||||
		"raw_tracepoint/": RawTracepoint,
 | 
			
		||||
		"xdp":             XDP,
 | 
			
		||||
		"perf_event":      PerfEvent,
 | 
			
		||||
		"lwt_in":          LWTIn,
 | 
			
		||||
		"lwt_out":         LWTOut,
 | 
			
		||||
		"lwt_xmit":        LWTXmit,
 | 
			
		||||
		"lwt_seg6local":   LWTSeg6Local,
 | 
			
		||||
		"sockops":         SockOps,
 | 
			
		||||
		"sk_skb":          SkSKB,
 | 
			
		||||
		"sk_msg":          SkMsg,
 | 
			
		||||
		"lirc_mode2":      LircMode2,
 | 
			
		||||
		"flow_dissector":  FlowDissector,
 | 
			
		||||
func getProgType(sectionName string) (ProgramType, AttachType, string) {
 | 
			
		||||
	types := map[string]struct {
 | 
			
		||||
		progType   ProgramType
 | 
			
		||||
		attachType AttachType
 | 
			
		||||
	}{
 | 
			
		||||
		// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c
 | 
			
		||||
		"socket":                {SocketFilter, AttachNone},
 | 
			
		||||
		"seccomp":               {SocketFilter, AttachNone},
 | 
			
		||||
		"kprobe/":               {Kprobe, AttachNone},
 | 
			
		||||
		"uprobe/":               {Kprobe, AttachNone},
 | 
			
		||||
		"kretprobe/":            {Kprobe, AttachNone},
 | 
			
		||||
		"uretprobe/":            {Kprobe, AttachNone},
 | 
			
		||||
		"tracepoint/":           {TracePoint, AttachNone},
 | 
			
		||||
		"raw_tracepoint/":       {RawTracepoint, AttachNone},
 | 
			
		||||
		"xdp":                   {XDP, AttachNone},
 | 
			
		||||
		"perf_event":            {PerfEvent, AttachNone},
 | 
			
		||||
		"lwt_in":                {LWTIn, AttachNone},
 | 
			
		||||
		"lwt_out":               {LWTOut, AttachNone},
 | 
			
		||||
		"lwt_xmit":              {LWTXmit, AttachNone},
 | 
			
		||||
		"lwt_seg6local":         {LWTSeg6Local, AttachNone},
 | 
			
		||||
		"sockops":               {SockOps, AttachCGroupSockOps},
 | 
			
		||||
		"sk_skb/stream_parser":  {SkSKB, AttachSkSKBStreamParser},
 | 
			
		||||
		"sk_skb/stream_verdict": {SkSKB, AttachSkSKBStreamParser},
 | 
			
		||||
		"sk_msg":                {SkMsg, AttachSkSKBStreamVerdict},
 | 
			
		||||
		"lirc_mode2":            {LircMode2, AttachLircMode2},
 | 
			
		||||
		"flow_dissector":        {FlowDissector, AttachFlowDissector},
 | 
			
		||||
		"iter/":                 {Tracing, AttachTraceIter},
 | 
			
		||||
 | 
			
		||||
		"cgroup_skb/":       CGroupSKB,
 | 
			
		||||
		"cgroup/dev":        CGroupDevice,
 | 
			
		||||
		"cgroup/skb":        CGroupSKB,
 | 
			
		||||
		"cgroup/sock":       CGroupSock,
 | 
			
		||||
		"cgroup/post_bind":  CGroupSock,
 | 
			
		||||
		"cgroup/bind":       CGroupSockAddr,
 | 
			
		||||
		"cgroup/connect":    CGroupSockAddr,
 | 
			
		||||
		"cgroup/sendmsg":    CGroupSockAddr,
 | 
			
		||||
		"cgroup/recvmsg":    CGroupSockAddr,
 | 
			
		||||
		"cgroup/sysctl":     CGroupSysctl,
 | 
			
		||||
		"cgroup/getsockopt": CGroupSockopt,
 | 
			
		||||
		"cgroup/setsockopt": CGroupSockopt,
 | 
			
		||||
		"classifier":        SchedCLS,
 | 
			
		||||
		"action":            SchedACT,
 | 
			
		||||
	}
 | 
			
		||||
	attachTypes := map[string]AttachType{
 | 
			
		||||
		"cgroup_skb/ingress":    AttachCGroupInetIngress,
 | 
			
		||||
		"cgroup_skb/egress":     AttachCGroupInetEgress,
 | 
			
		||||
		"cgroup/sock":           AttachCGroupInetSockCreate,
 | 
			
		||||
		"cgroup/post_bind4":     AttachCGroupInet4PostBind,
 | 
			
		||||
		"cgroup/post_bind6":     AttachCGroupInet6PostBind,
 | 
			
		||||
		"cgroup/dev":            AttachCGroupDevice,
 | 
			
		||||
		"sockops":               AttachCGroupSockOps,
 | 
			
		||||
		"sk_skb/stream_parser":  AttachSkSKBStreamParser,
 | 
			
		||||
		"sk_skb/stream_verdict": AttachSkSKBStreamVerdict,
 | 
			
		||||
		"sk_msg":                AttachSkSKBStreamVerdict,
 | 
			
		||||
		"lirc_mode2":            AttachLircMode2,
 | 
			
		||||
		"flow_dissector":        AttachFlowDissector,
 | 
			
		||||
		"cgroup/bind4":          AttachCGroupInet4Bind,
 | 
			
		||||
		"cgroup/bind6":          AttachCGroupInet6Bind,
 | 
			
		||||
		"cgroup/connect4":       AttachCGroupInet4Connect,
 | 
			
		||||
		"cgroup/connect6":       AttachCGroupInet6Connect,
 | 
			
		||||
		"cgroup/sendmsg4":       AttachCGroupUDP4Sendmsg,
 | 
			
		||||
		"cgroup/sendmsg6":       AttachCGroupUDP6Sendmsg,
 | 
			
		||||
		"cgroup/recvmsg4":       AttachCGroupUDP4Recvmsg,
 | 
			
		||||
		"cgroup/recvmsg6":       AttachCGroupUDP6Recvmsg,
 | 
			
		||||
		"cgroup/sysctl":         AttachCGroupSysctl,
 | 
			
		||||
		"cgroup/getsockopt":     AttachCGroupGetsockopt,
 | 
			
		||||
		"cgroup/setsockopt":     AttachCGroupSetsockopt,
 | 
			
		||||
	}
 | 
			
		||||
	attachType := AttachNone
 | 
			
		||||
	for k, t := range attachTypes {
 | 
			
		||||
		if strings.HasPrefix(v, k) {
 | 
			
		||||
			attachType = t
 | 
			
		||||
		}
 | 
			
		||||
		"cgroup_skb/ingress": {CGroupSKB, AttachCGroupInetIngress},
 | 
			
		||||
		"cgroup_skb/egress":  {CGroupSKB, AttachCGroupInetEgress},
 | 
			
		||||
		"cgroup/dev":         {CGroupDevice, AttachCGroupDevice},
 | 
			
		||||
		"cgroup/skb":         {CGroupSKB, AttachNone},
 | 
			
		||||
		"cgroup/sock":        {CGroupSock, AttachCGroupInetSockCreate},
 | 
			
		||||
		"cgroup/post_bind4":  {CGroupSock, AttachCGroupInet4PostBind},
 | 
			
		||||
		"cgroup/post_bind6":  {CGroupSock, AttachCGroupInet6PostBind},
 | 
			
		||||
		"cgroup/bind4":       {CGroupSockAddr, AttachCGroupInet4Bind},
 | 
			
		||||
		"cgroup/bind6":       {CGroupSockAddr, AttachCGroupInet6Bind},
 | 
			
		||||
		"cgroup/connect4":    {CGroupSockAddr, AttachCGroupInet4Connect},
 | 
			
		||||
		"cgroup/connect6":    {CGroupSockAddr, AttachCGroupInet6Connect},
 | 
			
		||||
		"cgroup/sendmsg4":    {CGroupSockAddr, AttachCGroupUDP4Sendmsg},
 | 
			
		||||
		"cgroup/sendmsg6":    {CGroupSockAddr, AttachCGroupUDP6Sendmsg},
 | 
			
		||||
		"cgroup/recvmsg4":    {CGroupSockAddr, AttachCGroupUDP4Recvmsg},
 | 
			
		||||
		"cgroup/recvmsg6":    {CGroupSockAddr, AttachCGroupUDP6Recvmsg},
 | 
			
		||||
		"cgroup/sysctl":      {CGroupSysctl, AttachCGroupSysctl},
 | 
			
		||||
		"cgroup/getsockopt":  {CGroupSockopt, AttachCGroupGetsockopt},
 | 
			
		||||
		"cgroup/setsockopt":  {CGroupSockopt, AttachCGroupSetsockopt},
 | 
			
		||||
		"classifier":         {SchedCLS, AttachNone},
 | 
			
		||||
		"action":             {SchedACT, AttachNone},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for k, t := range types {
 | 
			
		||||
		if strings.HasPrefix(v, k) {
 | 
			
		||||
			return t, attachType
 | 
			
		||||
	for prefix, t := range types {
 | 
			
		||||
		if !strings.HasPrefix(sectionName, prefix) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !strings.HasSuffix(prefix, "/") {
 | 
			
		||||
			return t.progType, t.attachType, ""
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return t.progType, t.attachType, sectionName[len(prefix):]
 | 
			
		||||
	}
 | 
			
		||||
	return UnspecifiedProgram, AttachNone
 | 
			
		||||
 | 
			
		||||
	return UnspecifiedProgram, AttachNone, ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ec *elfCode) loadRelocations(sections map[elf.SectionIndex]*elf.Section) (map[elf.SectionIndex]map[uint64]elf.Symbol, error) {
 | 
			
		||||
func (ec *elfCode) loadRelocations(sections map[elf.SectionIndex]*elf.Section) (map[elf.SectionIndex]map[uint64]elf.Symbol, map[elf.SectionIndex]bool, error) {
 | 
			
		||||
	result := make(map[elf.SectionIndex]map[uint64]elf.Symbol)
 | 
			
		||||
	targets := make(map[elf.SectionIndex]bool)
 | 
			
		||||
	for idx, sec := range sections {
 | 
			
		||||
		rels := make(map[uint64]elf.Symbol)
 | 
			
		||||
 | 
			
		||||
		if sec.Entsize < 16 {
 | 
			
		||||
			return nil, xerrors.Errorf("section %s: relocations are less than 16 bytes", sec.Name)
 | 
			
		||||
			return nil, nil, fmt.Errorf("section %s: relocations are less than 16 bytes", sec.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		r := sec.Open()
 | 
			
		||||
@@ -660,20 +690,22 @@ func (ec *elfCode) loadRelocations(sections map[elf.SectionIndex]*elf.Section) (
 | 
			
		||||
 | 
			
		||||
			var rel elf.Rel64
 | 
			
		||||
			if binary.Read(ent, ec.ByteOrder, &rel) != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("can't parse relocation at offset %v", off)
 | 
			
		||||
				return nil, nil, fmt.Errorf("can't parse relocation at offset %v", off)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			symNo := int(elf.R_SYM64(rel.Info) - 1)
 | 
			
		||||
			if symNo >= len(ec.symbols) {
 | 
			
		||||
				return nil, xerrors.Errorf("relocation at offset %d: symbol %v doesnt exist", off, symNo)
 | 
			
		||||
				return nil, nil, fmt.Errorf("relocation at offset %d: symbol %v doesnt exist", off, symNo)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			symbol := ec.symbols[symNo]
 | 
			
		||||
			targets[symbol.Section] = true
 | 
			
		||||
			rels[rel.Off] = ec.symbols[symNo]
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		result[idx] = rels
 | 
			
		||||
	}
 | 
			
		||||
	return result, nil
 | 
			
		||||
	return result, targets, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func symbolsPerSection(symbols []elf.Symbol) map[elf.SectionIndex]map[uint64]elf.Symbol {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/cilium/ebpf/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/cilium/ebpf/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,8 +1,5 @@
 | 
			
		||||
module github.com/cilium/ebpf
 | 
			
		||||
 | 
			
		||||
go 1.12
 | 
			
		||||
go 1.13
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9
 | 
			
		||||
	golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
 | 
			
		||||
)
 | 
			
		||||
require golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/cilium/ebpf/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/cilium/ebpf/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,6 +1,2 @@
 | 
			
		||||
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU=
 | 
			
		||||
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk=
 | 
			
		||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/cilium/ebpf/internal/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/cilium/ebpf/internal/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -14,14 +14,12 @@ go_library(
 | 
			
		||||
        "ptr_32_le.go",
 | 
			
		||||
        "ptr_64.go",
 | 
			
		||||
        "syscall.go",
 | 
			
		||||
        "syscall_string.go",
 | 
			
		||||
    ],
 | 
			
		||||
    importmap = "k8s.io/kubernetes/vendor/github.com/cilium/ebpf/internal",
 | 
			
		||||
    importpath = "github.com/cilium/ebpf/internal",
 | 
			
		||||
    visibility = ["//vendor/github.com/cilium/ebpf:__subpackages__"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//vendor/github.com/cilium/ebpf/internal/unix:go_default_library",
 | 
			
		||||
        "//vendor/golang.org/x/xerrors:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
    deps = ["//vendor/github.com/cilium/ebpf/internal/unix:go_default_library"],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
filegroup(
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/btf/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/btf/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -17,7 +17,6 @@ go_library(
 | 
			
		||||
        "//vendor/github.com/cilium/ebpf/asm:go_default_library",
 | 
			
		||||
        "//vendor/github.com/cilium/ebpf/internal:go_default_library",
 | 
			
		||||
        "//vendor/github.com/cilium/ebpf/internal/unix:go_default_library",
 | 
			
		||||
        "//vendor/golang.org/x/xerrors:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										261
									
								
								vendor/github.com/cilium/ebpf/internal/btf/btf.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										261
									
								
								vendor/github.com/cilium/ebpf/internal/btf/btf.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -4,23 +4,27 @@ import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"debug/elf"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"math"
 | 
			
		||||
	"os"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const btfMagic = 0xeB9F
 | 
			
		||||
 | 
			
		||||
// Errors returned by BTF functions.
 | 
			
		||||
var (
 | 
			
		||||
	ErrNotSupported = internal.ErrNotSupported
 | 
			
		||||
	ErrNotSupported   = internal.ErrNotSupported
 | 
			
		||||
	ErrNotFound       = errors.New("not found")
 | 
			
		||||
	ErrNoExtendedInfo = errors.New("no extended info")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Spec represents decoded BTF.
 | 
			
		||||
@@ -73,7 +77,7 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if sec.Size > math.MaxUint32 {
 | 
			
		||||
				return nil, xerrors.Errorf("section %s exceeds maximum size", sec.Name)
 | 
			
		||||
				return nil, fmt.Errorf("section %s exceeds maximum size", sec.Name)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			sectionSizes[sec.Name] = uint32(sec.Size)
 | 
			
		||||
@@ -86,7 +90,7 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
 | 
			
		||||
 | 
			
		||||
	symbols, err := file.Symbols()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't read symbols: %v", err)
 | 
			
		||||
		return nil, fmt.Errorf("can't read symbols: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	variableOffsets := make(map[variable]uint32)
 | 
			
		||||
@@ -102,13 +106,31 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if symbol.Value > math.MaxUint32 {
 | 
			
		||||
			return nil, xerrors.Errorf("section %s: symbol %s: size exceeds maximum", secName, symbol.Name)
 | 
			
		||||
			return nil, fmt.Errorf("section %s: symbol %s: size exceeds maximum", secName, symbol.Name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		variableOffsets[variable{secName, symbol.Name}] = uint32(symbol.Value)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rawTypes, rawStrings, err := parseBTF(btfSection.Open(), file.ByteOrder)
 | 
			
		||||
	spec, err := loadNakedSpec(btfSection.Open(), file.ByteOrder, sectionSizes, variableOffsets)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if btfExtSection == nil {
 | 
			
		||||
		return spec, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	spec.funcInfos, spec.lineInfos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("can't read ext info: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return spec, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func loadNakedSpec(btf io.ReadSeeker, bo binary.ByteOrder, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) (*Spec, error) {
 | 
			
		||||
	rawTypes, rawStrings, err := parseBTF(btf, bo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -123,77 +145,99 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		funcInfos = make(map[string]extInfo)
 | 
			
		||||
		lineInfos = make(map[string]extInfo)
 | 
			
		||||
	)
 | 
			
		||||
	if btfExtSection != nil {
 | 
			
		||||
		funcInfos, lineInfos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, rawStrings)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("can't read ext info: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Spec{
 | 
			
		||||
		rawTypes:  rawTypes,
 | 
			
		||||
		types:     types,
 | 
			
		||||
		strings:   rawStrings,
 | 
			
		||||
		funcInfos: funcInfos,
 | 
			
		||||
		lineInfos: lineInfos,
 | 
			
		||||
		byteOrder: file.ByteOrder,
 | 
			
		||||
		byteOrder: bo,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var kernelBTF struct {
 | 
			
		||||
	sync.Mutex
 | 
			
		||||
	*Spec
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadKernelSpec returns the current kernel's BTF information.
 | 
			
		||||
//
 | 
			
		||||
// Requires a >= 5.5 kernel with CONFIG_DEBUG_INFO_BTF enabled. Returns
 | 
			
		||||
// ErrNotSupported if BTF is not enabled.
 | 
			
		||||
func LoadKernelSpec() (*Spec, error) {
 | 
			
		||||
	kernelBTF.Lock()
 | 
			
		||||
	defer kernelBTF.Unlock()
 | 
			
		||||
 | 
			
		||||
	if kernelBTF.Spec != nil {
 | 
			
		||||
		return kernelBTF.Spec, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	kernelBTF.Spec, err = loadKernelSpec()
 | 
			
		||||
	return kernelBTF.Spec, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func loadKernelSpec() (*Spec, error) {
 | 
			
		||||
	fh, err := os.Open("/sys/kernel/btf/vmlinux")
 | 
			
		||||
	if os.IsNotExist(err) {
 | 
			
		||||
		return nil, fmt.Errorf("can't open kernel BTF at /sys/kernel/btf/vmlinux: %w", ErrNotFound)
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("can't read kernel BTF: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer fh.Close()
 | 
			
		||||
 | 
			
		||||
	return loadNakedSpec(fh, internal.NativeEndian, nil, nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseBTF(btf io.ReadSeeker, bo binary.ByteOrder) ([]rawType, stringTable, error) {
 | 
			
		||||
	rawBTF, err := ioutil.ReadAll(btf)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("can't read BTF: %v", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("can't read BTF: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rd := bytes.NewReader(rawBTF)
 | 
			
		||||
 | 
			
		||||
	var header btfHeader
 | 
			
		||||
	if err := binary.Read(rd, bo, &header); err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("can't read header: %v", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("can't read header: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if header.Magic != btfMagic {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("incorrect magic value %v", header.Magic)
 | 
			
		||||
		return nil, nil, fmt.Errorf("incorrect magic value %v", header.Magic)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if header.Version != 1 {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("unexpected version %v", header.Version)
 | 
			
		||||
		return nil, nil, fmt.Errorf("unexpected version %v", header.Version)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if header.Flags != 0 {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("unsupported flags %v", header.Flags)
 | 
			
		||||
		return nil, nil, fmt.Errorf("unsupported flags %v", header.Flags)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	remainder := int64(header.HdrLen) - int64(binary.Size(&header))
 | 
			
		||||
	if remainder < 0 {
 | 
			
		||||
		return nil, nil, xerrors.New("header is too short")
 | 
			
		||||
		return nil, nil, errors.New("header is too short")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := io.CopyN(internal.DiscardZeroes{}, rd, remainder); err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("header padding: %v", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("header padding: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := rd.Seek(int64(header.HdrLen+header.StringOff), io.SeekStart); err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("can't seek to start of string section: %v", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("can't seek to start of string section: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rawStrings, err := readStringTable(io.LimitReader(rd, int64(header.StringLen)))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("can't read type names: %w", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("can't read type names: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := rd.Seek(int64(header.HdrLen+header.TypeOff), io.SeekStart); err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("can't seek to start of type section: %v", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("can't seek to start of type section: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rawTypes, err := readTypes(io.LimitReader(rd, int64(header.TypeLen)), bo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("can't read types: %w", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("can't read types: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return rawTypes, rawStrings, nil
 | 
			
		||||
@@ -215,9 +259,13 @@ func fixupDatasec(rawTypes []rawType, rawStrings stringTable, sectionSizes map[s
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if name == ".kconfig" || name == ".ksym" {
 | 
			
		||||
			return fmt.Errorf("reference to %s: %w", name, ErrNotSupported)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		size, ok := sectionSizes[name]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return xerrors.Errorf("data section %s: missing size", name)
 | 
			
		||||
			return fmt.Errorf("data section %s: missing size", name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		rawTypes[i].SizeType = size
 | 
			
		||||
@@ -226,17 +274,17 @@ func fixupDatasec(rawTypes []rawType, rawStrings stringTable, sectionSizes map[s
 | 
			
		||||
		for j, secInfo := range secinfos {
 | 
			
		||||
			id := int(secInfo.Type - 1)
 | 
			
		||||
			if id >= len(rawTypes) {
 | 
			
		||||
				return xerrors.Errorf("data section %s: invalid type id %d for variable %d", name, id, j)
 | 
			
		||||
				return fmt.Errorf("data section %s: invalid type id %d for variable %d", name, id, j)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			varName, err := rawStrings.Lookup(rawTypes[id].NameOff)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return xerrors.Errorf("data section %s: can't get name for type %d: %w", name, id, err)
 | 
			
		||||
				return fmt.Errorf("data section %s: can't get name for type %d: %w", name, id, err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			offset, ok := variableOffsets[variable{name, varName}]
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return xerrors.Errorf("data section %s: missing offset for variable %s", name, varName)
 | 
			
		||||
				return fmt.Errorf("data section %s: missing offset for variable %s", name, varName)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			secinfos[j].Offset = offset
 | 
			
		||||
@@ -246,7 +294,12 @@ func fixupDatasec(rawTypes []rawType, rawStrings stringTable, sectionSizes map[s
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Spec) marshal(bo binary.ByteOrder) ([]byte, error) {
 | 
			
		||||
type marshalOpts struct {
 | 
			
		||||
	ByteOrder        binary.ByteOrder
 | 
			
		||||
	StripFuncLinkage bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Spec) marshal(opts marshalOpts) ([]byte, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		buf       bytes.Buffer
 | 
			
		||||
		header    = new(btfHeader)
 | 
			
		||||
@@ -258,9 +311,14 @@ func (s *Spec) marshal(bo binary.ByteOrder) ([]byte, error) {
 | 
			
		||||
	_, _ = buf.Write(make([]byte, headerLen))
 | 
			
		||||
 | 
			
		||||
	// Write type section, just after the header.
 | 
			
		||||
	for _, typ := range s.rawTypes {
 | 
			
		||||
		if err := typ.Marshal(&buf, bo); err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("can't marshal BTF: %w", err)
 | 
			
		||||
	for _, raw := range s.rawTypes {
 | 
			
		||||
		switch {
 | 
			
		||||
		case opts.StripFuncLinkage && raw.Kind() == kindFunc:
 | 
			
		||||
			raw.SetLinkage(linkageStatic)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := raw.Marshal(&buf, opts.ByteOrder); err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("can't marshal BTF: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -282,9 +340,9 @@ func (s *Spec) marshal(bo binary.ByteOrder) ([]byte, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	raw := buf.Bytes()
 | 
			
		||||
	err := binary.Write(sliceWriter(raw[:headerLen]), bo, header)
 | 
			
		||||
	err := binary.Write(sliceWriter(raw[:headerLen]), opts.ByteOrder, header)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't write header: %v", err)
 | 
			
		||||
		return nil, fmt.Errorf("can't write header: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return raw, nil
 | 
			
		||||
@@ -294,7 +352,7 @@ type sliceWriter []byte
 | 
			
		||||
 | 
			
		||||
func (sw sliceWriter) Write(p []byte) (int, error) {
 | 
			
		||||
	if len(p) != len(sw) {
 | 
			
		||||
		return 0, xerrors.New("size doesn't match")
 | 
			
		||||
		return 0, errors.New("size doesn't match")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return copy(sw, p), nil
 | 
			
		||||
@@ -304,17 +362,22 @@ func (sw sliceWriter) Write(p []byte) (int, error) {
 | 
			
		||||
//
 | 
			
		||||
// Length is the number of bytes in the raw BPF instruction stream.
 | 
			
		||||
//
 | 
			
		||||
// Returns an error if there is no BTF.
 | 
			
		||||
// Returns an error which may wrap ErrNoExtendedInfo if the Spec doesn't
 | 
			
		||||
// contain extended BTF info.
 | 
			
		||||
func (s *Spec) Program(name string, length uint64) (*Program, error) {
 | 
			
		||||
	if length == 0 {
 | 
			
		||||
		return nil, xerrors.New("length musn't be zero")
 | 
			
		||||
		return nil, errors.New("length musn't be zero")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if s.funcInfos == nil && s.lineInfos == nil {
 | 
			
		||||
		return nil, fmt.Errorf("BTF for section %s: %w", name, ErrNoExtendedInfo)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	funcInfos, funcOK := s.funcInfos[name]
 | 
			
		||||
	lineInfos, lineOK := s.lineInfos[name]
 | 
			
		||||
 | 
			
		||||
	if !funcOK && !lineOK {
 | 
			
		||||
		return nil, xerrors.Errorf("no BTF for program %s", name)
 | 
			
		||||
		return nil, fmt.Errorf("no extended BTF info for section %s", name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Program{s, length, funcInfos, lineInfos}, nil
 | 
			
		||||
@@ -331,7 +394,7 @@ func (s *Spec) Map(name string) (*Map, []Member, error) {
 | 
			
		||||
 | 
			
		||||
	mapStruct, ok := mapVar.Type.(*Struct)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("expected struct, have %s", mapVar.Type)
 | 
			
		||||
		return nil, nil, fmt.Errorf("expected struct, have %s", mapVar.Type)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var key, value Type
 | 
			
		||||
@@ -346,11 +409,11 @@ func (s *Spec) Map(name string) (*Map, []Member, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if key == nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("map %s: missing 'key' in type", name)
 | 
			
		||||
		key = (*Void)(nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if value == nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("map %s: missing 'value' in type", name)
 | 
			
		||||
		value = (*Void)(nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Map{s, key, value}, mapStruct.Members, nil
 | 
			
		||||
@@ -360,19 +423,18 @@ func (s *Spec) Map(name string) (*Map, []Member, error) {
 | 
			
		||||
func (s *Spec) Datasec(name string) (*Map, error) {
 | 
			
		||||
	var datasec Datasec
 | 
			
		||||
	if err := s.FindType(name, &datasec); err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("data section %s: can't get BTF: %w", name, err)
 | 
			
		||||
		return nil, fmt.Errorf("data section %s: can't get BTF: %w", name, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Map{s, &Void{}, &datasec}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var errNotFound = xerrors.New("not found")
 | 
			
		||||
 | 
			
		||||
// FindType searches for a type with a specific name.
 | 
			
		||||
//
 | 
			
		||||
// hint determines the type of the returned Type.
 | 
			
		||||
//
 | 
			
		||||
// Returns an error if there is no or multiple matches.
 | 
			
		||||
// Returns an error wrapping ErrNotFound if no matching
 | 
			
		||||
// type exists in spec.
 | 
			
		||||
func (s *Spec) FindType(name string, typ Type) error {
 | 
			
		||||
	var (
 | 
			
		||||
		wanted    = reflect.TypeOf(typ)
 | 
			
		||||
@@ -385,14 +447,14 @@ func (s *Spec) FindType(name string, typ Type) error {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if candidate != nil {
 | 
			
		||||
			return xerrors.Errorf("type %s: multiple candidates for %T", name, typ)
 | 
			
		||||
			return fmt.Errorf("type %s: multiple candidates for %T", name, typ)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		candidate = typ
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if candidate == nil {
 | 
			
		||||
		return xerrors.Errorf("type %s: %w", name, errNotFound)
 | 
			
		||||
		return fmt.Errorf("type %s: %w", name, ErrNotFound)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value := reflect.Indirect(reflect.ValueOf(copyType(candidate)))
 | 
			
		||||
@@ -414,16 +476,19 @@ func NewHandle(spec *Spec) (*Handle, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if spec.byteOrder != internal.NativeEndian {
 | 
			
		||||
		return nil, xerrors.Errorf("can't load %s BTF on %s", spec.byteOrder, internal.NativeEndian)
 | 
			
		||||
		return nil, fmt.Errorf("can't load %s BTF on %s", spec.byteOrder, internal.NativeEndian)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	btf, err := spec.marshal(internal.NativeEndian)
 | 
			
		||||
	btf, err := spec.marshal(marshalOpts{
 | 
			
		||||
		ByteOrder:        internal.NativeEndian,
 | 
			
		||||
		StripFuncLinkage: haveFuncLinkage() != nil,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't marshal BTF: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("can't marshal BTF: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if uint64(len(btf)) > math.MaxUint32 {
 | 
			
		||||
		return nil, xerrors.New("BTF exceeds the maximum size")
 | 
			
		||||
		return nil, errors.New("BTF exceeds the maximum size")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	attr := &bpfLoadBTFAttr{
 | 
			
		||||
@@ -507,12 +572,12 @@ func ProgramSpec(s *Program) *Spec {
 | 
			
		||||
func ProgramAppend(s, other *Program) error {
 | 
			
		||||
	funcInfos, err := s.funcInfos.append(other.funcInfos, s.length)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return xerrors.Errorf("func infos: %w", err)
 | 
			
		||||
		return fmt.Errorf("func infos: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lineInfos, err := s.lineInfos.append(other.lineInfos, s.length)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return xerrors.Errorf("line infos: %w", err)
 | 
			
		||||
		return fmt.Errorf("line infos: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.length += other.length
 | 
			
		||||
@@ -566,26 +631,36 @@ func bpfLoadBTF(attr *bpfLoadBTFAttr) (*internal.FD, error) {
 | 
			
		||||
	return internal.NewFD(uint32(fd)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func minimalBTF(bo binary.ByteOrder) []byte {
 | 
			
		||||
func marshalBTF(types interface{}, strings []byte, bo binary.ByteOrder) []byte {
 | 
			
		||||
	const minHeaderLength = 24
 | 
			
		||||
 | 
			
		||||
	typesLen := uint32(binary.Size(types))
 | 
			
		||||
	header := btfHeader{
 | 
			
		||||
		Magic:     btfMagic,
 | 
			
		||||
		Version:   1,
 | 
			
		||||
		HdrLen:    minHeaderLength,
 | 
			
		||||
		TypeOff:   0,
 | 
			
		||||
		TypeLen:   typesLen,
 | 
			
		||||
		StringOff: typesLen,
 | 
			
		||||
		StringLen: uint32(len(strings)),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	_ = binary.Write(buf, bo, &header)
 | 
			
		||||
	_ = binary.Write(buf, bo, types)
 | 
			
		||||
	buf.Write(strings)
 | 
			
		||||
 | 
			
		||||
	return buf.Bytes()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var haveBTF = internal.FeatureTest("BTF", "5.1", func() (bool, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		types struct {
 | 
			
		||||
			Integer btfType
 | 
			
		||||
			Var     btfType
 | 
			
		||||
			btfVar  struct{ Linkage uint32 }
 | 
			
		||||
		}
 | 
			
		||||
		typLen  = uint32(binary.Size(&types))
 | 
			
		||||
		strings = []byte{0, 'a', 0}
 | 
			
		||||
		header  = btfHeader{
 | 
			
		||||
			Magic:     btfMagic,
 | 
			
		||||
			Version:   1,
 | 
			
		||||
			HdrLen:    minHeaderLength,
 | 
			
		||||
			TypeOff:   0,
 | 
			
		||||
			TypeLen:   typLen,
 | 
			
		||||
			StringOff: typLen,
 | 
			
		||||
			StringLen: uint32(len(strings)),
 | 
			
		||||
		}
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// We use a BTF_KIND_VAR here, to make sure that
 | 
			
		||||
@@ -596,16 +671,8 @@ func minimalBTF(bo binary.ByteOrder) []byte {
 | 
			
		||||
	types.Var.SetKind(kindVar)
 | 
			
		||||
	types.Var.SizeType = 1
 | 
			
		||||
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	_ = binary.Write(buf, bo, &header)
 | 
			
		||||
	_ = binary.Write(buf, bo, &types)
 | 
			
		||||
	buf.Write(strings)
 | 
			
		||||
	btf := marshalBTF(&types, strings, internal.NativeEndian)
 | 
			
		||||
 | 
			
		||||
	return buf.Bytes()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var haveBTF = internal.FeatureTest("BTF", "5.1", func() bool {
 | 
			
		||||
	btf := minimalBTF(internal.NativeEndian)
 | 
			
		||||
	fd, err := bpfLoadBTF(&bpfLoadBTFAttr{
 | 
			
		||||
		btf:     internal.NewSlicePointer(btf),
 | 
			
		||||
		btfSize: uint32(len(btf)),
 | 
			
		||||
@@ -615,5 +682,35 @@ var haveBTF = internal.FeatureTest("BTF", "5.1", func() bool {
 | 
			
		||||
	}
 | 
			
		||||
	// Check for EINVAL specifically, rather than err != nil since we
 | 
			
		||||
	// otherwise misdetect due to insufficient permissions.
 | 
			
		||||
	return !xerrors.Is(err, unix.EINVAL)
 | 
			
		||||
	return !errors.Is(err, unix.EINVAL), nil
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
var haveFuncLinkage = internal.FeatureTest("BTF func linkage", "5.6", func() (bool, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		types struct {
 | 
			
		||||
			FuncProto btfType
 | 
			
		||||
			Func      btfType
 | 
			
		||||
		}
 | 
			
		||||
		strings = []byte{0, 'a', 0}
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	types.FuncProto.SetKind(kindFuncProto)
 | 
			
		||||
	types.Func.SetKind(kindFunc)
 | 
			
		||||
	types.Func.SizeType = 1 // aka FuncProto
 | 
			
		||||
	types.Func.NameOff = 1
 | 
			
		||||
	types.Func.SetLinkage(linkageGlobal)
 | 
			
		||||
 | 
			
		||||
	btf := marshalBTF(&types, strings, internal.NativeEndian)
 | 
			
		||||
 | 
			
		||||
	fd, err := bpfLoadBTF(&bpfLoadBTFAttr{
 | 
			
		||||
		btf:     internal.NewSlicePointer(btf),
 | 
			
		||||
		btfSize: uint32(len(btf)),
 | 
			
		||||
	})
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		fd.Close()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check for EINVAL specifically, rather than err != nil since we
 | 
			
		||||
	// otherwise misdetect due to insufficient permissions.
 | 
			
		||||
	return !errors.Is(err, unix.EINVAL), nil
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -4,8 +4,6 @@ import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// btfKind describes a Type.
 | 
			
		||||
@@ -33,6 +31,14 @@ const (
 | 
			
		||||
	kindDatasec
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type btfFuncLinkage uint8
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	linkageStatic btfFuncLinkage = iota
 | 
			
		||||
	linkageGlobal
 | 
			
		||||
	linkageExtern
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	btfTypeKindShift = 24
 | 
			
		||||
	btfTypeKindLen   = 4
 | 
			
		||||
@@ -44,7 +50,7 @@ const (
 | 
			
		||||
type btfType struct {
 | 
			
		||||
	NameOff uint32
 | 
			
		||||
	/* "info" bits arrangement
 | 
			
		||||
	 * bits  0-15: vlen (e.g. # of struct's members)
 | 
			
		||||
	 * bits  0-15: vlen (e.g. # of struct's members), linkage
 | 
			
		||||
	 * bits 16-23: unused
 | 
			
		||||
	 * bits 24-27: kind (e.g. int, ptr, array...etc)
 | 
			
		||||
	 * bits 28-30: unused
 | 
			
		||||
@@ -130,6 +136,14 @@ func (bt *btfType) SetVlen(vlen int) {
 | 
			
		||||
	bt.setInfo(uint32(vlen), btfTypeVlenMask, btfTypeVlenShift)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (bt *btfType) Linkage() btfFuncLinkage {
 | 
			
		||||
	return btfFuncLinkage(bt.info(btfTypeVlenMask, btfTypeVlenShift))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (bt *btfType) SetLinkage(linkage btfFuncLinkage) {
 | 
			
		||||
	bt.setInfo(uint32(linkage), btfTypeVlenMask, btfTypeVlenShift)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (bt *btfType) Type() TypeID {
 | 
			
		||||
	// TODO: Panic here if wrong kind?
 | 
			
		||||
	return TypeID(bt.SizeType)
 | 
			
		||||
@@ -199,7 +213,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
 | 
			
		||||
		if err := binary.Read(r, bo, &header); err == io.EOF {
 | 
			
		||||
			return types, nil
 | 
			
		||||
		} else if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("can't read type info for id %v: %v", id, err)
 | 
			
		||||
			return nil, fmt.Errorf("can't read type info for id %v: %v", id, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var data interface{}
 | 
			
		||||
@@ -228,7 +242,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
 | 
			
		||||
		case kindDatasec:
 | 
			
		||||
			data = make([]btfVarSecinfo, header.Vlen())
 | 
			
		||||
		default:
 | 
			
		||||
			return nil, xerrors.Errorf("type id %v: unknown kind: %v", id, header.Kind())
 | 
			
		||||
			return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind())
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if data == nil {
 | 
			
		||||
@@ -237,7 +251,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := binary.Read(r, bo, data); err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("type id %d: kind %v: can't read %T: %v", id, header.Kind(), data, err)
 | 
			
		||||
			return nil, fmt.Errorf("type id %d: kind %v: can't read %T: %v", id, header.Kind(), data, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		types = append(types, rawType{header, data})
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										44
									
								
								vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -3,13 +3,13 @@ package btf
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/asm"
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type btfExtHeader struct {
 | 
			
		||||
@@ -27,49 +27,49 @@ type btfExtHeader struct {
 | 
			
		||||
func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (funcInfo, lineInfo map[string]extInfo, err error) {
 | 
			
		||||
	var header btfExtHeader
 | 
			
		||||
	if err := binary.Read(r, bo, &header); err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("can't read header: %v", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("can't read header: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if header.Magic != btfMagic {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("incorrect magic value %v", header.Magic)
 | 
			
		||||
		return nil, nil, fmt.Errorf("incorrect magic value %v", header.Magic)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if header.Version != 1 {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("unexpected version %v", header.Version)
 | 
			
		||||
		return nil, nil, fmt.Errorf("unexpected version %v", header.Version)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if header.Flags != 0 {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("unsupported flags %v", header.Flags)
 | 
			
		||||
		return nil, nil, fmt.Errorf("unsupported flags %v", header.Flags)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	remainder := int64(header.HdrLen) - int64(binary.Size(&header))
 | 
			
		||||
	if remainder < 0 {
 | 
			
		||||
		return nil, nil, xerrors.New("header is too short")
 | 
			
		||||
		return nil, nil, errors.New("header is too short")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Of course, the .BTF.ext header has different semantics than the
 | 
			
		||||
	// .BTF ext header. We need to ignore non-null values.
 | 
			
		||||
	_, err = io.CopyN(ioutil.Discard, r, remainder)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("header padding: %v", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("header padding: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := r.Seek(int64(header.HdrLen+header.FuncInfoOff), io.SeekStart); err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("can't seek to function info section: %v", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("can't seek to function info section: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	funcInfo, err = parseExtInfo(io.LimitReader(r, int64(header.FuncInfoLen)), bo, strings)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("function info: %w", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("function info: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := r.Seek(int64(header.HdrLen+header.LineInfoOff), io.SeekStart); err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("can't seek to line info section: %v", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("can't seek to line info section: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lineInfo, err = parseExtInfo(io.LimitReader(r, int64(header.LineInfoLen)), bo, strings)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, xerrors.Errorf("line info: %w", err)
 | 
			
		||||
		return nil, nil, fmt.Errorf("line info: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return funcInfo, lineInfo, nil
 | 
			
		||||
@@ -92,7 +92,7 @@ type extInfo struct {
 | 
			
		||||
 | 
			
		||||
func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
 | 
			
		||||
	if other.recordSize != ei.recordSize {
 | 
			
		||||
		return extInfo{}, xerrors.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize)
 | 
			
		||||
		return extInfo{}, fmt.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	records := make([]extInfoRecord, 0, len(ei.records)+len(other.records))
 | 
			
		||||
@@ -117,7 +117,7 @@ func (ei extInfo) MarshalBinary() ([]byte, error) {
 | 
			
		||||
		// while the ELF tracks it in bytes.
 | 
			
		||||
		insnOff := uint32(info.InsnOff / asm.InstructionSize)
 | 
			
		||||
		if err := binary.Write(buf, internal.NativeEndian, insnOff); err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("can't write instruction offset: %v", err)
 | 
			
		||||
			return nil, fmt.Errorf("can't write instruction offset: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		buf.Write(info.Opaque)
 | 
			
		||||
@@ -129,12 +129,12 @@ func (ei extInfo) MarshalBinary() ([]byte, error) {
 | 
			
		||||
func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[string]extInfo, error) {
 | 
			
		||||
	var recordSize uint32
 | 
			
		||||
	if err := binary.Read(r, bo, &recordSize); err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't read record size: %v", err)
 | 
			
		||||
		return nil, fmt.Errorf("can't read record size: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if recordSize < 4 {
 | 
			
		||||
		// Need at least insnOff
 | 
			
		||||
		return nil, xerrors.New("record size too short")
 | 
			
		||||
		return nil, errors.New("record size too short")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result := make(map[string]extInfo)
 | 
			
		||||
@@ -143,32 +143,32 @@ func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[st
 | 
			
		||||
		if err := binary.Read(r, bo, &infoHeader); err == io.EOF {
 | 
			
		||||
			return result, nil
 | 
			
		||||
		} else if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("can't read ext info header: %v", err)
 | 
			
		||||
			return nil, fmt.Errorf("can't read ext info header: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		secName, err := strings.Lookup(infoHeader.SecNameOff)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("can't get section name: %w", err)
 | 
			
		||||
			return nil, fmt.Errorf("can't get section name: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if infoHeader.NumInfo == 0 {
 | 
			
		||||
			return nil, xerrors.Errorf("section %s has invalid number of records", secName)
 | 
			
		||||
			return nil, fmt.Errorf("section %s has invalid number of records", secName)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var records []extInfoRecord
 | 
			
		||||
		for i := uint32(0); i < infoHeader.NumInfo; i++ {
 | 
			
		||||
			var byteOff uint32
 | 
			
		||||
			if err := binary.Read(r, bo, &byteOff); err != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("section %v: can't read extended info offset: %v", secName, err)
 | 
			
		||||
				return nil, fmt.Errorf("section %v: can't read extended info offset: %v", secName, err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			buf := make([]byte, int(recordSize-4))
 | 
			
		||||
			if _, err := io.ReadFull(r, buf); err != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("section %v: can't read record: %v", secName, err)
 | 
			
		||||
				return nil, fmt.Errorf("section %v: can't read record: %v", secName, err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if byteOff%asm.InstructionSize != 0 {
 | 
			
		||||
				return nil, xerrors.Errorf("section %v: offset %v is not aligned with instruction size", secName, byteOff)
 | 
			
		||||
				return nil, fmt.Errorf("section %v: offset %v is not aligned with instruction size", secName, byteOff)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			records = append(records, extInfoRecord{uint64(byteOff), buf})
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/github.com/cilium/ebpf/internal/btf/strings.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/cilium/ebpf/internal/btf/strings.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -2,10 +2,10 @@ package btf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type stringTable []byte
 | 
			
		||||
@@ -13,19 +13,19 @@ type stringTable []byte
 | 
			
		||||
func readStringTable(r io.Reader) (stringTable, error) {
 | 
			
		||||
	contents, err := ioutil.ReadAll(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't read string table: %v", err)
 | 
			
		||||
		return nil, fmt.Errorf("can't read string table: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(contents) < 1 {
 | 
			
		||||
		return nil, xerrors.New("string table is empty")
 | 
			
		||||
		return nil, errors.New("string table is empty")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if contents[0] != '\x00' {
 | 
			
		||||
		return nil, xerrors.New("first item in string table is non-empty")
 | 
			
		||||
		return nil, errors.New("first item in string table is non-empty")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if contents[len(contents)-1] != '\x00' {
 | 
			
		||||
		return nil, xerrors.New("string table isn't null terminated")
 | 
			
		||||
		return nil, errors.New("string table isn't null terminated")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return stringTable(contents), nil
 | 
			
		||||
@@ -33,22 +33,22 @@ func readStringTable(r io.Reader) (stringTable, error) {
 | 
			
		||||
 | 
			
		||||
func (st stringTable) Lookup(offset uint32) (string, error) {
 | 
			
		||||
	if int64(offset) > int64(^uint(0)>>1) {
 | 
			
		||||
		return "", xerrors.Errorf("offset %d overflows int", offset)
 | 
			
		||||
		return "", fmt.Errorf("offset %d overflows int", offset)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pos := int(offset)
 | 
			
		||||
	if pos >= len(st) {
 | 
			
		||||
		return "", xerrors.Errorf("offset %d is out of bounds", offset)
 | 
			
		||||
		return "", fmt.Errorf("offset %d is out of bounds", offset)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if pos > 0 && st[pos-1] != '\x00' {
 | 
			
		||||
		return "", xerrors.Errorf("offset %d isn't start of a string", offset)
 | 
			
		||||
		return "", fmt.Errorf("offset %d isn't start of a string", offset)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	str := st[pos:]
 | 
			
		||||
	end := bytes.IndexByte(str, '\x00')
 | 
			
		||||
	if end == -1 {
 | 
			
		||||
		return "", xerrors.Errorf("offset %d isn't null terminated", offset)
 | 
			
		||||
		return "", fmt.Errorf("offset %d isn't null terminated", offset)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return string(str[:end]), nil
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								vendor/github.com/cilium/ebpf/internal/btf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/cilium/ebpf/internal/btf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,9 +1,9 @@
 | 
			
		||||
package btf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const maxTypeDepth = 32
 | 
			
		||||
@@ -38,9 +38,10 @@ func (n Name) name() string {
 | 
			
		||||
// Void is the unit type of BTF.
 | 
			
		||||
type Void struct{}
 | 
			
		||||
 | 
			
		||||
func (v Void) ID() TypeID      { return 0 }
 | 
			
		||||
func (v Void) copy() Type      { return Void{} }
 | 
			
		||||
func (v Void) walk(*copyStack) {}
 | 
			
		||||
func (v *Void) ID() TypeID      { return 0 }
 | 
			
		||||
func (v *Void) size() uint32    { return 0 }
 | 
			
		||||
func (v *Void) copy() Type      { return (*Void)(nil) }
 | 
			
		||||
func (v *Void) walk(*copyStack) {}
 | 
			
		||||
 | 
			
		||||
// Int is an integer of a given length.
 | 
			
		||||
type Int struct {
 | 
			
		||||
@@ -310,7 +311,7 @@ func Sizeof(typ Type) (int, error) {
 | 
			
		||||
		switch v := typ.(type) {
 | 
			
		||||
		case *Array:
 | 
			
		||||
			if n > 0 && int64(v.Nelems) > math.MaxInt64/n {
 | 
			
		||||
				return 0, xerrors.New("overflow")
 | 
			
		||||
				return 0, errors.New("overflow")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Arrays may be of zero length, which allows
 | 
			
		||||
@@ -336,22 +337,22 @@ func Sizeof(typ Type) (int, error) {
 | 
			
		||||
			continue
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			return 0, xerrors.Errorf("unrecognized type %T", typ)
 | 
			
		||||
			return 0, fmt.Errorf("unrecognized type %T", typ)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if n > 0 && elem > math.MaxInt64/n {
 | 
			
		||||
			return 0, xerrors.New("overflow")
 | 
			
		||||
			return 0, errors.New("overflow")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		size := n * elem
 | 
			
		||||
		if int64(int(size)) != size {
 | 
			
		||||
			return 0, xerrors.New("overflow")
 | 
			
		||||
			return 0, errors.New("overflow")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return int(size), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0, xerrors.New("exceeded type depth")
 | 
			
		||||
	return 0, errors.New("exceeded type depth")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// copy a Type recursively.
 | 
			
		||||
@@ -433,7 +434,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
 | 
			
		||||
		for i, btfMember := range raw {
 | 
			
		||||
			name, err := rawStrings.LookupName(btfMember.NameOff)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("can't get name for member %d: %w", i, err)
 | 
			
		||||
				return nil, fmt.Errorf("can't get name for member %d: %w", i, err)
 | 
			
		||||
			}
 | 
			
		||||
			members = append(members, Member{
 | 
			
		||||
				Name:   name,
 | 
			
		||||
@@ -447,7 +448,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	types := make([]Type, 0, len(rawTypes))
 | 
			
		||||
	types = append(types, Void{})
 | 
			
		||||
	types = append(types, (*Void)(nil))
 | 
			
		||||
	namedTypes = make(map[string][]Type)
 | 
			
		||||
 | 
			
		||||
	for i, raw := range rawTypes {
 | 
			
		||||
@@ -460,7 +461,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
 | 
			
		||||
 | 
			
		||||
		name, err := rawStrings.LookupName(raw.NameOff)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("can't get name for type id %d: %w", id, err)
 | 
			
		||||
			return nil, fmt.Errorf("can't get name for type id %d: %w", id, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch raw.Kind() {
 | 
			
		||||
@@ -484,14 +485,14 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
 | 
			
		||||
		case kindStruct:
 | 
			
		||||
			members, err := convertMembers(raw.data.([]btfMember))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("struct %s (id %d): %w", name, id, err)
 | 
			
		||||
				return nil, fmt.Errorf("struct %s (id %d): %w", name, id, err)
 | 
			
		||||
			}
 | 
			
		||||
			typ = &Struct{id, name, raw.Size(), members}
 | 
			
		||||
 | 
			
		||||
		case kindUnion:
 | 
			
		||||
			members, err := convertMembers(raw.data.([]btfMember))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("union %s (id %d): %w", name, id, err)
 | 
			
		||||
				return nil, fmt.Errorf("union %s (id %d): %w", name, id, err)
 | 
			
		||||
			}
 | 
			
		||||
			typ = &Union{id, name, raw.Size(), members}
 | 
			
		||||
 | 
			
		||||
@@ -551,7 +552,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
 | 
			
		||||
			typ = &Datasec{id, name, raw.SizeType, vars}
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			return nil, xerrors.Errorf("type id %d: unknown kind: %v", id, raw.Kind())
 | 
			
		||||
			return nil, fmt.Errorf("type id %d: unknown kind: %v", id, raw.Kind())
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		types = append(types, typ)
 | 
			
		||||
@@ -566,7 +567,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
 | 
			
		||||
	for _, fixup := range fixups {
 | 
			
		||||
		i := int(fixup.id)
 | 
			
		||||
		if i >= len(types) {
 | 
			
		||||
			return nil, xerrors.Errorf("reference to invalid type id: %d", fixup.id)
 | 
			
		||||
			return nil, fmt.Errorf("reference to invalid type id: %d", fixup.id)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Default void (id 0) to unknown
 | 
			
		||||
@@ -576,7 +577,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if expected := fixup.expectedKind; expected != kindUnknown && rawKind != expected {
 | 
			
		||||
			return nil, xerrors.Errorf("expected type id %d to have kind %s, found %s", fixup.id, expected, rawKind)
 | 
			
		||||
			return nil, fmt.Errorf("expected type id %d to have kind %s, found %s", fixup.id, expected, rawKind)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		*fixup.typ = types[i]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/cilium/ebpf/internal/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/cilium/ebpf/internal/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -2,11 +2,11 @@ package internal
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ErrorWithLog returns an error that includes logs from the
 | 
			
		||||
@@ -16,7 +16,7 @@ import (
 | 
			
		||||
// the log. It is used to check for truncation of the output.
 | 
			
		||||
func ErrorWithLog(err error, log []byte, logErr error) error {
 | 
			
		||||
	logStr := strings.Trim(CString(log), "\t\r\n ")
 | 
			
		||||
	if xerrors.Is(logErr, unix.ENOSPC) {
 | 
			
		||||
	if errors.Is(logErr, unix.ENOSPC) {
 | 
			
		||||
		logStr += " (truncated...)"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/github.com/cilium/ebpf/internal/fd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/cilium/ebpf/internal/fd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,15 +1,16 @@
 | 
			
		||||
package internal
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var ErrClosedFd = xerrors.New("use of closed file descriptor")
 | 
			
		||||
var ErrClosedFd = errors.New("use of closed file descriptor")
 | 
			
		||||
 | 
			
		||||
type FD struct {
 | 
			
		||||
	raw int64
 | 
			
		||||
@@ -56,8 +57,13 @@ func (fd *FD) Dup() (*FD, error) {
 | 
			
		||||
 | 
			
		||||
	dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't dup fd: %v", err)
 | 
			
		||||
		return nil, fmt.Errorf("can't dup fd: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NewFD(uint32(dup)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fd *FD) File(name string) *os.File {
 | 
			
		||||
	fd.Forget()
 | 
			
		||||
	return os.NewFile(uintptr(fd.raw), name)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										67
									
								
								vendor/github.com/cilium/ebpf/internal/feature.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										67
									
								
								vendor/github.com/cilium/ebpf/internal/feature.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,14 +1,13 @@
 | 
			
		||||
package internal
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ErrNotSupported indicates that a feature is not supported by the current kernel.
 | 
			
		||||
var ErrNotSupported = xerrors.New("not supported")
 | 
			
		||||
var ErrNotSupported = errors.New("not supported")
 | 
			
		||||
 | 
			
		||||
// UnsupportedFeatureError is returned by FeatureTest() functions.
 | 
			
		||||
type UnsupportedFeatureError struct {
 | 
			
		||||
@@ -29,33 +28,63 @@ func (ufe *UnsupportedFeatureError) Is(target error) bool {
 | 
			
		||||
	return target == ErrNotSupported
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type featureTest struct {
 | 
			
		||||
	sync.Mutex
 | 
			
		||||
	successful bool
 | 
			
		||||
	result     error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FeatureTestFn is used to determine whether the kernel supports
 | 
			
		||||
// a certain feature.
 | 
			
		||||
//
 | 
			
		||||
// The return values have the following semantics:
 | 
			
		||||
//
 | 
			
		||||
//   err != nil: the test couldn't be executed
 | 
			
		||||
//   err == nil && available: the feature is available
 | 
			
		||||
//   err == nil && !available: the feature isn't available
 | 
			
		||||
type FeatureTestFn func() (available bool, err error)
 | 
			
		||||
 | 
			
		||||
// FeatureTest wraps a function so that it is run at most once.
 | 
			
		||||
//
 | 
			
		||||
// name should identify the tested feature, while version must be in the
 | 
			
		||||
// form Major.Minor[.Patch].
 | 
			
		||||
//
 | 
			
		||||
// Returns a descriptive UnsupportedFeatureError if the feature is not available.
 | 
			
		||||
func FeatureTest(name, version string, fn func() bool) func() error {
 | 
			
		||||
// Returns an error wrapping ErrNotSupported if the feature is not supported.
 | 
			
		||||
func FeatureTest(name, version string, fn FeatureTestFn) func() error {
 | 
			
		||||
	v, err := NewVersion(version)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return func() error { return err }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		once   sync.Once
 | 
			
		||||
		result error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	ft := new(featureTest)
 | 
			
		||||
	return func() error {
 | 
			
		||||
		once.Do(func() {
 | 
			
		||||
			if !fn() {
 | 
			
		||||
				result = &UnsupportedFeatureError{
 | 
			
		||||
					MinimumVersion: v,
 | 
			
		||||
					Name:           name,
 | 
			
		||||
				}
 | 
			
		||||
		ft.Lock()
 | 
			
		||||
		defer ft.Unlock()
 | 
			
		||||
 | 
			
		||||
		if ft.successful {
 | 
			
		||||
			return ft.result
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		available, err := fn()
 | 
			
		||||
		if errors.Is(err, ErrNotSupported) {
 | 
			
		||||
			// The feature test aborted because a dependent feature
 | 
			
		||||
			// is missing, which we should cache.
 | 
			
		||||
			available = false
 | 
			
		||||
		} else if err != nil {
 | 
			
		||||
			// We couldn't execute the feature test to a point
 | 
			
		||||
			// where it could make a determination.
 | 
			
		||||
			// Don't cache the result, just return it.
 | 
			
		||||
			return fmt.Errorf("can't detect support for %s: %w", name, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ft.successful = true
 | 
			
		||||
		if !available {
 | 
			
		||||
			ft.result = &UnsupportedFeatureError{
 | 
			
		||||
				MinimumVersion: v,
 | 
			
		||||
				Name:           name,
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
		return result
 | 
			
		||||
		}
 | 
			
		||||
		return ft.result
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -69,7 +98,7 @@ func NewVersion(ver string) (Version, error) {
 | 
			
		||||
	var major, minor, patch uint16
 | 
			
		||||
	n, _ := fmt.Sscanf(ver, "%d.%d.%d", &major, &minor, &patch)
 | 
			
		||||
	if n < 2 {
 | 
			
		||||
		return Version{}, xerrors.Errorf("invalid version: %s", ver)
 | 
			
		||||
		return Version{}, fmt.Errorf("invalid version: %s", ver)
 | 
			
		||||
	}
 | 
			
		||||
	return Version{major, minor, patch}, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/cilium/ebpf/internal/io.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/cilium/ebpf/internal/io.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
package internal
 | 
			
		||||
 | 
			
		||||
import "golang.org/x/xerrors"
 | 
			
		||||
import "errors"
 | 
			
		||||
 | 
			
		||||
// DiscardZeroes makes sure that all written bytes are zero
 | 
			
		||||
// before discarding them.
 | 
			
		||||
@@ -9,7 +9,7 @@ type DiscardZeroes struct{}
 | 
			
		||||
func (DiscardZeroes) Write(p []byte) (int, error) {
 | 
			
		||||
	for _, b := range p {
 | 
			
		||||
		if b != 0 {
 | 
			
		||||
			return 0, xerrors.New("encountered non-zero byte")
 | 
			
		||||
			return 0, errors.New("encountered non-zero byte")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return len(p), nil
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										118
									
								
								vendor/github.com/cilium/ebpf/internal/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										118
									
								
								vendor/github.com/cilium/ebpf/internal/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,16 +1,61 @@
 | 
			
		||||
package internal
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//go:generate stringer -output syscall_string.go -type=BPFCmd
 | 
			
		||||
 | 
			
		||||
// BPFCmd identifies a subcommand of the bpf syscall.
 | 
			
		||||
type BPFCmd int
 | 
			
		||||
 | 
			
		||||
// Well known BPF commands.
 | 
			
		||||
const (
 | 
			
		||||
	BPF_MAP_CREATE BPFCmd = iota
 | 
			
		||||
	BPF_MAP_LOOKUP_ELEM
 | 
			
		||||
	BPF_MAP_UPDATE_ELEM
 | 
			
		||||
	BPF_MAP_DELETE_ELEM
 | 
			
		||||
	BPF_MAP_GET_NEXT_KEY
 | 
			
		||||
	BPF_PROG_LOAD
 | 
			
		||||
	BPF_OBJ_PIN
 | 
			
		||||
	BPF_OBJ_GET
 | 
			
		||||
	BPF_PROG_ATTACH
 | 
			
		||||
	BPF_PROG_DETACH
 | 
			
		||||
	BPF_PROG_TEST_RUN
 | 
			
		||||
	BPF_PROG_GET_NEXT_ID
 | 
			
		||||
	BPF_MAP_GET_NEXT_ID
 | 
			
		||||
	BPF_PROG_GET_FD_BY_ID
 | 
			
		||||
	BPF_MAP_GET_FD_BY_ID
 | 
			
		||||
	BPF_OBJ_GET_INFO_BY_FD
 | 
			
		||||
	BPF_PROG_QUERY
 | 
			
		||||
	BPF_RAW_TRACEPOINT_OPEN
 | 
			
		||||
	BPF_BTF_LOAD
 | 
			
		||||
	BPF_BTF_GET_FD_BY_ID
 | 
			
		||||
	BPF_TASK_FD_QUERY
 | 
			
		||||
	BPF_MAP_LOOKUP_AND_DELETE_ELEM
 | 
			
		||||
	BPF_MAP_FREEZE
 | 
			
		||||
	BPF_BTF_GET_NEXT_ID
 | 
			
		||||
	BPF_MAP_LOOKUP_BATCH
 | 
			
		||||
	BPF_MAP_LOOKUP_AND_DELETE_BATCH
 | 
			
		||||
	BPF_MAP_UPDATE_BATCH
 | 
			
		||||
	BPF_MAP_DELETE_BATCH
 | 
			
		||||
	BPF_LINK_CREATE
 | 
			
		||||
	BPF_LINK_UPDATE
 | 
			
		||||
	BPF_LINK_GET_FD_BY_ID
 | 
			
		||||
	BPF_LINK_GET_NEXT_ID
 | 
			
		||||
	BPF_ENABLE_STATS
 | 
			
		||||
	BPF_ITER_CREATE
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// BPF wraps SYS_BPF.
 | 
			
		||||
//
 | 
			
		||||
// Any pointers contained in attr must use the Pointer type from this package.
 | 
			
		||||
func BPF(cmd int, attr unsafe.Pointer, size uintptr) (uintptr, error) {
 | 
			
		||||
func BPF(cmd BPFCmd, attr unsafe.Pointer, size uintptr) (uintptr, error) {
 | 
			
		||||
	r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size)
 | 
			
		||||
	runtime.KeepAlive(attr)
 | 
			
		||||
 | 
			
		||||
@@ -21,3 +66,74 @@ func BPF(cmd int, attr unsafe.Pointer, size uintptr) (uintptr, error) {
 | 
			
		||||
 | 
			
		||||
	return r1, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BPFProgAttachAttr struct {
 | 
			
		||||
	TargetFd     uint32
 | 
			
		||||
	AttachBpfFd  uint32
 | 
			
		||||
	AttachType   uint32
 | 
			
		||||
	AttachFlags  uint32
 | 
			
		||||
	ReplaceBpfFd uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BPFProgAttach(attr *BPFProgAttachAttr) error {
 | 
			
		||||
	_, err := BPF(BPF_PROG_ATTACH, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BPFProgDetachAttr struct {
 | 
			
		||||
	TargetFd    uint32
 | 
			
		||||
	AttachBpfFd uint32
 | 
			
		||||
	AttachType  uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BPFProgDetach(attr *BPFProgDetachAttr) error {
 | 
			
		||||
	_, err := BPF(BPF_PROG_DETACH, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfObjAttr struct {
 | 
			
		||||
	fileName  Pointer
 | 
			
		||||
	fd        uint32
 | 
			
		||||
	fileFlags uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const bpfFSType = 0xcafe4a11
 | 
			
		||||
 | 
			
		||||
// BPFObjPin wraps BPF_OBJ_PIN.
 | 
			
		||||
func BPFObjPin(fileName string, fd *FD) error {
 | 
			
		||||
	dirName := filepath.Dir(fileName)
 | 
			
		||||
	var statfs unix.Statfs_t
 | 
			
		||||
	if err := unix.Statfs(dirName, &statfs); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if uint64(statfs.Type) != bpfFSType {
 | 
			
		||||
		return fmt.Errorf("%s is not on a bpf filesystem", fileName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value, err := fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	attr := bpfObjAttr{
 | 
			
		||||
		fileName: NewStringPointer(fileName),
 | 
			
		||||
		fd:       value,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = BPF(BPF_OBJ_PIN, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("pin object %s: %w", fileName, err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BPFObjGet wraps BPF_OBJ_GET.
 | 
			
		||||
func BPFObjGet(fileName string) (*FD, error) {
 | 
			
		||||
	attr := bpfObjAttr{
 | 
			
		||||
		fileName: NewStringPointer(fileName),
 | 
			
		||||
	}
 | 
			
		||||
	ptr, err := BPF(BPF_OBJ_GET, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("get object %s: %w", fileName, err)
 | 
			
		||||
	}
 | 
			
		||||
	return NewFD(uint32(ptr)), nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										56
									
								
								vendor/github.com/cilium/ebpf/internal/syscall_string.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								vendor/github.com/cilium/ebpf/internal/syscall_string.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
// Code generated by "stringer -output syscall_string.go -type=BPFCmd"; DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package internal
 | 
			
		||||
 | 
			
		||||
import "strconv"
 | 
			
		||||
 | 
			
		||||
func _() {
 | 
			
		||||
	// An "invalid array index" compiler error signifies that the constant values have changed.
 | 
			
		||||
	// Re-run the stringer command to generate them again.
 | 
			
		||||
	var x [1]struct{}
 | 
			
		||||
	_ = x[BPF_MAP_CREATE-0]
 | 
			
		||||
	_ = x[BPF_MAP_LOOKUP_ELEM-1]
 | 
			
		||||
	_ = x[BPF_MAP_UPDATE_ELEM-2]
 | 
			
		||||
	_ = x[BPF_MAP_DELETE_ELEM-3]
 | 
			
		||||
	_ = x[BPF_MAP_GET_NEXT_KEY-4]
 | 
			
		||||
	_ = x[BPF_PROG_LOAD-5]
 | 
			
		||||
	_ = x[BPF_OBJ_PIN-6]
 | 
			
		||||
	_ = x[BPF_OBJ_GET-7]
 | 
			
		||||
	_ = x[BPF_PROG_ATTACH-8]
 | 
			
		||||
	_ = x[BPF_PROG_DETACH-9]
 | 
			
		||||
	_ = x[BPF_PROG_TEST_RUN-10]
 | 
			
		||||
	_ = x[BPF_PROG_GET_NEXT_ID-11]
 | 
			
		||||
	_ = x[BPF_MAP_GET_NEXT_ID-12]
 | 
			
		||||
	_ = x[BPF_PROG_GET_FD_BY_ID-13]
 | 
			
		||||
	_ = x[BPF_MAP_GET_FD_BY_ID-14]
 | 
			
		||||
	_ = x[BPF_OBJ_GET_INFO_BY_FD-15]
 | 
			
		||||
	_ = x[BPF_PROG_QUERY-16]
 | 
			
		||||
	_ = x[BPF_RAW_TRACEPOINT_OPEN-17]
 | 
			
		||||
	_ = x[BPF_BTF_LOAD-18]
 | 
			
		||||
	_ = x[BPF_BTF_GET_FD_BY_ID-19]
 | 
			
		||||
	_ = x[BPF_TASK_FD_QUERY-20]
 | 
			
		||||
	_ = x[BPF_MAP_LOOKUP_AND_DELETE_ELEM-21]
 | 
			
		||||
	_ = x[BPF_MAP_FREEZE-22]
 | 
			
		||||
	_ = x[BPF_BTF_GET_NEXT_ID-23]
 | 
			
		||||
	_ = x[BPF_MAP_LOOKUP_BATCH-24]
 | 
			
		||||
	_ = x[BPF_MAP_LOOKUP_AND_DELETE_BATCH-25]
 | 
			
		||||
	_ = x[BPF_MAP_UPDATE_BATCH-26]
 | 
			
		||||
	_ = x[BPF_MAP_DELETE_BATCH-27]
 | 
			
		||||
	_ = x[BPF_LINK_CREATE-28]
 | 
			
		||||
	_ = x[BPF_LINK_UPDATE-29]
 | 
			
		||||
	_ = x[BPF_LINK_GET_FD_BY_ID-30]
 | 
			
		||||
	_ = x[BPF_LINK_GET_NEXT_ID-31]
 | 
			
		||||
	_ = x[BPF_ENABLE_STATS-32]
 | 
			
		||||
	_ = x[BPF_ITER_CREATE-33]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const _BPFCmd_name = "BPF_MAP_CREATEBPF_MAP_LOOKUP_ELEMBPF_MAP_UPDATE_ELEMBPF_MAP_DELETE_ELEMBPF_MAP_GET_NEXT_KEYBPF_PROG_LOADBPF_OBJ_PINBPF_OBJ_GETBPF_PROG_ATTACHBPF_PROG_DETACHBPF_PROG_TEST_RUNBPF_PROG_GET_NEXT_IDBPF_MAP_GET_NEXT_IDBPF_PROG_GET_FD_BY_IDBPF_MAP_GET_FD_BY_IDBPF_OBJ_GET_INFO_BY_FDBPF_PROG_QUERYBPF_RAW_TRACEPOINT_OPENBPF_BTF_LOADBPF_BTF_GET_FD_BY_IDBPF_TASK_FD_QUERYBPF_MAP_LOOKUP_AND_DELETE_ELEMBPF_MAP_FREEZEBPF_BTF_GET_NEXT_IDBPF_MAP_LOOKUP_BATCHBPF_MAP_LOOKUP_AND_DELETE_BATCHBPF_MAP_UPDATE_BATCHBPF_MAP_DELETE_BATCHBPF_LINK_CREATEBPF_LINK_UPDATEBPF_LINK_GET_FD_BY_IDBPF_LINK_GET_NEXT_IDBPF_ENABLE_STATSBPF_ITER_CREATE"
 | 
			
		||||
 | 
			
		||||
var _BPFCmd_index = [...]uint16{0, 14, 33, 52, 71, 91, 104, 115, 126, 141, 156, 173, 193, 212, 233, 253, 275, 289, 312, 324, 344, 361, 391, 405, 424, 444, 475, 495, 515, 530, 545, 566, 586, 602, 617}
 | 
			
		||||
 | 
			
		||||
func (i BPFCmd) String() string {
 | 
			
		||||
	if i < 0 || i >= BPFCmd(len(_BPFCmd_index)-1) {
 | 
			
		||||
		return "BPFCmd(" + strconv.FormatInt(int64(i), 10) + ")"
 | 
			
		||||
	}
 | 
			
		||||
	return _BPFCmd_name[_BPFCmd_index[i]:_BPFCmd_index[i+1]]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -16,6 +16,7 @@ const (
 | 
			
		||||
	EINVAL                   = linux.EINVAL
 | 
			
		||||
	EPOLLIN                  = linux.EPOLLIN
 | 
			
		||||
	EINTR                    = linux.EINTR
 | 
			
		||||
	EPERM                    = linux.EPERM
 | 
			
		||||
	ESRCH                    = linux.ESRCH
 | 
			
		||||
	ENODEV                   = linux.ENODEV
 | 
			
		||||
	BPF_F_RDONLY_PROG        = linux.BPF_F_RDONLY_PROG
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -17,6 +17,7 @@ const (
 | 
			
		||||
	ENOSPC                   = syscall.ENOSPC
 | 
			
		||||
	EINVAL                   = syscall.EINVAL
 | 
			
		||||
	EINTR                    = syscall.EINTR
 | 
			
		||||
	EPERM                    = syscall.EPERM
 | 
			
		||||
	ESRCH                    = syscall.ESRCH
 | 
			
		||||
	ENODEV                   = syscall.ENODEV
 | 
			
		||||
	BPF_F_RDONLY_PROG        = 0
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								vendor/github.com/cilium/ebpf/linker.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/cilium/ebpf/linker.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,10 +1,10 @@
 | 
			
		||||
package ebpf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/asm"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// link resolves bpf-to-bpf calls.
 | 
			
		||||
@@ -28,7 +28,7 @@ func link(prog *ProgramSpec, libs []*ProgramSpec) error {
 | 
			
		||||
 | 
			
		||||
			needed, err := needSection(insns, lib.Instructions)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return xerrors.Errorf("linking %s: %w", lib.Name, err)
 | 
			
		||||
				return fmt.Errorf("linking %s: %w", lib.Name, err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !needed {
 | 
			
		||||
@@ -41,7 +41,7 @@ func link(prog *ProgramSpec, libs []*ProgramSpec) error {
 | 
			
		||||
 | 
			
		||||
			if prog.BTF != nil && lib.BTF != nil {
 | 
			
		||||
				if err := btf.ProgramAppend(prog.BTF, lib.BTF); err != nil {
 | 
			
		||||
					return xerrors.Errorf("linking BTF of %s: %w", lib.Name, err)
 | 
			
		||||
					return fmt.Errorf("linking BTF of %s: %w", lib.Name, err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										105
									
								
								vendor/github.com/cilium/ebpf/map.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										105
									
								
								vendor/github.com/cilium/ebpf/map.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,21 +1,20 @@
 | 
			
		||||
package ebpf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Errors returned by Map and MapIterator methods.
 | 
			
		||||
var (
 | 
			
		||||
	ErrKeyNotExist      = xerrors.New("key does not exist")
 | 
			
		||||
	ErrKeyExist         = xerrors.New("key already exists")
 | 
			
		||||
	ErrIterationAborted = xerrors.New("iteration aborted")
 | 
			
		||||
	ErrKeyNotExist      = errors.New("key does not exist")
 | 
			
		||||
	ErrKeyExist         = errors.New("key already exists")
 | 
			
		||||
	ErrIterationAborted = errors.New("iteration aborted")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MapID represents the unique ID of an eBPF map
 | 
			
		||||
@@ -92,7 +91,7 @@ type Map struct {
 | 
			
		||||
// You should not use fd after calling this function.
 | 
			
		||||
func NewMapFromFD(fd int) (*Map, error) {
 | 
			
		||||
	if fd < 0 {
 | 
			
		||||
		return nil, xerrors.New("invalid fd")
 | 
			
		||||
		return nil, errors.New("invalid fd")
 | 
			
		||||
	}
 | 
			
		||||
	bpfFd := internal.NewFD(uint32(fd))
 | 
			
		||||
 | 
			
		||||
@@ -118,8 +117,8 @@ func NewMap(spec *MapSpec) (*Map, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	handle, err := btf.NewHandle(btf.MapSpec(spec.BTF))
 | 
			
		||||
	if err != nil && !xerrors.Is(err, btf.ErrNotSupported) {
 | 
			
		||||
		return nil, xerrors.Errorf("can't load BTF: %w", err)
 | 
			
		||||
	if err != nil && !errors.Is(err, btf.ErrNotSupported) {
 | 
			
		||||
		return nil, fmt.Errorf("can't load BTF: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newMapWithBTF(spec, handle)
 | 
			
		||||
@@ -131,7 +130,7 @@ func newMapWithBTF(spec *MapSpec, handle *btf.Handle) (*Map, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if spec.InnerMap == nil {
 | 
			
		||||
		return nil, xerrors.Errorf("%s requires InnerMap", spec.Type)
 | 
			
		||||
		return nil, fmt.Errorf("%s requires InnerMap", spec.Type)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template, err := createMap(spec.InnerMap, nil, handle)
 | 
			
		||||
@@ -155,25 +154,25 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if abi.ValueSize != 0 && abi.ValueSize != 4 {
 | 
			
		||||
			return nil, xerrors.New("ValueSize must be zero or four for map of map")
 | 
			
		||||
			return nil, errors.New("ValueSize must be zero or four for map of map")
 | 
			
		||||
		}
 | 
			
		||||
		abi.ValueSize = 4
 | 
			
		||||
 | 
			
		||||
	case PerfEventArray:
 | 
			
		||||
		if abi.KeySize != 0 && abi.KeySize != 4 {
 | 
			
		||||
			return nil, xerrors.New("KeySize must be zero or four for perf event array")
 | 
			
		||||
			return nil, errors.New("KeySize must be zero or four for perf event array")
 | 
			
		||||
		}
 | 
			
		||||
		abi.KeySize = 4
 | 
			
		||||
 | 
			
		||||
		if abi.ValueSize != 0 && abi.ValueSize != 4 {
 | 
			
		||||
			return nil, xerrors.New("ValueSize must be zero or four for perf event array")
 | 
			
		||||
			return nil, errors.New("ValueSize must be zero or four for perf event array")
 | 
			
		||||
		}
 | 
			
		||||
		abi.ValueSize = 4
 | 
			
		||||
 | 
			
		||||
		if abi.MaxEntries == 0 {
 | 
			
		||||
			n, err := internal.PossibleCPUs()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, xerrors.Errorf("perf event array: %w", err)
 | 
			
		||||
				return nil, fmt.Errorf("perf event array: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
			abi.MaxEntries = uint32(n)
 | 
			
		||||
		}
 | 
			
		||||
@@ -181,7 +180,7 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err
 | 
			
		||||
 | 
			
		||||
	if abi.Flags&(unix.BPF_F_RDONLY_PROG|unix.BPF_F_WRONLY_PROG) > 0 || spec.Freeze {
 | 
			
		||||
		if err := haveMapMutabilityModifiers(); err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("map create: %w", err)
 | 
			
		||||
			return nil, fmt.Errorf("map create: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -197,7 +196,7 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err
 | 
			
		||||
		var err error
 | 
			
		||||
		attr.innerMapFd, err = inner.Value()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("map create: %w", err)
 | 
			
		||||
			return nil, fmt.Errorf("map create: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -213,7 +212,7 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err
 | 
			
		||||
 | 
			
		||||
	fd, err := bpfMapCreate(&attr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("map create: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("map create: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m, err := newMap(fd, spec.Name, abi)
 | 
			
		||||
@@ -223,13 +222,13 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err
 | 
			
		||||
 | 
			
		||||
	if err := m.populate(spec.Contents); err != nil {
 | 
			
		||||
		m.Close()
 | 
			
		||||
		return nil, xerrors.Errorf("map create: can't set initial contents: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("map create: can't set initial contents: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if spec.Freeze {
 | 
			
		||||
		if err := m.Freeze(); err != nil {
 | 
			
		||||
			m.Close()
 | 
			
		||||
			return nil, xerrors.Errorf("can't freeze map: %w", err)
 | 
			
		||||
			return nil, fmt.Errorf("can't freeze map: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -301,9 +300,9 @@ func (m *Map) Lookup(key, valueOut interface{}) error {
 | 
			
		||||
		*value = m
 | 
			
		||||
		return nil
 | 
			
		||||
	case *Map:
 | 
			
		||||
		return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
 | 
			
		||||
		return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
 | 
			
		||||
	case Map:
 | 
			
		||||
		return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
 | 
			
		||||
		return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
 | 
			
		||||
 | 
			
		||||
	case **Program:
 | 
			
		||||
		p, err := unmarshalProgram(valueBytes)
 | 
			
		||||
@@ -315,9 +314,9 @@ func (m *Map) Lookup(key, valueOut interface{}) error {
 | 
			
		||||
		*value = p
 | 
			
		||||
		return nil
 | 
			
		||||
	case *Program:
 | 
			
		||||
		return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
 | 
			
		||||
		return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
 | 
			
		||||
	case Program:
 | 
			
		||||
		return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
 | 
			
		||||
		return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		return unmarshalBytes(valueOut, valueBytes)
 | 
			
		||||
@@ -332,11 +331,11 @@ func (m *Map) LookupAndDelete(key, valueOut interface{}) error {
 | 
			
		||||
 | 
			
		||||
	keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return xerrors.Errorf("can't marshal key: %w", err)
 | 
			
		||||
		return fmt.Errorf("can't marshal key: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := bpfMapLookupAndDelete(m.fd, keyPtr, valuePtr); err != nil {
 | 
			
		||||
		return xerrors.Errorf("lookup and delete failed: %w", err)
 | 
			
		||||
		return fmt.Errorf("lookup and delete failed: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return unmarshalBytes(valueOut, valueBytes)
 | 
			
		||||
@@ -350,7 +349,7 @@ func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
 | 
			
		||||
	valuePtr := internal.NewSlicePointer(valueBytes)
 | 
			
		||||
 | 
			
		||||
	err := m.lookup(key, valuePtr)
 | 
			
		||||
	if xerrors.Is(err, ErrKeyNotExist) {
 | 
			
		||||
	if errors.Is(err, ErrKeyNotExist) {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -360,11 +359,11 @@ func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
 | 
			
		||||
func (m *Map) lookup(key interface{}, valueOut internal.Pointer) error {
 | 
			
		||||
	keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return xerrors.Errorf("can't marshal key: %w", err)
 | 
			
		||||
		return fmt.Errorf("can't marshal key: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = bpfMapLookupElem(m.fd, keyPtr, valueOut); err != nil {
 | 
			
		||||
		return xerrors.Errorf("lookup failed: %w", err)
 | 
			
		||||
		return fmt.Errorf("lookup failed: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -394,7 +393,7 @@ func (m *Map) Put(key, value interface{}) error {
 | 
			
		||||
func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error {
 | 
			
		||||
	keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return xerrors.Errorf("can't marshal key: %w", err)
 | 
			
		||||
		return fmt.Errorf("can't marshal key: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var valuePtr internal.Pointer
 | 
			
		||||
@@ -404,11 +403,11 @@ func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error {
 | 
			
		||||
		valuePtr, err = marshalPtr(value, int(m.abi.ValueSize))
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return xerrors.Errorf("can't marshal value: %w", err)
 | 
			
		||||
		return fmt.Errorf("can't marshal value: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = bpfMapUpdateElem(m.fd, keyPtr, valuePtr, uint64(flags)); err != nil {
 | 
			
		||||
		return xerrors.Errorf("update failed: %w", err)
 | 
			
		||||
		return fmt.Errorf("update failed: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
@@ -420,11 +419,11 @@ func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error {
 | 
			
		||||
func (m *Map) Delete(key interface{}) error {
 | 
			
		||||
	keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return xerrors.Errorf("can't marshal key: %w", err)
 | 
			
		||||
		return fmt.Errorf("can't marshal key: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = bpfMapDeleteElem(m.fd, keyPtr); err != nil {
 | 
			
		||||
		return xerrors.Errorf("delete failed: %w", err)
 | 
			
		||||
		return fmt.Errorf("delete failed: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -446,7 +445,7 @@ func (m *Map) NextKey(key, nextKeyOut interface{}) error {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := unmarshalBytes(nextKeyOut, nextKeyBytes); err != nil {
 | 
			
		||||
		return xerrors.Errorf("can't unmarshal next key: %w", err)
 | 
			
		||||
		return fmt.Errorf("can't unmarshal next key: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -463,7 +462,7 @@ func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) {
 | 
			
		||||
	nextKeyPtr := internal.NewSlicePointer(nextKey)
 | 
			
		||||
 | 
			
		||||
	err := m.nextKey(key, nextKeyPtr)
 | 
			
		||||
	if xerrors.Is(err, ErrKeyNotExist) {
 | 
			
		||||
	if errors.Is(err, ErrKeyNotExist) {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -479,12 +478,12 @@ func (m *Map) nextKey(key interface{}, nextKeyOut internal.Pointer) error {
 | 
			
		||||
	if key != nil {
 | 
			
		||||
		keyPtr, err = marshalPtr(key, int(m.abi.KeySize))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return xerrors.Errorf("can't marshal key: %w", err)
 | 
			
		||||
			return fmt.Errorf("can't marshal key: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = bpfMapGetNextKey(m.fd, keyPtr, nextKeyOut); err != nil {
 | 
			
		||||
		return xerrors.Errorf("next key failed: %w", err)
 | 
			
		||||
		return fmt.Errorf("next key failed: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -537,7 +536,7 @@ func (m *Map) Clone() (*Map, error) {
 | 
			
		||||
 | 
			
		||||
	dup, err := m.fd.Dup()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't clone map: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("can't clone map: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newMap(dup, m.name, &m.abi)
 | 
			
		||||
@@ -547,7 +546,7 @@ func (m *Map) Clone() (*Map, error) {
 | 
			
		||||
//
 | 
			
		||||
// This requires bpffs to be mounted above fileName. See http://cilium.readthedocs.io/en/doc-1.0/kubernetes/install/#mounting-the-bpf-fs-optional
 | 
			
		||||
func (m *Map) Pin(fileName string) error {
 | 
			
		||||
	return bpfPinObject(fileName, m.fd)
 | 
			
		||||
	return internal.BPFObjPin(fileName, m.fd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Freeze prevents a map to be modified from user space.
 | 
			
		||||
@@ -555,11 +554,11 @@ func (m *Map) Pin(fileName string) error {
 | 
			
		||||
// It makes no changes to kernel-side restrictions.
 | 
			
		||||
func (m *Map) Freeze() error {
 | 
			
		||||
	if err := haveMapMutabilityModifiers(); err != nil {
 | 
			
		||||
		return xerrors.Errorf("can't freeze map: %w", err)
 | 
			
		||||
		return fmt.Errorf("can't freeze map: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := bpfMapFreeze(m.fd); err != nil {
 | 
			
		||||
		return xerrors.Errorf("can't freeze map: %w", err)
 | 
			
		||||
		return fmt.Errorf("can't freeze map: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -567,7 +566,7 @@ func (m *Map) Freeze() error {
 | 
			
		||||
func (m *Map) populate(contents []MapKV) error {
 | 
			
		||||
	for _, kv := range contents {
 | 
			
		||||
		if err := m.Put(kv.Key, kv.Value); err != nil {
 | 
			
		||||
			return xerrors.Errorf("key %v: %w", kv.Key, err)
 | 
			
		||||
			return fmt.Errorf("key %v: %w", kv.Key, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
@@ -578,7 +577,7 @@ func (m *Map) populate(contents []MapKV) error {
 | 
			
		||||
// The function is not compatible with nested maps.
 | 
			
		||||
// Use LoadPinnedMapExplicit in these situations.
 | 
			
		||||
func LoadPinnedMap(fileName string) (*Map, error) {
 | 
			
		||||
	fd, err := bpfGetObject(fileName)
 | 
			
		||||
	fd, err := internal.BPFObjGet(fileName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -592,7 +591,7 @@ func LoadPinnedMap(fileName string) (*Map, error) {
 | 
			
		||||
 | 
			
		||||
// LoadPinnedMapExplicit loads a map with explicit parameters.
 | 
			
		||||
func LoadPinnedMapExplicit(fileName string, abi *MapABI) (*Map, error) {
 | 
			
		||||
	fd, err := bpfGetObject(fileName)
 | 
			
		||||
	fd, err := internal.BPFObjGet(fileName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -601,7 +600,7 @@ func LoadPinnedMapExplicit(fileName string, abi *MapABI) (*Map, error) {
 | 
			
		||||
 | 
			
		||||
func unmarshalMap(buf []byte) (*Map, error) {
 | 
			
		||||
	if len(buf) != 4 {
 | 
			
		||||
		return nil, xerrors.New("map id requires 4 byte value")
 | 
			
		||||
		return nil, errors.New("map id requires 4 byte value")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Looking up an entry in a nested map or prog array returns an id,
 | 
			
		||||
@@ -626,12 +625,12 @@ func patchValue(value []byte, typ btf.Type, replacements map[string]interface{})
 | 
			
		||||
	replaced := make(map[string]bool)
 | 
			
		||||
	replace := func(name string, offset, size int, replacement interface{}) error {
 | 
			
		||||
		if offset+size > len(value) {
 | 
			
		||||
			return xerrors.Errorf("%s: offset %d(+%d) is out of bounds", name, offset, size)
 | 
			
		||||
			return fmt.Errorf("%s: offset %d(+%d) is out of bounds", name, offset, size)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		buf, err := marshalBytes(replacement, size)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return xerrors.Errorf("marshal %s: %w", name, err)
 | 
			
		||||
			return fmt.Errorf("marshal %s: %w", name, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		copy(value[offset:offset+size], buf)
 | 
			
		||||
@@ -655,7 +654,7 @@ func patchValue(value []byte, typ btf.Type, replacements map[string]interface{})
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		return xerrors.Errorf("patching %T is not supported", typ)
 | 
			
		||||
		return fmt.Errorf("patching %T is not supported", typ)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(replaced) == len(replacements) {
 | 
			
		||||
@@ -670,10 +669,10 @@ func patchValue(value []byte, typ btf.Type, replacements map[string]interface{})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(missing) == 1 {
 | 
			
		||||
		return xerrors.Errorf("unknown field: %s", missing[0])
 | 
			
		||||
		return fmt.Errorf("unknown field: %s", missing[0])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return xerrors.Errorf("unknown fields: %s", strings.Join(missing, ","))
 | 
			
		||||
	return fmt.Errorf("unknown fields: %s", strings.Join(missing, ","))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MapIterator iterates a Map.
 | 
			
		||||
@@ -731,7 +730,7 @@ func (mi *MapIterator) Next(keyOut, valueOut interface{}) bool {
 | 
			
		||||
		mi.prevKey = mi.prevBytes
 | 
			
		||||
 | 
			
		||||
		mi.err = mi.target.Lookup(nextBytes, valueOut)
 | 
			
		||||
		if xerrors.Is(mi.err, ErrKeyNotExist) {
 | 
			
		||||
		if errors.Is(mi.err, ErrKeyNotExist) {
 | 
			
		||||
			// Even though the key should be valid, we couldn't look up
 | 
			
		||||
			// its value. If we're iterating a hash map this is probably
 | 
			
		||||
			// because a concurrent delete removed the value before we
 | 
			
		||||
@@ -750,7 +749,7 @@ func (mi *MapIterator) Next(keyOut, valueOut interface{}) bool {
 | 
			
		||||
		return mi.err == nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mi.err = xerrors.Errorf("%w", ErrIterationAborted)
 | 
			
		||||
	mi.err = fmt.Errorf("%w", ErrIterationAborted)
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -767,7 +766,7 @@ func (mi *MapIterator) Err() error {
 | 
			
		||||
//
 | 
			
		||||
// Returns ErrNotExist, if there is no next eBPF map.
 | 
			
		||||
func MapGetNextID(startID MapID) (MapID, error) {
 | 
			
		||||
	id, err := objGetNextID(_MapGetNextID, uint32(startID))
 | 
			
		||||
	id, err := objGetNextID(internal.BPF_MAP_GET_NEXT_ID, uint32(startID))
 | 
			
		||||
	return MapID(id), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -775,7 +774,7 @@ func MapGetNextID(startID MapID) (MapID, error) {
 | 
			
		||||
//
 | 
			
		||||
// Returns ErrNotExist, if there is no eBPF map with the given id.
 | 
			
		||||
func NewMapFromID(id MapID) (*Map, error) {
 | 
			
		||||
	fd, err := bpfObjGetFDByID(_MapGetFDByID, uint32(id))
 | 
			
		||||
	fd, err := bpfObjGetFDByID(internal.BPF_MAP_GET_FD_BY_ID, uint32(id))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								vendor/github.com/cilium/ebpf/marshalers.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/cilium/ebpf/marshalers.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -4,13 +4,13 @@ import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func marshalPtr(data interface{}, length int) (internal.Pointer, error) {
 | 
			
		||||
@@ -18,7 +18,7 @@ func marshalPtr(data interface{}, length int) (internal.Pointer, error) {
 | 
			
		||||
		if length == 0 {
 | 
			
		||||
			return internal.NewPointer(nil), nil
 | 
			
		||||
		}
 | 
			
		||||
		return internal.Pointer{}, xerrors.New("can't use nil as key of map")
 | 
			
		||||
		return internal.Pointer{}, errors.New("can't use nil as key of map")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ptr, ok := data.(unsafe.Pointer); ok {
 | 
			
		||||
@@ -42,12 +42,12 @@ func marshalBytes(data interface{}, length int) (buf []byte, err error) {
 | 
			
		||||
	case []byte:
 | 
			
		||||
		buf = value
 | 
			
		||||
	case unsafe.Pointer:
 | 
			
		||||
		err = xerrors.New("can't marshal from unsafe.Pointer")
 | 
			
		||||
		err = errors.New("can't marshal from unsafe.Pointer")
 | 
			
		||||
	default:
 | 
			
		||||
		var wr bytes.Buffer
 | 
			
		||||
		err = binary.Write(&wr, internal.NativeEndian, value)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			err = xerrors.Errorf("encoding %T: %v", value, err)
 | 
			
		||||
			err = fmt.Errorf("encoding %T: %v", value, err)
 | 
			
		||||
		}
 | 
			
		||||
		buf = wr.Bytes()
 | 
			
		||||
	}
 | 
			
		||||
@@ -56,7 +56,7 @@ func marshalBytes(data interface{}, length int) (buf []byte, err error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(buf) != length {
 | 
			
		||||
		return nil, xerrors.Errorf("%T doesn't marshal to %d bytes", data, length)
 | 
			
		||||
		return nil, fmt.Errorf("%T doesn't marshal to %d bytes", data, length)
 | 
			
		||||
	}
 | 
			
		||||
	return buf, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -92,13 +92,13 @@ func unmarshalBytes(data interface{}, buf []byte) error {
 | 
			
		||||
		*value = buf
 | 
			
		||||
		return nil
 | 
			
		||||
	case string:
 | 
			
		||||
		return xerrors.New("require pointer to string")
 | 
			
		||||
		return errors.New("require pointer to string")
 | 
			
		||||
	case []byte:
 | 
			
		||||
		return xerrors.New("require pointer to []byte")
 | 
			
		||||
		return errors.New("require pointer to []byte")
 | 
			
		||||
	default:
 | 
			
		||||
		rd := bytes.NewReader(buf)
 | 
			
		||||
		if err := binary.Read(rd, internal.NativeEndian, value); err != nil {
 | 
			
		||||
			return xerrors.Errorf("decoding %T: %v", value, err)
 | 
			
		||||
			return fmt.Errorf("decoding %T: %v", value, err)
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
@@ -113,7 +113,7 @@ func unmarshalBytes(data interface{}, buf []byte) error {
 | 
			
		||||
func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, error) {
 | 
			
		||||
	sliceType := reflect.TypeOf(slice)
 | 
			
		||||
	if sliceType.Kind() != reflect.Slice {
 | 
			
		||||
		return internal.Pointer{}, xerrors.New("per-CPU value requires slice")
 | 
			
		||||
		return internal.Pointer{}, errors.New("per-CPU value requires slice")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	possibleCPUs, err := internal.PossibleCPUs()
 | 
			
		||||
@@ -124,7 +124,7 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, er
 | 
			
		||||
	sliceValue := reflect.ValueOf(slice)
 | 
			
		||||
	sliceLen := sliceValue.Len()
 | 
			
		||||
	if sliceLen > possibleCPUs {
 | 
			
		||||
		return internal.Pointer{}, xerrors.Errorf("per-CPU value exceeds number of CPUs")
 | 
			
		||||
		return internal.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	alignedElemLength := align(elemLength, 8)
 | 
			
		||||
@@ -151,7 +151,7 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, er
 | 
			
		||||
func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) error {
 | 
			
		||||
	slicePtrType := reflect.TypeOf(slicePtr)
 | 
			
		||||
	if slicePtrType.Kind() != reflect.Ptr || slicePtrType.Elem().Kind() != reflect.Slice {
 | 
			
		||||
		return xerrors.Errorf("per-cpu value requires pointer to slice")
 | 
			
		||||
		return fmt.Errorf("per-cpu value requires pointer to slice")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	possibleCPUs, err := internal.PossibleCPUs()
 | 
			
		||||
@@ -170,7 +170,7 @@ func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) erro
 | 
			
		||||
 | 
			
		||||
	step := len(buf) / possibleCPUs
 | 
			
		||||
	if step < elemLength {
 | 
			
		||||
		return xerrors.Errorf("per-cpu element length is larger than available data")
 | 
			
		||||
		return fmt.Errorf("per-cpu element length is larger than available data")
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < possibleCPUs; i++ {
 | 
			
		||||
		var elem interface{}
 | 
			
		||||
@@ -188,7 +188,7 @@ func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) erro
 | 
			
		||||
 | 
			
		||||
		err := unmarshalBytes(elem, elemBytes)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return xerrors.Errorf("cpu %d: %w", i, err)
 | 
			
		||||
			return fmt.Errorf("cpu %d: %w", i, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		buf = buf[step:]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										168
									
								
								vendor/github.com/cilium/ebpf/prog.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										168
									
								
								vendor/github.com/cilium/ebpf/prog.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -3,18 +3,16 @@ package ebpf
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/asm"
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ErrNotSupported is returned whenever the kernel doesn't support a feature.
 | 
			
		||||
@@ -48,11 +46,24 @@ type ProgramOptions struct {
 | 
			
		||||
type ProgramSpec struct {
 | 
			
		||||
	// Name is passed to the kernel as a debug aid. Must only contain
 | 
			
		||||
	// alpha numeric and '_' characters.
 | 
			
		||||
	Name          string
 | 
			
		||||
	Type          ProgramType
 | 
			
		||||
	AttachType    AttachType
 | 
			
		||||
	Instructions  asm.Instructions
 | 
			
		||||
	License       string
 | 
			
		||||
	Name string
 | 
			
		||||
	// Type determines at which hook in the kernel a program will run.
 | 
			
		||||
	Type       ProgramType
 | 
			
		||||
	AttachType AttachType
 | 
			
		||||
	// Name of a kernel data structure to attach to. It's interpretation
 | 
			
		||||
	// depends on Type and AttachType.
 | 
			
		||||
	AttachTo     string
 | 
			
		||||
	Instructions asm.Instructions
 | 
			
		||||
 | 
			
		||||
	// License of the program. Some helpers are only available if
 | 
			
		||||
	// the license is deemed compatible with the GPL.
 | 
			
		||||
	//
 | 
			
		||||
	// See https://www.kernel.org/doc/html/latest/process/license-rules.html#id1
 | 
			
		||||
	License string
 | 
			
		||||
 | 
			
		||||
	// Version used by tracing programs.
 | 
			
		||||
	//
 | 
			
		||||
	// Deprecated: superseded by BTF.
 | 
			
		||||
	KernelVersion uint32
 | 
			
		||||
 | 
			
		||||
	// The BTF associated with this program. Changing Instructions
 | 
			
		||||
@@ -84,9 +95,10 @@ type Program struct {
 | 
			
		||||
	// otherwise it is empty.
 | 
			
		||||
	VerifierLog string
 | 
			
		||||
 | 
			
		||||
	fd   *internal.FD
 | 
			
		||||
	name string
 | 
			
		||||
	abi  ProgramABI
 | 
			
		||||
	fd         *internal.FD
 | 
			
		||||
	name       string
 | 
			
		||||
	abi        ProgramABI
 | 
			
		||||
	attachType AttachType
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewProgram creates a new Program.
 | 
			
		||||
@@ -107,8 +119,8 @@ func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	handle, err := btf.NewHandle(btf.ProgramSpec(spec.BTF))
 | 
			
		||||
	if err != nil && !xerrors.Is(err, btf.ErrNotSupported) {
 | 
			
		||||
		return nil, xerrors.Errorf("can't load BTF: %w", err)
 | 
			
		||||
	if err != nil && !errors.Is(err, btf.ErrNotSupported) {
 | 
			
		||||
		return nil, fmt.Errorf("can't load BTF: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newProgramWithBTF(spec, handle, opts)
 | 
			
		||||
@@ -152,7 +164,7 @@ func newProgramWithBTF(spec *ProgramSpec, btf *btf.Handle, opts ProgramOptions)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = internal.ErrorWithLog(err, logBuf, logErr)
 | 
			
		||||
	return nil, xerrors.Errorf("can't load program: %w", err)
 | 
			
		||||
	return nil, fmt.Errorf("can't load program: %w", err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewProgramFromFD creates a program from a raw fd.
 | 
			
		||||
@@ -162,7 +174,7 @@ func newProgramWithBTF(spec *ProgramSpec, btf *btf.Handle, opts ProgramOptions)
 | 
			
		||||
// Requires at least Linux 4.11.
 | 
			
		||||
func NewProgramFromFD(fd int) (*Program, error) {
 | 
			
		||||
	if fd < 0 {
 | 
			
		||||
		return nil, xerrors.New("invalid fd")
 | 
			
		||||
		return nil, errors.New("invalid fd")
 | 
			
		||||
	}
 | 
			
		||||
	bpfFd := internal.NewFD(uint32(fd))
 | 
			
		||||
 | 
			
		||||
@@ -185,15 +197,15 @@ func newProgram(fd *internal.FD, name string, abi *ProgramABI) *Program {
 | 
			
		||||
 | 
			
		||||
func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr, error) {
 | 
			
		||||
	if len(spec.Instructions) == 0 {
 | 
			
		||||
		return nil, xerrors.New("Instructions cannot be empty")
 | 
			
		||||
		return nil, errors.New("Instructions cannot be empty")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(spec.License) == 0 {
 | 
			
		||||
		return nil, xerrors.New("License cannot be empty")
 | 
			
		||||
		return nil, errors.New("License cannot be empty")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian {
 | 
			
		||||
		return nil, xerrors.Errorf("can't load %s program on %s", spec.ByteOrder, internal.NativeEndian)
 | 
			
		||||
		return nil, fmt.Errorf("can't load %s program on %s", spec.ByteOrder, internal.NativeEndian)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf := bytes.NewBuffer(make([]byte, 0, len(spec.Instructions)*asm.InstructionSize))
 | 
			
		||||
@@ -222,7 +234,7 @@ func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr
 | 
			
		||||
 | 
			
		||||
		recSize, bytes, err := btf.ProgramLineInfos(spec.BTF)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("can't get BTF line infos: %w", err)
 | 
			
		||||
			return nil, fmt.Errorf("can't get BTF line infos: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
		attr.lineInfoRecSize = recSize
 | 
			
		||||
		attr.lineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
 | 
			
		||||
@@ -230,13 +242,23 @@ func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr
 | 
			
		||||
 | 
			
		||||
		recSize, bytes, err = btf.ProgramFuncInfos(spec.BTF)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("can't get BTF function infos: %w", err)
 | 
			
		||||
			return nil, fmt.Errorf("can't get BTF function infos: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
		attr.funcInfoRecSize = recSize
 | 
			
		||||
		attr.funcInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
 | 
			
		||||
		attr.funcInfo = internal.NewSlicePointer(bytes)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if spec.AttachTo != "" {
 | 
			
		||||
		target, err := resolveBTFType(spec.AttachTo, spec.Type, spec.AttachType)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if target != nil {
 | 
			
		||||
			attr.attachBTFID = target.ID()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return attr, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -278,7 +300,7 @@ func (p *Program) Clone() (*Program, error) {
 | 
			
		||||
 | 
			
		||||
	dup, err := p.fd.Dup()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't clone program: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("can't clone program: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newProgram(dup, p.name, &p.abi), nil
 | 
			
		||||
@@ -288,8 +310,8 @@ func (p *Program) Clone() (*Program, error) {
 | 
			
		||||
//
 | 
			
		||||
// This requires bpffs to be mounted above fileName. See http://cilium.readthedocs.io/en/doc-1.0/kubernetes/install/#mounting-the-bpf-fs-optional
 | 
			
		||||
func (p *Program) Pin(fileName string) error {
 | 
			
		||||
	if err := bpfPinObject(fileName, p.fd); err != nil {
 | 
			
		||||
		return xerrors.Errorf("can't pin program: %w", err)
 | 
			
		||||
	if err := internal.BPFObjPin(fileName, p.fd); err != nil {
 | 
			
		||||
		return fmt.Errorf("can't pin program: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -313,7 +335,7 @@ func (p *Program) Close() error {
 | 
			
		||||
func (p *Program) Test(in []byte) (uint32, []byte, error) {
 | 
			
		||||
	ret, out, _, err := p.testRun(in, 1, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return ret, nil, xerrors.Errorf("can't test program: %w", err)
 | 
			
		||||
		return ret, nil, fmt.Errorf("can't test program: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return ret, out, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -332,12 +354,12 @@ func (p *Program) Test(in []byte) (uint32, []byte, error) {
 | 
			
		||||
func (p *Program) Benchmark(in []byte, repeat int, reset func()) (uint32, time.Duration, error) {
 | 
			
		||||
	ret, _, total, err := p.testRun(in, repeat, reset)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return ret, total, xerrors.Errorf("can't benchmark program: %w", err)
 | 
			
		||||
		return ret, total, fmt.Errorf("can't benchmark program: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return ret, total, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() bool {
 | 
			
		||||
var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() (bool, error) {
 | 
			
		||||
	prog, err := NewProgram(&ProgramSpec{
 | 
			
		||||
		Type: SocketFilter,
 | 
			
		||||
		Instructions: asm.Instructions{
 | 
			
		||||
@@ -348,28 +370,23 @@ var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() b
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// This may be because we lack sufficient permissions, etc.
 | 
			
		||||
		return false
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	defer prog.Close()
 | 
			
		||||
 | 
			
		||||
	fd, err := prog.fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Programs require at least 14 bytes input
 | 
			
		||||
	in := make([]byte, 14)
 | 
			
		||||
	attr := bpfProgTestRunAttr{
 | 
			
		||||
		fd:         fd,
 | 
			
		||||
		fd:         uint32(prog.FD()),
 | 
			
		||||
		dataSizeIn: uint32(len(in)),
 | 
			
		||||
		dataIn:     internal.NewSlicePointer(in),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = internal.BPF(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	err = bpfProgTestRun(&attr)
 | 
			
		||||
 | 
			
		||||
	// Check for EINVAL specifically, rather than err != nil since we
 | 
			
		||||
	// otherwise misdetect due to insufficient permissions.
 | 
			
		||||
	return !xerrors.Is(err, unix.EINVAL)
 | 
			
		||||
	return !errors.Is(err, unix.EINVAL), nil
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
func (p *Program) testRun(in []byte, repeat int, reset func()) (uint32, []byte, time.Duration, error) {
 | 
			
		||||
@@ -411,19 +428,19 @@ func (p *Program) testRun(in []byte, repeat int, reset func()) (uint32, []byte,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		_, err = internal.BPF(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
		err = bpfProgTestRun(&attr)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if xerrors.Is(err, unix.EINTR) {
 | 
			
		||||
		if errors.Is(err, unix.EINTR) {
 | 
			
		||||
			if reset != nil {
 | 
			
		||||
				reset()
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return 0, nil, 0, xerrors.Errorf("can't run test: %w", err)
 | 
			
		||||
		return 0, nil, 0, fmt.Errorf("can't run test: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if int(attr.dataSizeOut) > cap(out) {
 | 
			
		||||
@@ -439,7 +456,7 @@ func (p *Program) testRun(in []byte, repeat int, reset func()) (uint32, []byte,
 | 
			
		||||
 | 
			
		||||
func unmarshalProgram(buf []byte) (*Program, error) {
 | 
			
		||||
	if len(buf) != 4 {
 | 
			
		||||
		return nil, xerrors.New("program id requires 4 byte value")
 | 
			
		||||
		return nil, errors.New("program id requires 4 byte value")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Looking up an entry in a nested map or prog array returns an id,
 | 
			
		||||
@@ -460,10 +477,12 @@ func (p *Program) MarshalBinary() ([]byte, error) {
 | 
			
		||||
	return buf, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Attach a Program to a container object fd
 | 
			
		||||
// Attach a Program.
 | 
			
		||||
//
 | 
			
		||||
// Deprecated: use link.RawAttachProgram instead.
 | 
			
		||||
func (p *Program) Attach(fd int, typ AttachType, flags AttachFlags) error {
 | 
			
		||||
	if fd < 0 {
 | 
			
		||||
		return xerrors.New("invalid fd")
 | 
			
		||||
		return errors.New("invalid fd")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pfd, err := p.fd.Value()
 | 
			
		||||
@@ -471,20 +490,26 @@ func (p *Program) Attach(fd int, typ AttachType, flags AttachFlags) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	attr := bpfProgAlterAttr{
 | 
			
		||||
		targetFd:    uint32(fd),
 | 
			
		||||
		attachBpfFd: pfd,
 | 
			
		||||
		attachType:  uint32(typ),
 | 
			
		||||
		attachFlags: uint32(flags),
 | 
			
		||||
	attr := internal.BPFProgAttachAttr{
 | 
			
		||||
		TargetFd:    uint32(fd),
 | 
			
		||||
		AttachBpfFd: pfd,
 | 
			
		||||
		AttachType:  uint32(typ),
 | 
			
		||||
		AttachFlags: uint32(flags),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bpfProgAlter(_ProgAttach, &attr)
 | 
			
		||||
	return internal.BPFProgAttach(&attr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Detach a Program from a container object fd
 | 
			
		||||
// Detach a Program.
 | 
			
		||||
//
 | 
			
		||||
// Deprecated: use link.RawDetachProgram instead.
 | 
			
		||||
func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error {
 | 
			
		||||
	if fd < 0 {
 | 
			
		||||
		return xerrors.New("invalid fd")
 | 
			
		||||
		return errors.New("invalid fd")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if flags != 0 {
 | 
			
		||||
		return errors.New("flags must be zero")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pfd, err := p.fd.Value()
 | 
			
		||||
@@ -492,21 +517,20 @@ func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	attr := bpfProgAlterAttr{
 | 
			
		||||
		targetFd:    uint32(fd),
 | 
			
		||||
		attachBpfFd: pfd,
 | 
			
		||||
		attachType:  uint32(typ),
 | 
			
		||||
		attachFlags: uint32(flags),
 | 
			
		||||
	attr := internal.BPFProgDetachAttr{
 | 
			
		||||
		TargetFd:    uint32(fd),
 | 
			
		||||
		AttachBpfFd: pfd,
 | 
			
		||||
		AttachType:  uint32(typ),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bpfProgAlter(_ProgDetach, &attr)
 | 
			
		||||
	return internal.BPFProgDetach(&attr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadPinnedProgram loads a Program from a BPF file.
 | 
			
		||||
//
 | 
			
		||||
// Requires at least Linux 4.11.
 | 
			
		||||
func LoadPinnedProgram(fileName string) (*Program, error) {
 | 
			
		||||
	fd, err := bpfGetObject(fileName)
 | 
			
		||||
	fd, err := internal.BPFObjGet(fileName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -514,7 +538,7 @@ func LoadPinnedProgram(fileName string) (*Program, error) {
 | 
			
		||||
	name, abi, err := newProgramABIFromFd(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		_ = fd.Close()
 | 
			
		||||
		return nil, xerrors.Errorf("can't get ABI for %s: %w", fileName, err)
 | 
			
		||||
		return nil, fmt.Errorf("can't get ABI for %s: %w", fileName, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newProgram(fd, name, abi), nil
 | 
			
		||||
@@ -540,7 +564,7 @@ func SanitizeName(name string, replacement rune) string {
 | 
			
		||||
//
 | 
			
		||||
// Returns ErrNotExist, if there is no next eBPF program.
 | 
			
		||||
func ProgramGetNextID(startID ProgramID) (ProgramID, error) {
 | 
			
		||||
	id, err := objGetNextID(_ProgGetNextID, uint32(startID))
 | 
			
		||||
	id, err := objGetNextID(internal.BPF_PROG_GET_NEXT_ID, uint32(startID))
 | 
			
		||||
	return ProgramID(id), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -548,7 +572,7 @@ func ProgramGetNextID(startID ProgramID) (ProgramID, error) {
 | 
			
		||||
//
 | 
			
		||||
// Returns ErrNotExist, if there is no eBPF program with the given id.
 | 
			
		||||
func NewProgramFromID(id ProgramID) (*Program, error) {
 | 
			
		||||
	fd, err := bpfObjGetFDByID(_ProgGetFDByID, uint32(id))
 | 
			
		||||
	fd, err := bpfObjGetFDByID(internal.BPF_PROG_GET_FD_BY_ID, uint32(id))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -570,3 +594,29 @@ func (p *Program) ID() (ProgramID, error) {
 | 
			
		||||
	}
 | 
			
		||||
	return ProgramID(info.id), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func resolveBTFType(name string, progType ProgramType, attachType AttachType) (btf.Type, error) {
 | 
			
		||||
	kernel, err := btf.LoadKernelSpec()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("can't resolve BTF type %s: %w", name, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type match struct {
 | 
			
		||||
		p ProgramType
 | 
			
		||||
		a AttachType
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	target := match{progType, attachType}
 | 
			
		||||
	switch target {
 | 
			
		||||
	case match{Tracing, AttachTraceIter}:
 | 
			
		||||
		var target btf.Func
 | 
			
		||||
		if err := kernel.FindType("bpf_iter_"+name, &target); err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("can't resolve BTF for iterator %s: %w", name, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return &target, nil
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								vendor/github.com/cilium/ebpf/run-tests.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/cilium/ebpf/run-tests.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -15,8 +15,13 @@ if [[ "${1:-}" = "--in-vm" ]]; then
 | 
			
		||||
  export GOPROXY=file:///run/go-root/pkg/mod/cache/download
 | 
			
		||||
  export GOCACHE=/run/go-cache
 | 
			
		||||
 | 
			
		||||
  elfs=""
 | 
			
		||||
  if [[ -d "/run/input/bpf" ]]; then
 | 
			
		||||
    elfs="/run/input/bpf"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  echo Running tests...
 | 
			
		||||
  /usr/local/bin/go test -coverprofile="$1/coverage.txt" -covermode=atomic -v ./...
 | 
			
		||||
  /usr/local/bin/go test -coverprofile="$1/coverage.txt" -covermode=atomic -v -elfs "$elfs" ./...
 | 
			
		||||
  touch "$1/success"
 | 
			
		||||
  exit 0
 | 
			
		||||
fi
 | 
			
		||||
@@ -39,20 +44,34 @@ if [[ -z "${kernel_version}" ]]; then
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
readonly kernel="linux-${kernel_version}.bz"
 | 
			
		||||
readonly selftests="linux-${kernel_version}-selftests-bpf.bz"
 | 
			
		||||
readonly input="$(mktemp -d)"
 | 
			
		||||
readonly output="$(mktemp -d)"
 | 
			
		||||
readonly tmp_dir="${TMPDIR:-$(mktemp -d)}"
 | 
			
		||||
readonly tmp_dir="${TMPDIR:-/tmp}"
 | 
			
		||||
readonly branch="${BRANCH:-master}"
 | 
			
		||||
 | 
			
		||||
test -e "${tmp_dir}/${kernel}" || {
 | 
			
		||||
  echo Fetching "${kernel}"
 | 
			
		||||
  curl --fail -L "https://github.com/cilium/ci-kernels/blob/master/${kernel}?raw=true" -o "${tmp_dir}/${kernel}"
 | 
			
		||||
fetch() {
 | 
			
		||||
    echo Fetching "${1}"
 | 
			
		||||
    wget -nv -N -P "${tmp_dir}" "https://github.com/cilium/ci-kernels/raw/${branch}/${1}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fetch "${kernel}"
 | 
			
		||||
 | 
			
		||||
if fetch "${selftests}"; then
 | 
			
		||||
  mkdir "${input}/bpf"
 | 
			
		||||
  tar --strip-components=4 -xjf "${tmp_dir}/${selftests}" -C "${input}/bpf"
 | 
			
		||||
else
 | 
			
		||||
  echo "No selftests found, disabling"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo Testing on "${kernel_version}"
 | 
			
		||||
$sudo virtme-run --kimg "${tmp_dir}/${kernel}" --memory 512M --pwd \
 | 
			
		||||
  --rwdir=/run/input="${input}" \
 | 
			
		||||
  --rwdir=/run/output="${output}" \
 | 
			
		||||
  --rodir=/run/go-path="$(go env GOPATH)" \
 | 
			
		||||
  --rwdir=/run/go-cache="$(go env GOCACHE)" \
 | 
			
		||||
  --script-sh "$(realpath "$0") --in-vm /run/output"
 | 
			
		||||
  --script-sh "$(realpath "$0") --in-vm /run/output" \
 | 
			
		||||
  --qemu-opts -smp 2 # need at least two CPUs for some tests
 | 
			
		||||
 | 
			
		||||
if [[ ! -e "${output}/success" ]]; then
 | 
			
		||||
  echo "Test failed on ${kernel_version}"
 | 
			
		||||
@@ -66,4 +85,5 @@ else
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
$sudo rm -r "${input}"
 | 
			
		||||
$sudo rm -r "${output}"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										135
									
								
								vendor/github.com/cilium/ebpf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										135
									
								
								vendor/github.com/cilium/ebpf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,20 +1,19 @@
 | 
			
		||||
package ebpf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Generic errors returned by BPF syscalls.
 | 
			
		||||
var (
 | 
			
		||||
	ErrNotExist = xerrors.New("requested object does not exist")
 | 
			
		||||
	ErrNotExist = errors.New("requested object does not exist")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// bpfObjName is a null-terminated string made up of
 | 
			
		||||
@@ -80,12 +79,6 @@ type bpfMapInfo struct {
 | 
			
		||||
	mapName    bpfObjName // since 4.15 ad5b177bd73f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfPinObjAttr struct {
 | 
			
		||||
	fileName internal.Pointer
 | 
			
		||||
	fd       uint32
 | 
			
		||||
	padding  uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfProgLoadAttr struct {
 | 
			
		||||
	progType           ProgramType
 | 
			
		||||
	insCount           uint32
 | 
			
		||||
@@ -106,6 +99,8 @@ type bpfProgLoadAttr struct {
 | 
			
		||||
	lineInfoRecSize    uint32
 | 
			
		||||
	lineInfo           internal.Pointer
 | 
			
		||||
	lineInfoCnt        uint32
 | 
			
		||||
	attachBTFID        btf.TypeID
 | 
			
		||||
	attachProgFd       uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfProgInfo struct {
 | 
			
		||||
@@ -134,13 +129,6 @@ type bpfProgTestRunAttr struct {
 | 
			
		||||
	duration    uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfProgAlterAttr struct {
 | 
			
		||||
	targetFd    uint32
 | 
			
		||||
	attachBpfFd uint32
 | 
			
		||||
	attachType  uint32
 | 
			
		||||
	attachFlags uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfObjGetInfoByFDAttr struct {
 | 
			
		||||
	fd      uint32
 | 
			
		||||
	infoLen uint32
 | 
			
		||||
@@ -164,7 +152,7 @@ type bpfObjGetNextIDAttr struct {
 | 
			
		||||
 | 
			
		||||
func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) {
 | 
			
		||||
	for {
 | 
			
		||||
		fd, err := internal.BPF(_ProgLoad, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
		fd, err := internal.BPF(internal.BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
		// As of ~4.20 the verifier can be interrupted by a signal,
 | 
			
		||||
		// and returns EAGAIN in that case.
 | 
			
		||||
		if err == unix.EAGAIN {
 | 
			
		||||
@@ -179,15 +167,15 @@ func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfProgAlter(cmd int, attr *bpfProgAlterAttr) error {
 | 
			
		||||
	_, err := internal.BPF(cmd, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
func bpfProgTestRun(attr *bpfProgTestRunAttr) error {
 | 
			
		||||
	_, err := internal.BPF(internal.BPF_PROG_TEST_RUN, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) {
 | 
			
		||||
	fd, err := internal.BPF(_MapCreate, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
	if xerrors.Is(err, os.ErrPermission) {
 | 
			
		||||
		return nil, xerrors.New("permission denied or insufficient rlimit to lock memory for map")
 | 
			
		||||
	fd, err := internal.BPF(internal.BPF_MAP_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
	if errors.Is(err, os.ErrPermission) {
 | 
			
		||||
		return nil, errors.New("permission denied or insufficient rlimit to lock memory for map")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -197,7 +185,7 @@ func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) {
 | 
			
		||||
	return internal.NewFD(uint32(fd)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
 | 
			
		||||
var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() (bool, error) {
 | 
			
		||||
	inner, err := bpfMapCreate(&bpfMapCreateAttr{
 | 
			
		||||
		mapType:    Array,
 | 
			
		||||
		keySize:    4,
 | 
			
		||||
@@ -205,7 +193,7 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
 | 
			
		||||
		maxEntries: 1,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	defer inner.Close()
 | 
			
		||||
 | 
			
		||||
@@ -218,14 +206,14 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
 | 
			
		||||
		innerMapFd: innerFd,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_ = nested.Close()
 | 
			
		||||
	return true
 | 
			
		||||
	return true, nil
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
var haveMapMutabilityModifiers = internal.FeatureTest("read- and write-only maps", "5.2", func() bool {
 | 
			
		||||
var haveMapMutabilityModifiers = internal.FeatureTest("read- and write-only maps", "5.2", func() (bool, error) {
 | 
			
		||||
	// This checks BPF_F_RDONLY_PROG and BPF_F_WRONLY_PROG. Since
 | 
			
		||||
	// BPF_MAP_FREEZE appeared in 5.2 as well we don't do a separate check.
 | 
			
		||||
	m, err := bpfMapCreate(&bpfMapCreateAttr{
 | 
			
		||||
@@ -236,10 +224,10 @@ var haveMapMutabilityModifiers = internal.FeatureTest("read- and write-only maps
 | 
			
		||||
		flags:      unix.BPF_F_RDONLY_PROG,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
	_ = m.Close()
 | 
			
		||||
	return true
 | 
			
		||||
	return true, nil
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
func bpfMapLookupElem(m *internal.FD, key, valueOut internal.Pointer) error {
 | 
			
		||||
@@ -253,7 +241,7 @@ func bpfMapLookupElem(m *internal.FD, key, valueOut internal.Pointer) error {
 | 
			
		||||
		key:   key,
 | 
			
		||||
		value: valueOut,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = internal.BPF(_MapLookupElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	_, err = internal.BPF(internal.BPF_MAP_LOOKUP_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return wrapMapError(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -268,7 +256,7 @@ func bpfMapLookupAndDelete(m *internal.FD, key, valueOut internal.Pointer) error
 | 
			
		||||
		key:   key,
 | 
			
		||||
		value: valueOut,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = internal.BPF(_MapLookupAndDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	_, err = internal.BPF(internal.BPF_MAP_LOOKUP_AND_DELETE_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return wrapMapError(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -284,7 +272,7 @@ func bpfMapUpdateElem(m *internal.FD, key, valueOut internal.Pointer, flags uint
 | 
			
		||||
		value: valueOut,
 | 
			
		||||
		flags: flags,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = internal.BPF(_MapUpdateElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	_, err = internal.BPF(internal.BPF_MAP_UPDATE_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return wrapMapError(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -298,7 +286,7 @@ func bpfMapDeleteElem(m *internal.FD, key internal.Pointer) error {
 | 
			
		||||
		mapFd: fd,
 | 
			
		||||
		key:   key,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = internal.BPF(_MapDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	_, err = internal.BPF(internal.BPF_MAP_DELETE_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return wrapMapError(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -313,11 +301,11 @@ func bpfMapGetNextKey(m *internal.FD, key, nextKeyOut internal.Pointer) error {
 | 
			
		||||
		key:   key,
 | 
			
		||||
		value: nextKeyOut,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = internal.BPF(_MapGetNextKey, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	_, err = internal.BPF(internal.BPF_MAP_GET_NEXT_KEY, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return wrapMapError(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func objGetNextID(cmd int, start uint32) (uint32, error) {
 | 
			
		||||
func objGetNextID(cmd internal.BPFCmd, start uint32) (uint32, error) {
 | 
			
		||||
	attr := bpfObjGetNextIDAttr{
 | 
			
		||||
		startID: start,
 | 
			
		||||
	}
 | 
			
		||||
@@ -329,11 +317,11 @@ func wrapObjError(err error) error {
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if xerrors.Is(err, unix.ENOENT) {
 | 
			
		||||
		return xerrors.Errorf("%w", ErrNotExist)
 | 
			
		||||
	if errors.Is(err, unix.ENOENT) {
 | 
			
		||||
		return fmt.Errorf("%w", ErrNotExist)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return xerrors.New(err.Error())
 | 
			
		||||
	return errors.New(err.Error())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func wrapMapError(err error) error {
 | 
			
		||||
@@ -341,15 +329,15 @@ func wrapMapError(err error) error {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if xerrors.Is(err, unix.ENOENT) {
 | 
			
		||||
	if errors.Is(err, unix.ENOENT) {
 | 
			
		||||
		return ErrKeyNotExist
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if xerrors.Is(err, unix.EEXIST) {
 | 
			
		||||
	if errors.Is(err, unix.EEXIST) {
 | 
			
		||||
		return ErrKeyExist
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return xerrors.New(err.Error())
 | 
			
		||||
	return errors.New(err.Error())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfMapFreeze(m *internal.FD) error {
 | 
			
		||||
@@ -361,47 +349,10 @@ func bpfMapFreeze(m *internal.FD) error {
 | 
			
		||||
	attr := bpfMapFreezeAttr{
 | 
			
		||||
		mapFd: fd,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = internal.BPF(_MapFreeze, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	_, err = internal.BPF(internal.BPF_MAP_FREEZE, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const bpfFSType = 0xcafe4a11
 | 
			
		||||
 | 
			
		||||
func bpfPinObject(fileName string, fd *internal.FD) error {
 | 
			
		||||
	dirName := filepath.Dir(fileName)
 | 
			
		||||
	var statfs unix.Statfs_t
 | 
			
		||||
	if err := unix.Statfs(dirName, &statfs); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if uint64(statfs.Type) != bpfFSType {
 | 
			
		||||
		return xerrors.Errorf("%s is not on a bpf filesystem", fileName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value, err := fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = internal.BPF(_ObjPin, unsafe.Pointer(&bpfPinObjAttr{
 | 
			
		||||
		fileName: internal.NewStringPointer(fileName),
 | 
			
		||||
		fd:       value,
 | 
			
		||||
	}), 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return xerrors.Errorf("pin object %s: %w", fileName, err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfGetObject(fileName string) (*internal.FD, error) {
 | 
			
		||||
	ptr, err := internal.BPF(_ObjGet, unsafe.Pointer(&bpfPinObjAttr{
 | 
			
		||||
		fileName: internal.NewStringPointer(fileName),
 | 
			
		||||
	}), 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("get object %s: %w", fileName, err)
 | 
			
		||||
	}
 | 
			
		||||
	return internal.NewFD(uint32(ptr)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) error {
 | 
			
		||||
	value, err := fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -414,9 +365,9 @@ func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) er
 | 
			
		||||
		infoLen: uint32(size),
 | 
			
		||||
		info:    internal.NewPointer(info),
 | 
			
		||||
	}
 | 
			
		||||
	_, err = internal.BPF(_ObjGetInfoByFD, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	_, err = internal.BPF(internal.BPF_OBJ_GET_INFO_BY_FD, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return xerrors.Errorf("fd %d: %w", fd, err)
 | 
			
		||||
		return fmt.Errorf("fd %d: %w", fd, err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -424,7 +375,7 @@ func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) er
 | 
			
		||||
func bpfGetProgInfoByFD(fd *internal.FD) (*bpfProgInfo, error) {
 | 
			
		||||
	var info bpfProgInfo
 | 
			
		||||
	if err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't get program info: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("can't get program info: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return &info, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -433,12 +384,12 @@ func bpfGetMapInfoByFD(fd *internal.FD) (*bpfMapInfo, error) {
 | 
			
		||||
	var info bpfMapInfo
 | 
			
		||||
	err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("can't get map info: %w", err)
 | 
			
		||||
		return nil, fmt.Errorf("can't get map info: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return &info, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var haveObjName = internal.FeatureTest("object names", "4.15", func() bool {
 | 
			
		||||
var haveObjName = internal.FeatureTest("object names", "4.15", func() (bool, error) {
 | 
			
		||||
	attr := bpfMapCreateAttr{
 | 
			
		||||
		mapType:    Array,
 | 
			
		||||
		keySize:    4,
 | 
			
		||||
@@ -449,16 +400,16 @@ var haveObjName = internal.FeatureTest("object names", "4.15", func() bool {
 | 
			
		||||
 | 
			
		||||
	fd, err := bpfMapCreate(&attr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_ = fd.Close()
 | 
			
		||||
	return true
 | 
			
		||||
	return true, nil
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func() bool {
 | 
			
		||||
var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func() (bool, error) {
 | 
			
		||||
	if err := haveObjName(); err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	attr := bpfMapCreateAttr{
 | 
			
		||||
@@ -471,14 +422,14 @@ var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func()
 | 
			
		||||
 | 
			
		||||
	fd, err := bpfMapCreate(&attr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_ = fd.Close()
 | 
			
		||||
	return true
 | 
			
		||||
	return true, nil
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
func bpfObjGetFDByID(cmd int, id uint32) (*internal.FD, error) {
 | 
			
		||||
func bpfObjGetFDByID(cmd internal.BPFCmd, id uint32) (*internal.FD, error) {
 | 
			
		||||
	attr := bpfGetFDByIDAttr{
 | 
			
		||||
		id: id,
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/github.com/cilium/ebpf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/cilium/ebpf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
package ebpf
 | 
			
		||||
 | 
			
		||||
//go:generate stringer -output types_string.go -type=MapType,ProgramType
 | 
			
		||||
//go:generate stringer -output types_string.go -type=MapType,ProgramType,AttachType
 | 
			
		||||
 | 
			
		||||
// MapType indicates the type map structure
 | 
			
		||||
// that will be initialized in the kernel.
 | 
			
		||||
@@ -85,39 +85,12 @@ const (
 | 
			
		||||
 | 
			
		||||
// hasPerCPUValue returns true if the Map stores a value per CPU.
 | 
			
		||||
func (mt MapType) hasPerCPUValue() bool {
 | 
			
		||||
	if mt == PerCPUHash || mt == PerCPUArray {
 | 
			
		||||
	if mt == PerCPUHash || mt == PerCPUArray || mt == LRUCPUHash {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	_MapCreate = iota
 | 
			
		||||
	_MapLookupElem
 | 
			
		||||
	_MapUpdateElem
 | 
			
		||||
	_MapDeleteElem
 | 
			
		||||
	_MapGetNextKey
 | 
			
		||||
	_ProgLoad
 | 
			
		||||
	_ObjPin
 | 
			
		||||
	_ObjGet
 | 
			
		||||
	_ProgAttach
 | 
			
		||||
	_ProgDetach
 | 
			
		||||
	_ProgTestRun
 | 
			
		||||
	_ProgGetNextID
 | 
			
		||||
	_MapGetNextID
 | 
			
		||||
	_ProgGetFDByID
 | 
			
		||||
	_MapGetFDByID
 | 
			
		||||
	_ObjGetInfoByFD
 | 
			
		||||
	_ProgQuery
 | 
			
		||||
	_RawTracepointOpen
 | 
			
		||||
	_BTFLoad
 | 
			
		||||
	_BTFGetFDByID
 | 
			
		||||
	_TaskFDQuery
 | 
			
		||||
	_MapLookupAndDeleteElem
 | 
			
		||||
	_MapFreeze
 | 
			
		||||
	_BTFGetNextID
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ProgramType of the eBPF program
 | 
			
		||||
type ProgramType uint32
 | 
			
		||||
 | 
			
		||||
@@ -214,6 +187,9 @@ const (
 | 
			
		||||
	AttachTraceRawTp
 | 
			
		||||
	AttachTraceFEntry
 | 
			
		||||
	AttachTraceFExit
 | 
			
		||||
	AttachModifyReturn
 | 
			
		||||
	AttachLSMMac
 | 
			
		||||
	AttachTraceIter
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// AttachFlags of the eBPF program used in BPF_PROG_ATTACH command
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								vendor/github.com/cilium/ebpf/types_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/cilium/ebpf/types_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Code generated by "stringer -output types_string.go -type=MapType,ProgramType"; DO NOT EDIT.
 | 
			
		||||
// Code generated by "stringer -output types_string.go -type=MapType,ProgramType,AttachType"; DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package ebpf
 | 
			
		||||
 | 
			
		||||
@@ -89,3 +89,49 @@ func (i ProgramType) String() string {
 | 
			
		||||
	}
 | 
			
		||||
	return _ProgramType_name[_ProgramType_index[i]:_ProgramType_index[i+1]]
 | 
			
		||||
}
 | 
			
		||||
func _() {
 | 
			
		||||
	// An "invalid array index" compiler error signifies that the constant values have changed.
 | 
			
		||||
	// Re-run the stringer command to generate them again.
 | 
			
		||||
	var x [1]struct{}
 | 
			
		||||
	_ = x[AttachNone-0]
 | 
			
		||||
	_ = x[AttachCGroupInetIngress-0]
 | 
			
		||||
	_ = x[AttachCGroupInetEgress-1]
 | 
			
		||||
	_ = x[AttachCGroupInetSockCreate-2]
 | 
			
		||||
	_ = x[AttachCGroupSockOps-3]
 | 
			
		||||
	_ = x[AttachSkSKBStreamParser-4]
 | 
			
		||||
	_ = x[AttachSkSKBStreamVerdict-5]
 | 
			
		||||
	_ = x[AttachCGroupDevice-6]
 | 
			
		||||
	_ = x[AttachSkMsgVerdict-7]
 | 
			
		||||
	_ = x[AttachCGroupInet4Bind-8]
 | 
			
		||||
	_ = x[AttachCGroupInet6Bind-9]
 | 
			
		||||
	_ = x[AttachCGroupInet4Connect-10]
 | 
			
		||||
	_ = x[AttachCGroupInet6Connect-11]
 | 
			
		||||
	_ = x[AttachCGroupInet4PostBind-12]
 | 
			
		||||
	_ = x[AttachCGroupInet6PostBind-13]
 | 
			
		||||
	_ = x[AttachCGroupUDP4Sendmsg-14]
 | 
			
		||||
	_ = x[AttachCGroupUDP6Sendmsg-15]
 | 
			
		||||
	_ = x[AttachLircMode2-16]
 | 
			
		||||
	_ = x[AttachFlowDissector-17]
 | 
			
		||||
	_ = x[AttachCGroupSysctl-18]
 | 
			
		||||
	_ = x[AttachCGroupUDP4Recvmsg-19]
 | 
			
		||||
	_ = x[AttachCGroupUDP6Recvmsg-20]
 | 
			
		||||
	_ = x[AttachCGroupGetsockopt-21]
 | 
			
		||||
	_ = x[AttachCGroupSetsockopt-22]
 | 
			
		||||
	_ = x[AttachTraceRawTp-23]
 | 
			
		||||
	_ = x[AttachTraceFEntry-24]
 | 
			
		||||
	_ = x[AttachTraceFExit-25]
 | 
			
		||||
	_ = x[AttachModifyReturn-26]
 | 
			
		||||
	_ = x[AttachLSMMac-27]
 | 
			
		||||
	_ = x[AttachTraceIter-28]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const _AttachType_name = "AttachNoneAttachCGroupInetEgressAttachCGroupInetSockCreateAttachCGroupSockOpsAttachSkSKBStreamParserAttachSkSKBStreamVerdictAttachCGroupDeviceAttachSkMsgVerdictAttachCGroupInet4BindAttachCGroupInet6BindAttachCGroupInet4ConnectAttachCGroupInet6ConnectAttachCGroupInet4PostBindAttachCGroupInet6PostBindAttachCGroupUDP4SendmsgAttachCGroupUDP6SendmsgAttachLircMode2AttachFlowDissectorAttachCGroupSysctlAttachCGroupUDP4RecvmsgAttachCGroupUDP6RecvmsgAttachCGroupGetsockoptAttachCGroupSetsockoptAttachTraceRawTpAttachTraceFEntryAttachTraceFExitAttachModifyReturnAttachLSMMacAttachTraceIter"
 | 
			
		||||
 | 
			
		||||
var _AttachType_index = [...]uint16{0, 10, 32, 58, 77, 100, 124, 142, 160, 181, 202, 226, 250, 275, 300, 323, 346, 361, 380, 398, 421, 444, 466, 488, 504, 521, 537, 555, 567, 582}
 | 
			
		||||
 | 
			
		||||
func (i AttachType) String() string {
 | 
			
		||||
	if i >= AttachType(len(_AttachType_index)-1) {
 | 
			
		||||
		return "AttachType(" + strconv.FormatInt(int64(i), 10) + ")"
 | 
			
		||||
	}
 | 
			
		||||
	return _AttachType_name[_AttachType_index[i]:_AttachType_index[i+1]]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -23,6 +23,9 @@ func (s *DevicesGroup) Name() string {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *DevicesGroup) Apply(d *cgroupData) error {
 | 
			
		||||
	if d.config.SkipDevices {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	_, err := d.join("devices")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// We will return error even it's `not found` error, devices
 | 
			
		||||
@@ -52,7 +55,7 @@ func buildEmulator(rules []*configs.DeviceRule) (*devices.Emulator, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *DevicesGroup) Set(path string, cgroup *configs.Cgroup) error {
 | 
			
		||||
	if system.RunningInUserNS() {
 | 
			
		||||
	if system.RunningInUserNS() || cgroup.SkipDevices {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/fs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -204,7 +204,7 @@ func (m *manager) Apply(pid int) (err error) {
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			// The non-presence of the devices subsystem is
 | 
			
		||||
			// considered fatal for security reasons.
 | 
			
		||||
			if cgroups.IsNotFound(err) && sys.Name() != "devices" {
 | 
			
		||||
			if cgroups.IsNotFound(err) && (c.SkipDevices || sys.Name() != "devices") {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			return err
 | 
			
		||||
@@ -298,7 +298,7 @@ func (m *manager) Set(container *configs.Config) error {
 | 
			
		||||
 | 
			
		||||
// Freeze toggles the container's freezer cgroup depending on the state
 | 
			
		||||
// provided
 | 
			
		||||
func (m *manager) Freeze(state configs.FreezerState) (Err error) {
 | 
			
		||||
func (m *manager) Freeze(state configs.FreezerState) error {
 | 
			
		||||
	path := m.Path("freezer")
 | 
			
		||||
	if m.cgroups == nil || path == "" {
 | 
			
		||||
		return errors.New("cannot toggle freezer: cgroups not configured for container")
 | 
			
		||||
@@ -306,17 +306,9 @@ func (m *manager) Freeze(state configs.FreezerState) (Err error) {
 | 
			
		||||
 | 
			
		||||
	prevState := m.cgroups.Resources.Freezer
 | 
			
		||||
	m.cgroups.Resources.Freezer = state
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if Err != nil {
 | 
			
		||||
			m.cgroups.Resources.Freezer = prevState
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	freezer, err := m.getSubsystems().Get("freezer")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	freezer := &FreezerGroup{}
 | 
			
		||||
	if err := freezer.Set(path, m.cgroups); err != nil {
 | 
			
		||||
		m.cgroups.Resources.Freezer = prevState
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
@@ -359,14 +351,14 @@ func getCgroupData(c *configs.Cgroup, pid int) (*cgroupData, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (raw *cgroupData) path(subsystem string) (string, error) {
 | 
			
		||||
	mnt, err := cgroups.FindCgroupMountpoint(raw.root, subsystem)
 | 
			
		||||
	// If we didn't mount the subsystem, there is no point we make the path.
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
 | 
			
		||||
	if filepath.IsAbs(raw.innerPath) {
 | 
			
		||||
		mnt, err := cgroups.FindCgroupMountpoint(raw.root, subsystem)
 | 
			
		||||
		// If we didn't mount the subsystem, there is no point we make the path.
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Sometimes subsystems can be mounted together as 'cpu,cpuacct'.
 | 
			
		||||
		return filepath.Join(raw.root, filepath.Base(mnt), raw.innerPath), nil
 | 
			
		||||
	}
 | 
			
		||||
@@ -418,13 +410,12 @@ func (m *manager) GetCgroups() (*configs.Cgroup, error) {
 | 
			
		||||
 | 
			
		||||
func (m *manager) GetFreezerState() (configs.FreezerState, error) {
 | 
			
		||||
	dir := m.Path("freezer")
 | 
			
		||||
	freezer, err := m.getSubsystems().Get("freezer")
 | 
			
		||||
 | 
			
		||||
	// If the container doesn't have the freezer cgroup, say it's undefined.
 | 
			
		||||
	if err != nil || dir == "" {
 | 
			
		||||
	if dir == "" {
 | 
			
		||||
		return configs.Undefined, nil
 | 
			
		||||
	}
 | 
			
		||||
	return freezer.(*FreezerGroup).GetState(dir)
 | 
			
		||||
	freezer := &FreezerGroup{}
 | 
			
		||||
	return freezer.GetState(dir)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *manager) Exists() bool {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs2/devices.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -37,6 +37,9 @@ func canSkipEBPFError(cgroup *configs.Cgroup) bool {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setDevices(dirPath string, cgroup *configs.Cgroup) error {
 | 
			
		||||
	if cgroup.SkipDevices {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	// XXX: This is currently a white-list (but all callers pass a blacklist of
 | 
			
		||||
	//      devices). This is bad for a whole variety of reasons, but will need
 | 
			
		||||
	//      to be fixed with co-ordinated effort with downstreams.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/common.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/common.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -27,6 +27,9 @@ var (
 | 
			
		||||
	versionOnce sync.Once
 | 
			
		||||
	version     int
 | 
			
		||||
	versionErr  error
 | 
			
		||||
 | 
			
		||||
	isRunningSystemdOnce sync.Once
 | 
			
		||||
	isRunningSystemd     bool
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NOTE: This function comes from package github.com/coreos/go-systemd/util
 | 
			
		||||
@@ -37,11 +40,11 @@ var (
 | 
			
		||||
// checks whether /run/systemd/system/ exists and is a directory.
 | 
			
		||||
// http://www.freedesktop.org/software/systemd/man/sd_booted.html
 | 
			
		||||
func IsRunningSystemd() bool {
 | 
			
		||||
	fi, err := os.Lstat("/run/systemd/system")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return fi.IsDir()
 | 
			
		||||
	isRunningSystemdOnce.Do(func() {
 | 
			
		||||
		fi, err := os.Lstat("/run/systemd/system")
 | 
			
		||||
		isRunningSystemd = err == nil && fi.IsDir()
 | 
			
		||||
	})
 | 
			
		||||
	return isRunningSystemd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// systemd represents slice hierarchy using `-`, so we need to follow suit when
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v1.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v1.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -222,7 +222,14 @@ func (m *legacyManager) Destroy() error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	unitName := getUnitName(m.cgroups)
 | 
			
		||||
	if err := stopUnit(dbusConnection, unitName); err != nil {
 | 
			
		||||
 | 
			
		||||
	err = stopUnit(dbusConnection, unitName)
 | 
			
		||||
	// Both on success and on error, cleanup all the cgroups we are aware of.
 | 
			
		||||
	// Some of them were created directly by Apply() and are not managed by systemd.
 | 
			
		||||
	if err := cgroups.RemovePaths(m.paths); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	m.paths = make(map[string]string)
 | 
			
		||||
@@ -319,10 +326,7 @@ func (m *legacyManager) Freeze(state configs.FreezerState) error {
 | 
			
		||||
	}
 | 
			
		||||
	prevState := m.cgroups.Resources.Freezer
 | 
			
		||||
	m.cgroups.Resources.Freezer = state
 | 
			
		||||
	freezer, err := legacySubsystems.Get("freezer")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	freezer := &fs.FreezerGroup{}
 | 
			
		||||
	err = freezer.Set(path, m.cgroups)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		m.cgroups.Resources.Freezer = prevState
 | 
			
		||||
@@ -379,24 +383,27 @@ func (m *legacyManager) Set(container *configs.Config) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Figure out the current freezer state, so we can revert to it after we
 | 
			
		||||
	// temporarily freeze the container.
 | 
			
		||||
	targetFreezerState, err := m.GetFreezerState()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if targetFreezerState == configs.Undefined {
 | 
			
		||||
		targetFreezerState = configs.Thawed
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We have to freeze the container while systemd sets the cgroup settings.
 | 
			
		||||
	// The reason for this is that systemd's application of DeviceAllow rules
 | 
			
		||||
	// is done disruptively, resulting in spurrious errors to common devices
 | 
			
		||||
	// (unlike our fs driver, they will happily write deny-all rules to running
 | 
			
		||||
	// containers). So we freeze the container to avoid them hitting the cgroup
 | 
			
		||||
	// error. But if the freezer cgroup isn't supported, we just warn about it.
 | 
			
		||||
	if err := m.Freeze(configs.Frozen); err != nil {
 | 
			
		||||
		logrus.Infof("freeze container before SetUnitProperties failed: %v", err)
 | 
			
		||||
	targetFreezerState := configs.Undefined
 | 
			
		||||
	if !m.cgroups.SkipDevices {
 | 
			
		||||
		// Figure out the current freezer state, so we can revert to it after we
 | 
			
		||||
		// temporarily freeze the container.
 | 
			
		||||
		targetFreezerState, err = m.GetFreezerState()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if targetFreezerState == configs.Undefined {
 | 
			
		||||
			targetFreezerState = configs.Thawed
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := m.Freeze(configs.Frozen); err != nil {
 | 
			
		||||
			logrus.Infof("freeze container before SetUnitProperties failed: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := dbusConnection.SetUnitProperties(getUnitName(container.Cgroups), true, properties...); err != nil {
 | 
			
		||||
@@ -458,11 +465,8 @@ func (m *legacyManager) GetFreezerState() (configs.FreezerState, error) {
 | 
			
		||||
	if err != nil && !cgroups.IsNotFound(err) {
 | 
			
		||||
		return configs.Undefined, err
 | 
			
		||||
	}
 | 
			
		||||
	freezer, err := legacySubsystems.Get("freezer")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return configs.Undefined, err
 | 
			
		||||
	}
 | 
			
		||||
	return freezer.(*fs.FreezerGroup).GetState(path)
 | 
			
		||||
	freezer := &fs.FreezerGroup{}
 | 
			
		||||
	return freezer.GetState(path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *legacyManager) Exists() bool {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v2.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/v2.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -298,24 +298,27 @@ func (m *unifiedManager) Set(container *configs.Config) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Figure out the current freezer state, so we can revert to it after we
 | 
			
		||||
	// temporarily freeze the container.
 | 
			
		||||
	targetFreezerState, err := m.GetFreezerState()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if targetFreezerState == configs.Undefined {
 | 
			
		||||
		targetFreezerState = configs.Thawed
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We have to freeze the container while systemd sets the cgroup settings.
 | 
			
		||||
	// The reason for this is that systemd's application of DeviceAllow rules
 | 
			
		||||
	// is done disruptively, resulting in spurrious errors to common devices
 | 
			
		||||
	// (unlike our fs driver, they will happily write deny-all rules to running
 | 
			
		||||
	// containers). So we freeze the container to avoid them hitting the cgroup
 | 
			
		||||
	// error. But if the freezer cgroup isn't supported, we just warn about it.
 | 
			
		||||
	if err := m.Freeze(configs.Frozen); err != nil {
 | 
			
		||||
		logrus.Infof("freeze container before SetUnitProperties failed: %v", err)
 | 
			
		||||
	targetFreezerState := configs.Undefined
 | 
			
		||||
	if !m.cgroups.SkipDevices {
 | 
			
		||||
		// Figure out the current freezer state, so we can revert to it after we
 | 
			
		||||
		// temporarily freeze the container.
 | 
			
		||||
		targetFreezerState, err = m.GetFreezerState()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if targetFreezerState == configs.Undefined {
 | 
			
		||||
			targetFreezerState = configs.Thawed
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := m.Freeze(configs.Frozen); err != nil {
 | 
			
		||||
			logrus.Infof("freeze container before SetUnitProperties failed: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := dbusConnection.SetUnitProperties(getUnitName(m.cgroups), true, properties...); err != nil {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -126,4 +126,11 @@ type Resources struct {
 | 
			
		||||
 | 
			
		||||
	// CpuWeight sets a proportional bandwidth limit.
 | 
			
		||||
	CpuWeight uint64 `json:"cpu_weight"`
 | 
			
		||||
 | 
			
		||||
	// SkipDevices allows to skip configuring device permissions.
 | 
			
		||||
	// Used by e.g. kubelet while creating a parent cgroup (kubepods)
 | 
			
		||||
	// common for many containers.
 | 
			
		||||
	//
 | 
			
		||||
	// NOTE it is impossible to start a container which has this flag set.
 | 
			
		||||
	SkipDevices bool `json:"skip_devices"`
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/opencontainers/runc/libcontainer/container_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/opencontainers/runc/libcontainer/container_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -251,6 +251,9 @@ func (c *linuxContainer) Set(config configs.Config) error {
 | 
			
		||||
func (c *linuxContainer) Start(process *Process) error {
 | 
			
		||||
	c.m.Lock()
 | 
			
		||||
	defer c.m.Unlock()
 | 
			
		||||
	if c.config.Cgroups.Resources.SkipDevices {
 | 
			
		||||
		return newGenericError(errors.New("can't start container with SkipDevices set"), ConfigInvalid)
 | 
			
		||||
	}
 | 
			
		||||
	if process.Init {
 | 
			
		||||
		if err := c.createExecFifo(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/opencontainers/runc/libcontainer/init_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/opencontainers/runc/libcontainer/init_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -184,6 +184,9 @@ func setupConsole(socket *os.File, config *initConfig, mount bool) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// After we return from here, we don't need the console anymore.
 | 
			
		||||
	defer pty.Close()
 | 
			
		||||
 | 
			
		||||
	if config.ConsoleHeight != 0 && config.ConsoleWidth != 0 {
 | 
			
		||||
		err = pty.Resize(console.WinSize{
 | 
			
		||||
			Height: config.ConsoleHeight,
 | 
			
		||||
@@ -195,9 +198,6 @@ func setupConsole(socket *os.File, config *initConfig, mount bool) error {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// After we return from here, we don't need the console anymore.
 | 
			
		||||
	defer pty.Close()
 | 
			
		||||
 | 
			
		||||
	// Mount the console inside our rootfs.
 | 
			
		||||
	if mount {
 | 
			
		||||
		if err := mountConsole(slavePath); err != nil {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/opencontainers/runc/libcontainer/user/user.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/opencontainers/runc/libcontainer/user/user.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -60,7 +60,7 @@ type Group struct {
 | 
			
		||||
 | 
			
		||||
// groupFromOS converts an os/user.(*Group) to local Group
 | 
			
		||||
//
 | 
			
		||||
// (This does not include Pass, Shell or Gecos)
 | 
			
		||||
// (This does not include Pass or List)
 | 
			
		||||
func groupFromOS(g *user.Group) (Group, error) {
 | 
			
		||||
	newGroup := Group{
 | 
			
		||||
		Name: g.Name,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							@@ -135,7 +135,7 @@ github.com/chai2010/gettext-go/gettext/po
 | 
			
		||||
# github.com/checkpoint-restore/go-criu/v4 v4.0.2 => github.com/checkpoint-restore/go-criu/v4 v4.0.2
 | 
			
		||||
github.com/checkpoint-restore/go-criu/v4
 | 
			
		||||
github.com/checkpoint-restore/go-criu/v4/rpc
 | 
			
		||||
# github.com/cilium/ebpf v0.0.0-20200601085316-9f1617e5c574 => github.com/cilium/ebpf v0.0.0-20200601085316-9f1617e5c574
 | 
			
		||||
# github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775 => github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775
 | 
			
		||||
github.com/cilium/ebpf
 | 
			
		||||
github.com/cilium/ebpf/asm
 | 
			
		||||
github.com/cilium/ebpf/internal
 | 
			
		||||
@@ -575,7 +575,7 @@ github.com/opencontainers/go-digest
 | 
			
		||||
# github.com/opencontainers/image-spec v1.0.1 => github.com/opencontainers/image-spec v1.0.1
 | 
			
		||||
github.com/opencontainers/image-spec/specs-go
 | 
			
		||||
github.com/opencontainers/image-spec/specs-go/v1
 | 
			
		||||
# github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657 => github.com/opencontainers/runc v1.0.0-rc90.0.20200624011356-1b94395c0657
 | 
			
		||||
# github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb => github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb
 | 
			
		||||
github.com/opencontainers/runc/libcontainer
 | 
			
		||||
github.com/opencontainers/runc/libcontainer/apparmor
 | 
			
		||||
github.com/opencontainers/runc/libcontainer/cgroups
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user