mirror of
				https://github.com/opencontainers/runc.git
				synced 2025-10-31 19:13:12 +08:00 
			
		
		
		
	build(deps): bump github.com/cilium/ebpf from 0.16.0 to 0.17.0
Bumps [github.com/cilium/ebpf](https://github.com/cilium/ebpf) from 0.16.0 to 0.17.0. - [Release notes](https://github.com/cilium/ebpf/releases) - [Commits](https://github.com/cilium/ebpf/compare/v0.16.0...v0.17.0) --- updated-dependencies: - dependency-name: github.com/cilium/ebpf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
		
							
								
								
									
										3
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								go.mod
									
									
									
									
									
								
							| @@ -9,7 +9,7 @@ toolchain go1.22.4 | ||||
|  | ||||
| require ( | ||||
| 	github.com/checkpoint-restore/go-criu/v6 v6.3.0 | ||||
| 	github.com/cilium/ebpf v0.16.0 | ||||
| 	github.com/cilium/ebpf v0.17.0 | ||||
| 	github.com/containerd/console v1.0.4 | ||||
| 	github.com/coreos/go-systemd/v22 v22.5.0 | ||||
| 	github.com/cyphar/filepath-securejoin v0.3.6 | ||||
| @@ -35,5 +35,4 @@ require ( | ||||
| 	github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect | ||||
| 	github.com/russross/blackfriday/v2 v2.1.0 // indirect | ||||
| 	github.com/vishvananda/netns v0.0.4 // indirect | ||||
| 	golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect | ||||
| ) | ||||
|   | ||||
							
								
								
									
										6
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								go.sum
									
									
									
									
									
								
							| @@ -1,8 +1,8 @@ | ||||
| github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= | ||||
| github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA= | ||||
| github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= | ||||
| github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= | ||||
| github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= | ||||
| github.com/cilium/ebpf v0.17.0 h1:wAgiAWE86w8DxbR/UJ9KsaaoUfjrO0yhg5yE7f898As= | ||||
| github.com/cilium/ebpf v0.17.0/go.mod h1:vay2FaYSmIlv3r8dNACd4mW/OCaZLJKJOo+IHBvCIO8= | ||||
| github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= | ||||
| github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= | ||||
| github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= | ||||
| @@ -81,8 +81,6 @@ github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQ | ||||
| github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= | ||||
| github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= | ||||
| github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= | ||||
| golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= | ||||
| golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= | ||||
| golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= | ||||
| golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= | ||||
| golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= | ||||
|   | ||||
							
								
								
									
										6
									
								
								vendor/github.com/cilium/ebpf/.golangci.yaml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/cilium/ebpf/.golangci.yaml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -11,3 +11,9 @@ linters: | ||||
|     - typecheck | ||||
|     - unused | ||||
|     - gofmt | ||||
| linters-settings: | ||||
|   goimports: | ||||
|     # A comma-separated list of prefixes, which, if set, checks import paths | ||||
|     # with the given prefixes are grouped after 3rd-party packages. | ||||
|     # Default: "" | ||||
|     local-prefixes: github.com/cilium/ebpf | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/cilium/ebpf/CODEOWNERS
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/cilium/ebpf/CODEOWNERS
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -9,3 +9,5 @@ ringbuf/ @florianl | ||||
| btf/ @dylandreimerink | ||||
|  | ||||
| cmd/bpf2go/ @mejedi | ||||
|  | ||||
| docs/ @ti-mo | ||||
|   | ||||
							
								
								
									
										6
									
								
								vendor/github.com/cilium/ebpf/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/cilium/ebpf/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -39,16 +39,18 @@ TARGETS := \ | ||||
| 	testdata/subprog_reloc \ | ||||
| 	testdata/fwd_decl \ | ||||
| 	testdata/kconfig \ | ||||
| 	testdata/kconfig_config \ | ||||
| 	testdata/ksym \ | ||||
| 	testdata/kfunc \ | ||||
| 	testdata/invalid-kfunc \ | ||||
| 	testdata/kfunc-kmod \ | ||||
| 	testdata/constants \ | ||||
| 	testdata/errors \ | ||||
| 	testdata/variables \ | ||||
| 	btf/testdata/relocs \ | ||||
| 	btf/testdata/relocs_read \ | ||||
| 	btf/testdata/relocs_read_tgt \ | ||||
| 	btf/testdata/relocs_enum \ | ||||
| 	btf/testdata/tags \ | ||||
| 	cmd/bpf2go/testdata/minimal | ||||
|  | ||||
| .PHONY: all clean container-all container-shell generate | ||||
| @@ -57,7 +59,7 @@ TARGETS := \ | ||||
|  | ||||
| # Build all ELF binaries using a containerized LLVM toolchain. | ||||
| container-all: | ||||
| 	+${CONTAINER_ENGINE} run --rm -t ${CONTAINER_RUN_ARGS} \ | ||||
| 	+${CONTAINER_ENGINE} run --rm -ti ${CONTAINER_RUN_ARGS} \ | ||||
| 		-v "${REPODIR}":/ebpf -w /ebpf --env MAKEFLAGS \ | ||||
| 		--env HOME="/tmp" \ | ||||
| 		--env BPF2GO_CC="$(CLANG)" \ | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -53,6 +53,7 @@ This library includes the following packages: | ||||
| * [rlimit](https://pkg.go.dev/github.com/cilium/ebpf/rlimit) provides a convenient API to lift | ||||
|   the `RLIMIT_MEMLOCK` constraint on kernels before 5.11. | ||||
| * [btf](https://pkg.go.dev/github.com/cilium/ebpf/btf) allows reading the BPF Type Format. | ||||
| * [pin](https://pkg.go.dev/github.com/cilium/ebpf/pin) provides APIs for working with pinned objects on bpffs. | ||||
|  | ||||
| ## Requirements | ||||
|  | ||||
|   | ||||
							
								
								
									
										3
									
								
								vendor/github.com/cilium/ebpf/asm/instruction.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/cilium/ebpf/asm/instruction.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -12,7 +12,6 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/internal/sys" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
|  | ||||
| // InstructionSize is the size of a BPF instruction in bytes | ||||
| @@ -804,7 +803,7 @@ func (insns Instructions) Tag(bo binary.ByteOrder) (string, error) { | ||||
| 			return "", fmt.Errorf("instruction %d: %w", i, err) | ||||
| 		} | ||||
| 	} | ||||
| 	return hex.EncodeToString(h.Sum(nil)[:unix.BPF_TAG_SIZE]), nil | ||||
| 	return hex.EncodeToString(h.Sum(nil)[:sys.BPF_TAG_SIZE]), nil | ||||
| } | ||||
|  | ||||
| // encodeFunctionReferences populates the Offset (or Constant, depending on | ||||
|   | ||||
							
								
								
									
										24
									
								
								vendor/github.com/cilium/ebpf/btf/btf.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/cilium/ebpf/btf/btf.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -443,13 +443,19 @@ func fixupDatasec(types []Type, sectionSizes map[string]uint32, offsets map[symb | ||||
| 		// Some Datasecs are virtual and don't have corresponding ELF sections. | ||||
| 		switch name { | ||||
| 		case ".ksyms": | ||||
| 			// .ksyms describes forward declarations of kfunc signatures. | ||||
| 			// .ksyms describes forward declarations of kfunc signatures, as well as | ||||
| 			// references to kernel symbols. | ||||
| 			// Nothing to fix up, all sizes and offsets are 0. | ||||
| 			for _, vsi := range ds.Vars { | ||||
| 				_, ok := vsi.Type.(*Func) | ||||
| 				if !ok { | ||||
| 					// Only Funcs are supported in the .ksyms Datasec. | ||||
| 					return fmt.Errorf("data section %s: expected *btf.Func, not %T: %w", name, vsi.Type, ErrNotSupported) | ||||
| 				switch t := vsi.Type.(type) { | ||||
| 				case *Func: | ||||
| 					continue | ||||
| 				case *Var: | ||||
| 					if _, ok := t.Type.(*Void); !ok { | ||||
| 						return fmt.Errorf("data section %s: expected %s to be *Void, not %T: %w", name, vsi.Type.TypeName(), vsi.Type, ErrNotSupported) | ||||
| 					} | ||||
| 				default: | ||||
| 					return fmt.Errorf("data section %s: expected to be either *btf.Func or *btf.Var, not %T: %w", name, vsi.Type, ErrNotSupported) | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| @@ -695,5 +701,13 @@ func (iter *TypesIterator) Next() bool { | ||||
| 	iter.Type, ok = iter.spec.typeByID(iter.id) | ||||
| 	iter.id++ | ||||
| 	iter.done = !ok | ||||
| 	if !iter.done { | ||||
| 		// Skip declTags, during unmarshaling declTags become `Tags` fields of other types. | ||||
| 		// We keep them in the spec to avoid holes in the ID space, but for the purposes of | ||||
| 		// iteration, they are not useful to the user. | ||||
| 		if _, ok := iter.Type.(*declTag); ok { | ||||
| 			return iter.Next() | ||||
| 		} | ||||
| 	} | ||||
| 	return !iter.done | ||||
| } | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/btf/btf_types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/btf/btf_types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -39,6 +39,7 @@ const ( | ||||
| 	kindFloat // Float | ||||
| 	// Added 5.16 | ||||
| 	kindDeclTag // DeclTag | ||||
| 	// Added 5.17 | ||||
| 	kindTypeTag // TypeTag | ||||
| 	// Added 6.0 | ||||
| 	kindEnum64 // Enum64 | ||||
|   | ||||
							
								
								
									
										150
									
								
								vendor/github.com/cilium/ebpf/btf/ext_info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										150
									
								
								vendor/github.com/cilium/ebpf/btf/ext_info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -16,8 +16,8 @@ import ( | ||||
| // ExtInfos contains ELF section metadata. | ||||
| type ExtInfos struct { | ||||
| 	// The slices are sorted by offset in ascending order. | ||||
| 	funcInfos       map[string]FuncInfos | ||||
| 	lineInfos       map[string]LineInfos | ||||
| 	funcInfos       map[string]FuncOffsets | ||||
| 	lineInfos       map[string]LineOffsets | ||||
| 	relocationInfos map[string]CORERelocationInfos | ||||
| } | ||||
|  | ||||
| @@ -58,9 +58,9 @@ func loadExtInfos(r io.ReaderAt, bo binary.ByteOrder, spec *Spec) (*ExtInfos, er | ||||
| 		return nil, fmt.Errorf("parsing BTF function info: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	funcInfos := make(map[string]FuncInfos, len(btfFuncInfos)) | ||||
| 	funcInfos := make(map[string]FuncOffsets, len(btfFuncInfos)) | ||||
| 	for section, bfis := range btfFuncInfos { | ||||
| 		funcInfos[section], err = newFuncInfos(bfis, spec) | ||||
| 		funcInfos[section], err = newFuncOffsets(bfis, spec) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("section %s: func infos: %w", section, err) | ||||
| 		} | ||||
| @@ -72,7 +72,7 @@ func loadExtInfos(r io.ReaderAt, bo binary.ByteOrder, spec *Spec) (*ExtInfos, er | ||||
| 		return nil, fmt.Errorf("parsing BTF line info: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	lineInfos := make(map[string]LineInfos, len(btfLineInfos)) | ||||
| 	lineInfos := make(map[string]LineOffsets, len(btfLineInfos)) | ||||
| 	for section, blis := range btfLineInfos { | ||||
| 		lineInfos[section], err = newLineInfos(blis, spec.strings) | ||||
| 		if err != nil { | ||||
| @@ -102,8 +102,10 @@ func loadExtInfos(r io.ReaderAt, bo binary.ByteOrder, spec *Spec) (*ExtInfos, er | ||||
| 	return &ExtInfos{funcInfos, lineInfos, coreRelos}, nil | ||||
| } | ||||
|  | ||||
| type funcInfoMeta struct{} | ||||
| type coreRelocationMeta struct{} | ||||
| type ( | ||||
| 	funcInfoMeta       struct{} | ||||
| 	coreRelocationMeta struct{} | ||||
| ) | ||||
|  | ||||
| // Assign per-section metadata from BTF to a section's instructions. | ||||
| func (ei *ExtInfos) Assign(insns asm.Instructions, section string) { | ||||
| @@ -117,20 +119,20 @@ func (ei *ExtInfos) Assign(insns asm.Instructions, section string) { | ||||
| // Assign per-instruction metadata to the instructions in insns. | ||||
| func AssignMetadataToInstructions( | ||||
| 	insns asm.Instructions, | ||||
| 	funcInfos FuncInfos, | ||||
| 	lineInfos LineInfos, | ||||
| 	funcInfos FuncOffsets, | ||||
| 	lineInfos LineOffsets, | ||||
| 	reloInfos CORERelocationInfos, | ||||
| ) { | ||||
| 	iter := insns.Iterate() | ||||
| 	for iter.Next() { | ||||
| 		if len(funcInfos.infos) > 0 && funcInfos.infos[0].offset == iter.Offset { | ||||
| 			*iter.Ins = WithFuncMetadata(*iter.Ins, funcInfos.infos[0].fn) | ||||
| 			funcInfos.infos = funcInfos.infos[1:] | ||||
| 		if len(funcInfos) > 0 && funcInfos[0].Offset == iter.Offset { | ||||
| 			*iter.Ins = WithFuncMetadata(*iter.Ins, funcInfos[0].Func) | ||||
| 			funcInfos = funcInfos[1:] | ||||
| 		} | ||||
|  | ||||
| 		if len(lineInfos.infos) > 0 && lineInfos.infos[0].offset == iter.Offset { | ||||
| 			*iter.Ins = iter.Ins.WithSource(lineInfos.infos[0].line) | ||||
| 			lineInfos.infos = lineInfos.infos[1:] | ||||
| 		if len(lineInfos) > 0 && lineInfos[0].Offset == iter.Offset { | ||||
| 			*iter.Ins = iter.Ins.WithSource(lineInfos[0].Line) | ||||
| 			lineInfos = lineInfos[1:] | ||||
| 		} | ||||
|  | ||||
| 		if len(reloInfos.infos) > 0 && reloInfos.infos[0].offset == iter.Offset { | ||||
| @@ -159,9 +161,9 @@ marshal: | ||||
| 	var fiBuf, liBuf bytes.Buffer | ||||
| 	for { | ||||
| 		if fn := FuncMetadata(iter.Ins); fn != nil { | ||||
| 			fi := &funcInfo{ | ||||
| 				fn:     fn, | ||||
| 				offset: iter.Offset, | ||||
| 			fi := &FuncOffset{ | ||||
| 				Func:   fn, | ||||
| 				Offset: iter.Offset, | ||||
| 			} | ||||
| 			if err := fi.marshal(&fiBuf, b); err != nil { | ||||
| 				return nil, nil, fmt.Errorf("write func info: %w", err) | ||||
| @@ -178,9 +180,9 @@ marshal: | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			li := &lineInfo{ | ||||
| 				line:   line, | ||||
| 				offset: iter.Offset, | ||||
| 			li := &LineOffset{ | ||||
| 				Offset: iter.Offset, | ||||
| 				Line:   line, | ||||
| 			} | ||||
| 			if err := li.marshal(&liBuf, b); err != nil { | ||||
| 				return nil, nil, fmt.Errorf("write line info: %w", err) | ||||
| @@ -333,17 +335,17 @@ func parseExtInfoRecordSize(r io.Reader, bo binary.ByteOrder) (uint32, error) { | ||||
| 	return recordSize, nil | ||||
| } | ||||
|  | ||||
| // FuncInfos contains a sorted list of func infos. | ||||
| type FuncInfos struct { | ||||
| 	infos []funcInfo | ||||
| } | ||||
| // FuncOffsets is a sorted slice of FuncOffset. | ||||
| type FuncOffsets []FuncOffset | ||||
|  | ||||
| // The size of a FuncInfo in BTF wire format. | ||||
| var FuncInfoSize = uint32(binary.Size(bpfFuncInfo{})) | ||||
|  | ||||
| type funcInfo struct { | ||||
| 	fn     *Func | ||||
| 	offset asm.RawInstructionOffset | ||||
| // FuncOffset represents a [btf.Func] and its raw instruction offset within a | ||||
| // BPF program. | ||||
| type FuncOffset struct { | ||||
| 	Offset asm.RawInstructionOffset | ||||
| 	Func   *Func | ||||
| } | ||||
|  | ||||
| type bpfFuncInfo struct { | ||||
| @@ -352,7 +354,7 @@ type bpfFuncInfo struct { | ||||
| 	TypeID  TypeID | ||||
| } | ||||
|  | ||||
| func newFuncInfo(fi bpfFuncInfo, spec *Spec) (*funcInfo, error) { | ||||
| func newFuncOffset(fi bpfFuncInfo, spec *Spec) (*FuncOffset, error) { | ||||
| 	typ, err := spec.TypeByID(fi.TypeID) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -368,31 +370,32 @@ func newFuncInfo(fi bpfFuncInfo, spec *Spec) (*funcInfo, error) { | ||||
| 		return nil, fmt.Errorf("func with type ID %d doesn't have a name", fi.TypeID) | ||||
| 	} | ||||
|  | ||||
| 	return &funcInfo{ | ||||
| 		fn, | ||||
| 	return &FuncOffset{ | ||||
| 		asm.RawInstructionOffset(fi.InsnOff), | ||||
| 		fn, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func newFuncInfos(bfis []bpfFuncInfo, spec *Spec) (FuncInfos, error) { | ||||
| 	fis := FuncInfos{ | ||||
| 		infos: make([]funcInfo, 0, len(bfis)), | ||||
| 	} | ||||
| func newFuncOffsets(bfis []bpfFuncInfo, spec *Spec) (FuncOffsets, error) { | ||||
| 	fos := make(FuncOffsets, 0, len(bfis)) | ||||
|  | ||||
| 	for _, bfi := range bfis { | ||||
| 		fi, err := newFuncInfo(bfi, spec) | ||||
| 		fi, err := newFuncOffset(bfi, spec) | ||||
| 		if err != nil { | ||||
| 			return FuncInfos{}, fmt.Errorf("offset %d: %w", bfi.InsnOff, err) | ||||
| 			return FuncOffsets{}, fmt.Errorf("offset %d: %w", bfi.InsnOff, err) | ||||
| 		} | ||||
| 		fis.infos = append(fis.infos, *fi) | ||||
| 		fos = append(fos, *fi) | ||||
| 	} | ||||
| 	sort.Slice(fis.infos, func(i, j int) bool { | ||||
| 		return fis.infos[i].offset <= fis.infos[j].offset | ||||
| 	sort.Slice(fos, func(i, j int) bool { | ||||
| 		return fos[i].Offset <= fos[j].Offset | ||||
| 	}) | ||||
| 	return fis, nil | ||||
| 	return fos, nil | ||||
| } | ||||
|  | ||||
| // LoadFuncInfos parses BTF func info in kernel wire format. | ||||
| func LoadFuncInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec *Spec) (FuncInfos, error) { | ||||
| // LoadFuncInfos parses BTF func info from kernel wire format into a | ||||
| // [FuncOffsets], a sorted slice of [btf.Func]s of (sub)programs within a BPF | ||||
| // program with their corresponding raw instruction offsets. | ||||
| func LoadFuncInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec *Spec) (FuncOffsets, error) { | ||||
| 	fis, err := parseFuncInfoRecords( | ||||
| 		reader, | ||||
| 		bo, | ||||
| @@ -401,20 +404,20 @@ func LoadFuncInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec | ||||
| 		false, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return FuncInfos{}, fmt.Errorf("parsing BTF func info: %w", err) | ||||
| 		return FuncOffsets{}, fmt.Errorf("parsing BTF func info: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return newFuncInfos(fis, spec) | ||||
| 	return newFuncOffsets(fis, spec) | ||||
| } | ||||
|  | ||||
| // marshal into the BTF wire format. | ||||
| func (fi *funcInfo) marshal(w *bytes.Buffer, b *Builder) error { | ||||
| 	id, err := b.Add(fi.fn) | ||||
| func (fi *FuncOffset) marshal(w *bytes.Buffer, b *Builder) error { | ||||
| 	id, err := b.Add(fi.Func) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	bfi := bpfFuncInfo{ | ||||
| 		InsnOff: uint32(fi.offset), | ||||
| 		InsnOff: uint32(fi.Offset), | ||||
| 		TypeID:  id, | ||||
| 	} | ||||
| 	buf := make([]byte, FuncInfoSize) | ||||
| @@ -515,14 +518,13 @@ func (li *Line) String() string { | ||||
| 	return li.line | ||||
| } | ||||
|  | ||||
| // LineInfos contains a sorted list of line infos. | ||||
| type LineInfos struct { | ||||
| 	infos []lineInfo | ||||
| } | ||||
| // LineOffsets contains a sorted list of line infos. | ||||
| type LineOffsets []LineOffset | ||||
|  | ||||
| type lineInfo struct { | ||||
| 	line   *Line | ||||
| 	offset asm.RawInstructionOffset | ||||
| // LineOffset represents a line info and its raw instruction offset. | ||||
| type LineOffset struct { | ||||
| 	Offset asm.RawInstructionOffset | ||||
| 	Line   *Line | ||||
| } | ||||
|  | ||||
| // Constants for the format of bpfLineInfo.LineCol. | ||||
| @@ -541,7 +543,7 @@ type bpfLineInfo struct { | ||||
| } | ||||
|  | ||||
| // LoadLineInfos parses BTF line info in kernel wire format. | ||||
| func LoadLineInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec *Spec) (LineInfos, error) { | ||||
| func LoadLineInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec *Spec) (LineOffsets, error) { | ||||
| 	lis, err := parseLineInfoRecords( | ||||
| 		reader, | ||||
| 		bo, | ||||
| @@ -550,57 +552,55 @@ func LoadLineInfos(reader io.Reader, bo binary.ByteOrder, recordNum uint32, spec | ||||
| 		false, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return LineInfos{}, fmt.Errorf("parsing BTF line info: %w", err) | ||||
| 		return LineOffsets{}, fmt.Errorf("parsing BTF line info: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return newLineInfos(lis, spec.strings) | ||||
| } | ||||
|  | ||||
| func newLineInfo(li bpfLineInfo, strings *stringTable) (lineInfo, error) { | ||||
| func newLineInfo(li bpfLineInfo, strings *stringTable) (LineOffset, error) { | ||||
| 	line, err := strings.Lookup(li.LineOff) | ||||
| 	if err != nil { | ||||
| 		return lineInfo{}, fmt.Errorf("lookup of line: %w", err) | ||||
| 		return LineOffset{}, fmt.Errorf("lookup of line: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	fileName, err := strings.Lookup(li.FileNameOff) | ||||
| 	if err != nil { | ||||
| 		return lineInfo{}, fmt.Errorf("lookup of filename: %w", err) | ||||
| 		return LineOffset{}, fmt.Errorf("lookup of filename: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	lineNumber := li.LineCol >> bpfLineShift | ||||
| 	lineColumn := li.LineCol & bpfColumnMax | ||||
|  | ||||
| 	return lineInfo{ | ||||
| 	return LineOffset{ | ||||
| 		asm.RawInstructionOffset(li.InsnOff), | ||||
| 		&Line{ | ||||
| 			fileName, | ||||
| 			line, | ||||
| 			lineNumber, | ||||
| 			lineColumn, | ||||
| 		}, | ||||
| 		asm.RawInstructionOffset(li.InsnOff), | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func newLineInfos(blis []bpfLineInfo, strings *stringTable) (LineInfos, error) { | ||||
| 	lis := LineInfos{ | ||||
| 		infos: make([]lineInfo, 0, len(blis)), | ||||
| 	} | ||||
| func newLineInfos(blis []bpfLineInfo, strings *stringTable) (LineOffsets, error) { | ||||
| 	lis := make([]LineOffset, 0, len(blis)) | ||||
| 	for _, bli := range blis { | ||||
| 		li, err := newLineInfo(bli, strings) | ||||
| 		if err != nil { | ||||
| 			return LineInfos{}, fmt.Errorf("offset %d: %w", bli.InsnOff, err) | ||||
| 			return LineOffsets{}, fmt.Errorf("offset %d: %w", bli.InsnOff, err) | ||||
| 		} | ||||
| 		lis.infos = append(lis.infos, li) | ||||
| 		lis = append(lis, li) | ||||
| 	} | ||||
| 	sort.Slice(lis.infos, func(i, j int) bool { | ||||
| 		return lis.infos[i].offset <= lis.infos[j].offset | ||||
| 	sort.Slice(lis, func(i, j int) bool { | ||||
| 		return lis[i].Offset <= lis[j].Offset | ||||
| 	}) | ||||
| 	return lis, nil | ||||
| } | ||||
|  | ||||
| // marshal writes the binary representation of the LineInfo to w. | ||||
| func (li *lineInfo) marshal(w *bytes.Buffer, b *Builder) error { | ||||
| 	line := li.line | ||||
| func (li *LineOffset) marshal(w *bytes.Buffer, b *Builder) error { | ||||
| 	line := li.Line | ||||
| 	if line.lineNumber > bpfLineMax { | ||||
| 		return fmt.Errorf("line %d exceeds %d", line.lineNumber, bpfLineMax) | ||||
| 	} | ||||
| @@ -620,7 +620,7 @@ func (li *lineInfo) marshal(w *bytes.Buffer, b *Builder) error { | ||||
| 	} | ||||
|  | ||||
| 	bli := bpfLineInfo{ | ||||
| 		uint32(li.offset), | ||||
| 		uint32(li.Offset), | ||||
| 		fileNameOff, | ||||
| 		lineOff, | ||||
| 		(line.lineNumber << bpfLineShift) | line.lineColumn, | ||||
| @@ -799,7 +799,7 @@ func parseCORERelos(r io.Reader, bo binary.ByteOrder, strings *stringTable) (map | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		records, err := parseCOREReloRecords(r, bo, recordSize, infoHeader.NumInfo) | ||||
| 		records, err := parseCOREReloRecords(r, bo, infoHeader.NumInfo) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("section %v: %w", secName, err) | ||||
| 		} | ||||
| @@ -811,7 +811,7 @@ func parseCORERelos(r io.Reader, bo binary.ByteOrder, strings *stringTable) (map | ||||
| // parseCOREReloRecords parses a stream of CO-RE relocation entries into a | ||||
| // coreRelos. These records appear after a btf_ext_info_sec header in the | ||||
| // core_relos sub-section of .BTF.ext. | ||||
| func parseCOREReloRecords(r io.Reader, bo binary.ByteOrder, recordSize uint32, recordNum uint32) ([]bpfCORERelo, error) { | ||||
| func parseCOREReloRecords(r io.Reader, bo binary.ByteOrder, recordNum uint32) ([]bpfCORERelo, error) { | ||||
| 	var out []bpfCORERelo | ||||
|  | ||||
| 	var relo bpfCORERelo | ||||
|   | ||||
							
								
								
									
										55
									
								
								vendor/github.com/cilium/ebpf/btf/feature.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										55
									
								
								vendor/github.com/cilium/ebpf/btf/feature.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -11,19 +11,19 @@ import ( | ||||
|  | ||||
| // haveBTF attempts to load a BTF blob containing an Int. It should pass on any | ||||
| // kernel that supports BPF_BTF_LOAD. | ||||
| var haveBTF = internal.NewFeatureTest("BTF", "4.18", func() error { | ||||
| var haveBTF = internal.NewFeatureTest("BTF", func() error { | ||||
| 	// 0-length anonymous integer | ||||
| 	err := probeBTF(&Int{}) | ||||
| 	if errors.Is(err, unix.EINVAL) || errors.Is(err, unix.EPERM) { | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	return err | ||||
| }) | ||||
| }, "4.18") | ||||
|  | ||||
| // haveMapBTF attempts to load a minimal BTF blob containing a Var. It is | ||||
| // used as a proxy for .bss, .data and .rodata map support, which generally | ||||
| // come with a Var and Datasec. These were introduced in Linux 5.2. | ||||
| var haveMapBTF = internal.NewFeatureTest("Map BTF (Var/Datasec)", "5.2", func() error { | ||||
| var haveMapBTF = internal.NewFeatureTest("Map BTF (Var/Datasec)", func() error { | ||||
| 	if err := haveBTF(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -40,12 +40,12 @@ var haveMapBTF = internal.NewFeatureTest("Map BTF (Var/Datasec)", "5.2", func() | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	return err | ||||
| }) | ||||
| }, "5.2") | ||||
|  | ||||
| // haveProgBTF attempts to load a BTF blob containing a Func and FuncProto. It | ||||
| // is used as a proxy for ext_info (func_info) support, which depends on | ||||
| // Func(Proto) by definition. | ||||
| var haveProgBTF = internal.NewFeatureTest("Program BTF (func/line_info)", "5.0", func() error { | ||||
| var haveProgBTF = internal.NewFeatureTest("Program BTF (func/line_info)", func() error { | ||||
| 	if err := haveBTF(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -60,9 +60,9 @@ var haveProgBTF = internal.NewFeatureTest("Program BTF (func/line_info)", "5.0", | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	return err | ||||
| }) | ||||
| }, "5.0") | ||||
|  | ||||
| var haveFuncLinkage = internal.NewFeatureTest("BTF func linkage", "5.6", func() error { | ||||
| var haveFuncLinkage = internal.NewFeatureTest("BTF func linkage", func() error { | ||||
| 	if err := haveProgBTF(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -78,9 +78,44 @@ var haveFuncLinkage = internal.NewFeatureTest("BTF func linkage", "5.6", func() | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	return err | ||||
| }) | ||||
| }, "5.6") | ||||
|  | ||||
| var haveEnum64 = internal.NewFeatureTest("ENUM64", "6.0", func() error { | ||||
| var haveDeclTags = internal.NewFeatureTest("BTF decl tags", func() error { | ||||
| 	if err := haveBTF(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	t := &Typedef{ | ||||
| 		Name: "a", | ||||
| 		Type: &Int{}, | ||||
| 		Tags: []string{"a"}, | ||||
| 	} | ||||
|  | ||||
| 	err := probeBTF(t) | ||||
| 	if errors.Is(err, unix.EINVAL) { | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	return err | ||||
| }, "5.16") | ||||
|  | ||||
| var haveTypeTags = internal.NewFeatureTest("BTF type tags", func() error { | ||||
| 	if err := haveBTF(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	t := &TypeTag{ | ||||
| 		Type:  &Int{}, | ||||
| 		Value: "a", | ||||
| 	} | ||||
|  | ||||
| 	err := probeBTF(t) | ||||
| 	if errors.Is(err, unix.EINVAL) { | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	return err | ||||
| }, "5.17") | ||||
|  | ||||
| var haveEnum64 = internal.NewFeatureTest("ENUM64", func() error { | ||||
| 	if err := haveBTF(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -97,7 +132,7 @@ var haveEnum64 = internal.NewFeatureTest("ENUM64", "6.0", func() error { | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	return err | ||||
| }) | ||||
| }, "6.0") | ||||
|  | ||||
| func probeBTF(typ Type) error { | ||||
| 	b, err := NewBuilder([]Type{typ}) | ||||
|   | ||||
							
								
								
									
										3
									
								
								vendor/github.com/cilium/ebpf/btf/format.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/cilium/ebpf/btf/format.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -161,6 +161,9 @@ func (gf *GoFormatter) writeTypeLit(typ Type, depth int) error { | ||||
| 	case *Datasec: | ||||
| 		err = gf.writeDatasecLit(v, depth) | ||||
|  | ||||
| 	case *Var: | ||||
| 		err = gf.writeTypeLit(v.Type, depth) | ||||
|  | ||||
| 	default: | ||||
| 		return fmt.Errorf("type %T: %w", v, ErrNotSupported) | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										6
									
								
								vendor/github.com/cilium/ebpf/btf/kernel.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/cilium/ebpf/btf/kernel.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -8,7 +8,7 @@ import ( | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/kallsyms" | ||||
| 	"github.com/cilium/ebpf/internal/linux" | ||||
| ) | ||||
|  | ||||
| var kernelBTF = struct { | ||||
| @@ -21,8 +21,6 @@ var kernelBTF = struct { | ||||
|  | ||||
| // FlushKernelSpec removes any cached kernel type information. | ||||
| func FlushKernelSpec() { | ||||
| 	kallsyms.FlushKernelModuleCache() | ||||
|  | ||||
| 	kernelBTF.Lock() | ||||
| 	defer kernelBTF.Unlock() | ||||
|  | ||||
| @@ -130,7 +128,7 @@ func loadKernelModuleSpec(module string, base *Spec) (*Spec, error) { | ||||
|  | ||||
| // findVMLinux scans multiple well-known paths for vmlinux kernel images. | ||||
| func findVMLinux() (*os.File, error) { | ||||
| 	release, err := internal.KernelRelease() | ||||
| 	release, err := linux.KernelRelease() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										83
									
								
								vendor/github.com/cilium/ebpf/btf/marshal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										83
									
								
								vendor/github.com/cilium/ebpf/btf/marshal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -18,6 +18,10 @@ type MarshalOptions struct { | ||||
| 	Order binary.ByteOrder | ||||
| 	// Remove function linkage information for compatibility with <5.6 kernels. | ||||
| 	StripFuncLinkage bool | ||||
| 	// Replace decl tags with a placeholder for compatibility with <5.16 kernels. | ||||
| 	ReplaceDeclTags bool | ||||
| 	// Replace TypeTags with a placeholder for compatibility with <5.17 kernels. | ||||
| 	ReplaceTypeTags bool | ||||
| 	// Replace Enum64 with a placeholder for compatibility with <6.0 kernels. | ||||
| 	ReplaceEnum64 bool | ||||
| 	// Prevent the "No type found" error when loading BTF without any types. | ||||
| @@ -29,6 +33,8 @@ func KernelMarshalOptions() *MarshalOptions { | ||||
| 	return &MarshalOptions{ | ||||
| 		Order:              internal.NativeEndian, | ||||
| 		StripFuncLinkage:   haveFuncLinkage() != nil, | ||||
| 		ReplaceDeclTags:    haveDeclTags() != nil, | ||||
| 		ReplaceTypeTags:    haveTypeTags() != nil, | ||||
| 		ReplaceEnum64:      haveEnum64() != nil, | ||||
| 		PreventNoTypeFound: true, // All current kernels require this. | ||||
| 	} | ||||
| @@ -318,15 +324,7 @@ func (e *encoder) deflateType(typ Type) (err error) { | ||||
| 		return errors.New("Void is implicit in BTF wire format") | ||||
|  | ||||
| 	case *Int: | ||||
| 		raw.SetKind(kindInt) | ||||
| 		raw.SetSize(v.Size) | ||||
|  | ||||
| 		var bi btfInt | ||||
| 		bi.SetEncoding(v.Encoding) | ||||
| 		// We need to set bits in addition to size, since btf_type_int_is_regular | ||||
| 		// otherwise flags this as a bitfield. | ||||
| 		bi.SetBits(byte(v.Size) * 8) | ||||
| 		raw.data = bi | ||||
| 		e.deflateInt(&raw, v) | ||||
|  | ||||
| 	case *Pointer: | ||||
| 		raw.SetKind(kindPointer) | ||||
| @@ -368,8 +366,7 @@ func (e *encoder) deflateType(typ Type) (err error) { | ||||
| 		raw.SetType(e.id(v.Type)) | ||||
|  | ||||
| 	case *Const: | ||||
| 		raw.SetKind(kindConst) | ||||
| 		raw.SetType(e.id(v.Type)) | ||||
| 		e.deflateConst(&raw, v) | ||||
|  | ||||
| 	case *Restrict: | ||||
| 		raw.SetKind(kindRestrict) | ||||
| @@ -404,15 +401,10 @@ func (e *encoder) deflateType(typ Type) (err error) { | ||||
| 		raw.SetSize(v.Size) | ||||
|  | ||||
| 	case *declTag: | ||||
| 		raw.SetKind(kindDeclTag) | ||||
| 		raw.SetType(e.id(v.Type)) | ||||
| 		raw.data = &btfDeclTag{uint32(v.Index)} | ||||
| 		raw.NameOff, err = e.strings.Add(v.Value) | ||||
| 		err = e.deflateDeclTag(&raw, v) | ||||
|  | ||||
| 	case *typeTag: | ||||
| 		raw.SetKind(kindTypeTag) | ||||
| 		raw.SetType(e.id(v.Type)) | ||||
| 		raw.NameOff, err = e.strings.Add(v.Value) | ||||
| 	case *TypeTag: | ||||
| 		err = e.deflateTypeTag(&raw, v) | ||||
|  | ||||
| 	default: | ||||
| 		return fmt.Errorf("don't know how to deflate %T", v) | ||||
| @@ -425,6 +417,57 @@ func (e *encoder) deflateType(typ Type) (err error) { | ||||
| 	return raw.Marshal(e.buf, e.Order) | ||||
| } | ||||
|  | ||||
| func (e *encoder) deflateInt(raw *rawType, i *Int) { | ||||
| 	raw.SetKind(kindInt) | ||||
| 	raw.SetSize(i.Size) | ||||
|  | ||||
| 	var bi btfInt | ||||
| 	bi.SetEncoding(i.Encoding) | ||||
| 	// We need to set bits in addition to size, since btf_type_int_is_regular | ||||
| 	// otherwise flags this as a bitfield. | ||||
| 	bi.SetBits(byte(i.Size) * 8) | ||||
| 	raw.data = bi | ||||
| } | ||||
|  | ||||
| func (e *encoder) deflateDeclTag(raw *rawType, tag *declTag) (err error) { | ||||
| 	// Replace a decl tag with an integer for compatibility with <5.16 kernels, | ||||
| 	// following libbpf behaviour. | ||||
| 	if e.ReplaceDeclTags { | ||||
| 		typ := &Int{"decl_tag_placeholder", 1, Unsigned} | ||||
| 		e.deflateInt(raw, typ) | ||||
|  | ||||
| 		// Add the placeholder type name to the string table. The encoder added the | ||||
| 		// original type name before this call. | ||||
| 		raw.NameOff, err = e.strings.Add(typ.TypeName()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	raw.SetKind(kindDeclTag) | ||||
| 	raw.SetType(e.id(tag.Type)) | ||||
| 	raw.data = &btfDeclTag{uint32(tag.Index)} | ||||
| 	raw.NameOff, err = e.strings.Add(tag.Value) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (e *encoder) deflateConst(raw *rawType, c *Const) { | ||||
| 	raw.SetKind(kindConst) | ||||
| 	raw.SetType(e.id(c.Type)) | ||||
| } | ||||
|  | ||||
| func (e *encoder) deflateTypeTag(raw *rawType, tag *TypeTag) (err error) { | ||||
| 	// Replace a type tag with a const qualifier for compatibility with <5.17 | ||||
| 	// kernels, following libbpf behaviour. | ||||
| 	if e.ReplaceTypeTags { | ||||
| 		e.deflateConst(raw, &Const{tag.Type}) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	raw.SetKind(kindTypeTag) | ||||
| 	raw.SetType(e.id(tag.Type)) | ||||
| 	raw.NameOff, err = e.strings.Add(tag.Value) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (e *encoder) deflateUnion(raw *rawType, union *Union) (err error) { | ||||
| 	raw.SetKind(kindUnion) | ||||
| 	raw.SetSize(union.Size) | ||||
| @@ -521,7 +564,7 @@ func (e *encoder) deflateEnum64(raw *rawType, enum *Enum) (err error) { | ||||
| 			}) | ||||
| 		} | ||||
|  | ||||
| 		return e.deflateUnion(raw, &Union{enum.Name, enum.Size, members}) | ||||
| 		return e.deflateUnion(raw, &Union{enum.Name, enum.Size, members, nil}) | ||||
| 	} | ||||
|  | ||||
| 	raw.SetKind(kindEnum64) | ||||
|   | ||||
							
								
								
									
										48
									
								
								vendor/github.com/cilium/ebpf/btf/traversal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/cilium/ebpf/btf/traversal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -40,9 +40,12 @@ func children(typ Type, yield func(child *Type) bool) bool { | ||||
| 	// Explicitly type switch on the most common types to allow the inliner to | ||||
| 	// do its work. This avoids allocating intermediate slices from walk() on | ||||
| 	// the heap. | ||||
| 	var tags []string | ||||
| 	switch v := typ.(type) { | ||||
| 	case *Void, *Int, *Enum, *Fwd, *Float: | ||||
| 	case *Void, *Int, *Enum, *Fwd, *Float, *declTag: | ||||
| 		// No children to traverse. | ||||
| 		// declTags is declared as a leaf type since it's parsed into .Tags fields of other types | ||||
| 		// during unmarshaling. | ||||
| 	case *Pointer: | ||||
| 		if !yield(&v.Target) { | ||||
| 			return false | ||||
| @@ -59,17 +62,32 @@ func children(typ Type, yield func(child *Type) bool) bool { | ||||
| 			if !yield(&v.Members[i].Type) { | ||||
| 				return false | ||||
| 			} | ||||
| 			for _, t := range v.Members[i].Tags { | ||||
| 				var tag Type = &declTag{v, t, i} | ||||
| 				if !yield(&tag) { | ||||
| 					return false | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		tags = v.Tags | ||||
| 	case *Union: | ||||
| 		for i := range v.Members { | ||||
| 			if !yield(&v.Members[i].Type) { | ||||
| 				return false | ||||
| 			} | ||||
| 			for _, t := range v.Members[i].Tags { | ||||
| 				var tag Type = &declTag{v, t, i} | ||||
| 				if !yield(&tag) { | ||||
| 					return false | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		tags = v.Tags | ||||
| 	case *Typedef: | ||||
| 		if !yield(&v.Type) { | ||||
| 			return false | ||||
| 		} | ||||
| 		tags = v.Tags | ||||
| 	case *Volatile: | ||||
| 		if !yield(&v.Type) { | ||||
| 			return false | ||||
| @@ -86,6 +104,20 @@ func children(typ Type, yield func(child *Type) bool) bool { | ||||
| 		if !yield(&v.Type) { | ||||
| 			return false | ||||
| 		} | ||||
| 		if fp, ok := v.Type.(*FuncProto); ok { | ||||
| 			for i := range fp.Params { | ||||
| 				if len(v.ParamTags) <= i { | ||||
| 					continue | ||||
| 				} | ||||
| 				for _, t := range v.ParamTags[i] { | ||||
| 					var tag Type = &declTag{v, t, i} | ||||
| 					if !yield(&tag) { | ||||
| 						return false | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		tags = v.Tags | ||||
| 	case *FuncProto: | ||||
| 		if !yield(&v.Return) { | ||||
| 			return false | ||||
| @@ -99,17 +131,14 @@ func children(typ Type, yield func(child *Type) bool) bool { | ||||
| 		if !yield(&v.Type) { | ||||
| 			return false | ||||
| 		} | ||||
| 		tags = v.Tags | ||||
| 	case *Datasec: | ||||
| 		for i := range v.Vars { | ||||
| 			if !yield(&v.Vars[i].Type) { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 	case *declTag: | ||||
| 		if !yield(&v.Type) { | ||||
| 			return false | ||||
| 		} | ||||
| 	case *typeTag: | ||||
| 	case *TypeTag: | ||||
| 		if !yield(&v.Type) { | ||||
| 			return false | ||||
| 		} | ||||
| @@ -119,5 +148,12 @@ func children(typ Type, yield func(child *Type) bool) bool { | ||||
| 		panic(fmt.Sprintf("don't know how to walk Type %T", v)) | ||||
| 	} | ||||
|  | ||||
| 	for _, t := range tags { | ||||
| 		var tag Type = &declTag{typ, t, -1} | ||||
| 		if !yield(&tag) { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|   | ||||
							
								
								
									
										138
									
								
								vendor/github.com/cilium/ebpf/btf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										138
									
								
								vendor/github.com/cilium/ebpf/btf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -67,7 +67,7 @@ var ( | ||||
| 	_ Type = (*Datasec)(nil) | ||||
| 	_ Type = (*Float)(nil) | ||||
| 	_ Type = (*declTag)(nil) | ||||
| 	_ Type = (*typeTag)(nil) | ||||
| 	_ Type = (*TypeTag)(nil) | ||||
| 	_ Type = (*cycle)(nil) | ||||
| ) | ||||
|  | ||||
| @@ -169,6 +169,7 @@ type Struct struct { | ||||
| 	// The size of the struct including padding, in bytes | ||||
| 	Size    uint32 | ||||
| 	Members []Member | ||||
| 	Tags    []string | ||||
| } | ||||
|  | ||||
| func (s *Struct) Format(fs fmt.State, verb rune) { | ||||
| @@ -182,6 +183,7 @@ func (s *Struct) size() uint32 { return s.Size } | ||||
| func (s *Struct) copy() Type { | ||||
| 	cpy := *s | ||||
| 	cpy.Members = copyMembers(s.Members) | ||||
| 	cpy.Tags = copyTags(cpy.Tags) | ||||
| 	return &cpy | ||||
| } | ||||
|  | ||||
| @@ -195,6 +197,7 @@ type Union struct { | ||||
| 	// The size of the union including padding, in bytes. | ||||
| 	Size    uint32 | ||||
| 	Members []Member | ||||
| 	Tags    []string | ||||
| } | ||||
|  | ||||
| func (u *Union) Format(fs fmt.State, verb rune) { | ||||
| @@ -208,6 +211,7 @@ func (u *Union) size() uint32 { return u.Size } | ||||
| func (u *Union) copy() Type { | ||||
| 	cpy := *u | ||||
| 	cpy.Members = copyMembers(u.Members) | ||||
| 	cpy.Tags = copyTags(cpy.Tags) | ||||
| 	return &cpy | ||||
| } | ||||
|  | ||||
| @@ -218,6 +222,18 @@ func (u *Union) members() []Member { | ||||
| func copyMembers(orig []Member) []Member { | ||||
| 	cpy := make([]Member, len(orig)) | ||||
| 	copy(cpy, orig) | ||||
| 	for i, member := range cpy { | ||||
| 		cpy[i].Tags = copyTags(member.Tags) | ||||
| 	} | ||||
| 	return cpy | ||||
| } | ||||
|  | ||||
| func copyTags(orig []string) []string { | ||||
| 	if orig == nil { // preserve nil vs zero-len slice distinction | ||||
| 		return nil | ||||
| 	} | ||||
| 	cpy := make([]string, len(orig)) | ||||
| 	copy(cpy, orig) | ||||
| 	return cpy | ||||
| } | ||||
|  | ||||
| @@ -247,6 +263,7 @@ type Member struct { | ||||
| 	Type         Type | ||||
| 	Offset       Bits | ||||
| 	BitfieldSize Bits | ||||
| 	Tags         []string | ||||
| } | ||||
|  | ||||
| // Enum lists possible values. | ||||
| @@ -334,6 +351,7 @@ func (f *Fwd) matches(typ Type) bool { | ||||
| type Typedef struct { | ||||
| 	Name string | ||||
| 	Type Type | ||||
| 	Tags []string | ||||
| } | ||||
|  | ||||
| func (td *Typedef) Format(fs fmt.State, verb rune) { | ||||
| @@ -344,6 +362,7 @@ func (td *Typedef) TypeName() string { return td.Name } | ||||
|  | ||||
| func (td *Typedef) copy() Type { | ||||
| 	cpy := *td | ||||
| 	cpy.Tags = copyTags(td.Tags) | ||||
| 	return &cpy | ||||
| } | ||||
|  | ||||
| @@ -403,6 +422,12 @@ type Func struct { | ||||
| 	Name    string | ||||
| 	Type    Type | ||||
| 	Linkage FuncLinkage | ||||
| 	Tags    []string | ||||
| 	// ParamTags holds a list of tags for each parameter of the FuncProto to which `Type` points. | ||||
| 	// If no tags are present for any param, the outer slice will be nil/len(ParamTags)==0. | ||||
| 	// If at least 1 param has a tag, the outer slice will have the same length as the number of params. | ||||
| 	// The inner slice contains the tags and may be nil/len(ParamTags[i])==0 if no tags are present for that param. | ||||
| 	ParamTags [][]string | ||||
| } | ||||
|  | ||||
| func FuncMetadata(ins *asm.Instruction) *Func { | ||||
| @@ -424,6 +449,14 @@ func (f *Func) TypeName() string { return f.Name } | ||||
|  | ||||
| func (f *Func) copy() Type { | ||||
| 	cpy := *f | ||||
| 	cpy.Tags = copyTags(f.Tags) | ||||
| 	if f.ParamTags != nil { // preserve nil vs zero-len slice distinction | ||||
| 		ptCopy := make([][]string, len(f.ParamTags)) | ||||
| 		for i, tags := range f.ParamTags { | ||||
| 			ptCopy[i] = copyTags(tags) | ||||
| 		} | ||||
| 		cpy.ParamTags = ptCopy | ||||
| 	} | ||||
| 	return &cpy | ||||
| } | ||||
|  | ||||
| @@ -456,6 +489,7 @@ type Var struct { | ||||
| 	Name    string | ||||
| 	Type    Type | ||||
| 	Linkage VarLinkage | ||||
| 	Tags    []string | ||||
| } | ||||
|  | ||||
| func (v *Var) Format(fs fmt.State, verb rune) { | ||||
| @@ -466,6 +500,7 @@ func (v *Var) TypeName() string { return v.Name } | ||||
|  | ||||
| func (v *Var) copy() Type { | ||||
| 	cpy := *v | ||||
| 	cpy.Tags = copyTags(v.Tags) | ||||
| 	return &cpy | ||||
| } | ||||
|  | ||||
| @@ -540,19 +575,25 @@ func (dt *declTag) copy() Type { | ||||
| 	return &cpy | ||||
| } | ||||
|  | ||||
| // typeTag associates metadata with a type. | ||||
| type typeTag struct { | ||||
| // TypeTag associates metadata with a pointer type. Tag types act as a custom | ||||
| // modifier(const, restrict, volatile) for the target type. Unlike declTags, | ||||
| // TypeTags are ordered so the order in which they are added matters. | ||||
| // | ||||
| // One of their uses is to mark pointers as `__kptr` meaning a pointer points | ||||
| // to kernel memory. Adding a `__kptr` to pointers in map values allows you | ||||
| // to store pointers to kernel memory in maps. | ||||
| type TypeTag struct { | ||||
| 	Type  Type | ||||
| 	Value string | ||||
| } | ||||
|  | ||||
| func (tt *typeTag) Format(fs fmt.State, verb rune) { | ||||
| func (tt *TypeTag) Format(fs fmt.State, verb rune) { | ||||
| 	formatType(fs, verb, tt, "type=", tt.Type, "value=", tt.Value) | ||||
| } | ||||
|  | ||||
| func (tt *typeTag) TypeName() string { return "" } | ||||
| func (tt *typeTag) qualify() Type    { return tt.Type } | ||||
| func (tt *typeTag) copy() Type { | ||||
| func (tt *TypeTag) TypeName() string { return "" } | ||||
| func (tt *TypeTag) qualify() Type    { return tt.Type } | ||||
| func (tt *TypeTag) copy() Type { | ||||
| 	cpy := *tt | ||||
| 	return &cpy | ||||
| } | ||||
| @@ -591,7 +632,7 @@ var ( | ||||
| 	_ qualifier = (*Const)(nil) | ||||
| 	_ qualifier = (*Restrict)(nil) | ||||
| 	_ qualifier = (*Volatile)(nil) | ||||
| 	_ qualifier = (*typeTag)(nil) | ||||
| 	_ qualifier = (*TypeTag)(nil) | ||||
| ) | ||||
|  | ||||
| var errUnsizedType = errors.New("type is unsized") | ||||
| @@ -918,7 +959,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("struct %s (id %d): %w", name, id, err) | ||||
| 			} | ||||
| 			typ = &Struct{name, header.Size(), members} | ||||
| 			typ = &Struct{name, header.Size(), members, nil} | ||||
|  | ||||
| 		case kindUnion: | ||||
| 			vlen := header.Vlen() | ||||
| @@ -935,7 +976,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("union %s (id %d): %w", name, id, err) | ||||
| 			} | ||||
| 			typ = &Union{name, header.Size(), members} | ||||
| 			typ = &Union{name, header.Size(), members, nil} | ||||
|  | ||||
| 		case kindEnum: | ||||
| 			vlen := header.Vlen() | ||||
| @@ -968,7 +1009,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt | ||||
| 			typ = &Fwd{name, header.FwdKind()} | ||||
|  | ||||
| 		case kindTypedef: | ||||
| 			typedef := &Typedef{name, nil} | ||||
| 			typedef := &Typedef{name, nil, nil} | ||||
| 			fixup(header.Type(), &typedef.Type) | ||||
| 			typ = typedef | ||||
|  | ||||
| @@ -988,7 +1029,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt | ||||
| 			typ = restrict | ||||
|  | ||||
| 		case kindFunc: | ||||
| 			fn := &Func{name, nil, header.Linkage()} | ||||
| 			fn := &Func{name, nil, header.Linkage(), nil, nil} | ||||
| 			fixup(header.Type(), &fn.Type) | ||||
| 			typ = fn | ||||
|  | ||||
| @@ -1030,7 +1071,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt | ||||
| 				return nil, fmt.Errorf("can't read btfVariable, id: %d: %w", id, err) | ||||
| 			} | ||||
|  | ||||
| 			v := &Var{name, nil, VarLinkage(bVariable.Linkage)} | ||||
| 			v := &Var{name, nil, VarLinkage(bVariable.Linkage), nil} | ||||
| 			fixup(header.Type(), &v.Type) | ||||
| 			typ = v | ||||
|  | ||||
| @@ -1081,7 +1122,7 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt | ||||
| 			declTags = append(declTags, dt) | ||||
|  | ||||
| 		case kindTypeTag: | ||||
| 			tt := &typeTag{nil, name} | ||||
| 			tt := &TypeTag{nil, name} | ||||
| 			fixup(header.Type(), &tt.Type) | ||||
| 			typ = tt | ||||
|  | ||||
| @@ -1142,26 +1183,69 @@ func readAndInflateTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32, rawSt | ||||
|  | ||||
| 	for _, dt := range declTags { | ||||
| 		switch t := dt.Type.(type) { | ||||
| 		case *Var, *Typedef: | ||||
| 		case *Var: | ||||
| 			if dt.Index != -1 { | ||||
| 				return nil, fmt.Errorf("type %s: index %d is not -1", dt, dt.Index) | ||||
| 				return nil, fmt.Errorf("type %s: component idx %d is not -1", dt, dt.Index) | ||||
| 			} | ||||
| 			t.Tags = append(t.Tags, dt.Value) | ||||
|  | ||||
| 		case *Typedef: | ||||
| 			if dt.Index != -1 { | ||||
| 				return nil, fmt.Errorf("type %s: component idx %d is not -1", dt, dt.Index) | ||||
| 			} | ||||
| 			t.Tags = append(t.Tags, dt.Value) | ||||
|  | ||||
| 		case composite: | ||||
| 			if dt.Index >= len(t.members()) { | ||||
| 				return nil, fmt.Errorf("type %s: index %d exceeds members of %s", dt, dt.Index, t) | ||||
| 			if dt.Index >= 0 { | ||||
| 				members := t.members() | ||||
| 				if dt.Index >= len(members) { | ||||
| 					return nil, fmt.Errorf("type %s: component idx %d exceeds members of %s", dt, dt.Index, t) | ||||
| 				} | ||||
|  | ||||
| 				members[dt.Index].Tags = append(members[dt.Index].Tags, dt.Value) | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if dt.Index == -1 { | ||||
| 				switch t2 := t.(type) { | ||||
| 				case *Struct: | ||||
| 					t2.Tags = append(t2.Tags, dt.Value) | ||||
| 				case *Union: | ||||
| 					t2.Tags = append(t2.Tags, dt.Value) | ||||
| 				} | ||||
|  | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			return nil, fmt.Errorf("type %s: decl tag for type %s has invalid component idx", dt, t) | ||||
|  | ||||
| 		case *Func: | ||||
| 			fp, ok := t.Type.(*FuncProto) | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("type %s: %s is not a FuncProto", dt, t.Type) | ||||
| 			} | ||||
|  | ||||
| 			if dt.Index >= len(fp.Params) { | ||||
| 				return nil, fmt.Errorf("type %s: index %d exceeds params of %s", dt, dt.Index, t) | ||||
| 			// Ensure the number of argument tag lists equals the number of arguments | ||||
| 			if len(t.ParamTags) == 0 { | ||||
| 				t.ParamTags = make([][]string, len(fp.Params)) | ||||
| 			} | ||||
|  | ||||
| 			if dt.Index >= 0 { | ||||
| 				if dt.Index >= len(fp.Params) { | ||||
| 					return nil, fmt.Errorf("type %s: component idx %d exceeds params of %s", dt, dt.Index, t) | ||||
| 				} | ||||
|  | ||||
| 				t.ParamTags[dt.Index] = append(t.ParamTags[dt.Index], dt.Value) | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if dt.Index == -1 { | ||||
| 				t.Tags = append(t.Tags, dt.Value) | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			return nil, fmt.Errorf("type %s: decl tag for type %s has invalid component idx", dt, t) | ||||
|  | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("type %s: decl tag for type %s is not supported", dt, t) | ||||
| 		} | ||||
| @@ -1207,6 +1291,20 @@ func UnderlyingType(typ Type) Type { | ||||
| 	return &cycle{typ} | ||||
| } | ||||
|  | ||||
| // QualifiedType returns the type with all qualifiers removed. | ||||
| func QualifiedType(typ Type) Type { | ||||
| 	result := typ | ||||
| 	for depth := 0; depth <= maxResolveDepth; depth++ { | ||||
| 		switch v := (result).(type) { | ||||
| 		case qualifier: | ||||
| 			result = v.qualify() | ||||
| 		default: | ||||
| 			return result | ||||
| 		} | ||||
| 	} | ||||
| 	return &cycle{typ} | ||||
| } | ||||
|  | ||||
| // As returns typ if is of type T. Otherwise it peels qualifiers and Typedefs | ||||
| // until it finds a T. | ||||
| // | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/cilium/ebpf/btf/workarounds.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/cilium/ebpf/btf/workarounds.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -12,7 +12,7 @@ func datasecResolveWorkaround(b *Builder, ds *Datasec) error { | ||||
| 		} | ||||
|  | ||||
| 		switch v.Type.(type) { | ||||
| 		case *Typedef, *Volatile, *Const, *Restrict, *typeTag: | ||||
| 		case *Typedef, *Volatile, *Const, *Restrict, *TypeTag: | ||||
| 			// NB: We must never call Add on a Datasec, otherwise we risk | ||||
| 			// infinite recursion. | ||||
| 			_, err := b.Add(v.Type) | ||||
|   | ||||
							
								
								
									
										261
									
								
								vendor/github.com/cilium/ebpf/collection.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										261
									
								
								vendor/github.com/cilium/ebpf/collection.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -10,8 +10,10 @@ import ( | ||||
| 	"github.com/cilium/ebpf/asm" | ||||
| 	"github.com/cilium/ebpf/btf" | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/kallsyms" | ||||
| 	"github.com/cilium/ebpf/internal/kconfig" | ||||
| 	"github.com/cilium/ebpf/internal/sysenc" | ||||
| 	"github.com/cilium/ebpf/internal/linux" | ||||
| 	"github.com/cilium/ebpf/internal/sys" | ||||
| ) | ||||
|  | ||||
| // CollectionOptions control loading a collection into the kernel. | ||||
| @@ -38,6 +40,11 @@ type CollectionSpec struct { | ||||
| 	Maps     map[string]*MapSpec | ||||
| 	Programs map[string]*ProgramSpec | ||||
|  | ||||
| 	// Variables refer to global variables declared in the ELF. They can be read | ||||
| 	// and modified freely before loading the Collection. Modifying them after | ||||
| 	// loading has no effect on a running eBPF program. | ||||
| 	Variables map[string]*VariableSpec | ||||
|  | ||||
| 	// Types holds type information about Maps and Programs. | ||||
| 	// Modifications to Types are currently undefined behaviour. | ||||
| 	Types *btf.Spec | ||||
| @@ -56,6 +63,7 @@ func (cs *CollectionSpec) Copy() *CollectionSpec { | ||||
| 	cpy := CollectionSpec{ | ||||
| 		Maps:      make(map[string]*MapSpec, len(cs.Maps)), | ||||
| 		Programs:  make(map[string]*ProgramSpec, len(cs.Programs)), | ||||
| 		Variables: make(map[string]*VariableSpec, len(cs.Variables)), | ||||
| 		ByteOrder: cs.ByteOrder, | ||||
| 		Types:     cs.Types.Copy(), | ||||
| 	} | ||||
| @@ -68,6 +76,10 @@ func (cs *CollectionSpec) Copy() *CollectionSpec { | ||||
| 		cpy.Programs[name] = spec.Copy() | ||||
| 	} | ||||
|  | ||||
| 	for name, spec := range cs.Variables { | ||||
| 		cpy.Variables[name] = spec.copy(&cpy) | ||||
| 	} | ||||
|  | ||||
| 	return &cpy | ||||
| } | ||||
|  | ||||
| @@ -134,65 +146,24 @@ func (m *MissingConstantsError) Error() string { | ||||
| // From Linux 5.5 the verifier will use constants to eliminate dead code. | ||||
| // | ||||
| // Returns an error wrapping [MissingConstantsError] if a constant doesn't exist. | ||||
| // | ||||
| // Deprecated: Use [CollectionSpec.Variables] to interact with constants instead. | ||||
| // RewriteConstants is now a wrapper around the VariableSpec API. | ||||
| func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error { | ||||
| 	replaced := make(map[string]bool) | ||||
|  | ||||
| 	for name, spec := range cs.Maps { | ||||
| 		if !strings.HasPrefix(name, ".rodata") { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		b, ds, err := spec.dataSection() | ||||
| 		if errors.Is(err, errMapNoBTFValue) { | ||||
| 			// Data sections without a BTF Datasec are valid, but don't support | ||||
| 			// constant replacements. | ||||
| 			continue | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("map %s: %w", name, err) | ||||
| 		} | ||||
|  | ||||
| 		// MapSpec.Copy() performs a shallow copy. Fully copy the byte slice | ||||
| 		// to avoid any changes affecting other copies of the MapSpec. | ||||
| 		cpy := make([]byte, len(b)) | ||||
| 		copy(cpy, b) | ||||
|  | ||||
| 		for _, v := range ds.Vars { | ||||
| 			vname := v.Type.TypeName() | ||||
| 			replacement, ok := consts[vname] | ||||
| 			if !ok { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if _, ok := v.Type.(*btf.Var); !ok { | ||||
| 				return fmt.Errorf("section %s: unexpected type %T for variable %s", name, v.Type, vname) | ||||
| 			} | ||||
|  | ||||
| 			if replaced[vname] { | ||||
| 				return fmt.Errorf("section %s: duplicate variable %s", name, vname) | ||||
| 			} | ||||
|  | ||||
| 			if int(v.Offset+v.Size) > len(cpy) { | ||||
| 				return fmt.Errorf("section %s: offset %d(+%d) for variable %s is out of bounds", name, v.Offset, v.Size, vname) | ||||
| 			} | ||||
|  | ||||
| 			b, err := sysenc.Marshal(replacement, int(v.Size)) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("marshaling constant replacement %s: %w", vname, err) | ||||
| 			} | ||||
|  | ||||
| 			b.CopyTo(cpy[v.Offset : v.Offset+v.Size]) | ||||
|  | ||||
| 			replaced[vname] = true | ||||
| 		} | ||||
|  | ||||
| 		spec.Contents[0] = MapKV{Key: uint32(0), Value: cpy} | ||||
| 	} | ||||
|  | ||||
| 	var missing []string | ||||
| 	for c := range consts { | ||||
| 		if !replaced[c] { | ||||
| 			missing = append(missing, c) | ||||
| 	for n, c := range consts { | ||||
| 		v, ok := cs.Variables[n] | ||||
| 		if !ok { | ||||
| 			missing = append(missing, n) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if !v.Constant() { | ||||
| 			return fmt.Errorf("variable %s is not a constant", n) | ||||
| 		} | ||||
|  | ||||
| 		if err := v.Set(c); err != nil { | ||||
| 			return fmt.Errorf("rewriting constant %s: %w", n, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -210,25 +181,23 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error | ||||
| // if this sounds useful. | ||||
| // | ||||
| // 'to' must be a pointer to a struct. A field of the | ||||
| // struct is updated with values from Programs or Maps if it | ||||
| // has an `ebpf` tag and its type is *ProgramSpec or *MapSpec. | ||||
| // struct is updated with values from Programs, Maps or Variables if it | ||||
| // has an `ebpf` tag and its type is *ProgramSpec, *MapSpec or *VariableSpec. | ||||
| // The tag's value specifies the name of the program or map as | ||||
| // found in the CollectionSpec. | ||||
| // | ||||
| //	struct { | ||||
| //	    Foo     *ebpf.ProgramSpec `ebpf:"xdp_foo"` | ||||
| //	    Bar     *ebpf.MapSpec     `ebpf:"bar_map"` | ||||
| //	    Foo     *ebpf.ProgramSpec  `ebpf:"xdp_foo"` | ||||
| //	    Bar     *ebpf.MapSpec      `ebpf:"bar_map"` | ||||
| //	    Var     *ebpf.VariableSpec `ebpf:"some_var"` | ||||
| //	    Ignored int | ||||
| //	} | ||||
| // | ||||
| // Returns an error if any of the eBPF objects can't be found, or | ||||
| // if the same MapSpec or ProgramSpec is assigned multiple times. | ||||
| // if the same Spec is assigned multiple times. | ||||
| func (cs *CollectionSpec) Assign(to interface{}) error { | ||||
| 	// Assign() only supports assigning ProgramSpecs and MapSpecs, | ||||
| 	// so doesn't load any resources into the kernel. | ||||
| 	getValue := func(typ reflect.Type, name string) (interface{}, error) { | ||||
| 		switch typ { | ||||
|  | ||||
| 		case reflect.TypeOf((*ProgramSpec)(nil)): | ||||
| 			if p := cs.Programs[name]; p != nil { | ||||
| 				return p, nil | ||||
| @@ -241,6 +210,12 @@ func (cs *CollectionSpec) Assign(to interface{}) error { | ||||
| 			} | ||||
| 			return nil, fmt.Errorf("missing map %q", name) | ||||
|  | ||||
| 		case reflect.TypeOf((*VariableSpec)(nil)): | ||||
| 			if v := cs.Variables[name]; v != nil { | ||||
| 				return v, nil | ||||
| 			} | ||||
| 			return nil, fmt.Errorf("missing variable %q", name) | ||||
|  | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("unsupported type %s", typ) | ||||
| 		} | ||||
| @@ -286,6 +261,7 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) | ||||
| 	// Support assigning Programs and Maps, lazy-loading the required objects. | ||||
| 	assignedMaps := make(map[string]bool) | ||||
| 	assignedProgs := make(map[string]bool) | ||||
| 	assignedVars := make(map[string]bool) | ||||
|  | ||||
| 	getValue := func(typ reflect.Type, name string) (interface{}, error) { | ||||
| 		switch typ { | ||||
| @@ -298,6 +274,10 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) | ||||
| 			assignedMaps[name] = true | ||||
| 			return loader.loadMap(name) | ||||
|  | ||||
| 		case reflect.TypeOf((*Variable)(nil)): | ||||
| 			assignedVars[name] = true | ||||
| 			return loader.loadVariable(name) | ||||
|  | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("unsupported type %s", typ) | ||||
| 		} | ||||
| @@ -338,15 +318,22 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) | ||||
| 	for p := range assignedProgs { | ||||
| 		delete(loader.programs, p) | ||||
| 	} | ||||
| 	for p := range assignedVars { | ||||
| 		delete(loader.vars, p) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Collection is a collection of Programs and Maps associated | ||||
| // with their symbols | ||||
| // Collection is a collection of live BPF resources present in the kernel. | ||||
| type Collection struct { | ||||
| 	Programs map[string]*Program | ||||
| 	Maps     map[string]*Map | ||||
|  | ||||
| 	// Variables contains global variables used by the Collection's program(s). On | ||||
| 	// kernels older than 5.5, most interactions with Variables return | ||||
| 	// [ErrNotSupported]. | ||||
| 	Variables map[string]*Variable | ||||
| } | ||||
|  | ||||
| // NewCollection creates a Collection from the given spec, creating and | ||||
| @@ -387,19 +374,26 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for varName := range spec.Variables { | ||||
| 		if _, err := loader.loadVariable(varName); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Maps can contain Program and Map stubs, so populate them after | ||||
| 	// all Maps and Programs have been successfully loaded. | ||||
| 	if err := loader.populateDeferredMaps(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// Prevent loader.cleanup from closing maps and programs. | ||||
| 	maps, progs := loader.maps, loader.programs | ||||
| 	loader.maps, loader.programs = nil, nil | ||||
| 	// Prevent loader.cleanup from closing maps, programs and vars. | ||||
| 	maps, progs, vars := loader.maps, loader.programs, loader.vars | ||||
| 	loader.maps, loader.programs, loader.vars = nil, nil, nil | ||||
|  | ||||
| 	return &Collection{ | ||||
| 		progs, | ||||
| 		maps, | ||||
| 		vars, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| @@ -408,6 +402,7 @@ type collectionLoader struct { | ||||
| 	opts     *CollectionOptions | ||||
| 	maps     map[string]*Map | ||||
| 	programs map[string]*Program | ||||
| 	vars     map[string]*Variable | ||||
| } | ||||
|  | ||||
| func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) (*collectionLoader, error) { | ||||
| @@ -427,14 +422,58 @@ func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) (*collec | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err := populateKallsyms(coll.Programs); err != nil { | ||||
| 		return nil, fmt.Errorf("populating kallsyms caches: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return &collectionLoader{ | ||||
| 		coll, | ||||
| 		opts, | ||||
| 		make(map[string]*Map), | ||||
| 		make(map[string]*Program), | ||||
| 		make(map[string]*Variable), | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // populateKallsyms populates kallsyms caches, making lookups cheaper later on | ||||
| // during individual program loading. Since we have less context available | ||||
| // at those stages, we batch the lookups here instead to avoid redundant work. | ||||
| func populateKallsyms(progs map[string]*ProgramSpec) error { | ||||
| 	// Look up associated kernel modules for all symbols referenced by | ||||
| 	// ProgramSpec.AttachTo for program types that support attaching to kmods. | ||||
| 	mods := make(map[string]string) | ||||
| 	for _, p := range progs { | ||||
| 		if p.AttachTo != "" && p.targetsKernelModule() { | ||||
| 			mods[p.AttachTo] = "" | ||||
| 		} | ||||
| 	} | ||||
| 	if len(mods) != 0 { | ||||
| 		if err := kallsyms.AssignModules(mods); err != nil { | ||||
| 			return fmt.Errorf("getting modules from kallsyms: %w", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Look up addresses of all kernel symbols referenced by all programs. | ||||
| 	addrs := make(map[string]uint64) | ||||
| 	for _, p := range progs { | ||||
| 		iter := p.Instructions.Iterate() | ||||
| 		for iter.Next() { | ||||
| 			ins := iter.Ins | ||||
| 			meta, _ := ins.Metadata.Get(ksymMetaKey{}).(*ksymMeta) | ||||
| 			if meta != nil { | ||||
| 				addrs[meta.Name] = 0 | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if len(addrs) != 0 { | ||||
| 		if err := kallsyms.AssignAddresses(addrs); err != nil { | ||||
| 			return fmt.Errorf("getting addresses from kallsyms: %w", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // close all resources left over in the collectionLoader. | ||||
| func (cl *collectionLoader) close() { | ||||
| 	for _, m := range cl.maps { | ||||
| @@ -466,6 +505,13 @@ func (cl *collectionLoader) loadMap(mapName string) (*Map, error) { | ||||
| 		return m, nil | ||||
| 	} | ||||
|  | ||||
| 	// Defer setting the mmapable flag on maps until load time. This avoids the | ||||
| 	// MapSpec having different flags on some kernel versions. Also avoid running | ||||
| 	// syscalls during ELF loading, so platforms like wasm can also parse an ELF. | ||||
| 	if isDataSection(mapSpec.Name) && haveMmapableMaps() == nil { | ||||
| 		mapSpec.Flags |= sys.BPF_F_MMAPABLE | ||||
| 	} | ||||
|  | ||||
| 	m, err := newMapWithOptions(mapSpec, cl.opts.Maps) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("map %s: %w", mapName, err) | ||||
| @@ -537,6 +583,58 @@ func (cl *collectionLoader) loadProgram(progName string) (*Program, error) { | ||||
| 	return prog, nil | ||||
| } | ||||
|  | ||||
| func (cl *collectionLoader) loadVariable(varName string) (*Variable, error) { | ||||
| 	if v := cl.vars[varName]; v != nil { | ||||
| 		return v, nil | ||||
| 	} | ||||
|  | ||||
| 	varSpec := cl.coll.Variables[varName] | ||||
| 	if varSpec == nil { | ||||
| 		return nil, fmt.Errorf("unknown variable %s", varName) | ||||
| 	} | ||||
|  | ||||
| 	// Get the key of the VariableSpec's MapSpec in the CollectionSpec. | ||||
| 	var mapName string | ||||
| 	for n, ms := range cl.coll.Maps { | ||||
| 		if ms == varSpec.m { | ||||
| 			mapName = n | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	if mapName == "" { | ||||
| 		return nil, fmt.Errorf("variable %s: underlying MapSpec %s was removed from CollectionSpec", varName, varSpec.m.Name) | ||||
| 	} | ||||
|  | ||||
| 	m, err := cl.loadMap(mapName) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("variable %s: %w", varName, err) | ||||
| 	} | ||||
|  | ||||
| 	// If the kernel is too old or the underlying map was created without | ||||
| 	// BPF_F_MMAPABLE, [Map.Memory] will return ErrNotSupported. In this case, | ||||
| 	// emit a Variable with a nil Memory. This keeps Collection{Spec}.Variables | ||||
| 	// consistent across systems with different feature sets without breaking | ||||
| 	// LoadAndAssign. | ||||
| 	mm, err := m.Memory() | ||||
| 	if err != nil && !errors.Is(err, ErrNotSupported) { | ||||
| 		return nil, fmt.Errorf("variable %s: getting memory for map %s: %w", varName, mapName, err) | ||||
| 	} | ||||
|  | ||||
| 	v, err := newVariable( | ||||
| 		varSpec.name, | ||||
| 		varSpec.offset, | ||||
| 		varSpec.size, | ||||
| 		varSpec.t, | ||||
| 		mm, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("variable %s: %w", varName, err) | ||||
| 	} | ||||
|  | ||||
| 	cl.vars[varName] = v | ||||
| 	return v, nil | ||||
| } | ||||
|  | ||||
| // populateDeferredMaps iterates maps holding programs or other maps and loads | ||||
| // any dependencies. Populates all maps in cl and freezes them if specified. | ||||
| func (cl *collectionLoader) populateDeferredMaps() error { | ||||
| @@ -603,6 +701,7 @@ func resolveKconfig(m *MapSpec) error { | ||||
|  | ||||
| 	type configInfo struct { | ||||
| 		offset uint32 | ||||
| 		size   uint32 | ||||
| 		typ    btf.Type | ||||
| 	} | ||||
|  | ||||
| @@ -619,7 +718,7 @@ func resolveKconfig(m *MapSpec) error { | ||||
| 				return fmt.Errorf("variable %s must be a 32 bits integer, got %s", n, v.Type) | ||||
| 			} | ||||
|  | ||||
| 			kv, err := internal.KernelVersion() | ||||
| 			kv, err := linux.KernelVersion() | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("getting kernel version: %w", err) | ||||
| 			} | ||||
| @@ -644,6 +743,7 @@ func resolveKconfig(m *MapSpec) error { | ||||
| 		default: // Catch CONFIG_*. | ||||
| 			configs[n] = configInfo{ | ||||
| 				offset: vsi.Offset, | ||||
| 				size:   vsi.Size, | ||||
| 				typ:    v.Type, | ||||
| 			} | ||||
| 		} | ||||
| @@ -651,7 +751,7 @@ func resolveKconfig(m *MapSpec) error { | ||||
|  | ||||
| 	// We only parse kconfig file if a CONFIG_* variable was found. | ||||
| 	if len(configs) > 0 { | ||||
| 		f, err := kconfig.Find() | ||||
| 		f, err := linux.FindKConfig() | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("cannot find a kconfig file: %w", err) | ||||
| 		} | ||||
| @@ -670,10 +770,10 @@ func resolveKconfig(m *MapSpec) error { | ||||
| 		for n, info := range configs { | ||||
| 			value, ok := kernelConfig[n] | ||||
| 			if !ok { | ||||
| 				return fmt.Errorf("config option %q does not exists for this kernel", n) | ||||
| 				return fmt.Errorf("config option %q does not exist on this kernel", n) | ||||
| 			} | ||||
|  | ||||
| 			err := kconfig.PutValue(data[info.offset:], info.typ, value) | ||||
| 			err := kconfig.PutValue(data[info.offset:info.offset+info.size], info.typ, value) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("problem adding value for %s: %w", n, err) | ||||
| 			} | ||||
| @@ -723,6 +823,7 @@ func LoadCollection(file string) (*Collection, error) { | ||||
| func (coll *Collection) Assign(to interface{}) error { | ||||
| 	assignedMaps := make(map[string]bool) | ||||
| 	assignedProgs := make(map[string]bool) | ||||
| 	assignedVars := make(map[string]bool) | ||||
|  | ||||
| 	// Assign() only transfers already-loaded Maps and Programs. No extra | ||||
| 	// loading is done. | ||||
| @@ -743,6 +844,13 @@ func (coll *Collection) Assign(to interface{}) error { | ||||
| 			} | ||||
| 			return nil, fmt.Errorf("missing map %q", name) | ||||
|  | ||||
| 		case reflect.TypeOf((*Variable)(nil)): | ||||
| 			if v := coll.Variables[name]; v != nil { | ||||
| 				assignedVars[name] = true | ||||
| 				return v, nil | ||||
| 			} | ||||
| 			return nil, fmt.Errorf("missing variable %q", name) | ||||
|  | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("unsupported type %s", typ) | ||||
| 		} | ||||
| @@ -759,6 +867,9 @@ func (coll *Collection) Assign(to interface{}) error { | ||||
| 	for m := range assignedMaps { | ||||
| 		delete(coll.Maps, m) | ||||
| 	} | ||||
| 	for s := range assignedVars { | ||||
| 		delete(coll.Variables, s) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
							
								
								
									
										172
									
								
								vendor/github.com/cilium/ebpf/elf_reader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										172
									
								
								vendor/github.com/cilium/ebpf/elf_reader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -16,7 +16,6 @@ import ( | ||||
| 	"github.com/cilium/ebpf/btf" | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/sys" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
|  | ||||
| type kconfigMetaKey struct{} | ||||
| @@ -33,6 +32,13 @@ type kfuncMeta struct { | ||||
| 	Func    *btf.Func | ||||
| } | ||||
|  | ||||
| type ksymMetaKey struct{} | ||||
|  | ||||
| type ksymMeta struct { | ||||
| 	Binding elf.SymBind | ||||
| 	Name    string | ||||
| } | ||||
|  | ||||
| // elfCode is a convenience to reduce the amount of arguments that have to | ||||
| // be passed around explicitly. You should treat its contents as immutable. | ||||
| type elfCode struct { | ||||
| @@ -43,7 +49,9 @@ type elfCode struct { | ||||
| 	btf      *btf.Spec | ||||
| 	extInfo  *btf.ExtInfos | ||||
| 	maps     map[string]*MapSpec | ||||
| 	vars     map[string]*VariableSpec | ||||
| 	kfuncs   map[string]*btf.Func | ||||
| 	ksyms    map[string]struct{} | ||||
| 	kconfig  *MapSpec | ||||
| } | ||||
|  | ||||
| @@ -71,7 +79,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { | ||||
|  | ||||
| 	// Checks if the ELF file is for BPF data. | ||||
| 	// Old LLVM versions set e_machine to EM_NONE. | ||||
| 	if f.File.Machine != unix.EM_NONE && f.File.Machine != elf.EM_BPF { | ||||
| 	if f.File.Machine != elf.EM_NONE && f.File.Machine != elf.EM_BPF { | ||||
| 		return nil, fmt.Errorf("unexpected machine type for BPF ELF: %s", f.File.Machine) | ||||
| 	} | ||||
|  | ||||
| @@ -101,7 +109,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { | ||||
| 			sections[idx] = newElfSection(sec, mapSection) | ||||
| 		case sec.Name == ".maps": | ||||
| 			sections[idx] = newElfSection(sec, btfMapSection) | ||||
| 		case sec.Name == ".bss" || sec.Name == ".data" || strings.HasPrefix(sec.Name, ".rodata"): | ||||
| 		case isDataSection(sec.Name): | ||||
| 			sections[idx] = newElfSection(sec, dataSection) | ||||
| 		case sec.Type == elf.SHT_REL: | ||||
| 			// Store relocations under the section index of the target | ||||
| @@ -134,7 +142,9 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { | ||||
| 		btf:         btfSpec, | ||||
| 		extInfo:     btfExtInfo, | ||||
| 		maps:        make(map[string]*MapSpec), | ||||
| 		vars:        make(map[string]*VariableSpec), | ||||
| 		kfuncs:      make(map[string]*btf.Func), | ||||
| 		ksyms:       make(map[string]struct{}), | ||||
| 	} | ||||
|  | ||||
| 	symbols, err := f.Symbols() | ||||
| @@ -174,7 +184,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { | ||||
| 		return nil, fmt.Errorf("load programs: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return &CollectionSpec{ec.maps, progs, btfSpec, ec.ByteOrder}, nil | ||||
| 	return &CollectionSpec{ec.maps, progs, ec.vars, btfSpec, ec.ByteOrder}, nil | ||||
| } | ||||
|  | ||||
| func loadLicense(sec *elf.Section) (string, error) { | ||||
| @@ -201,6 +211,18 @@ func loadVersion(sec *elf.Section, bo binary.ByteOrder) (uint32, error) { | ||||
| 	return version, nil | ||||
| } | ||||
|  | ||||
| func isDataSection(name string) bool { | ||||
| 	return name == ".bss" || strings.HasPrefix(name, ".data") || strings.HasPrefix(name, ".rodata") | ||||
| } | ||||
|  | ||||
| func isConstantDataSection(name string) bool { | ||||
| 	return strings.HasPrefix(name, ".rodata") | ||||
| } | ||||
|  | ||||
| func isKconfigSection(name string) bool { | ||||
| 	return name == ".kconfig" | ||||
| } | ||||
|  | ||||
| type elfSectionKind int | ||||
|  | ||||
| const ( | ||||
| @@ -506,7 +528,7 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err | ||||
|  | ||||
| 		case elf.STT_OBJECT: | ||||
| 			// LLVM 9 emits OBJECT-LOCAL symbols for anonymous constants. | ||||
| 			if bind != elf.STB_GLOBAL && bind != elf.STB_LOCAL { | ||||
| 			if bind != elf.STB_GLOBAL && bind != elf.STB_LOCAL && bind != elf.STB_WEAK { | ||||
| 				return fmt.Errorf("direct load: %s: %w: %s", name, errUnsupportedBinding, bind) | ||||
| 			} | ||||
|  | ||||
| @@ -614,6 +636,8 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err | ||||
| 		} | ||||
|  | ||||
| 		kf := ec.kfuncs[name] | ||||
| 		_, ks := ec.ksyms[name] | ||||
|  | ||||
| 		switch { | ||||
| 		// If a Call / DWordLoad instruction is found and the datasec has a btf.Func with a Name | ||||
| 		// that matches the symbol name we mark the instruction as a referencing a kfunc. | ||||
| @@ -634,6 +658,15 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err | ||||
|  | ||||
| 			ins.Constant = 0 | ||||
|  | ||||
| 		case ks && ins.OpCode.IsDWordLoad(): | ||||
| 			if bind != elf.STB_GLOBAL && bind != elf.STB_WEAK { | ||||
| 				return fmt.Errorf("asm relocation: %s: %w: %s", name, errUnsupportedBinding, bind) | ||||
| 			} | ||||
| 			ins.Metadata.Set(ksymMetaKey{}, &ksymMeta{ | ||||
| 				Binding: bind, | ||||
| 				Name:    name, | ||||
| 			}) | ||||
|  | ||||
| 		// If no kconfig map is found, this must be a symbol reference from inline | ||||
| 		// asm (see testdata/loader.c:asm_relocation()) or a call to a forward | ||||
| 		// function declaration (see testdata/fwd_decl.c). Don't interfere, These | ||||
| @@ -980,6 +1013,13 @@ func mapSpecFromBTF(es *elfSection, vs *btf.VarSecinfo, def *btf.Struct, spec *b | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Some maps don't support value sizes, but annotating their map definitions | ||||
| 	// with __type macros can still be useful, especially to let bpf2go generate | ||||
| 	// type definitions for them. | ||||
| 	if value != nil && !mapType.canHaveValueSize() { | ||||
| 		valueSize = 0 | ||||
| 	} | ||||
|  | ||||
| 	return &MapSpec{ | ||||
| 		Name:       SanitizeName(name, -1), | ||||
| 		Type:       MapType(mapType), | ||||
| @@ -1092,12 +1132,21 @@ func (ec *elfCode) loadDataSections() error { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if sec.references == 0 { | ||||
| 			// Prune data sections which are not referenced by any | ||||
| 			// instructions. | ||||
| 		// If a section has no references, it will be freed as soon as the | ||||
| 		// Collection closes, so creating and populating it is wasteful. If it has | ||||
| 		// no symbols, it is likely an ephemeral section used during compilation | ||||
| 		// that wasn't sanitized by the bpf linker. (like .rodata.str1.1) | ||||
| 		// | ||||
| 		// No symbols means no VariableSpecs can be generated from it, making it | ||||
| 		// pointless to emit a data section for. | ||||
| 		if sec.references == 0 && len(sec.symbols) == 0 { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if sec.Size > math.MaxUint32 { | ||||
| 			return fmt.Errorf("data section %s: contents exceed maximum size", sec.Name) | ||||
| 		} | ||||
|  | ||||
| 		mapSpec := &MapSpec{ | ||||
| 			Name:       SanitizeName(sec.Name, -1), | ||||
| 			Type:       Array, | ||||
| @@ -1106,6 +1155,10 @@ func (ec *elfCode) loadDataSections() error { | ||||
| 			MaxEntries: 1, | ||||
| 		} | ||||
|  | ||||
| 		if isConstantDataSection(sec.Name) { | ||||
| 			mapSpec.Flags = sys.BPF_F_RDONLY_PROG | ||||
| 		} | ||||
|  | ||||
| 		switch sec.Type { | ||||
| 		// Only open the section if we know there's actual data to be read. | ||||
| 		case elf.SHT_PROGBITS: | ||||
| @@ -1113,20 +1166,56 @@ func (ec *elfCode) loadDataSections() error { | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("data section %s: can't get contents: %w", sec.Name, err) | ||||
| 			} | ||||
|  | ||||
| 			if uint64(len(data)) > math.MaxUint32 { | ||||
| 				return fmt.Errorf("data section %s: contents exceed maximum size", sec.Name) | ||||
| 			} | ||||
| 			mapSpec.Contents = []MapKV{{uint32(0), data}} | ||||
|  | ||||
| 		case elf.SHT_NOBITS: | ||||
| 			// NOBITS sections like .bss contain only zeroes, and since data sections | ||||
| 			// are Arrays, the kernel already preallocates them. Skip reading zeroes | ||||
| 			// from the ELF. | ||||
| 			// NOBITS sections like .bss contain only zeroes and are not allocated in | ||||
| 			// the ELF. Since data sections are Arrays, the kernel can preallocate | ||||
| 			// them. Don't attempt reading zeroes from the ELF, instead allocate the | ||||
| 			// zeroed memory to support getting and setting VariableSpecs for sections | ||||
| 			// like .bss. | ||||
| 			mapSpec.Contents = []MapKV{{uint32(0), make([]byte, sec.Size)}} | ||||
|  | ||||
| 		default: | ||||
| 			return fmt.Errorf("data section %s: unknown section type %s", sec.Name, sec.Type) | ||||
| 		} | ||||
|  | ||||
| 		for off, sym := range sec.symbols { | ||||
| 			// Skip symbols marked with the 'hidden' attribute. | ||||
| 			if elf.ST_VISIBILITY(sym.Other) == elf.STV_HIDDEN || | ||||
| 				elf.ST_VISIBILITY(sym.Other) == elf.STV_INTERNAL { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			// Only accept symbols with global or weak bindings. The common | ||||
| 			// alternative is STB_LOCAL, which are either function-scoped or declared | ||||
| 			// 'static'. | ||||
| 			if elf.ST_BIND(sym.Info) != elf.STB_GLOBAL && | ||||
| 				elf.ST_BIND(sym.Info) != elf.STB_WEAK { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if ec.vars[sym.Name] != nil { | ||||
| 				return fmt.Errorf("data section %s: duplicate variable %s", sec.Name, sym.Name) | ||||
| 			} | ||||
|  | ||||
| 			// Skip symbols starting with a dot, they are compiler-internal symbols | ||||
| 			// emitted by clang 11 and earlier and are not cleaned up by the bpf | ||||
| 			// compiler backend (e.g. symbols named .Lconstinit.1 in sections like | ||||
| 			// .rodata.cst32). Variables in C cannot start with a dot, so filter these | ||||
| 			// out. | ||||
| 			if strings.HasPrefix(sym.Name, ".") { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			ec.vars[sym.Name] = &VariableSpec{ | ||||
| 				name:   sym.Name, | ||||
| 				offset: off, | ||||
| 				size:   sym.Size, | ||||
| 				m:      mapSpec, | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// It is possible for a data section to exist without a corresponding BTF Datasec | ||||
| 		// if it only contains anonymous values like macro-defined arrays. | ||||
| 		if ec.btf != nil { | ||||
| @@ -1135,12 +1224,38 @@ func (ec *elfCode) loadDataSections() error { | ||||
| 				// Assign the spec's key and BTF only if the Datasec lookup was successful. | ||||
| 				mapSpec.Key = &btf.Void{} | ||||
| 				mapSpec.Value = ds | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if strings.HasPrefix(sec.Name, ".rodata") { | ||||
| 			mapSpec.Flags = unix.BPF_F_RDONLY_PROG | ||||
| 			mapSpec.Freeze = true | ||||
| 				// Populate VariableSpecs with type information, if available. | ||||
| 				for _, v := range ds.Vars { | ||||
| 					name := v.Type.TypeName() | ||||
| 					if name == "" { | ||||
| 						return fmt.Errorf("data section %s: anonymous variable %v", sec.Name, v) | ||||
| 					} | ||||
|  | ||||
| 					vt, ok := v.Type.(*btf.Var) | ||||
| 					if !ok { | ||||
| 						return fmt.Errorf("data section %s: unexpected type %T for variable %s", sec.Name, v.Type, name) | ||||
| 					} | ||||
|  | ||||
| 					ev := ec.vars[name] | ||||
| 					if ev == nil { | ||||
| 						// Hidden symbols appear in the BTF Datasec but don't receive a VariableSpec. | ||||
| 						continue | ||||
| 					} | ||||
|  | ||||
| 					if uint64(v.Offset) != ev.offset { | ||||
| 						return fmt.Errorf("data section %s: variable %s datasec offset (%d) doesn't match ELF symbol offset (%d)", sec.Name, name, v.Offset, ev.offset) | ||||
| 					} | ||||
|  | ||||
| 					if uint64(v.Size) != ev.size { | ||||
| 						return fmt.Errorf("data section %s: variable %s size in datasec (%d) doesn't match ELF symbol size (%d)", sec.Name, name, v.Size, ev.size) | ||||
| 					} | ||||
|  | ||||
| 					// Decouple the Var in the VariableSpec from the underlying DataSec in | ||||
| 					// the MapSpec to avoid modifications from affecting map loads later on. | ||||
| 					ev.t = btf.Copy(vt).(*btf.Var) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		ec.maps[sec.Name] = mapSpec | ||||
| @@ -1175,8 +1290,7 @@ func (ec *elfCode) loadKconfigSection() error { | ||||
| 		KeySize:    uint32(4), | ||||
| 		ValueSize:  ds.Size, | ||||
| 		MaxEntries: 1, | ||||
| 		Flags:      unix.BPF_F_RDONLY_PROG, | ||||
| 		Freeze:     true, | ||||
| 		Flags:      sys.BPF_F_RDONLY_PROG, | ||||
| 		Key:        &btf.Int{Size: 4}, | ||||
| 		Value:      ds, | ||||
| 	} | ||||
| @@ -1201,8 +1315,14 @@ func (ec *elfCode) loadKsymsSection() error { | ||||
| 	} | ||||
|  | ||||
| 	for _, v := range ds.Vars { | ||||
| 		// we have already checked the .ksyms Datasec to only contain Func Vars. | ||||
| 		ec.kfuncs[v.Type.TypeName()] = v.Type.(*btf.Func) | ||||
| 		switch t := v.Type.(type) { | ||||
| 		case *btf.Func: | ||||
| 			ec.kfuncs[t.TypeName()] = t | ||||
| 		case *btf.Var: | ||||
| 			ec.ksyms[t.TypeName()] = struct{}{} | ||||
| 		default: | ||||
| 			return fmt.Errorf("unexpected variable type in .ksyms: %T", v) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| @@ -1266,10 +1386,10 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) { | ||||
|  | ||||
| 		var flags uint32 | ||||
| 		if t.flags&_SEC_SLEEPABLE > 0 { | ||||
| 			flags |= unix.BPF_F_SLEEPABLE | ||||
| 			flags |= sys.BPF_F_SLEEPABLE | ||||
| 		} | ||||
| 		if t.flags&_SEC_XDP_FRAGS > 0 { | ||||
| 			flags |= unix.BPF_F_XDP_HAS_FRAGS | ||||
| 			flags |= sys.BPF_F_XDP_HAS_FRAGS | ||||
| 		} | ||||
| 		if t.flags&_SEC_EXP_ATTACH_OPT > 0 { | ||||
| 			if programType == XDP { | ||||
|   | ||||
							
								
								
									
										370
									
								
								vendor/github.com/cilium/ebpf/info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										370
									
								
								vendor/github.com/cilium/ebpf/info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -8,10 +8,10 @@ import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/asm" | ||||
| 	"github.com/cilium/ebpf/btf" | ||||
| @@ -39,53 +39,83 @@ import ( | ||||
|  | ||||
| // MapInfo describes a map. | ||||
| type MapInfo struct { | ||||
| 	Type       MapType | ||||
| 	id         MapID | ||||
| 	KeySize    uint32 | ||||
| 	ValueSize  uint32 | ||||
| 	// Type of the map. | ||||
| 	Type MapType | ||||
| 	// KeySize is the size of the map key in bytes. | ||||
| 	KeySize uint32 | ||||
| 	// ValueSize is the size of the map value in bytes. | ||||
| 	ValueSize uint32 | ||||
| 	// MaxEntries is the maximum number of entries the map can hold. Its meaning | ||||
| 	// is map-specific. | ||||
| 	MaxEntries uint32 | ||||
| 	Flags      uint32 | ||||
| 	// Flags used during map creation. | ||||
| 	Flags uint32 | ||||
| 	// Name as supplied by user space at load time. Available from 4.15. | ||||
| 	Name string | ||||
|  | ||||
| 	btf btf.ID | ||||
| 	id       MapID | ||||
| 	btf      btf.ID | ||||
| 	mapExtra uint64 | ||||
| 	memlock  uint64 | ||||
| 	frozen   bool | ||||
| } | ||||
|  | ||||
| // newMapInfoFromFd queries map information about the given fd. [sys.ObjInfo] is | ||||
| // attempted first, supplementing any missing values with information from | ||||
| // /proc/self/fdinfo. Ignores EINVAL from ObjInfo as well as ErrNotSupported | ||||
| // from reading fdinfo (indicating the file exists, but no fields of interest | ||||
| // were found). If both fail, an error is always returned. | ||||
| func newMapInfoFromFd(fd *sys.FD) (*MapInfo, error) { | ||||
| 	var info sys.MapInfo | ||||
| 	err := sys.ObjInfo(fd, &info) | ||||
| 	if errors.Is(err, syscall.EINVAL) { | ||||
| 		return newMapInfoFromProc(fd) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	err1 := sys.ObjInfo(fd, &info) | ||||
| 	// EINVAL means the kernel doesn't support BPF_OBJ_GET_INFO_BY_FD. Continue | ||||
| 	// with fdinfo if that's the case. | ||||
| 	if err1 != nil && !errors.Is(err1, unix.EINVAL) { | ||||
| 		return nil, fmt.Errorf("getting object info: %w", err1) | ||||
| 	} | ||||
|  | ||||
| 	return &MapInfo{ | ||||
| 	mi := &MapInfo{ | ||||
| 		MapType(info.Type), | ||||
| 		MapID(info.Id), | ||||
| 		info.KeySize, | ||||
| 		info.ValueSize, | ||||
| 		info.MaxEntries, | ||||
| 		uint32(info.MapFlags), | ||||
| 		unix.ByteSliceToString(info.Name[:]), | ||||
| 		MapID(info.Id), | ||||
| 		btf.ID(info.BtfId), | ||||
| 	}, nil | ||||
| 		info.MapExtra, | ||||
| 		0, | ||||
| 		false, | ||||
| 	} | ||||
|  | ||||
| 	// Supplement OBJ_INFO with data from /proc/self/fdinfo. It contains fields | ||||
| 	// like memlock and frozen that are not present in OBJ_INFO. | ||||
| 	err2 := readMapInfoFromProc(fd, mi) | ||||
| 	if err2 != nil && !errors.Is(err2, ErrNotSupported) { | ||||
| 		return nil, fmt.Errorf("getting map info from fdinfo: %w", err2) | ||||
| 	} | ||||
|  | ||||
| 	if err1 != nil && err2 != nil { | ||||
| 		return nil, fmt.Errorf("ObjInfo and fdinfo both failed: objinfo: %w, fdinfo: %w", err1, err2) | ||||
| 	} | ||||
|  | ||||
| 	return mi, nil | ||||
| } | ||||
|  | ||||
| func newMapInfoFromProc(fd *sys.FD) (*MapInfo, error) { | ||||
| 	var mi MapInfo | ||||
| 	err := scanFdInfo(fd, map[string]interface{}{ | ||||
| // readMapInfoFromProc queries map information about the given fd from | ||||
| // /proc/self/fdinfo. It only writes data into fields that have a zero value. | ||||
| func readMapInfoFromProc(fd *sys.FD, mi *MapInfo) error { | ||||
| 	return scanFdInfo(fd, map[string]interface{}{ | ||||
| 		"map_type":    &mi.Type, | ||||
| 		"map_id":      &mi.id, | ||||
| 		"key_size":    &mi.KeySize, | ||||
| 		"value_size":  &mi.ValueSize, | ||||
| 		"max_entries": &mi.MaxEntries, | ||||
| 		"map_flags":   &mi.Flags, | ||||
| 		"map_extra":   &mi.mapExtra, | ||||
| 		"memlock":     &mi.memlock, | ||||
| 		"frozen":      &mi.frozen, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &mi, nil | ||||
| } | ||||
|  | ||||
| // ID returns the map ID. | ||||
| @@ -109,6 +139,35 @@ func (mi *MapInfo) BTFID() (btf.ID, bool) { | ||||
| 	return mi.btf, mi.btf > 0 | ||||
| } | ||||
|  | ||||
| // MapExtra returns an opaque field whose meaning is map-specific. | ||||
| // | ||||
| // Available from 5.16. | ||||
| // | ||||
| // The bool return value indicates whether this optional field is available and | ||||
| // populated, if it was specified during Map creation. | ||||
| func (mi *MapInfo) MapExtra() (uint64, bool) { | ||||
| 	return mi.mapExtra, mi.mapExtra > 0 | ||||
| } | ||||
|  | ||||
| // Memlock returns an approximate number of bytes allocated to this map. | ||||
| // | ||||
| // Available from 4.10. | ||||
| // | ||||
| // The bool return value indicates whether this optional field is available. | ||||
| func (mi *MapInfo) Memlock() (uint64, bool) { | ||||
| 	return mi.memlock, mi.memlock > 0 | ||||
| } | ||||
|  | ||||
| // Frozen indicates whether [Map.Freeze] was called on this map. If true, | ||||
| // modifications from user space are not allowed. | ||||
| // | ||||
| // Available from 5.2. Requires access to procfs. | ||||
| // | ||||
| // If the kernel doesn't support map freezing, this field will always be false. | ||||
| func (mi *MapInfo) Frozen() bool { | ||||
| 	return mi.frozen | ||||
| } | ||||
|  | ||||
| // programStats holds statistics of a program. | ||||
| type programStats struct { | ||||
| 	// Total accumulated runtime of the program ins ns. | ||||
| @@ -120,6 +179,40 @@ type programStats struct { | ||||
| 	recursionMisses uint64 | ||||
| } | ||||
|  | ||||
| // programJitedInfo holds information about JITed info of a program. | ||||
| type programJitedInfo struct { | ||||
| 	// ksyms holds the ksym addresses of the BPF program, including those of its | ||||
| 	// subprograms. | ||||
| 	// | ||||
| 	// Available from 4.18. | ||||
| 	ksyms    []uintptr | ||||
| 	numKsyms uint32 | ||||
|  | ||||
| 	// insns holds the JITed machine native instructions of the program, | ||||
| 	// including those of its subprograms. | ||||
| 	// | ||||
| 	// Available from 4.13. | ||||
| 	insns    []byte | ||||
| 	numInsns uint32 | ||||
|  | ||||
| 	// lineInfos holds the JITed line infos, which are kernel addresses. | ||||
| 	// | ||||
| 	// Available from 5.0. | ||||
| 	lineInfos    []uint64 | ||||
| 	numLineInfos uint32 | ||||
|  | ||||
| 	// lineInfoRecSize is the size of a single line info record. | ||||
| 	// | ||||
| 	// Available from 5.0. | ||||
| 	lineInfoRecSize uint32 | ||||
|  | ||||
| 	// funcLens holds the insns length of each function. | ||||
| 	// | ||||
| 	// Available from 4.18. | ||||
| 	funcLens    []uint32 | ||||
| 	numFuncLens uint32 | ||||
| } | ||||
|  | ||||
| // ProgramInfo describes a program. | ||||
| type ProgramInfo struct { | ||||
| 	Type ProgramType | ||||
| @@ -133,9 +226,14 @@ type ProgramInfo struct { | ||||
| 	haveCreatedByUID bool | ||||
| 	btf              btf.ID | ||||
| 	stats            *programStats | ||||
| 	loadTime         time.Duration | ||||
|  | ||||
| 	maps  []MapID | ||||
| 	insns []byte | ||||
| 	maps                 []MapID | ||||
| 	insns                []byte | ||||
| 	jitedSize            uint32 | ||||
| 	verifiedInstructions uint32 | ||||
|  | ||||
| 	jitedInfo programJitedInfo | ||||
|  | ||||
| 	lineInfos    []byte | ||||
| 	numLineInfos uint32 | ||||
| @@ -164,6 +262,9 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) { | ||||
| 			runCount:        info.RunCnt, | ||||
| 			recursionMisses: info.RecursionMisses, | ||||
| 		}, | ||||
| 		jitedSize:            info.JitedProgLen, | ||||
| 		loadTime:             time.Duration(info.LoadTime), | ||||
| 		verifiedInstructions: info.VerifiedInsns, | ||||
| 	} | ||||
|  | ||||
| 	// Start with a clean struct for the second call, otherwise we may get EFAULT. | ||||
| @@ -174,7 +275,7 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) { | ||||
| 	if info.NrMapIds > 0 { | ||||
| 		pi.maps = make([]MapID, info.NrMapIds) | ||||
| 		info2.NrMapIds = info.NrMapIds | ||||
| 		info2.MapIds = sys.NewPointer(unsafe.Pointer(&pi.maps[0])) | ||||
| 		info2.MapIds = sys.NewSlicePointer(pi.maps) | ||||
| 		makeSecondCall = true | ||||
| 	} else if haveProgramInfoMapIDs() == nil { | ||||
| 		// This program really has no associated maps. | ||||
| @@ -215,6 +316,40 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) { | ||||
| 		makeSecondCall = true | ||||
| 	} | ||||
|  | ||||
| 	pi.jitedInfo.lineInfoRecSize = info.JitedLineInfoRecSize | ||||
| 	if info.JitedProgLen > 0 { | ||||
| 		pi.jitedInfo.numInsns = info.JitedProgLen | ||||
| 		pi.jitedInfo.insns = make([]byte, info.JitedProgLen) | ||||
| 		info2.JitedProgLen = info.JitedProgLen | ||||
| 		info2.JitedProgInsns = sys.NewSlicePointer(pi.jitedInfo.insns) | ||||
| 		makeSecondCall = true | ||||
| 	} | ||||
|  | ||||
| 	if info.NrJitedFuncLens > 0 { | ||||
| 		pi.jitedInfo.numFuncLens = info.NrJitedFuncLens | ||||
| 		pi.jitedInfo.funcLens = make([]uint32, info.NrJitedFuncLens) | ||||
| 		info2.NrJitedFuncLens = info.NrJitedFuncLens | ||||
| 		info2.JitedFuncLens = sys.NewSlicePointer(pi.jitedInfo.funcLens) | ||||
| 		makeSecondCall = true | ||||
| 	} | ||||
|  | ||||
| 	if info.NrJitedLineInfo > 0 { | ||||
| 		pi.jitedInfo.numLineInfos = info.NrJitedLineInfo | ||||
| 		pi.jitedInfo.lineInfos = make([]uint64, info.NrJitedLineInfo) | ||||
| 		info2.NrJitedLineInfo = info.NrJitedLineInfo | ||||
| 		info2.JitedLineInfo = sys.NewSlicePointer(pi.jitedInfo.lineInfos) | ||||
| 		info2.JitedLineInfoRecSize = info.JitedLineInfoRecSize | ||||
| 		makeSecondCall = true | ||||
| 	} | ||||
|  | ||||
| 	if info.NrJitedKsyms > 0 { | ||||
| 		pi.jitedInfo.numKsyms = info.NrJitedKsyms | ||||
| 		pi.jitedInfo.ksyms = make([]uintptr, info.NrJitedKsyms) | ||||
| 		info2.JitedKsyms = sys.NewSlicePointer(pi.jitedInfo.ksyms) | ||||
| 		info2.NrJitedKsyms = info.NrJitedKsyms | ||||
| 		makeSecondCall = true | ||||
| 	} | ||||
|  | ||||
| 	if makeSecondCall { | ||||
| 		if err := sys.ObjInfo(fd, &info2); err != nil { | ||||
| 			return nil, err | ||||
| @@ -230,7 +365,7 @@ func newProgramInfoFromProc(fd *sys.FD) (*ProgramInfo, error) { | ||||
| 		"prog_type": &info.Type, | ||||
| 		"prog_tag":  &info.Tag, | ||||
| 	}) | ||||
| 	if errors.Is(err, errMissingFields) { | ||||
| 	if errors.Is(err, ErrNotSupported) { | ||||
| 		return nil, &internal.UnsupportedFeatureError{ | ||||
| 			Name:           "reading program info from /proc/self/fdinfo", | ||||
| 			MinimumVersion: internal.Version{4, 10, 0}, | ||||
| @@ -305,6 +440,52 @@ func (pi *ProgramInfo) RecursionMisses() (uint64, bool) { | ||||
| 	return 0, false | ||||
| } | ||||
|  | ||||
| // btfSpec returns the BTF spec associated with the program. | ||||
| func (pi *ProgramInfo) btfSpec() (*btf.Spec, error) { | ||||
| 	id, ok := pi.BTFID() | ||||
| 	if !ok { | ||||
| 		return nil, fmt.Errorf("program created without BTF or unsupported kernel: %w", ErrNotSupported) | ||||
| 	} | ||||
|  | ||||
| 	h, err := btf.NewHandleFromID(id) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("get BTF handle: %w", err) | ||||
| 	} | ||||
| 	defer h.Close() | ||||
|  | ||||
| 	spec, err := h.Spec(nil) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("get BTF spec: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return spec, nil | ||||
| } | ||||
|  | ||||
| // LineInfos returns the BTF line information of the program. | ||||
| // | ||||
| // Available from 5.0. | ||||
| // | ||||
| // Requires CAP_SYS_ADMIN or equivalent for reading BTF information. Returns | ||||
| // ErrNotSupported if the program was created without BTF or if the kernel | ||||
| // doesn't support the field. | ||||
| func (pi *ProgramInfo) LineInfos() (btf.LineOffsets, error) { | ||||
| 	if len(pi.lineInfos) == 0 { | ||||
| 		return nil, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported) | ||||
| 	} | ||||
|  | ||||
| 	spec, err := pi.btfSpec() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return btf.LoadLineInfos( | ||||
| 		bytes.NewReader(pi.lineInfos), | ||||
| 		internal.NativeEndian, | ||||
| 		pi.numLineInfos, | ||||
| 		spec, | ||||
| 	) | ||||
| } | ||||
|  | ||||
| // Instructions returns the 'xlated' instruction stream of the program | ||||
| // after it has been verified and rewritten by the kernel. These instructions | ||||
| // cannot be loaded back into the kernel as-is, this is mainly used for | ||||
| @@ -391,6 +572,29 @@ func (pi *ProgramInfo) Instructions() (asm.Instructions, error) { | ||||
| 	return insns, nil | ||||
| } | ||||
|  | ||||
| // JitedSize returns the size of the program's JIT-compiled machine code in bytes, which is the | ||||
| // actual code executed on the host's CPU. This field requires the BPF JIT compiler to be enabled. | ||||
| // | ||||
| // Available from 4.13. Reading this metadata requires CAP_BPF or equivalent. | ||||
| func (pi *ProgramInfo) JitedSize() (uint32, error) { | ||||
| 	if pi.jitedSize == 0 { | ||||
| 		return 0, fmt.Errorf("insufficient permissions, unsupported kernel, or JIT compiler disabled: %w", ErrNotSupported) | ||||
| 	} | ||||
| 	return pi.jitedSize, nil | ||||
| } | ||||
|  | ||||
| // TranslatedSize returns the size of the program's translated instructions in bytes, after it has | ||||
| // been verified and rewritten by the kernel. | ||||
| // | ||||
| // Available from 4.13. Reading this metadata requires CAP_BPF or equivalent. | ||||
| func (pi *ProgramInfo) TranslatedSize() (int, error) { | ||||
| 	insns := len(pi.insns) | ||||
| 	if insns == 0 { | ||||
| 		return 0, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported) | ||||
| 	} | ||||
| 	return insns, nil | ||||
| } | ||||
|  | ||||
| // MapIDs returns the maps related to the program. | ||||
| // | ||||
| // Available from 4.15. | ||||
| @@ -400,6 +604,89 @@ func (pi *ProgramInfo) MapIDs() ([]MapID, bool) { | ||||
| 	return pi.maps, pi.maps != nil | ||||
| } | ||||
|  | ||||
| // LoadTime returns when the program was loaded since boot time. | ||||
| // | ||||
| // Available from 4.15. | ||||
| // | ||||
| // The bool return value indicates whether this optional field is available. | ||||
| func (pi *ProgramInfo) LoadTime() (time.Duration, bool) { | ||||
| 	// loadTime and NrMapIds were introduced in the same kernel version. | ||||
| 	return pi.loadTime, pi.loadTime > 0 | ||||
| } | ||||
|  | ||||
| // VerifiedInstructions returns the number verified instructions in the program. | ||||
| // | ||||
| // Available from 5.16. | ||||
| // | ||||
| // The bool return value indicates whether this optional field is available. | ||||
| func (pi *ProgramInfo) VerifiedInstructions() (uint32, bool) { | ||||
| 	return pi.verifiedInstructions, pi.verifiedInstructions > 0 | ||||
| } | ||||
|  | ||||
| // JitedKsymAddrs returns the ksym addresses of the BPF program, including its | ||||
| // subprograms. The addresses correspond to their symbols in /proc/kallsyms. | ||||
| // | ||||
| // Available from 4.18. Note that before 5.x, this field can be empty for | ||||
| // programs without subprograms (bpf2bpf calls). | ||||
| // | ||||
| // The bool return value indicates whether this optional field is available. | ||||
| func (pi *ProgramInfo) JitedKsymAddrs() ([]uintptr, bool) { | ||||
| 	return pi.jitedInfo.ksyms, len(pi.jitedInfo.ksyms) > 0 | ||||
| } | ||||
|  | ||||
| // JitedInsns returns the JITed machine native instructions of the program. | ||||
| // | ||||
| // Available from 4.13. | ||||
| // | ||||
| // The bool return value indicates whether this optional field is available. | ||||
| func (pi *ProgramInfo) JitedInsns() ([]byte, bool) { | ||||
| 	return pi.jitedInfo.insns, len(pi.jitedInfo.insns) > 0 | ||||
| } | ||||
|  | ||||
| // JitedLineInfos returns the JITed line infos of the program. | ||||
| // | ||||
| // Available from 5.0. | ||||
| // | ||||
| // The bool return value indicates whether this optional field is available. | ||||
| func (pi *ProgramInfo) JitedLineInfos() ([]uint64, bool) { | ||||
| 	return pi.jitedInfo.lineInfos, len(pi.jitedInfo.lineInfos) > 0 | ||||
| } | ||||
|  | ||||
| // JitedFuncLens returns the insns length of each function in the JITed program. | ||||
| // | ||||
| // Available from 4.18. | ||||
| // | ||||
| // The bool return value indicates whether this optional field is available. | ||||
| func (pi *ProgramInfo) JitedFuncLens() ([]uint32, bool) { | ||||
| 	return pi.jitedInfo.funcLens, len(pi.jitedInfo.funcLens) > 0 | ||||
| } | ||||
|  | ||||
| // FuncInfos returns the offset and function information of all (sub)programs in | ||||
| // a BPF program. | ||||
| // | ||||
| // Available from 5.0. | ||||
| // | ||||
| // Requires CAP_SYS_ADMIN or equivalent for reading BTF information. Returns | ||||
| // ErrNotSupported if the program was created without BTF or if the kernel | ||||
| // doesn't support the field. | ||||
| func (pi *ProgramInfo) FuncInfos() (btf.FuncOffsets, error) { | ||||
| 	if len(pi.funcInfos) == 0 { | ||||
| 		return nil, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported) | ||||
| 	} | ||||
|  | ||||
| 	spec, err := pi.btfSpec() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return btf.LoadFuncInfos( | ||||
| 		bytes.NewReader(pi.funcInfos), | ||||
| 		internal.NativeEndian, | ||||
| 		pi.numFuncInfos, | ||||
| 		spec, | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func scanFdInfo(fd *sys.FD, fields map[string]interface{}) error { | ||||
| 	fh, err := os.Open(fmt.Sprintf("/proc/self/fdinfo/%d", fd.Int())) | ||||
| 	if err != nil { | ||||
| @@ -413,8 +700,6 @@ func scanFdInfo(fd *sys.FD, fields map[string]interface{}) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| var errMissingFields = errors.New("missing fields") | ||||
|  | ||||
| func scanFdInfoReader(r io.Reader, fields map[string]interface{}) error { | ||||
| 	var ( | ||||
| 		scanner = bufio.NewScanner(r) | ||||
| @@ -433,26 +718,37 @@ func scanFdInfoReader(r io.Reader, fields map[string]interface{}) error { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if n, err := fmt.Sscanln(parts[1], field); err != nil || n != 1 { | ||||
| 			return fmt.Errorf("can't parse field %s: %v", name, err) | ||||
| 		// If field already contains a non-zero value, don't overwrite it with fdinfo. | ||||
| 		if zero(field) { | ||||
| 			if n, err := fmt.Sscanln(parts[1], field); err != nil || n != 1 { | ||||
| 				return fmt.Errorf("can't parse field %s: %v", name, err) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		scanned++ | ||||
| 	} | ||||
|  | ||||
| 	if err := scanner.Err(); err != nil { | ||||
| 		return err | ||||
| 		return fmt.Errorf("scanning fdinfo: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	if len(fields) > 0 && scanned == 0 { | ||||
| 		return ErrNotSupported | ||||
| 	} | ||||
|  | ||||
| 	if scanned != len(fields) { | ||||
| 		return errMissingFields | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func zero(arg any) bool { | ||||
| 	v := reflect.ValueOf(arg) | ||||
|  | ||||
| 	// Unwrap pointers and interfaces. | ||||
| 	for v.Kind() == reflect.Pointer || | ||||
| 		v.Kind() == reflect.Interface { | ||||
| 		v = v.Elem() | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| 	return v.IsZero() | ||||
| } | ||||
|  | ||||
| // EnableStats starts the measuring of the runtime | ||||
| @@ -471,7 +767,7 @@ func EnableStats(which uint32) (io.Closer, error) { | ||||
| 	return fd, nil | ||||
| } | ||||
|  | ||||
| var haveProgramInfoMapIDs = internal.NewFeatureTest("map IDs in program info", "4.15", func() error { | ||||
| var haveProgramInfoMapIDs = internal.NewFeatureTest("map IDs in program info", func() error { | ||||
| 	prog, err := progLoad(asm.Instructions{ | ||||
| 		asm.LoadImm(asm.R0, 0, asm.DWord), | ||||
| 		asm.Return(), | ||||
| @@ -496,4 +792,4 @@ var haveProgramInfoMapIDs = internal.NewFeatureTest("map IDs in program info", " | ||||
| 	} | ||||
|  | ||||
| 	return err | ||||
| }) | ||||
| }, "4.15") | ||||
|   | ||||
							
								
								
									
										6
									
								
								vendor/github.com/cilium/ebpf/internal/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/cilium/ebpf/internal/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -23,7 +23,7 @@ func ErrorWithLog(source string, err error, log []byte) *VerifierError { | ||||
|  | ||||
| 	log = bytes.Trim(log, whitespace) | ||||
| 	if len(log) == 0 { | ||||
| 		return &VerifierError{source, err, nil, false} | ||||
| 		return &VerifierError{source, err, nil} | ||||
| 	} | ||||
|  | ||||
| 	logLines := bytes.Split(log, []byte{'\n'}) | ||||
| @@ -34,7 +34,7 @@ func ErrorWithLog(source string, err error, log []byte) *VerifierError { | ||||
| 		lines = append(lines, string(bytes.TrimRight(line, whitespace))) | ||||
| 	} | ||||
|  | ||||
| 	return &VerifierError{source, err, lines, false} | ||||
| 	return &VerifierError{source, err, lines} | ||||
| } | ||||
|  | ||||
| // VerifierError includes information from the eBPF verifier. | ||||
| @@ -46,8 +46,6 @@ type VerifierError struct { | ||||
| 	Cause error | ||||
| 	// The verifier output split into lines. | ||||
| 	Log []string | ||||
| 	// Deprecated: the log is never truncated anymore. | ||||
| 	Truncated bool | ||||
| } | ||||
|  | ||||
| func (le *VerifierError) Unwrap() error { | ||||
|   | ||||
							
								
								
									
										55
									
								
								vendor/github.com/cilium/ebpf/internal/feature.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										55
									
								
								vendor/github.com/cilium/ebpf/internal/feature.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -3,15 +3,25 @@ package internal | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| // ErrNotSupported indicates that a feature is not supported by the current kernel. | ||||
| // ErrNotSupported indicates that a feature is not supported. | ||||
| var ErrNotSupported = errors.New("not supported") | ||||
|  | ||||
| // ErrNotSupportedOnOS indicates that a feature is not supported on the current | ||||
| // operating system. | ||||
| var ErrNotSupportedOnOS = fmt.Errorf("%w on %s", ErrNotSupported, runtime.GOOS) | ||||
|  | ||||
| // UnsupportedFeatureError is returned by FeatureTest() functions. | ||||
| type UnsupportedFeatureError struct { | ||||
| 	// The minimum Linux mainline version required for this feature. | ||||
| 	// The minimum version required for this feature. | ||||
| 	// | ||||
| 	// On Linux this refers to the mainline kernel version, on other platforms | ||||
| 	// to the version of the runtime. | ||||
| 	// | ||||
| 	// Used for the error string, and for sanity checking during testing. | ||||
| 	MinimumVersion Version | ||||
|  | ||||
| @@ -58,11 +68,44 @@ type FeatureTest struct { | ||||
| type FeatureTestFn func() error | ||||
|  | ||||
| // NewFeatureTest is a convenient way to create a single [FeatureTest]. | ||||
| func NewFeatureTest(name, version string, fn FeatureTestFn) func() error { | ||||
| // | ||||
| // versions specifies in which version of a BPF runtime a feature appeared. | ||||
| // The format is "GOOS:Major.Minor[.Patch]". GOOS may be omitted when targeting | ||||
| // Linux. Returns [ErrNotSupportedOnOS] if there is no version specified for the | ||||
| // current OS. | ||||
| func NewFeatureTest(name string, fn FeatureTestFn, versions ...string) func() error { | ||||
| 	const nativePrefix = runtime.GOOS + ":" | ||||
|  | ||||
| 	if len(versions) == 0 { | ||||
| 		return func() error { | ||||
| 			return fmt.Errorf("feature test %q: no versions specified", name) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	ft := &FeatureTest{ | ||||
| 		Name:    name, | ||||
| 		Version: version, | ||||
| 		Fn:      fn, | ||||
| 		Name: name, | ||||
| 		Fn:   fn, | ||||
| 	} | ||||
|  | ||||
| 	for _, version := range versions { | ||||
| 		if strings.HasPrefix(version, nativePrefix) { | ||||
| 			ft.Version = strings.TrimPrefix(version, nativePrefix) | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		if runtime.GOOS == "linux" && !strings.ContainsRune(version, ':') { | ||||
| 			// Allow version numbers without a GOOS prefix on Linux. | ||||
| 			ft.Version = version | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if ft.Version == "" { | ||||
| 		return func() error { | ||||
| 			// We don't return an UnsupportedFeatureError here, since that will | ||||
| 			// trigger version checks which don't make sense. | ||||
| 			return fmt.Errorf("%s: %w", name, ErrNotSupportedOnOS) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return ft.execute | ||||
|   | ||||
							
								
								
									
										20
									
								
								vendor/github.com/cilium/ebpf/internal/kallsyms/cache.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/cilium/ebpf/internal/kallsyms/cache.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| package kallsyms | ||||
|  | ||||
| import "sync" | ||||
|  | ||||
| type cache[K, V comparable] struct { | ||||
| 	m sync.Map | ||||
| } | ||||
|  | ||||
| func (c *cache[K, V]) Load(key K) (value V, _ bool) { | ||||
| 	v, ok := c.m.Load(key) | ||||
| 	if !ok { | ||||
| 		return value, false | ||||
| 	} | ||||
| 	value = v.(V) | ||||
| 	return value, true | ||||
| } | ||||
|  | ||||
| func (c *cache[K, V]) Store(key K, value V) { | ||||
| 	c.m.Store(key, value) | ||||
| } | ||||
							
								
								
									
										297
									
								
								vendor/github.com/cilium/ebpf/internal/kallsyms/kallsyms.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										297
									
								
								vendor/github.com/cilium/ebpf/internal/kallsyms/kallsyms.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,74 +1,277 @@ | ||||
| package kallsyms | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"sync" | ||||
| 	"slices" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| var kernelModules struct { | ||||
| 	sync.RWMutex | ||||
| 	// function to kernel module mapping | ||||
| 	kmods map[string]string | ||||
| } | ||||
| var errAmbiguousKsym = errors.New("multiple kernel symbols with the same name") | ||||
|  | ||||
| // KernelModule returns the kernel module, if any, a probe-able function is contained in. | ||||
| func KernelModule(fn string) (string, error) { | ||||
| 	kernelModules.RLock() | ||||
| 	kmods := kernelModules.kmods | ||||
| 	kernelModules.RUnlock() | ||||
| var symAddrs cache[string, uint64] | ||||
| var symModules cache[string, string] | ||||
|  | ||||
| 	if kmods == nil { | ||||
| 		kernelModules.Lock() | ||||
| 		defer kernelModules.Unlock() | ||||
| 		kmods = kernelModules.kmods | ||||
| // Module returns the kernel module providing the given symbol in the kernel, if | ||||
| // any. Returns an empty string and no error if the symbol is not present in the | ||||
| // kernel. Only function symbols are considered. Returns an error if multiple | ||||
| // symbols with the same name were found. | ||||
| // | ||||
| // Consider [AssignModules] if you need to resolve multiple symbols, as it will | ||||
| // only perform one iteration over /proc/kallsyms. | ||||
| func Module(name string) (string, error) { | ||||
| 	if name == "" { | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	if kmods != nil { | ||||
| 		return kmods[fn], nil | ||||
| 	if mod, ok := symModules.Load(name); ok { | ||||
| 		return mod, nil | ||||
| 	} | ||||
|  | ||||
| 	request := map[string]string{name: ""} | ||||
| 	if err := AssignModules(request); err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return request[name], nil | ||||
| } | ||||
|  | ||||
| // AssignModules looks up the kernel module providing each given symbol, if any, | ||||
| // and assigns them to their corresponding values in the symbols map. Only | ||||
| // function symbols are considered. Results of all lookups are cached, | ||||
| // successful or otherwise. | ||||
| // | ||||
| // Any symbols missing in the kernel are ignored. Returns an error if multiple | ||||
| // symbols with a given name were found. | ||||
| func AssignModules(symbols map[string]string) error { | ||||
| 	if len(symbols) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// Attempt to fetch symbols from cache. | ||||
| 	request := make(map[string]string) | ||||
| 	for name := range symbols { | ||||
| 		if mod, ok := symModules.Load(name); ok { | ||||
| 			symbols[name] = mod | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// Mark the symbol to be read from /proc/kallsyms. | ||||
| 		request[name] = "" | ||||
| 	} | ||||
| 	if len(request) == 0 { | ||||
| 		// All symbols satisfied from cache. | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	f, err := os.Open("/proc/kallsyms") | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 		return err | ||||
| 	} | ||||
| 	defer f.Close() | ||||
| 	kmods, err = loadKernelModuleMapping(f) | ||||
|  | ||||
| 	if err := assignModules(f, request); err != nil { | ||||
| 		return fmt.Errorf("assigning symbol modules: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Update the cache with the new symbols. Cache all requested symbols, even if | ||||
| 	// they're missing or don't belong to a module. | ||||
| 	for name, mod := range request { | ||||
| 		symModules.Store(name, mod) | ||||
| 		symbols[name] = mod | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // assignModules assigns kernel symbol modules read from f to values requested | ||||
| // by symbols. Always scans the whole input to make sure the user didn't request | ||||
| // an ambiguous symbol. | ||||
| func assignModules(f io.Reader, symbols map[string]string) error { | ||||
| 	if len(symbols) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	found := make(map[string]struct{}) | ||||
| 	r := newReader(f) | ||||
| 	for r.Line() { | ||||
| 		// Only look for function symbols in the kernel's text section (tT). | ||||
| 		s, err, skip := parseSymbol(r, []rune{'t', 'T'}) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("parsing kallsyms line: %w", err) | ||||
| 		} | ||||
| 		if skip { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if _, requested := symbols[s.name]; !requested { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if _, ok := found[s.name]; ok { | ||||
| 			// We've already seen this symbol. Return an error to avoid silently | ||||
| 			// attaching to a symbol in the wrong module. libbpf also rejects | ||||
| 			// referring to ambiguous symbols. | ||||
| 			// | ||||
| 			// We can't simply check if we already have a value for the given symbol, | ||||
| 			// since many won't have an associated kernel module. | ||||
| 			return fmt.Errorf("symbol %s: duplicate found at address 0x%x (module %q): %w", | ||||
| 				s.name, s.addr, s.mod, errAmbiguousKsym) | ||||
| 		} | ||||
|  | ||||
| 		symbols[s.name] = s.mod | ||||
| 		found[s.name] = struct{}{} | ||||
| 	} | ||||
| 	if err := r.Err(); err != nil { | ||||
| 		return fmt.Errorf("reading kallsyms: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Address returns the address of the given symbol in the kernel. Returns 0 and | ||||
| // no error if the symbol is not present. Returns an error if multiple addresses | ||||
| // were found for a symbol. | ||||
| // | ||||
| // Consider [AssignAddresses] if you need to resolve multiple symbols, as it | ||||
| // will only perform one iteration over /proc/kallsyms. | ||||
| func Address(symbol string) (uint64, error) { | ||||
| 	if symbol == "" { | ||||
| 		return 0, nil | ||||
| 	} | ||||
|  | ||||
| 	if addr, ok := symAddrs.Load(symbol); ok { | ||||
| 		return addr, nil | ||||
| 	} | ||||
|  | ||||
| 	request := map[string]uint64{symbol: 0} | ||||
| 	if err := AssignAddresses(request); err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|  | ||||
| 	return request[symbol], nil | ||||
| } | ||||
|  | ||||
| // AssignAddresses looks up the addresses of the requested symbols in the kernel | ||||
| // and assigns them to their corresponding values in the symbols map. Results | ||||
| // of all lookups are cached, successful or otherwise. | ||||
| // | ||||
| // Any symbols missing in the kernel are ignored. Returns an error if multiple | ||||
| // addresses were found for a symbol. | ||||
| func AssignAddresses(symbols map[string]uint64) error { | ||||
| 	if len(symbols) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// Attempt to fetch symbols from cache. | ||||
| 	request := make(map[string]uint64) | ||||
| 	for name := range symbols { | ||||
| 		if addr, ok := symAddrs.Load(name); ok { | ||||
| 			symbols[name] = addr | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// Mark the symbol to be read from /proc/kallsyms. | ||||
| 		request[name] = 0 | ||||
| 	} | ||||
| 	if len(request) == 0 { | ||||
| 		// All symbols satisfied from cache. | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	f, err := os.Open("/proc/kallsyms") | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	kernelModules.kmods = kmods | ||||
| 	return kmods[fn], nil | ||||
| 	if err := assignAddresses(f, request); err != nil { | ||||
| 		return fmt.Errorf("loading symbol addresses: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Update the cache with the new symbols. Cache all requested symbols even if | ||||
| 	// they weren't found, to avoid repeated lookups. | ||||
| 	for name, addr := range request { | ||||
| 		symAddrs.Store(name, addr) | ||||
| 		symbols[name] = addr | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // FlushKernelModuleCache removes any cached information about function to kernel module mapping. | ||||
| func FlushKernelModuleCache() { | ||||
| 	kernelModules.Lock() | ||||
| 	defer kernelModules.Unlock() | ||||
|  | ||||
| 	kernelModules.kmods = nil | ||||
| } | ||||
|  | ||||
| func loadKernelModuleMapping(f io.Reader) (map[string]string, error) { | ||||
| 	mods := make(map[string]string) | ||||
| 	scanner := bufio.NewScanner(f) | ||||
| 	for scanner.Scan() { | ||||
| 		fields := bytes.Fields(scanner.Bytes()) | ||||
| 		if len(fields) < 4 { | ||||
| // assignAddresses assigns kernel symbol addresses read from f to values | ||||
| // requested by symbols. Always scans the whole input to make sure the user | ||||
| // didn't request an ambiguous symbol. | ||||
| func assignAddresses(f io.Reader, symbols map[string]uint64) error { | ||||
| 	if len(symbols) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	r := newReader(f) | ||||
| 	for r.Line() { | ||||
| 		s, err, skip := parseSymbol(r, nil) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("parsing kallsyms line: %w", err) | ||||
| 		} | ||||
| 		if skip { | ||||
| 			continue | ||||
| 		} | ||||
| 		switch string(fields[1]) { | ||||
| 		case "t", "T": | ||||
| 			mods[string(fields[2])] = string(bytes.Trim(fields[3], "[]")) | ||||
|  | ||||
| 		existing, requested := symbols[s.name] | ||||
| 		if existing != 0 { | ||||
| 			// Multiple addresses for a symbol have been found. Return a friendly | ||||
| 			// error to avoid silently attaching to the wrong symbol. libbpf also | ||||
| 			// rejects referring to ambiguous symbols. | ||||
| 			return fmt.Errorf("symbol %s(0x%x): duplicate found at address 0x%x: %w", s.name, existing, s.addr, errAmbiguousKsym) | ||||
| 		} | ||||
| 		if requested { | ||||
| 			symbols[s.name] = s.addr | ||||
| 		} | ||||
| 	} | ||||
| 	if err := r.Err(); err != nil { | ||||
| 		return fmt.Errorf("reading kallsyms: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type ksym struct { | ||||
| 	addr uint64 | ||||
| 	name string | ||||
| 	mod  string | ||||
| } | ||||
|  | ||||
| // parseSymbol parses a line from /proc/kallsyms into an address, type, name and | ||||
| // module. Skip will be true if the symbol doesn't match any of the given symbol | ||||
| // types. See `man 1 nm` for all available types. | ||||
| // | ||||
| // Example line: `ffffffffc1682010 T nf_nat_init  [nf_nat]` | ||||
| func parseSymbol(r *reader, types []rune) (s ksym, err error, skip bool) { | ||||
| 	for i := 0; r.Word(); i++ { | ||||
| 		switch i { | ||||
| 		// Address of the symbol. | ||||
| 		case 0: | ||||
| 			s.addr, err = strconv.ParseUint(r.Text(), 16, 64) | ||||
| 			if err != nil { | ||||
| 				return s, fmt.Errorf("parsing address: %w", err), false | ||||
| 			} | ||||
| 		// Type of the symbol. Assume the character is ASCII-encoded by converting | ||||
| 		// it directly to a rune, since it's a fixed field controlled by the kernel. | ||||
| 		case 1: | ||||
| 			if len(types) > 0 && !slices.Contains(types, rune(r.Bytes()[0])) { | ||||
| 				return s, nil, true | ||||
| 			} | ||||
| 		// Name of the symbol. | ||||
| 		case 2: | ||||
| 			s.name = r.Text() | ||||
| 		// Kernel module the symbol is provided by. | ||||
| 		case 3: | ||||
| 			s.mod = strings.Trim(r.Text(), "[]") | ||||
| 		// Ignore any future fields. | ||||
| 		default: | ||||
| 			continue | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	if scanner.Err() != nil { | ||||
| 		return nil, scanner.Err() | ||||
| 	} | ||||
| 	return mods, nil | ||||
|  | ||||
| 	return | ||||
| } | ||||
|   | ||||
							
								
								
									
										118
									
								
								vendor/github.com/cilium/ebpf/internal/kallsyms/reader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								vendor/github.com/cilium/ebpf/internal/kallsyms/reader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| package kallsyms | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"io" | ||||
| 	"unicode" | ||||
| 	"unicode/utf8" | ||||
| ) | ||||
|  | ||||
| // reader is a line and word-oriented reader built for reading /proc/kallsyms. | ||||
| // It takes an io.Reader and iterates its contents line by line, then word by | ||||
| // word. | ||||
| // | ||||
| // It's designed to allow partial reading of lines without paying the cost of | ||||
| // allocating objects that will never be accessed, resulting in less work for | ||||
| // the garbage collector. | ||||
| type reader struct { | ||||
| 	s    *bufio.Scanner | ||||
| 	line []byte | ||||
| 	word []byte | ||||
|  | ||||
| 	err error | ||||
| } | ||||
|  | ||||
| func newReader(r io.Reader) *reader { | ||||
| 	return &reader{ | ||||
| 		s: bufio.NewScanner(r), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Bytes returns the current word as a byte slice. | ||||
| func (r *reader) Bytes() []byte { | ||||
| 	return r.word | ||||
| } | ||||
|  | ||||
| // Text returns the output of Bytes as a string. | ||||
| func (r *reader) Text() string { | ||||
| 	return string(r.Bytes()) | ||||
| } | ||||
|  | ||||
| // Line advances the reader to the next line in the input. Calling Line resets | ||||
| // the current word, making [reader.Bytes] and [reader.Text] return empty | ||||
| // values. Follow this up with a call to [reader.Word]. | ||||
| // | ||||
| // Like [bufio.Scanner], [reader.Err] needs to be checked after Line returns | ||||
| // false to determine if an error occurred during reading. | ||||
| // | ||||
| // Returns true if Line can be called again. Returns false if all lines in the | ||||
| // input have been read. | ||||
| func (r *reader) Line() bool { | ||||
| 	for r.s.Scan() { | ||||
| 		line := r.s.Bytes() | ||||
| 		if len(line) == 0 { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		r.line = line | ||||
| 		r.word = nil | ||||
|  | ||||
| 		return true | ||||
| 	} | ||||
| 	if err := r.s.Err(); err != nil { | ||||
| 		r.err = err | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // Word advances the reader to the next word in the current line. | ||||
| // | ||||
| // Returns true if a word is found and Word should be called again. Returns | ||||
| // false when all words on the line have been read. | ||||
| func (r *reader) Word() bool { | ||||
| 	if len(r.line) == 0 { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	// Find next word start, skipping leading spaces. | ||||
| 	start := 0 | ||||
| 	for width := 0; start < len(r.line); start += width { | ||||
| 		var c rune | ||||
| 		c, width = utf8.DecodeRune(r.line[start:]) | ||||
| 		if !unicode.IsSpace(c) { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Whitespace scanning reached the end of the line due to trailing whitespace, | ||||
| 	// meaning there are no more words to read | ||||
| 	if start == len(r.line) { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	// Find next word end. | ||||
| 	for width, i := 0, start; i < len(r.line); i += width { | ||||
| 		var c rune | ||||
| 		c, width = utf8.DecodeRune(r.line[i:]) | ||||
| 		if unicode.IsSpace(c) { | ||||
| 			r.word = r.line[start:i] | ||||
| 			r.line = r.line[i:] | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// The line contains data, but no end-of-word boundary was found. This is the | ||||
| 	// last, unterminated word in the line. | ||||
| 	if len(r.line) > start { | ||||
| 		r.word = r.line[start:] | ||||
| 		r.line = nil | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (r *reader) Err() error { | ||||
| 	return r.err | ||||
| } | ||||
							
								
								
									
										45
									
								
								vendor/github.com/cilium/ebpf/internal/kconfig/kconfig.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								vendor/github.com/cilium/ebpf/internal/kconfig/kconfig.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| // Package kconfig implements a parser for the format of Linux's .config file. | ||||
| package kconfig | ||||
|  | ||||
| import ( | ||||
| @@ -7,7 +8,6 @@ import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"math" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
|  | ||||
| @@ -15,30 +15,6 @@ import ( | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| ) | ||||
|  | ||||
| // Find find a kconfig file on the host. | ||||
| // It first reads from /boot/config- of the current running kernel and tries | ||||
| // /proc/config.gz if nothing was found in /boot. | ||||
| // If none of the file provide a kconfig, it returns an error. | ||||
| func Find() (*os.File, error) { | ||||
| 	kernelRelease, err := internal.KernelRelease() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("cannot get kernel release: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	path := "/boot/config-" + kernelRelease | ||||
| 	f, err := os.Open(path) | ||||
| 	if err == nil { | ||||
| 		return f, nil | ||||
| 	} | ||||
|  | ||||
| 	f, err = os.Open("/proc/config.gz") | ||||
| 	if err == nil { | ||||
| 		return f, nil | ||||
| 	} | ||||
|  | ||||
| 	return nil, fmt.Errorf("neither %s nor /proc/config.gz provide a kconfig", path) | ||||
| } | ||||
|  | ||||
| // Parse parses the kconfig file for which a reader is given. | ||||
| // All the CONFIG_* which are in filter and which are set set will be | ||||
| // put in the returned map as key with their corresponding value as map value. | ||||
| @@ -127,12 +103,13 @@ func PutValue(data []byte, typ btf.Type, value string) error { | ||||
| 	switch value { | ||||
| 	case "y", "n", "m": | ||||
| 		return putValueTri(data, typ, value) | ||||
| 	default: | ||||
| 		if strings.HasPrefix(value, `"`) { | ||||
| 			return putValueString(data, typ, value) | ||||
| 		} | ||||
| 		return putValueNumber(data, typ, value) | ||||
| 	} | ||||
|  | ||||
| 	if strings.HasPrefix(value, `"`) { | ||||
| 		return putValueString(data, typ, value) | ||||
| 	} | ||||
|  | ||||
| 	return putValueNumber(data, typ, value) | ||||
| } | ||||
|  | ||||
| // Golang translation of libbpf_tristate enum: | ||||
| @@ -169,6 +146,10 @@ func putValueTri(data []byte, typ btf.Type, value string) error { | ||||
| 			return fmt.Errorf("cannot use enum %q, only libbpf_tristate is supported", v.Name) | ||||
| 		} | ||||
|  | ||||
| 		if len(data) != 4 { | ||||
| 			return fmt.Errorf("expected enum value to occupy 4 bytes in datasec, got: %d", len(data)) | ||||
| 		} | ||||
|  | ||||
| 		var tri triState | ||||
| 		switch value { | ||||
| 		case "y": | ||||
| @@ -178,10 +159,10 @@ func putValueTri(data []byte, typ btf.Type, value string) error { | ||||
| 		case "n": | ||||
| 			tri = TriNo | ||||
| 		default: | ||||
| 			return fmt.Errorf("value %q is not support for libbpf_tristate", value) | ||||
| 			return fmt.Errorf("value %q is not supported for libbpf_tristate", value) | ||||
| 		} | ||||
|  | ||||
| 		internal.NativeEndian.PutUint64(data, uint64(tri)) | ||||
| 		internal.NativeEndian.PutUint32(data, uint32(tri)) | ||||
| 	default: | ||||
| 		return fmt.Errorf("cannot add number value, expected btf.Int or btf.Enum, got: %T", v) | ||||
| 	} | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| package internal | ||||
| package linux | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
							
								
								
									
										2
									
								
								vendor/github.com/cilium/ebpf/internal/linux/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/cilium/ebpf/internal/linux/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| // Package linux contains OS specific wrappers around package unix. | ||||
| package linux | ||||
							
								
								
									
										31
									
								
								vendor/github.com/cilium/ebpf/internal/linux/kconfig.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/cilium/ebpf/internal/linux/kconfig.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| package linux | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| // FindKConfig searches for a kconfig file on the host. | ||||
| // | ||||
| // It first reads from /boot/config- of the current running kernel and tries | ||||
| // /proc/config.gz if nothing was found in /boot. | ||||
| // If none of the file provide a kconfig, it returns an error. | ||||
| func FindKConfig() (*os.File, error) { | ||||
| 	kernelRelease, err := KernelRelease() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("cannot get kernel release: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	path := "/boot/config-" + kernelRelease | ||||
| 	f, err := os.Open(path) | ||||
| 	if err == nil { | ||||
| 		return f, nil | ||||
| 	} | ||||
|  | ||||
| 	f, err = os.Open("/proc/config.gz") | ||||
| 	if err == nil { | ||||
| 		return f, nil | ||||
| 	} | ||||
|  | ||||
| 	return nil, fmt.Errorf("neither %s nor /proc/config.gz provide a kconfig", path) | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package internal | ||||
| package linux | ||||
| 
 | ||||
| import ( | ||||
| 	"runtime" | ||||
| @@ -1,4 +1,4 @@ | ||||
| package internal | ||||
| package linux | ||||
| 
 | ||||
| import ( | ||||
| 	"unsafe" | ||||
| @@ -1,4 +1,4 @@ | ||||
| package internal | ||||
| package linux | ||||
| 
 | ||||
| import ( | ||||
| 	"debug/elf" | ||||
| @@ -9,6 +9,7 @@ import ( | ||||
| 	"math" | ||||
| 	"os" | ||||
| 
 | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
| 
 | ||||
| @@ -82,7 +83,7 @@ type elfNoteHeader struct { | ||||
| // vdsoLinuxVersionCode returns the LINUX_VERSION_CODE embedded in | ||||
| // the ELF notes section of the binary provided by the reader. | ||||
| func vdsoLinuxVersionCode(r io.ReaderAt) (uint32, error) { | ||||
| 	hdr, err := NewSafeELFFile(r) | ||||
| 	hdr, err := internal.NewSafeELFFile(r) | ||||
| 	if err != nil { | ||||
| 		return 0, fmt.Errorf("reading vDSO ELF: %w", err) | ||||
| 	} | ||||
| @@ -110,7 +111,7 @@ func vdsoLinuxVersionCode(r io.ReaderAt) (uint32, error) { | ||||
| 			var name string | ||||
| 			if n.NameSize > 0 { | ||||
| 				// Read the note name, aligned to 4 bytes. | ||||
| 				buf := make([]byte, Align(n.NameSize, 4)) | ||||
| 				buf := make([]byte, internal.Align(n.NameSize, 4)) | ||||
| 				if err := binary.Read(sr, hdr.ByteOrder, &buf); err != nil { | ||||
| 					return 0, fmt.Errorf("reading note name: %w", err) | ||||
| 				} | ||||
| @@ -132,7 +133,7 @@ func vdsoLinuxVersionCode(r io.ReaderAt) (uint32, error) { | ||||
| 				} | ||||
| 
 | ||||
| 				// Discard the note descriptor if it exists but we're not interested in it. | ||||
| 				if _, err := io.CopyN(io.Discard, sr, int64(Align(n.DescSize, 4))); err != nil { | ||||
| 				if _, err := io.CopyN(io.Discard, sr, int64(internal.Align(n.DescSize, 4))); err != nil { | ||||
| 					return 0, err | ||||
| 				} | ||||
| 			} | ||||
							
								
								
									
										34
									
								
								vendor/github.com/cilium/ebpf/internal/linux/version.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/cilium/ebpf/internal/linux/version.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| package linux | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
|  | ||||
| // KernelVersion returns the version of the currently running kernel. | ||||
| var KernelVersion = sync.OnceValues(detectKernelVersion) | ||||
|  | ||||
| // detectKernelVersion returns the version of the running kernel. | ||||
| func detectKernelVersion() (internal.Version, error) { | ||||
| 	vc, err := vdsoVersion() | ||||
| 	if err != nil { | ||||
| 		return internal.Version{}, err | ||||
| 	} | ||||
| 	return internal.NewVersionFromCode(vc), nil | ||||
| } | ||||
|  | ||||
| // KernelRelease returns the release string of the running kernel. | ||||
| // Its format depends on the Linux distribution and corresponds to directory | ||||
| // names in /lib/modules by convention. Some examples are 5.15.17-1-lts and | ||||
| // 4.19.0-16-amd64. | ||||
| func KernelRelease() (string, error) { | ||||
| 	var uname unix.Utsname | ||||
| 	if err := unix.Uname(&uname); err != nil { | ||||
| 		return "", fmt.Errorf("uname failed: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return unix.ByteSliceToString(uname.Release[:]), nil | ||||
| } | ||||
							
								
								
									
										28
									
								
								vendor/github.com/cilium/ebpf/internal/math.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/cilium/ebpf/internal/math.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,13 +1,33 @@ | ||||
| package internal | ||||
|  | ||||
| import "golang.org/x/exp/constraints" | ||||
|  | ||||
| // Align returns 'n' updated to 'alignment' boundary. | ||||
| func Align[I constraints.Integer](n, alignment I) I { | ||||
| func Align[I Integer](n, alignment I) I { | ||||
| 	return (n + alignment - 1) / alignment * alignment | ||||
| } | ||||
|  | ||||
| // IsPow returns true if n is a power of two. | ||||
| func IsPow[I constraints.Integer](n I) bool { | ||||
| func IsPow[I Integer](n I) bool { | ||||
| 	return n != 0 && (n&(n-1)) == 0 | ||||
| } | ||||
|  | ||||
| // Between returns the value clamped between a and b. | ||||
| func Between[I Integer](val, a, b I) I { | ||||
| 	lower, upper := a, b | ||||
| 	if lower > upper { | ||||
| 		upper, lower = a, b | ||||
| 	} | ||||
|  | ||||
| 	val = min(val, upper) | ||||
| 	return max(val, lower) | ||||
| } | ||||
|  | ||||
| // Integer represents all possible integer types. | ||||
| // Remove when x/exp/constraints is moved to the standard library. | ||||
| type Integer interface { | ||||
| 	~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ||||
| } | ||||
|  | ||||
| // List of integer types known by the Go compiler. Used by TestIntegerConstraint | ||||
| // to warn if a new integer type is introduced. Remove when x/exp/constraints | ||||
| // is moved to the standard library. | ||||
| var integers = []string{"int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr"} | ||||
|   | ||||
							
								
								
									
										74
									
								
								vendor/github.com/cilium/ebpf/internal/sys/fd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										74
									
								
								vendor/github.com/cilium/ebpf/internal/sys/fd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -4,9 +4,12 @@ import ( | ||||
| 	"fmt" | ||||
| 	"math" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/internal/testutils/fdtrace" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
|  | ||||
| @@ -17,15 +20,7 @@ type FD struct { | ||||
| } | ||||
|  | ||||
| func newFD(value int) *FD { | ||||
| 	if onLeakFD != nil { | ||||
| 		// Attempt to store the caller's stack for the given fd value. | ||||
| 		// Panic if fds contains an existing stack for the fd. | ||||
| 		old, exist := fds.LoadOrStore(value, callersFrames()) | ||||
| 		if exist { | ||||
| 			f := old.(*runtime.Frames) | ||||
| 			panic(fmt.Sprintf("found existing stack for fd %d:\n%s", value, FormatFrames(f))) | ||||
| 		} | ||||
| 	} | ||||
| 	fdtrace.TraceFD(value, 1) | ||||
|  | ||||
| 	fd := &FD{value} | ||||
| 	runtime.SetFinalizer(fd, (*FD).finalize) | ||||
| @@ -39,13 +34,7 @@ func (fd *FD) finalize() { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Invoke the fd leak callback. Calls LoadAndDelete to guarantee the callback | ||||
| 	// is invoked at most once for one sys.FD allocation, runtime.Frames can only | ||||
| 	// be unwound once. | ||||
| 	f, ok := fds.LoadAndDelete(fd.Int()) | ||||
| 	if ok && onLeakFD != nil { | ||||
| 		onLeakFD(f.(*runtime.Frames)) | ||||
| 	} | ||||
| 	fdtrace.LeakFD(fd.raw) | ||||
|  | ||||
| 	_ = fd.Close() | ||||
| } | ||||
| @@ -92,12 +81,15 @@ func (fd *FD) Close() error { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return unix.Close(fd.disown()) | ||||
| 	return unix.Close(fd.Disown()) | ||||
| } | ||||
|  | ||||
| func (fd *FD) disown() int { | ||||
| 	value := int(fd.raw) | ||||
| 	fds.Delete(int(value)) | ||||
| // Disown destroys the FD and returns its raw file descriptor without closing | ||||
| // it. After this call, the underlying fd is no longer tied to the FD's | ||||
| // lifecycle. | ||||
| func (fd *FD) Disown() int { | ||||
| 	value := fd.raw | ||||
| 	fdtrace.ForgetFD(value) | ||||
| 	fd.raw = -1 | ||||
|  | ||||
| 	runtime.SetFinalizer(fd, nil) | ||||
| @@ -129,5 +121,45 @@ func (fd *FD) File(name string) *os.File { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return os.NewFile(uintptr(fd.disown()), name) | ||||
| 	return os.NewFile(uintptr(fd.Disown()), name) | ||||
| } | ||||
|  | ||||
| // ObjGetTyped wraps [ObjGet] with a readlink call to extract the type of the | ||||
| // underlying bpf object. | ||||
| func ObjGetTyped(attr *ObjGetAttr) (*FD, ObjType, error) { | ||||
| 	fd, err := ObjGet(attr) | ||||
| 	if err != nil { | ||||
| 		return nil, 0, err | ||||
| 	} | ||||
|  | ||||
| 	typ, err := readType(fd) | ||||
| 	if err != nil { | ||||
| 		_ = fd.Close() | ||||
| 		return nil, 0, fmt.Errorf("reading fd type: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return fd, typ, nil | ||||
| } | ||||
|  | ||||
| // readType returns the bpf object type of the file descriptor by calling | ||||
| // readlink(3). Returns an error if the file descriptor does not represent a bpf | ||||
| // object. | ||||
| func readType(fd *FD) (ObjType, error) { | ||||
| 	s, err := os.Readlink(filepath.Join("/proc/self/fd/", fd.String())) | ||||
| 	if err != nil { | ||||
| 		return 0, fmt.Errorf("readlink fd %d: %w", fd.Int(), err) | ||||
| 	} | ||||
|  | ||||
| 	s = strings.TrimPrefix(s, "anon_inode:") | ||||
|  | ||||
| 	switch s { | ||||
| 	case "bpf-map": | ||||
| 		return BPF_TYPE_MAP, nil | ||||
| 	case "bpf-prog": | ||||
| 		return BPF_TYPE_PROG, nil | ||||
| 	case "bpf-link": | ||||
| 		return BPF_TYPE_LINK, nil | ||||
| 	} | ||||
|  | ||||
| 	return 0, fmt.Errorf("unknown type %s of fd %d", s, fd.Int()) | ||||
| } | ||||
|   | ||||
							
								
								
									
										93
									
								
								vendor/github.com/cilium/ebpf/internal/sys/fd_trace.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										93
									
								
								vendor/github.com/cilium/ebpf/internal/sys/fd_trace.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,93 +0,0 @@ | ||||
| package sys | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"runtime" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| // OnLeakFD controls tracing [FD] lifetime to detect resources that are not | ||||
| // closed by Close(). | ||||
| // | ||||
| // If fn is not nil, tracing is enabled for all FDs created going forward. fn is | ||||
| // invoked for all FDs that are closed by the garbage collector instead of an | ||||
| // explicit Close() by a caller. Calling OnLeakFD twice with a non-nil fn | ||||
| // (without disabling tracing in the meantime) will cause a panic. | ||||
| // | ||||
| // If fn is nil, tracing will be disabled. Any FDs that have not been closed are | ||||
| // considered to be leaked, fn will be invoked for them, and the process will be | ||||
| // terminated. | ||||
| // | ||||
| // fn will be invoked at most once for every unique sys.FD allocation since a | ||||
| // runtime.Frames can only be unwound once. | ||||
| func OnLeakFD(fn func(*runtime.Frames)) { | ||||
| 	// Enable leak tracing if new fn is provided. | ||||
| 	if fn != nil { | ||||
| 		if onLeakFD != nil { | ||||
| 			panic("OnLeakFD called twice with non-nil fn") | ||||
| 		} | ||||
|  | ||||
| 		onLeakFD = fn | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// fn is nil past this point. | ||||
|  | ||||
| 	if onLeakFD == nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Call onLeakFD for all open fds. | ||||
| 	if fs := flushFrames(); len(fs) != 0 { | ||||
| 		for _, f := range fs { | ||||
| 			onLeakFD(f) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	onLeakFD = nil | ||||
| } | ||||
|  | ||||
| var onLeakFD func(*runtime.Frames) | ||||
|  | ||||
| // fds is a registry of all file descriptors wrapped into sys.fds that were | ||||
| // created while an fd tracer was active. | ||||
| var fds sync.Map // map[int]*runtime.Frames | ||||
|  | ||||
| // flushFrames removes all elements from fds and returns them as a slice. This | ||||
| // deals with the fact that a runtime.Frames can only be unwound once using | ||||
| // Next(). | ||||
| func flushFrames() []*runtime.Frames { | ||||
| 	var frames []*runtime.Frames | ||||
| 	fds.Range(func(key, value any) bool { | ||||
| 		frames = append(frames, value.(*runtime.Frames)) | ||||
| 		fds.Delete(key) | ||||
| 		return true | ||||
| 	}) | ||||
| 	return frames | ||||
| } | ||||
|  | ||||
| func callersFrames() *runtime.Frames { | ||||
| 	c := make([]uintptr, 32) | ||||
|  | ||||
| 	// Skip runtime.Callers and this function. | ||||
| 	i := runtime.Callers(2, c) | ||||
| 	if i == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return runtime.CallersFrames(c) | ||||
| } | ||||
|  | ||||
| // FormatFrames formats a runtime.Frames as a human-readable string. | ||||
| func FormatFrames(fs *runtime.Frames) string { | ||||
| 	var b bytes.Buffer | ||||
| 	for { | ||||
| 		f, more := fs.Next() | ||||
| 		b.WriteString(fmt.Sprintf("\t%s+%#x\n\t\t%s:%d\n", f.Function, f.PC-f.Entry, f.File, f.Line)) | ||||
| 		if !more { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	return b.String() | ||||
| } | ||||
							
								
								
									
										53
									
								
								vendor/github.com/cilium/ebpf/internal/sys/mapflags_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										53
									
								
								vendor/github.com/cilium/ebpf/internal/sys/mapflags_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,53 +0,0 @@ | ||||
| // Code generated by "stringer -type MapFlags"; DO NOT EDIT. | ||||
|  | ||||
| package sys | ||||
|  | ||||
| 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_F_NO_PREALLOC-1] | ||||
| 	_ = x[BPF_F_NO_COMMON_LRU-2] | ||||
| 	_ = x[BPF_F_NUMA_NODE-4] | ||||
| 	_ = x[BPF_F_RDONLY-8] | ||||
| 	_ = x[BPF_F_WRONLY-16] | ||||
| 	_ = x[BPF_F_STACK_BUILD_ID-32] | ||||
| 	_ = x[BPF_F_ZERO_SEED-64] | ||||
| 	_ = x[BPF_F_RDONLY_PROG-128] | ||||
| 	_ = x[BPF_F_WRONLY_PROG-256] | ||||
| 	_ = x[BPF_F_CLONE-512] | ||||
| 	_ = x[BPF_F_MMAPABLE-1024] | ||||
| 	_ = x[BPF_F_PRESERVE_ELEMS-2048] | ||||
| 	_ = x[BPF_F_INNER_MAP-4096] | ||||
| 	_ = x[BPF_F_LINK-8192] | ||||
| 	_ = x[BPF_F_PATH_FD-16384] | ||||
| } | ||||
|  | ||||
| const _MapFlags_name = "BPF_F_NO_PREALLOCBPF_F_NO_COMMON_LRUBPF_F_NUMA_NODEBPF_F_RDONLYBPF_F_WRONLYBPF_F_STACK_BUILD_IDBPF_F_ZERO_SEEDBPF_F_RDONLY_PROGBPF_F_WRONLY_PROGBPF_F_CLONEBPF_F_MMAPABLEBPF_F_PRESERVE_ELEMSBPF_F_INNER_MAPBPF_F_LINKBPF_F_PATH_FD" | ||||
|  | ||||
| var _MapFlags_map = map[MapFlags]string{ | ||||
| 	1:     _MapFlags_name[0:17], | ||||
| 	2:     _MapFlags_name[17:36], | ||||
| 	4:     _MapFlags_name[36:51], | ||||
| 	8:     _MapFlags_name[51:63], | ||||
| 	16:    _MapFlags_name[63:75], | ||||
| 	32:    _MapFlags_name[75:95], | ||||
| 	64:    _MapFlags_name[95:110], | ||||
| 	128:   _MapFlags_name[110:127], | ||||
| 	256:   _MapFlags_name[127:144], | ||||
| 	512:   _MapFlags_name[144:155], | ||||
| 	1024:  _MapFlags_name[155:169], | ||||
| 	2048:  _MapFlags_name[169:189], | ||||
| 	4096:  _MapFlags_name[189:204], | ||||
| 	8192:  _MapFlags_name[204:214], | ||||
| 	16384: _MapFlags_name[214:227], | ||||
| } | ||||
|  | ||||
| func (i MapFlags) String() string { | ||||
| 	if str, ok := _MapFlags_map[i]; ok { | ||||
| 		return str | ||||
| 	} | ||||
| 	return "MapFlags(" + strconv.FormatInt(int64(i), 10) + ")" | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package internal | ||||
| package sys | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| @@ -7,11 +7,11 @@ import ( | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
| 
 | ||||
| 	"github.com/cilium/ebpf/internal/sys" | ||||
| 	"github.com/cilium/ebpf/internal/linux" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
| 
 | ||||
| func Pin(currentPath, newPath string, fd *sys.FD) error { | ||||
| func Pin(currentPath, newPath string, fd *FD) error { | ||||
| 	if newPath == "" { | ||||
| 		return errors.New("given pinning path cannot be empty") | ||||
| 	} | ||||
| @@ -19,7 +19,7 @@ func Pin(currentPath, newPath string, fd *sys.FD) error { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	fsType, err := FSType(filepath.Dir(newPath)) | ||||
| 	fsType, err := linux.FSType(filepath.Dir(newPath)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -30,8 +30,8 @@ func Pin(currentPath, newPath string, fd *sys.FD) error { | ||||
| 	defer runtime.KeepAlive(fd) | ||||
| 
 | ||||
| 	if currentPath == "" { | ||||
| 		return sys.ObjPin(&sys.ObjPinAttr{ | ||||
| 			Pathname: sys.NewStringPointer(newPath), | ||||
| 		return ObjPin(&ObjPinAttr{ | ||||
| 			Pathname: NewStringPointer(newPath), | ||||
| 			BpfFd:    fd.Uint(), | ||||
| 		}) | ||||
| 	} | ||||
| @@ -47,8 +47,8 @@ func Pin(currentPath, newPath string, fd *sys.FD) error { | ||||
| 		return fmt.Errorf("unable to move pinned object to new path %v: %w", newPath, err) | ||||
| 	} | ||||
| 	// Internal state not in sync with the file system so let's fix it. | ||||
| 	return sys.ObjPin(&sys.ObjPinAttr{ | ||||
| 		Pathname: sys.NewStringPointer(newPath), | ||||
| 	return ObjPin(&ObjPinAttr{ | ||||
| 		Pathname: NewStringPointer(newPath), | ||||
| 		BpfFd:    fd.Uint(), | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										6
									
								
								vendor/github.com/cilium/ebpf/internal/sys/ptr.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/cilium/ebpf/internal/sys/ptr.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -11,13 +11,13 @@ func NewPointer(ptr unsafe.Pointer) Pointer { | ||||
| 	return Pointer{ptr: ptr} | ||||
| } | ||||
|  | ||||
| // NewSlicePointer creates a 64-bit pointer from a byte slice. | ||||
| func NewSlicePointer(buf []byte) Pointer { | ||||
| // NewSlicePointer creates a 64-bit pointer from a slice. | ||||
| func NewSlicePointer[T comparable](buf []T) Pointer { | ||||
| 	if len(buf) == 0 { | ||||
| 		return Pointer{} | ||||
| 	} | ||||
|  | ||||
| 	return Pointer{ptr: unsafe.Pointer(&buf[0])} | ||||
| 	return Pointer{ptr: unsafe.Pointer(unsafe.SliceData(buf))} | ||||
| } | ||||
|  | ||||
| // NewSlicePointerLen creates a 64-bit pointer from a byte slice. | ||||
|   | ||||
							
								
								
									
										37
									
								
								vendor/github.com/cilium/ebpf/internal/sys/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/cilium/ebpf/internal/sys/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -133,12 +133,12 @@ func ObjInfo(fd *FD, info Info) error { | ||||
|  | ||||
| // BPFObjName is a null-terminated string made up of | ||||
| // 'A-Za-z0-9_' characters. | ||||
| type ObjName [unix.BPF_OBJ_NAME_LEN]byte | ||||
| type ObjName [BPF_OBJ_NAME_LEN]byte | ||||
|  | ||||
| // NewObjName truncates the result if it is too long. | ||||
| func NewObjName(name string) ObjName { | ||||
| 	var result ObjName | ||||
| 	copy(result[:unix.BPF_OBJ_NAME_LEN-1], name) | ||||
| 	copy(result[:BPF_OBJ_NAME_LEN-1], name) | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| @@ -160,29 +160,6 @@ type BTFID uint32 | ||||
| // TypeID identifies a type in a BTF blob. | ||||
| type TypeID uint32 | ||||
|  | ||||
| // MapFlags control map behaviour. | ||||
| type MapFlags uint32 | ||||
|  | ||||
| //go:generate go run golang.org/x/tools/cmd/stringer@latest -type MapFlags | ||||
|  | ||||
| const ( | ||||
| 	BPF_F_NO_PREALLOC MapFlags = 1 << iota | ||||
| 	BPF_F_NO_COMMON_LRU | ||||
| 	BPF_F_NUMA_NODE | ||||
| 	BPF_F_RDONLY | ||||
| 	BPF_F_WRONLY | ||||
| 	BPF_F_STACK_BUILD_ID | ||||
| 	BPF_F_ZERO_SEED | ||||
| 	BPF_F_RDONLY_PROG | ||||
| 	BPF_F_WRONLY_PROG | ||||
| 	BPF_F_CLONE | ||||
| 	BPF_F_MMAPABLE | ||||
| 	BPF_F_PRESERVE_ELEMS | ||||
| 	BPF_F_INNER_MAP | ||||
| 	BPF_F_LINK | ||||
| 	BPF_F_PATH_FD | ||||
| ) | ||||
|  | ||||
| // Flags used by bpf_mprog. | ||||
| const ( | ||||
| 	BPF_F_REPLACE = 1 << (iota + 2) | ||||
| @@ -192,6 +169,16 @@ const ( | ||||
| 	BPF_F_LINK_MPROG = 1 << 13 // aka BPF_F_LINK | ||||
| ) | ||||
|  | ||||
| // Flags used by BPF_PROG_LOAD. | ||||
| const ( | ||||
| 	BPF_F_SLEEPABLE          = 1 << 4 | ||||
| 	BPF_F_XDP_HAS_FRAGS      = 1 << 5 | ||||
| 	BPF_F_XDP_DEV_BOUND_ONLY = 1 << 6 | ||||
| ) | ||||
|  | ||||
| const BPF_TAG_SIZE = 8 | ||||
| const BPF_OBJ_NAME_LEN = 16 | ||||
|  | ||||
| // wrappedErrno wraps syscall.Errno to prevent direct comparisons with | ||||
| // syscall.E* or unix.E* constants. | ||||
| // | ||||
|   | ||||
							
								
								
									
										185
									
								
								vendor/github.com/cilium/ebpf/internal/sys/types.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										185
									
								
								vendor/github.com/cilium/ebpf/internal/sys/types.go
									
									
									
									
										vendored
									
									
								
							| @@ -6,6 +6,170 @@ import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	BPF_ADJ_ROOM_ENCAP_L2_MASK                 = 255 | ||||
| 	BPF_ADJ_ROOM_ENCAP_L2_SHIFT                = 56 | ||||
| 	BPF_ANY                                    = 0 | ||||
| 	BPF_CSUM_LEVEL_DEC                         = 2 | ||||
| 	BPF_CSUM_LEVEL_INC                         = 1 | ||||
| 	BPF_CSUM_LEVEL_QUERY                       = 0 | ||||
| 	BPF_CSUM_LEVEL_RESET                       = 3 | ||||
| 	BPF_EXIST                                  = 2 | ||||
| 	BPF_FIB_LKUP_RET_BLACKHOLE                 = 1 | ||||
| 	BPF_FIB_LKUP_RET_FRAG_NEEDED               = 8 | ||||
| 	BPF_FIB_LKUP_RET_FWD_DISABLED              = 5 | ||||
| 	BPF_FIB_LKUP_RET_NOT_FWDED                 = 4 | ||||
| 	BPF_FIB_LKUP_RET_NO_NEIGH                  = 7 | ||||
| 	BPF_FIB_LKUP_RET_NO_SRC_ADDR               = 9 | ||||
| 	BPF_FIB_LKUP_RET_PROHIBIT                  = 3 | ||||
| 	BPF_FIB_LKUP_RET_SUCCESS                   = 0 | ||||
| 	BPF_FIB_LKUP_RET_UNREACHABLE               = 2 | ||||
| 	BPF_FIB_LKUP_RET_UNSUPP_LWT                = 6 | ||||
| 	BPF_FIB_LOOKUP_DIRECT                      = 1 | ||||
| 	BPF_FIB_LOOKUP_OUTPUT                      = 2 | ||||
| 	BPF_FIB_LOOKUP_SKIP_NEIGH                  = 4 | ||||
| 	BPF_FIB_LOOKUP_SRC                         = 16 | ||||
| 	BPF_FIB_LOOKUP_TBID                        = 8 | ||||
| 	BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG        = 1 | ||||
| 	BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP         = 4 | ||||
| 	BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL    = 2 | ||||
| 	BPF_F_ADJ_ROOM_DECAP_L3_IPV4               = 128 | ||||
| 	BPF_F_ADJ_ROOM_DECAP_L3_IPV6               = 256 | ||||
| 	BPF_F_ADJ_ROOM_ENCAP_L2_ETH                = 64 | ||||
| 	BPF_F_ADJ_ROOM_ENCAP_L3_IPV4               = 2 | ||||
| 	BPF_F_ADJ_ROOM_ENCAP_L3_IPV6               = 4 | ||||
| 	BPF_F_ADJ_ROOM_ENCAP_L4_GRE                = 8 | ||||
| 	BPF_F_ADJ_ROOM_ENCAP_L4_UDP                = 16 | ||||
| 	BPF_F_ADJ_ROOM_FIXED_GSO                   = 1 | ||||
| 	BPF_F_ADJ_ROOM_NO_CSUM_RESET               = 32 | ||||
| 	BPF_F_BPRM_SECUREEXEC                      = 1 | ||||
| 	BPF_F_BROADCAST                            = 8 | ||||
| 	BPF_F_CLONE                                = 512 | ||||
| 	BPF_F_CTXLEN_MASK                          = 4503595332403200 | ||||
| 	BPF_F_CURRENT_CPU                          = 4294967295 | ||||
| 	BPF_F_CURRENT_NETNS                        = 18446744073709551615 | ||||
| 	BPF_F_DONT_FRAGMENT                        = 4 | ||||
| 	BPF_F_EXCLUDE_INGRESS                      = 16 | ||||
| 	BPF_F_FAST_STACK_CMP                       = 512 | ||||
| 	BPF_F_GET_BRANCH_RECORDS_SIZE              = 1 | ||||
| 	BPF_F_HDR_FIELD_MASK                       = 15 | ||||
| 	BPF_F_INDEX_MASK                           = 4294967295 | ||||
| 	BPF_F_INGRESS                              = 1 | ||||
| 	BPF_F_INNER_MAP                            = 4096 | ||||
| 	BPF_F_INVALIDATE_HASH                      = 2 | ||||
| 	BPF_F_KPROBE_MULTI_RETURN                  = 1 | ||||
| 	BPF_F_LINK                                 = 8192 | ||||
| 	BPF_F_LOCK                                 = 4 | ||||
| 	BPF_F_MARK_ENFORCE                         = 64 | ||||
| 	BPF_F_MARK_MANGLED_0                       = 32 | ||||
| 	BPF_F_MMAPABLE                             = 1024 | ||||
| 	BPF_F_NEIGH                                = 2 | ||||
| 	BPF_F_NEXTHOP                              = 8 | ||||
| 	BPF_F_NO_COMMON_LRU                        = 2 | ||||
| 	BPF_F_NO_PREALLOC                          = 1 | ||||
| 	BPF_F_NO_TUNNEL_KEY                        = 16 | ||||
| 	BPF_F_NUMA_NODE                            = 4 | ||||
| 	BPF_F_PATH_FD                              = 16384 | ||||
| 	BPF_F_PEER                                 = 4 | ||||
| 	BPF_F_PRESERVE_ELEMS                       = 2048 | ||||
| 	BPF_F_PSEUDO_HDR                           = 16 | ||||
| 	BPF_F_RDONLY                               = 8 | ||||
| 	BPF_F_RDONLY_PROG                          = 128 | ||||
| 	BPF_F_RECOMPUTE_CSUM                       = 1 | ||||
| 	BPF_F_REUSE_STACKID                        = 1024 | ||||
| 	BPF_F_SEQ_NUMBER                           = 8 | ||||
| 	BPF_F_SKIP_FIELD_MASK                      = 255 | ||||
| 	BPF_F_STACK_BUILD_ID                       = 32 | ||||
| 	BPF_F_SYSCTL_BASE_NAME                     = 1 | ||||
| 	BPF_F_TIMER_ABS                            = 1 | ||||
| 	BPF_F_TIMER_CPU_PIN                        = 2 | ||||
| 	BPF_F_TUNINFO_FLAGS                        = 16 | ||||
| 	BPF_F_TUNINFO_IPV6                         = 1 | ||||
| 	BPF_F_UPROBE_MULTI_RETURN                  = 1 | ||||
| 	BPF_F_USER_BUILD_ID                        = 2048 | ||||
| 	BPF_F_USER_STACK                           = 256 | ||||
| 	BPF_F_WRONLY                               = 16 | ||||
| 	BPF_F_WRONLY_PROG                          = 256 | ||||
| 	BPF_F_ZERO_CSUM_TX                         = 2 | ||||
| 	BPF_F_ZERO_SEED                            = 64 | ||||
| 	BPF_LOAD_HDR_OPT_TCP_SYN                   = 1 | ||||
| 	BPF_LOCAL_STORAGE_GET_F_CREATE             = 1 | ||||
| 	BPF_MAX_LOOPS                              = 8388608 | ||||
| 	BPF_MAX_TRAMP_LINKS                        = 38 | ||||
| 	BPF_NOEXIST                                = 1 | ||||
| 	BPF_RB_AVAIL_DATA                          = 0 | ||||
| 	BPF_RB_CONS_POS                            = 2 | ||||
| 	BPF_RB_FORCE_WAKEUP                        = 2 | ||||
| 	BPF_RB_NO_WAKEUP                           = 1 | ||||
| 	BPF_RB_PROD_POS                            = 3 | ||||
| 	BPF_RB_RING_SIZE                           = 1 | ||||
| 	BPF_REG_0                                  = 0 | ||||
| 	BPF_REG_1                                  = 1 | ||||
| 	BPF_REG_10                                 = 10 | ||||
| 	BPF_REG_2                                  = 2 | ||||
| 	BPF_REG_3                                  = 3 | ||||
| 	BPF_REG_4                                  = 4 | ||||
| 	BPF_REG_5                                  = 5 | ||||
| 	BPF_REG_6                                  = 6 | ||||
| 	BPF_REG_7                                  = 7 | ||||
| 	BPF_REG_8                                  = 8 | ||||
| 	BPF_REG_9                                  = 9 | ||||
| 	BPF_RINGBUF_BUSY_BIT                       = 2147483648 | ||||
| 	BPF_RINGBUF_DISCARD_BIT                    = 1073741824 | ||||
| 	BPF_RINGBUF_HDR_SZ                         = 8 | ||||
| 	BPF_SKB_TSTAMP_DELIVERY_MONO               = 1 | ||||
| 	BPF_SKB_TSTAMP_UNSPEC                      = 0 | ||||
| 	BPF_SK_LOOKUP_F_NO_REUSEPORT               = 2 | ||||
| 	BPF_SK_LOOKUP_F_REPLACE                    = 1 | ||||
| 	BPF_SK_STORAGE_GET_F_CREATE                = 1 | ||||
| 	BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB         = 4 | ||||
| 	BPF_SOCK_OPS_ALL_CB_FLAGS                  = 127 | ||||
| 	BPF_SOCK_OPS_BASE_RTT                      = 7 | ||||
| 	BPF_SOCK_OPS_HDR_OPT_LEN_CB                = 14 | ||||
| 	BPF_SOCK_OPS_NEEDS_ECN                     = 6 | ||||
| 	BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG     = 16 | ||||
| 	BPF_SOCK_OPS_PARSE_HDR_OPT_CB              = 13 | ||||
| 	BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG = 32 | ||||
| 	BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB        = 5 | ||||
| 	BPF_SOCK_OPS_RETRANS_CB                    = 9 | ||||
| 	BPF_SOCK_OPS_RETRANS_CB_FLAG               = 2 | ||||
| 	BPF_SOCK_OPS_RTO_CB                        = 8 | ||||
| 	BPF_SOCK_OPS_RTO_CB_FLAG                   = 1 | ||||
| 	BPF_SOCK_OPS_RTT_CB                        = 12 | ||||
| 	BPF_SOCK_OPS_RTT_CB_FLAG                   = 8 | ||||
| 	BPF_SOCK_OPS_RWND_INIT                     = 2 | ||||
| 	BPF_SOCK_OPS_STATE_CB                      = 10 | ||||
| 	BPF_SOCK_OPS_STATE_CB_FLAG                 = 4 | ||||
| 	BPF_SOCK_OPS_TCP_CONNECT_CB                = 3 | ||||
| 	BPF_SOCK_OPS_TCP_LISTEN_CB                 = 11 | ||||
| 	BPF_SOCK_OPS_TIMEOUT_INIT                  = 1 | ||||
| 	BPF_SOCK_OPS_VOID                          = 0 | ||||
| 	BPF_SOCK_OPS_WRITE_HDR_OPT_CB              = 15 | ||||
| 	BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG         = 64 | ||||
| 	BPF_STRUCT_OPS_TYPE_bpf_dummy_ops          = 0 | ||||
| 	BPF_STRUCT_OPS_TYPE_tcp_congestion_ops     = 1 | ||||
| 	BPF_TASK_ITER_ALL_PROCS                    = 0 | ||||
| 	BPF_TASK_ITER_ALL_THREADS                  = 1 | ||||
| 	BPF_TASK_ITER_PROC_THREADS                 = 2 | ||||
| 	BPF_TCP_BOUND_INACTIVE                     = 13 | ||||
| 	BPF_TCP_CLOSE                              = 7 | ||||
| 	BPF_TCP_CLOSE_WAIT                         = 8 | ||||
| 	BPF_TCP_CLOSING                            = 11 | ||||
| 	BPF_TCP_ESTABLISHED                        = 1 | ||||
| 	BPF_TCP_FIN_WAIT1                          = 4 | ||||
| 	BPF_TCP_FIN_WAIT2                          = 5 | ||||
| 	BPF_TCP_LAST_ACK                           = 9 | ||||
| 	BPF_TCP_LISTEN                             = 10 | ||||
| 	BPF_TCP_MAX_STATES                         = 14 | ||||
| 	BPF_TCP_NEW_SYN_RECV                       = 12 | ||||
| 	BPF_TCP_SYN_RECV                           = 3 | ||||
| 	BPF_TCP_SYN_SENT                           = 2 | ||||
| 	BPF_TCP_TIME_WAIT                          = 6 | ||||
| 	BPF_WRITE_HDR_TCP_CURRENT_MSS              = 1 | ||||
| 	BPF_WRITE_HDR_TCP_SYNACK_COOKIE            = 2 | ||||
| 	BPF_XFRM_STATE_OPTS_SZ                     = 36 | ||||
| ) | ||||
|  | ||||
| type AdjRoomMode uint32 | ||||
|  | ||||
| const ( | ||||
| @@ -402,6 +566,15 @@ const ( | ||||
| 	BPF_MAP_TYPE_CGRP_STORAGE                     MapType = 32 | ||||
| ) | ||||
|  | ||||
| type ObjType uint32 | ||||
|  | ||||
| const ( | ||||
| 	BPF_TYPE_UNSPEC ObjType = 0 | ||||
| 	BPF_TYPE_PROG   ObjType = 1 | ||||
| 	BPF_TYPE_MAP    ObjType = 2 | ||||
| 	BPF_TYPE_LINK   ObjType = 3 | ||||
| ) | ||||
|  | ||||
| type PerfEventType uint32 | ||||
|  | ||||
| const ( | ||||
| @@ -537,7 +710,7 @@ type MapInfo struct { | ||||
| 	KeySize               uint32 | ||||
| 	ValueSize             uint32 | ||||
| 	MaxEntries            uint32 | ||||
| 	MapFlags              MapFlags | ||||
| 	MapFlags              uint32 | ||||
| 	Name                  ObjName | ||||
| 	Ifindex               uint32 | ||||
| 	BtfVmlinuxValueTypeId TypeID | ||||
| @@ -556,7 +729,7 @@ type ProgInfo struct { | ||||
| 	Tag                  [8]uint8 | ||||
| 	JitedProgLen         uint32 | ||||
| 	XlatedProgLen        uint32 | ||||
| 	JitedProgInsns       uint64 | ||||
| 	JitedProgInsns       Pointer | ||||
| 	XlatedProgInsns      Pointer | ||||
| 	LoadTime             uint64 | ||||
| 	CreatedByUid         uint32 | ||||
| @@ -569,15 +742,15 @@ type ProgInfo struct { | ||||
| 	NetnsIno             uint64 | ||||
| 	NrJitedKsyms         uint32 | ||||
| 	NrJitedFuncLens      uint32 | ||||
| 	JitedKsyms           uint64 | ||||
| 	JitedFuncLens        uint64 | ||||
| 	JitedKsyms           Pointer | ||||
| 	JitedFuncLens        Pointer | ||||
| 	BtfId                BTFID | ||||
| 	FuncInfoRecSize      uint32 | ||||
| 	FuncInfo             Pointer | ||||
| 	NrFuncInfo           uint32 | ||||
| 	NrLineInfo           uint32 | ||||
| 	LineInfo             Pointer | ||||
| 	JitedLineInfo        uint64 | ||||
| 	JitedLineInfo        Pointer | ||||
| 	NrJitedLineInfo      uint32 | ||||
| 	LineInfoRecSize      uint32 | ||||
| 	JitedLineInfoRecSize uint32 | ||||
| @@ -886,7 +1059,7 @@ type MapCreateAttr struct { | ||||
| 	KeySize               uint32 | ||||
| 	ValueSize             uint32 | ||||
| 	MaxEntries            uint32 | ||||
| 	MapFlags              MapFlags | ||||
| 	MapFlags              uint32 | ||||
| 	InnerMapFd            uint32 | ||||
| 	NumaNode              uint32 | ||||
| 	MapName               ObjName | ||||
|   | ||||
							
								
								
									
										10
									
								
								vendor/github.com/cilium/ebpf/internal/sysenc/buffer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/cilium/ebpf/internal/sysenc/buffer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -51,12 +51,12 @@ func SyscallOutput(dst any, size int) Buffer { | ||||
| // | ||||
| // Returns the number of copied bytes. | ||||
| func (b Buffer) CopyTo(dst []byte) int { | ||||
| 	return copy(dst, b.unsafeBytes()) | ||||
| 	return copy(dst, b.Bytes()) | ||||
| } | ||||
|  | ||||
| // AppendTo appends the buffer onto dst. | ||||
| func (b Buffer) AppendTo(dst []byte) []byte { | ||||
| 	return append(dst, b.unsafeBytes()...) | ||||
| 	return append(dst, b.Bytes()...) | ||||
| } | ||||
|  | ||||
| // Pointer returns the location where a syscall should write. | ||||
| @@ -72,10 +72,12 @@ func (b Buffer) Unmarshal(data any) error { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return Unmarshal(data, b.unsafeBytes()) | ||||
| 	return Unmarshal(data, b.Bytes()) | ||||
| } | ||||
|  | ||||
| func (b Buffer) unsafeBytes() []byte { | ||||
| // Bytes returns the buffer as a byte slice. Returns nil if the Buffer was | ||||
| // created using UnsafeBuffer or by zero-copy unmarshaling. | ||||
| func (b Buffer) Bytes() []byte { | ||||
| 	if b.size == syscallPointerOnly { | ||||
| 		return nil | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										103
									
								
								vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/fd_trace.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/fd_trace.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| package fdtrace | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
| 	"sync" | ||||
| 	"sync/atomic" | ||||
| ) | ||||
|  | ||||
| // foundLeak is atomic since the GC may collect objects in parallel. | ||||
| var foundLeak atomic.Bool | ||||
|  | ||||
| func onLeakFD(fs *runtime.Frames) { | ||||
| 	foundLeak.Store(true) | ||||
| 	fmt.Fprintln(os.Stderr, "leaked fd created at:") | ||||
| 	fmt.Fprintln(os.Stderr, formatFrames(fs)) | ||||
| } | ||||
|  | ||||
| // fds is a registry of all file descriptors wrapped into sys.fds that were | ||||
| // created while an fd tracer was active. | ||||
| var fds *sync.Map // map[int]*runtime.Frames | ||||
|  | ||||
| // TraceFD associates raw with the current execution stack. | ||||
| // | ||||
| // skip controls how many entries of the stack the function should skip. | ||||
| func TraceFD(raw int, skip int) { | ||||
| 	if fds == nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Attempt to store the caller's stack for the given fd value. | ||||
| 	// Panic if fds contains an existing stack for the fd. | ||||
| 	old, exist := fds.LoadOrStore(raw, callersFrames(skip)) | ||||
| 	if exist { | ||||
| 		f := old.(*runtime.Frames) | ||||
| 		panic(fmt.Sprintf("found existing stack for fd %d:\n%s", raw, formatFrames(f))) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ForgetFD removes any existing association for raw. | ||||
| func ForgetFD(raw int) { | ||||
| 	if fds != nil { | ||||
| 		fds.Delete(raw) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // LeakFD indicates that raw was leaked. | ||||
| // | ||||
| // Calling the function with a value that was not passed to [TraceFD] before | ||||
| // is undefined. | ||||
| func LeakFD(raw int) { | ||||
| 	if fds == nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Invoke the fd leak callback. Calls LoadAndDelete to guarantee the callback | ||||
| 	// is invoked at most once for one sys.FD allocation, runtime.Frames can only | ||||
| 	// be unwound once. | ||||
| 	f, ok := fds.LoadAndDelete(raw) | ||||
| 	if ok { | ||||
| 		onLeakFD(f.(*runtime.Frames)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // flushFrames removes all elements from fds and returns them as a slice. This | ||||
| // deals with the fact that a runtime.Frames can only be unwound once using | ||||
| // Next(). | ||||
| func flushFrames() []*runtime.Frames { | ||||
| 	var frames []*runtime.Frames | ||||
| 	fds.Range(func(key, value any) bool { | ||||
| 		frames = append(frames, value.(*runtime.Frames)) | ||||
| 		fds.Delete(key) | ||||
| 		return true | ||||
| 	}) | ||||
| 	return frames | ||||
| } | ||||
|  | ||||
| func callersFrames(skip int) *runtime.Frames { | ||||
| 	c := make([]uintptr, 32) | ||||
|  | ||||
| 	// Skip runtime.Callers and this function. | ||||
| 	i := runtime.Callers(skip+2, c) | ||||
| 	if i == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return runtime.CallersFrames(c) | ||||
| } | ||||
|  | ||||
| // formatFrames formats a runtime.Frames as a human-readable string. | ||||
| func formatFrames(fs *runtime.Frames) string { | ||||
| 	var b bytes.Buffer | ||||
| 	for { | ||||
| 		f, more := fs.Next() | ||||
| 		b.WriteString(fmt.Sprintf("\t%s+%#x\n\t\t%s:%d\n", f.Function, f.PC-f.Entry, f.File, f.Line)) | ||||
| 		if !more { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	return b.String() | ||||
| } | ||||
							
								
								
									
										31
									
								
								vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/main.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/cilium/ebpf/internal/testutils/fdtrace/main.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| package fdtrace | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| type testingM interface { | ||||
| 	Run() int | ||||
| } | ||||
|  | ||||
| // TestMain runs m with fd tracing enabled. | ||||
| // | ||||
| // The function calls [os.Exit] and does not return. | ||||
| func TestMain(m testingM) { | ||||
| 	fds = new(sync.Map) | ||||
|  | ||||
| 	ret := m.Run() | ||||
|  | ||||
| 	if fs := flushFrames(); len(fs) != 0 { | ||||
| 		for _, f := range fs { | ||||
| 			onLeakFD(f) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if foundLeak.Load() { | ||||
| 		ret = 99 | ||||
| 	} | ||||
|  | ||||
| 	os.Exit(ret) | ||||
| } | ||||
							
								
								
									
										8
									
								
								vendor/github.com/cilium/ebpf/internal/tracefs/kprobe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/cilium/ebpf/internal/tracefs/kprobe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -12,6 +12,7 @@ import ( | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/linux" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
|  | ||||
| @@ -121,7 +122,7 @@ var getTracefsPath = sync.OnceValues(func() (string, error) { | ||||
| 		// RHEL/CentOS | ||||
| 		{"/sys/kernel/debug/tracing", unix.DEBUGFS_MAGIC}, | ||||
| 	} { | ||||
| 		if fsType, err := internal.FSType(p.path); err == nil && fsType == p.fsType { | ||||
| 		if fsType, err := linux.FSType(p.path); err == nil && fsType == p.fsType { | ||||
| 			return p.path, nil | ||||
| 		} | ||||
| 	} | ||||
| @@ -213,7 +214,10 @@ func NewEvent(args ProbeArgs) (*Event, error) { | ||||
| 	if err == nil { | ||||
| 		return nil, fmt.Errorf("trace event %s/%s: %w", args.Group, eventName, os.ErrExist) | ||||
| 	} | ||||
| 	if err != nil && !errors.Is(err, os.ErrNotExist) { | ||||
| 	if errors.Is(err, unix.EINVAL) { | ||||
| 		return nil, fmt.Errorf("trace event %s/%s: %w (unknown symbol?)", args.Group, eventName, err) | ||||
| 	} | ||||
| 	if !errors.Is(err, os.ErrNotExist) { | ||||
| 		return nil, fmt.Errorf("checking trace event %s/%s: %w", args.Group, eventName, err) | ||||
| 	} | ||||
|  | ||||
|   | ||||
							
								
								
									
										5
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -81,15 +81,16 @@ const ( | ||||
| 	SO_DETACH_BPF             = linux.SO_DETACH_BPF | ||||
| 	SOL_SOCKET                = linux.SOL_SOCKET | ||||
| 	SIGPROF                   = linux.SIGPROF | ||||
| 	SIGUSR1                   = linux.SIGUSR1 | ||||
| 	SIG_BLOCK                 = linux.SIG_BLOCK | ||||
| 	SIG_UNBLOCK               = linux.SIG_UNBLOCK | ||||
| 	EM_NONE                   = linux.EM_NONE | ||||
| 	EM_BPF                    = linux.EM_BPF | ||||
| 	BPF_FS_MAGIC              = linux.BPF_FS_MAGIC | ||||
| 	TRACEFS_MAGIC             = linux.TRACEFS_MAGIC | ||||
| 	DEBUGFS_MAGIC             = linux.DEBUGFS_MAGIC | ||||
| 	BPF_RB_NO_WAKEUP          = linux.BPF_RB_NO_WAKEUP | ||||
| 	BPF_RB_FORCE_WAKEUP       = linux.BPF_RB_FORCE_WAKEUP | ||||
| 	AF_UNSPEC                 = linux.AF_UNSPEC | ||||
| 	IFF_UP                    = linux.IFF_UP | ||||
| ) | ||||
|  | ||||
| type Statfs_t = linux.Statfs_t | ||||
|   | ||||
							
								
								
									
										5
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -84,16 +84,17 @@ const ( | ||||
| 	SO_DETACH_BPF | ||||
| 	SOL_SOCKET | ||||
| 	SIGPROF | ||||
| 	SIGUSR1 | ||||
| 	SIG_BLOCK | ||||
| 	SIG_UNBLOCK | ||||
| 	EM_NONE | ||||
| 	EM_BPF | ||||
| 	BPF_FS_MAGIC | ||||
| 	TRACEFS_MAGIC | ||||
| 	DEBUGFS_MAGIC | ||||
| 	BPF_RB_NO_WAKEUP | ||||
| 	BPF_RB_FORCE_WAKEUP | ||||
| 	BPF_F_LOCK | ||||
| 	AF_UNSPEC | ||||
| 	IFF_UP | ||||
| ) | ||||
|  | ||||
| type Statfs_t struct { | ||||
|   | ||||
							
								
								
									
										30
									
								
								vendor/github.com/cilium/ebpf/internal/version.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/cilium/ebpf/internal/version.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,9 +2,6 @@ package internal | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| @@ -78,30 +75,3 @@ func (v Version) Kernel() uint32 { | ||||
| 	// each other when overflowing 8 bits. | ||||
| 	return uint32(uint8(v[0]))<<16 | uint32(uint8(v[1]))<<8 | uint32(uint8(s)) | ||||
| } | ||||
|  | ||||
| // KernelVersion returns the version of the currently running kernel. | ||||
| var KernelVersion = sync.OnceValues(func() (Version, error) { | ||||
| 	return detectKernelVersion() | ||||
| }) | ||||
|  | ||||
| // detectKernelVersion returns the version of the running kernel. | ||||
| func detectKernelVersion() (Version, error) { | ||||
| 	vc, err := vdsoVersion() | ||||
| 	if err != nil { | ||||
| 		return Version{}, err | ||||
| 	} | ||||
| 	return NewVersionFromCode(vc), nil | ||||
| } | ||||
|  | ||||
| // KernelRelease returns the release string of the running kernel. | ||||
| // Its format depends on the Linux distribution and corresponds to directory | ||||
| // names in /lib/modules by convention. Some examples are 5.15.17-1-lts and | ||||
| // 4.19.0-16-amd64. | ||||
| func KernelRelease() (string, error) { | ||||
| 	var uname unix.Utsname | ||||
| 	if err := unix.Uname(&uname); err != nil { | ||||
| 		return "", fmt.Errorf("uname failed: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return unix.ByteSliceToString(uname.Release[:]), nil | ||||
| } | ||||
|   | ||||
							
								
								
									
										12
									
								
								vendor/github.com/cilium/ebpf/link/kprobe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								vendor/github.com/cilium/ebpf/link/kprobe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -10,6 +10,7 @@ import ( | ||||
|  | ||||
| 	"github.com/cilium/ebpf" | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/linux" | ||||
| 	"github.com/cilium/ebpf/internal/sys" | ||||
| 	"github.com/cilium/ebpf/internal/tracefs" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| @@ -60,6 +61,9 @@ func (ko *KprobeOptions) cookie() uint64 { | ||||
| // platform's syscall prefix (e.g. __x64_) to support attaching to syscalls | ||||
| // in a portable fashion. | ||||
| // | ||||
| // On kernels 6.11 and later, setting a kprobe on a nonexistent symbol using | ||||
| // tracefs incorrectly returns [unix.EINVAL] instead of [os.ErrNotExist]. | ||||
| // | ||||
| // The returned Link may implement [PerfEvent]. | ||||
| func Kprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions) (Link, error) { | ||||
| 	k, err := kprobe(symbol, prog, opts, false) | ||||
| @@ -91,7 +95,7 @@ func Kprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions) (Link, error | ||||
| // in a portable fashion. | ||||
| // | ||||
| // On kernels 5.10 and earlier, setting a kretprobe on a nonexistent symbol | ||||
| // incorrectly returns unix.EINVAL instead of os.ErrNotExist. | ||||
| // incorrectly returns [unix.EINVAL] instead of [os.ErrNotExist]. | ||||
| // | ||||
| // The returned Link may implement [PerfEvent]. | ||||
| func Kretprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions) (Link, error) { | ||||
| @@ -169,7 +173,7 @@ func kprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions, ret bool) (* | ||||
| 	// Use kprobe PMU if the kernel has it available. | ||||
| 	tp, err := pmuProbe(args) | ||||
| 	if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) { | ||||
| 		if prefix := internal.PlatformPrefix(); prefix != "" { | ||||
| 		if prefix := linux.PlatformPrefix(); prefix != "" { | ||||
| 			args.Symbol = prefix + symbol | ||||
| 			tp, err = pmuProbe(args) | ||||
| 		} | ||||
| @@ -177,7 +181,7 @@ func kprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions, ret bool) (* | ||||
| 	if err == nil { | ||||
| 		return tp, nil | ||||
| 	} | ||||
| 	if err != nil && !errors.Is(err, ErrNotSupported) { | ||||
| 	if !errors.Is(err, ErrNotSupported) { | ||||
| 		return nil, fmt.Errorf("creating perf_kprobe PMU (arch-specific fallback for %q): %w", symbol, err) | ||||
| 	} | ||||
|  | ||||
| @@ -185,7 +189,7 @@ func kprobe(symbol string, prog *ebpf.Program, opts *KprobeOptions, ret bool) (* | ||||
| 	args.Symbol = symbol | ||||
| 	tp, err = tracefsProbe(args) | ||||
| 	if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) { | ||||
| 		if prefix := internal.PlatformPrefix(); prefix != "" { | ||||
| 		if prefix := linux.PlatformPrefix(); prefix != "" { | ||||
| 			args.Symbol = prefix + symbol | ||||
| 			tp, err = tracefsProbe(args) | ||||
| 		} | ||||
|   | ||||
							
								
								
									
										8
									
								
								vendor/github.com/cilium/ebpf/link/kprobe_multi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/cilium/ebpf/link/kprobe_multi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -60,7 +60,7 @@ func KprobeMulti(prog *ebpf.Program, opts KprobeMultiOptions) (Link, error) { | ||||
| // | ||||
| // Requires at least Linux 5.18. | ||||
| func KretprobeMulti(prog *ebpf.Program, opts KprobeMultiOptions) (Link, error) { | ||||
| 	return kprobeMulti(prog, opts, unix.BPF_F_KPROBE_MULTI_RETURN) | ||||
| 	return kprobeMulti(prog, opts, sys.BPF_F_KPROBE_MULTI_RETURN) | ||||
| } | ||||
|  | ||||
| func kprobeMulti(prog *ebpf.Program, opts KprobeMultiOptions, flags uint32) (Link, error) { | ||||
| @@ -126,7 +126,7 @@ type kprobeMultiLink struct { | ||||
|  | ||||
| var _ Link = (*kprobeMultiLink)(nil) | ||||
|  | ||||
| func (kml *kprobeMultiLink) Update(prog *ebpf.Program) error { | ||||
| func (kml *kprobeMultiLink) Update(_ *ebpf.Program) error { | ||||
| 	return fmt.Errorf("update kprobe_multi: %w", ErrNotSupported) | ||||
| } | ||||
|  | ||||
| @@ -149,7 +149,7 @@ func (kml *kprobeMultiLink) Info() (*Info, error) { | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| var haveBPFLinkKprobeMulti = internal.NewFeatureTest("bpf_link_kprobe_multi", "5.18", func() error { | ||||
| var haveBPFLinkKprobeMulti = internal.NewFeatureTest("bpf_link_kprobe_multi", func() error { | ||||
| 	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ | ||||
| 		Name: "probe_kpm_link", | ||||
| 		Type: ebpf.Kprobe, | ||||
| @@ -188,4 +188,4 @@ var haveBPFLinkKprobeMulti = internal.NewFeatureTest("bpf_link_kprobe_multi", "5 | ||||
| 	fd.Close() | ||||
|  | ||||
| 	return nil | ||||
| }) | ||||
| }, "5.18") | ||||
|   | ||||
							
								
								
									
										15
									
								
								vendor/github.com/cilium/ebpf/link/link.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/cilium/ebpf/link/link.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -78,7 +78,9 @@ func NewFromID(id ID) (Link, error) { | ||||
| 	return wrapRawLink(&RawLink{fd, ""}) | ||||
| } | ||||
|  | ||||
| // LoadPinnedLink loads a link that was persisted into a bpffs. | ||||
| // LoadPinnedLink loads a Link from a pin (file) on the BPF virtual filesystem. | ||||
| // | ||||
| // Requires at least Linux 5.7. | ||||
| func LoadPinnedLink(fileName string, opts *ebpf.LoadPinOptions) (Link, error) { | ||||
| 	raw, err := loadPinnedRawLink(fileName, opts) | ||||
| 	if err != nil { | ||||
| @@ -350,7 +352,7 @@ func AttachRawLink(opts RawLinkOptions) (*RawLink, error) { | ||||
| } | ||||
|  | ||||
| func loadPinnedRawLink(fileName string, opts *ebpf.LoadPinOptions) (*RawLink, error) { | ||||
| 	fd, err := sys.ObjGet(&sys.ObjGetAttr{ | ||||
| 	fd, typ, err := sys.ObjGetTyped(&sys.ObjGetAttr{ | ||||
| 		Pathname:  sys.NewStringPointer(fileName), | ||||
| 		FileFlags: opts.Marshal(), | ||||
| 	}) | ||||
| @@ -358,6 +360,11 @@ func loadPinnedRawLink(fileName string, opts *ebpf.LoadPinOptions) (*RawLink, er | ||||
| 		return nil, fmt.Errorf("load pinned link: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	if typ != sys.BPF_TYPE_LINK { | ||||
| 		_ = fd.Close() | ||||
| 		return nil, fmt.Errorf("%s is not a Link", fileName) | ||||
| 	} | ||||
|  | ||||
| 	return &RawLink{fd, fileName}, nil | ||||
| } | ||||
|  | ||||
| @@ -380,7 +387,7 @@ func (l *RawLink) Close() error { | ||||
| // Calling Close on a pinned Link will not break the link | ||||
| // until the pin is removed. | ||||
| func (l *RawLink) Pin(fileName string) error { | ||||
| 	if err := internal.Pin(l.pinnedPath, fileName, l.fd); err != nil { | ||||
| 	if err := sys.Pin(l.pinnedPath, fileName, l.fd); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	l.pinnedPath = fileName | ||||
| @@ -389,7 +396,7 @@ func (l *RawLink) Pin(fileName string) error { | ||||
|  | ||||
| // Unpin implements the Link interface. | ||||
| func (l *RawLink) Unpin() error { | ||||
| 	if err := internal.Unpin(l.pinnedPath); err != nil { | ||||
| 	if err := sys.Unpin(l.pinnedPath); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	l.pinnedPath = "" | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/cilium/ebpf/link/netfilter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/cilium/ebpf/link/netfilter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -63,7 +63,7 @@ func AttachNetfilter(opts NetfilterOptions) (Link, error) { | ||||
| 	return &netfilterLink{RawLink{fd, ""}}, nil | ||||
| } | ||||
|  | ||||
| func (*netfilterLink) Update(new *ebpf.Program) error { | ||||
| func (*netfilterLink) Update(_ *ebpf.Program) error { | ||||
| 	return fmt.Errorf("netfilter update: %w", ErrNotSupported) | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										8
									
								
								vendor/github.com/cilium/ebpf/link/perf_event.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/cilium/ebpf/link/perf_event.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -115,7 +115,7 @@ func (pl *perfEventLink) Close() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (pl *perfEventLink) Update(prog *ebpf.Program) error { | ||||
| func (pl *perfEventLink) Update(_ *ebpf.Program) error { | ||||
| 	return fmt.Errorf("perf event link update: %w", ErrNotSupported) | ||||
| } | ||||
|  | ||||
| @@ -185,7 +185,7 @@ func (pi *perfEventIoctl) isLink() {} | ||||
| // | ||||
| // Detaching a program from a perf event is currently not possible, so a | ||||
| // program replacement mechanism cannot be implemented for perf events. | ||||
| func (pi *perfEventIoctl) Update(prog *ebpf.Program) error { | ||||
| func (pi *perfEventIoctl) Update(_ *ebpf.Program) error { | ||||
| 	return fmt.Errorf("perf event ioctl update: %w", ErrNotSupported) | ||||
| } | ||||
|  | ||||
| @@ -303,7 +303,7 @@ func openTracepointPerfEvent(tid uint64, pid int) (*sys.FD, error) { | ||||
| // | ||||
| // https://elixir.bootlin.com/linux/v5.16.8/source/kernel/bpf/syscall.c#L4307 | ||||
| // https://github.com/torvalds/linux/commit/b89fbfbb854c9afc3047e8273cc3a694650b802e | ||||
| var haveBPFLinkPerfEvent = internal.NewFeatureTest("bpf_link_perf_event", "5.15", func() error { | ||||
| var haveBPFLinkPerfEvent = internal.NewFeatureTest("bpf_link_perf_event", func() error { | ||||
| 	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ | ||||
| 		Name: "probe_bpf_perf_link", | ||||
| 		Type: ebpf.Kprobe, | ||||
| @@ -329,4 +329,4 @@ var haveBPFLinkPerfEvent = internal.NewFeatureTest("bpf_link_perf_event", "5.15" | ||||
| 		return nil | ||||
| 	} | ||||
| 	return err | ||||
| }) | ||||
| }, "5.15") | ||||
|   | ||||
							
								
								
									
										24
									
								
								vendor/github.com/cilium/ebpf/link/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/cilium/ebpf/link/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -30,7 +30,7 @@ const ( | ||||
| 	NetkitType        = sys.BPF_LINK_TYPE_NETKIT | ||||
| ) | ||||
|  | ||||
| var haveProgAttach = internal.NewFeatureTest("BPF_PROG_ATTACH", "4.10", func() error { | ||||
| var haveProgAttach = internal.NewFeatureTest("BPF_PROG_ATTACH", func() error { | ||||
| 	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ | ||||
| 		Type:    ebpf.CGroupSKB, | ||||
| 		License: "MIT", | ||||
| @@ -48,9 +48,9 @@ var haveProgAttach = internal.NewFeatureTest("BPF_PROG_ATTACH", "4.10", func() e | ||||
| 	// have the syscall. | ||||
| 	prog.Close() | ||||
| 	return nil | ||||
| }) | ||||
| }, "4.10") | ||||
|  | ||||
| var haveProgAttachReplace = internal.NewFeatureTest("BPF_PROG_ATTACH atomic replacement of MULTI progs", "5.5", func() error { | ||||
| var haveProgAttachReplace = internal.NewFeatureTest("BPF_PROG_ATTACH atomic replacement of MULTI progs", func() error { | ||||
| 	if err := haveProgAttach(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -90,9 +90,9 @@ var haveProgAttachReplace = internal.NewFeatureTest("BPF_PROG_ATTACH atomic repl | ||||
| 		return nil | ||||
| 	} | ||||
| 	return err | ||||
| }) | ||||
| }, "5.5") | ||||
|  | ||||
| var haveBPFLink = internal.NewFeatureTest("bpf_link", "5.7", func() error { | ||||
| var haveBPFLink = internal.NewFeatureTest("bpf_link", func() error { | ||||
| 	attr := sys.LinkCreateAttr{ | ||||
| 		// This is a hopefully invalid file descriptor, which triggers EBADF. | ||||
| 		TargetFd:   ^uint32(0), | ||||
| @@ -107,9 +107,9 @@ var haveBPFLink = internal.NewFeatureTest("bpf_link", "5.7", func() error { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return err | ||||
| }) | ||||
| }, "5.7") | ||||
|  | ||||
| var haveProgQuery = internal.NewFeatureTest("BPF_PROG_QUERY", "4.15", func() error { | ||||
| var haveProgQuery = internal.NewFeatureTest("BPF_PROG_QUERY", func() error { | ||||
| 	attr := sys.ProgQueryAttr{ | ||||
| 		// We rely on this being checked during the syscall. | ||||
| 		// With an otherwise correct payload we expect EBADF here | ||||
| @@ -127,9 +127,9 @@ var haveProgQuery = internal.NewFeatureTest("BPF_PROG_QUERY", "4.15", func() err | ||||
| 		return ErrNotSupported | ||||
| 	} | ||||
| 	return errors.New("syscall succeeded unexpectedly") | ||||
| }) | ||||
| }, "4.15") | ||||
|  | ||||
| var haveTCX = internal.NewFeatureTest("tcx", "6.6", func() error { | ||||
| var haveTCX = internal.NewFeatureTest("tcx", func() error { | ||||
| 	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ | ||||
| 		Type:    ebpf.SchedCLS, | ||||
| 		License: "MIT", | ||||
| @@ -162,9 +162,9 @@ var haveTCX = internal.NewFeatureTest("tcx", "6.6", func() error { | ||||
| 		return ErrNotSupported | ||||
| 	} | ||||
| 	return errors.New("syscall succeeded unexpectedly") | ||||
| }) | ||||
| }, "6.6") | ||||
|  | ||||
| var haveNetkit = internal.NewFeatureTest("netkit", "6.7", func() error { | ||||
| var haveNetkit = internal.NewFeatureTest("netkit", func() error { | ||||
| 	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ | ||||
| 		Type:    ebpf.SchedCLS, | ||||
| 		License: "MIT", | ||||
| @@ -197,4 +197,4 @@ var haveNetkit = internal.NewFeatureTest("netkit", "6.7", func() error { | ||||
| 		return ErrNotSupported | ||||
| 	} | ||||
| 	return errors.New("syscall succeeded unexpectedly") | ||||
| }) | ||||
| }, "6.7") | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/cilium/ebpf/link/tracing.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/cilium/ebpf/link/tracing.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -14,7 +14,7 @@ type tracing struct { | ||||
| 	RawLink | ||||
| } | ||||
|  | ||||
| func (f *tracing) Update(new *ebpf.Program) error { | ||||
| func (f *tracing) Update(_ *ebpf.Program) error { | ||||
| 	return fmt.Errorf("tracing update: %w", ErrNotSupported) | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										6
									
								
								vendor/github.com/cilium/ebpf/link/uprobe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/cilium/ebpf/link/uprobe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -16,7 +16,7 @@ var ( | ||||
| 	uprobeRefCtrOffsetPMUPath = "/sys/bus/event_source/devices/uprobe/format/ref_ctr_offset" | ||||
| 	// elixir.bootlin.com/linux/v5.15-rc7/source/kernel/events/core.c#L9799 | ||||
| 	uprobeRefCtrOffsetShift = 32 | ||||
| 	haveRefCtrOffsetPMU     = internal.NewFeatureTest("RefCtrOffsetPMU", "4.20", func() error { | ||||
| 	haveRefCtrOffsetPMU     = internal.NewFeatureTest("RefCtrOffsetPMU", func() error { | ||||
| 		_, err := os.Stat(uprobeRefCtrOffsetPMUPath) | ||||
| 		if errors.Is(err, os.ErrNotExist) { | ||||
| 			return internal.ErrNotSupported | ||||
| @@ -25,7 +25,7 @@ var ( | ||||
| 			return err | ||||
| 		} | ||||
| 		return nil | ||||
| 	}) | ||||
| 	}, "4.20") | ||||
|  | ||||
| 	// ErrNoSymbol indicates that the given symbol was not found | ||||
| 	// in the ELF symbols table. | ||||
| @@ -321,7 +321,7 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti | ||||
| 	if err == nil { | ||||
| 		return tp, nil | ||||
| 	} | ||||
| 	if err != nil && !errors.Is(err, ErrNotSupported) { | ||||
| 	if !errors.Is(err, ErrNotSupported) { | ||||
| 		return nil, fmt.Errorf("creating perf_uprobe PMU: %w", err) | ||||
| 	} | ||||
|  | ||||
|   | ||||
							
								
								
									
										13
									
								
								vendor/github.com/cilium/ebpf/link/uprobe_multi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/cilium/ebpf/link/uprobe_multi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -47,7 +47,7 @@ func (ex *Executable) UretprobeMulti(symbols []string, prog *ebpf.Program, opts | ||||
| 	// The return probe is not limited for symbols entry, so there's no special | ||||
| 	// setup for return uprobes (other than the extra flag). The symbols, opts.Offsets | ||||
| 	// and opts.Addresses arrays follow the same logic as for entry uprobes. | ||||
| 	return ex.uprobeMulti(symbols, prog, opts, unix.BPF_F_UPROBE_MULTI_RETURN) | ||||
| 	return ex.uprobeMulti(symbols, prog, opts, sys.BPF_F_UPROBE_MULTI_RETURN) | ||||
| } | ||||
|  | ||||
| func (ex *Executable) uprobeMulti(symbols []string, prog *ebpf.Program, opts *UprobeMultiOptions, flags uint32) (Link, error) { | ||||
| @@ -99,8 +99,11 @@ func (ex *Executable) uprobeMulti(symbols []string, prog *ebpf.Program, opts *Up | ||||
| 	if errors.Is(err, unix.ESRCH) { | ||||
| 		return nil, fmt.Errorf("%w (specified pid not found?)", os.ErrNotExist) | ||||
| 	} | ||||
| 	// Since Linux commit 46ba0e49b642 ("bpf: fix multi-uprobe PID filtering | ||||
| 	// logic"), if the provided pid overflows MaxInt32 (turning it negative), the | ||||
| 	// kernel will return EINVAL instead of ESRCH. | ||||
| 	if errors.Is(err, unix.EINVAL) { | ||||
| 		return nil, fmt.Errorf("%w (missing symbol or prog's AttachType not AttachTraceUprobeMulti?)", err) | ||||
| 		return nil, fmt.Errorf("%w (invalid pid, missing symbol or prog's AttachType not AttachTraceUprobeMulti?)", err) | ||||
| 	} | ||||
|  | ||||
| 	if err != nil { | ||||
| @@ -168,11 +171,11 @@ type uprobeMultiLink struct { | ||||
|  | ||||
| var _ Link = (*uprobeMultiLink)(nil) | ||||
|  | ||||
| func (kml *uprobeMultiLink) Update(prog *ebpf.Program) error { | ||||
| func (kml *uprobeMultiLink) Update(_ *ebpf.Program) error { | ||||
| 	return fmt.Errorf("update uprobe_multi: %w", ErrNotSupported) | ||||
| } | ||||
|  | ||||
| var haveBPFLinkUprobeMulti = internal.NewFeatureTest("bpf_link_uprobe_multi", "6.6", func() error { | ||||
| var haveBPFLinkUprobeMulti = internal.NewFeatureTest("bpf_link_uprobe_multi", func() error { | ||||
| 	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ | ||||
| 		Name: "probe_upm_link", | ||||
| 		Type: ebpf.Kprobe, | ||||
| @@ -213,4 +216,4 @@ var haveBPFLinkUprobeMulti = internal.NewFeatureTest("bpf_link_uprobe_multi", "6 | ||||
| 	// should not happen | ||||
| 	fd.Close() | ||||
| 	return errors.New("successfully attached uprobe_multi to /, kernel bug?") | ||||
| }) | ||||
| }, "6.6") | ||||
|   | ||||
							
								
								
									
										41
									
								
								vendor/github.com/cilium/ebpf/linker.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/cilium/ebpf/linker.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -9,10 +9,12 @@ import ( | ||||
| 	"io/fs" | ||||
| 	"math" | ||||
| 	"slices" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/asm" | ||||
| 	"github.com/cilium/ebpf/btf" | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/kallsyms" | ||||
| ) | ||||
|  | ||||
| // handles stores handle objects to avoid gc cleanup | ||||
| @@ -457,3 +459,42 @@ func resolveKconfigReferences(insns asm.Instructions) (_ *Map, err error) { | ||||
|  | ||||
| 	return kconfig, nil | ||||
| } | ||||
|  | ||||
| func resolveKsymReferences(insns asm.Instructions) error { | ||||
| 	var missing []string | ||||
|  | ||||
| 	iter := insns.Iterate() | ||||
| 	for iter.Next() { | ||||
| 		ins := iter.Ins | ||||
| 		meta, _ := ins.Metadata.Get(ksymMetaKey{}).(*ksymMeta) | ||||
| 		if meta == nil { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		addr, err := kallsyms.Address(meta.Name) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("resolve ksym %s: %w", meta.Name, err) | ||||
| 		} | ||||
| 		if addr != 0 { | ||||
| 			ins.Constant = int64(addr) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if meta.Binding == elf.STB_WEAK { | ||||
| 			// A weak ksym variable in eBPF C means its resolution is optional. | ||||
| 			// Set a zero constant explicitly for clarity. | ||||
| 			ins.Constant = 0 | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if !slices.Contains(missing, meta.Name) { | ||||
| 			missing = append(missing, meta.Name) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(missing) > 0 { | ||||
| 		return fmt.Errorf("kernel is missing symbol: %s", strings.Join(missing, ",")) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
							
								
								
									
										127
									
								
								vendor/github.com/cilium/ebpf/map.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										127
									
								
								vendor/github.com/cilium/ebpf/map.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -66,16 +66,13 @@ type MapSpec struct { | ||||
| 	Pinning PinType | ||||
|  | ||||
| 	// Specify numa node during map creation | ||||
| 	// (effective only if unix.BPF_F_NUMA_NODE flag is set, | ||||
| 	// (effective only if sys.BPF_F_NUMA_NODE flag is set, | ||||
| 	// which can be imported from golang.org/x/sys/unix) | ||||
| 	NumaNode uint32 | ||||
|  | ||||
| 	// The initial contents of the map. May be nil. | ||||
| 	Contents []MapKV | ||||
|  | ||||
| 	// Whether to freeze a map after setting its initial contents. | ||||
| 	Freeze bool | ||||
|  | ||||
| 	// InnerMap is used as a template for ArrayOfMaps and HashOfMaps | ||||
| 	InnerMap *MapSpec | ||||
|  | ||||
| @@ -161,6 +158,17 @@ func (spec *MapSpec) fixupMagicFields() (*MapSpec, error) { | ||||
| 			// behaviour in the past. | ||||
| 			spec.MaxEntries = n | ||||
| 		} | ||||
|  | ||||
| 	case CPUMap: | ||||
| 		n, err := PossibleCPU() | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("fixup cpu map: %w", err) | ||||
| 		} | ||||
|  | ||||
| 		if n := uint32(n); spec.MaxEntries == 0 || spec.MaxEntries > n { | ||||
| 			// Perform clamping similar to PerfEventArray. | ||||
| 			spec.MaxEntries = n | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return spec, nil | ||||
| @@ -190,6 +198,14 @@ func (ms *MapSpec) dataSection() ([]byte, *btf.Datasec, error) { | ||||
| 	return value, ds, nil | ||||
| } | ||||
|  | ||||
| func (ms *MapSpec) readOnly() bool { | ||||
| 	return (ms.Flags & sys.BPF_F_RDONLY_PROG) > 0 | ||||
| } | ||||
|  | ||||
| func (ms *MapSpec) writeOnly() bool { | ||||
| 	return (ms.Flags & sys.BPF_F_WRONLY_PROG) > 0 | ||||
| } | ||||
|  | ||||
| // MapKV is used to initialize the contents of a Map. | ||||
| type MapKV struct { | ||||
| 	Key   interface{} | ||||
| @@ -222,7 +238,7 @@ func (ms *MapSpec) Compatible(m *Map) error { | ||||
|  | ||||
| 	// BPF_F_RDONLY_PROG is set unconditionally for devmaps. Explicitly allow this | ||||
| 	// mismatch. | ||||
| 	if !((ms.Type == DevMap || ms.Type == DevMapHash) && m.flags^ms.Flags == unix.BPF_F_RDONLY_PROG) && | ||||
| 	if !((ms.Type == DevMap || ms.Type == DevMapHash) && m.flags^ms.Flags == sys.BPF_F_RDONLY_PROG) && | ||||
| 		m.flags != ms.Flags { | ||||
| 		diffs = append(diffs, fmt.Sprintf("Flags: %d changed to %d", m.flags, ms.Flags)) | ||||
| 	} | ||||
| @@ -254,6 +270,8 @@ type Map struct { | ||||
| 	pinnedPath string | ||||
| 	// Per CPU maps return values larger than the size in the spec | ||||
| 	fullValueSize int | ||||
|  | ||||
| 	memory *Memory | ||||
| } | ||||
|  | ||||
| // NewMapFromFD creates a map from a raw fd. | ||||
| @@ -359,7 +377,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions) (_ *Map, err error) { | ||||
| 			return nil, errors.New("inner maps cannot be pinned") | ||||
| 		} | ||||
|  | ||||
| 		template, err := spec.InnerMap.createMap(nil, opts) | ||||
| 		template, err := spec.InnerMap.createMap(nil) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("inner map: %w", err) | ||||
| 		} | ||||
| @@ -371,7 +389,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions) (_ *Map, err error) { | ||||
| 		innerFd = template.fd | ||||
| 	} | ||||
|  | ||||
| 	m, err := spec.createMap(innerFd, opts) | ||||
| 	m, err := spec.createMap(innerFd) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -387,9 +405,54 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions) (_ *Map, err error) { | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| // Memory returns a memory-mapped region for the Map. The Map must have been | ||||
| // created with the BPF_F_MMAPABLE flag. Repeated calls to Memory return the | ||||
| // same mapping. Callers are responsible for coordinating access to Memory. | ||||
| func (m *Map) Memory() (*Memory, error) { | ||||
| 	if m.memory != nil { | ||||
| 		return m.memory, nil | ||||
| 	} | ||||
|  | ||||
| 	if m.flags&sys.BPF_F_MMAPABLE == 0 { | ||||
| 		return nil, fmt.Errorf("Map was not created with the BPF_F_MMAPABLE flag: %w", ErrNotSupported) | ||||
| 	} | ||||
|  | ||||
| 	size, err := m.memorySize() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	mm, err := newMemory(m.FD(), size) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("creating new Memory: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	m.memory = mm | ||||
|  | ||||
| 	return mm, nil | ||||
| } | ||||
|  | ||||
| func (m *Map) memorySize() (int, error) { | ||||
| 	switch m.Type() { | ||||
| 	case Array: | ||||
| 		// In Arrays, values are always laid out on 8-byte boundaries regardless of | ||||
| 		// architecture. Multiply by MaxEntries and align the result to the host's | ||||
| 		// page size. | ||||
| 		size := int(internal.Align(m.ValueSize(), 8) * m.MaxEntries()) | ||||
| 		size = internal.Align(size, os.Getpagesize()) | ||||
| 		return size, nil | ||||
| 	case Arena: | ||||
| 		// For Arenas, MaxEntries denotes the maximum number of pages available to | ||||
| 		// the arena. | ||||
| 		return int(m.MaxEntries()) * os.Getpagesize(), nil | ||||
| 	} | ||||
|  | ||||
| 	return 0, fmt.Errorf("determine memory size of map type %s: %w", m.Type(), ErrNotSupported) | ||||
| } | ||||
|  | ||||
| // createMap validates the spec's properties and creates the map in the kernel | ||||
| // using the given opts. It does not populate or freeze the map. | ||||
| func (spec *MapSpec) createMap(inner *sys.FD, opts MapOptions) (_ *Map, err error) { | ||||
| func (spec *MapSpec) createMap(inner *sys.FD) (_ *Map, err error) { | ||||
| 	closeOnError := func(closer io.Closer) { | ||||
| 		if err != nil { | ||||
| 			closer.Close() | ||||
| @@ -416,7 +479,7 @@ func (spec *MapSpec) createMap(inner *sys.FD, opts MapOptions) (_ *Map, err erro | ||||
| 		KeySize:    spec.KeySize, | ||||
| 		ValueSize:  spec.ValueSize, | ||||
| 		MaxEntries: spec.MaxEntries, | ||||
| 		MapFlags:   sys.MapFlags(spec.Flags), | ||||
| 		MapFlags:   spec.Flags, | ||||
| 		NumaNode:   spec.NumaNode, | ||||
| 	} | ||||
|  | ||||
| @@ -474,32 +537,32 @@ func handleMapCreateError(attr sys.MapCreateAttr, spec *MapSpec, err error) erro | ||||
| 	if errors.Is(err, unix.EINVAL) && spec.Type == UnspecifiedMap { | ||||
| 		return fmt.Errorf("map create: cannot use type %s", UnspecifiedMap) | ||||
| 	} | ||||
| 	if errors.Is(err, unix.EINVAL) && spec.Flags&unix.BPF_F_NO_PREALLOC > 0 { | ||||
| 	if errors.Is(err, unix.EINVAL) && spec.Flags&sys.BPF_F_NO_PREALLOC > 0 { | ||||
| 		return fmt.Errorf("map create: %w (noPrealloc flag may be incompatible with map type %s)", err, spec.Type) | ||||
| 	} | ||||
|  | ||||
| 	switch spec.Type { | ||||
| 	case ArrayOfMaps, HashOfMaps: | ||||
| 	if spec.Type.canStoreMap() { | ||||
| 		if haveFeatErr := haveNestedMaps(); haveFeatErr != nil { | ||||
| 			return fmt.Errorf("map create: %w", haveFeatErr) | ||||
| 		} | ||||
| 	} | ||||
| 	if spec.Flags&(unix.BPF_F_RDONLY_PROG|unix.BPF_F_WRONLY_PROG) > 0 || spec.Freeze { | ||||
|  | ||||
| 	if spec.readOnly() || spec.writeOnly() { | ||||
| 		if haveFeatErr := haveMapMutabilityModifiers(); haveFeatErr != nil { | ||||
| 			return fmt.Errorf("map create: %w", haveFeatErr) | ||||
| 		} | ||||
| 	} | ||||
| 	if spec.Flags&unix.BPF_F_MMAPABLE > 0 { | ||||
| 	if spec.Flags&sys.BPF_F_MMAPABLE > 0 { | ||||
| 		if haveFeatErr := haveMmapableMaps(); haveFeatErr != nil { | ||||
| 			return fmt.Errorf("map create: %w", haveFeatErr) | ||||
| 		} | ||||
| 	} | ||||
| 	if spec.Flags&unix.BPF_F_INNER_MAP > 0 { | ||||
| 	if spec.Flags&sys.BPF_F_INNER_MAP > 0 { | ||||
| 		if haveFeatErr := haveInnerMaps(); haveFeatErr != nil { | ||||
| 			return fmt.Errorf("map create: %w", haveFeatErr) | ||||
| 		} | ||||
| 	} | ||||
| 	if spec.Flags&unix.BPF_F_NO_PREALLOC > 0 { | ||||
| 	if spec.Flags&sys.BPF_F_NO_PREALLOC > 0 { | ||||
| 		if haveFeatErr := haveNoPreallocMaps(); haveFeatErr != nil { | ||||
| 			return fmt.Errorf("map create: %w", haveFeatErr) | ||||
| 		} | ||||
| @@ -530,6 +593,7 @@ func newMap(fd *sys.FD, name string, typ MapType, keySize, valueSize, maxEntries | ||||
| 		flags, | ||||
| 		"", | ||||
| 		int(valueSize), | ||||
| 		nil, | ||||
| 	} | ||||
|  | ||||
| 	if !typ.hasPerCPUValue() { | ||||
| @@ -577,7 +641,12 @@ func (m *Map) Flags() uint32 { | ||||
| 	return m.flags | ||||
| } | ||||
|  | ||||
| // Info returns metadata about the map. | ||||
| // Info returns metadata about the map. This was first introduced in Linux 4.5, | ||||
| // but newer kernels support more MapInfo fields with the introduction of more | ||||
| // features. See [MapInfo] and its methods for more details. | ||||
| // | ||||
| // Returns an error wrapping ErrNotSupported if the kernel supports neither | ||||
| // BPF_OBJ_GET_INFO_BY_FD nor reading map information from /proc/self/fdinfo. | ||||
| func (m *Map) Info() (*MapInfo, error) { | ||||
| 	return newMapInfoFromFd(m.fd) | ||||
| } | ||||
| @@ -604,7 +673,7 @@ func (m *Map) Handle() (*btf.Handle, error) { | ||||
| type MapLookupFlags uint64 | ||||
|  | ||||
| // LookupLock look up the value of a spin-locked map. | ||||
| const LookupLock MapLookupFlags = unix.BPF_F_LOCK | ||||
| const LookupLock MapLookupFlags = sys.BPF_F_LOCK | ||||
|  | ||||
| // Lookup retrieves a value from a Map. | ||||
| // | ||||
| @@ -1336,6 +1405,7 @@ func (m *Map) Clone() (*Map, error) { | ||||
| 		m.flags, | ||||
| 		"", | ||||
| 		m.fullValueSize, | ||||
| 		nil, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| @@ -1349,7 +1419,7 @@ func (m *Map) Clone() (*Map, error) { | ||||
| // This requires bpffs to be mounted above fileName. | ||||
| // See https://docs.cilium.io/en/stable/network/kubernetes/configuration/#mounting-bpffs-with-systemd | ||||
| func (m *Map) Pin(fileName string) error { | ||||
| 	if err := internal.Pin(m.pinnedPath, fileName, m.fd); err != nil { | ||||
| 	if err := sys.Pin(m.pinnedPath, fileName, m.fd); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	m.pinnedPath = fileName | ||||
| @@ -1362,7 +1432,7 @@ func (m *Map) Pin(fileName string) error { | ||||
| // | ||||
| // Unpinning an unpinned Map returns nil. | ||||
| func (m *Map) Unpin() error { | ||||
| 	if err := internal.Unpin(m.pinnedPath); err != nil { | ||||
| 	if err := sys.Unpin(m.pinnedPath); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	m.pinnedPath = "" | ||||
| @@ -1400,7 +1470,7 @@ func (m *Map) finalize(spec *MapSpec) error { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if spec.Freeze { | ||||
| 	if isConstantDataSection(spec.Name) || isKconfigSection(spec.Name) { | ||||
| 		if err := m.Freeze(); err != nil { | ||||
| 			return fmt.Errorf("freezing map: %w", err) | ||||
| 		} | ||||
| @@ -1501,9 +1571,11 @@ func (m *Map) unmarshalValue(value any, buf sysenc.Buffer) error { | ||||
| 	return buf.Unmarshal(value) | ||||
| } | ||||
|  | ||||
| // LoadPinnedMap loads a Map from a BPF file. | ||||
| // LoadPinnedMap opens a Map from a pin (file) on the BPF virtual filesystem. | ||||
| // | ||||
| // Requires at least Linux 4.5. | ||||
| func LoadPinnedMap(fileName string, opts *LoadPinOptions) (*Map, error) { | ||||
| 	fd, err := sys.ObjGet(&sys.ObjGetAttr{ | ||||
| 	fd, typ, err := sys.ObjGetTyped(&sys.ObjGetAttr{ | ||||
| 		Pathname:  sys.NewStringPointer(fileName), | ||||
| 		FileFlags: opts.Marshal(), | ||||
| 	}) | ||||
| @@ -1511,6 +1583,11 @@ func LoadPinnedMap(fileName string, opts *LoadPinOptions) (*Map, error) { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if typ != sys.BPF_TYPE_MAP { | ||||
| 		_ = fd.Close() | ||||
| 		return nil, fmt.Errorf("%s is not a Map", fileName) | ||||
| 	} | ||||
|  | ||||
| 	m, err := newMapFromFD(fd) | ||||
| 	if err == nil { | ||||
| 		m.pinnedPath = fileName | ||||
| @@ -1530,6 +1607,10 @@ func unmarshalMap(buf sysenc.Buffer) (*Map, error) { | ||||
|  | ||||
| // marshalMap marshals the fd of a map into a buffer in host endianness. | ||||
| func marshalMap(m *Map, length int) ([]byte, error) { | ||||
| 	if m == nil { | ||||
| 		return nil, errors.New("can't marshal a nil Map") | ||||
| 	} | ||||
|  | ||||
| 	if length != 4 { | ||||
| 		return nil, fmt.Errorf("can't marshal map to %d bytes", length) | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										145
									
								
								vendor/github.com/cilium/ebpf/memory.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								vendor/github.com/cilium/ebpf/memory.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| package ebpf | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"runtime" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
|  | ||||
| // Memory is the building block for accessing the memory of specific bpf map | ||||
| // types (Array and Arena at the time of writing) without going through the bpf | ||||
| // syscall interface. | ||||
| // | ||||
| // Given the fd of a bpf map created with the BPF_F_MMAPABLE flag, a shared | ||||
| // 'file'-based memory-mapped region can be allocated in the process' address | ||||
| // space, exposing the bpf map's memory by simply accessing a memory location. | ||||
|  | ||||
| var ErrReadOnly = errors.New("resource is read-only") | ||||
|  | ||||
| // Memory implements accessing a Map's memory without making any syscalls. | ||||
| // Pay attention to the difference between Go and C struct alignment rules. Use | ||||
| // [structs.HostLayout] on supported Go versions to help with alignment. | ||||
| // | ||||
| // Note on memory coherence: avoid using packed structs in memory shared between | ||||
| // user space and eBPF C programs. This drops a struct's memory alignment to 1, | ||||
| // forcing the compiler to use single-byte loads and stores for field accesses. | ||||
| // This may lead to partially-written data to be observed from user space. | ||||
| // | ||||
| // On most architectures, the memmove implementation used by Go's copy() will | ||||
| // access data in word-sized chunks. If paired with a matching access pattern on | ||||
| // the eBPF C side (and if using default memory alignment), accessing shared | ||||
| // memory without atomics or other synchronization primitives should be sound | ||||
| // for individual values. For accesses beyond a single value, the usual | ||||
| // concurrent programming rules apply. | ||||
| type Memory struct { | ||||
| 	b  []byte | ||||
| 	ro bool | ||||
| } | ||||
|  | ||||
| func newMemory(fd, size int) (*Memory, error) { | ||||
| 	// Typically, maps created with BPF_F_RDONLY_PROG remain writable from user | ||||
| 	// space until frozen. As a security precaution, the kernel doesn't allow | ||||
| 	// mapping bpf map memory as read-write into user space if the bpf map was | ||||
| 	// frozen, or if it was created using the RDONLY_PROG flag. | ||||
| 	// | ||||
| 	// The user would be able to write to the map after freezing (since the kernel | ||||
| 	// can't change the protection mode of an already-mapped page), while the | ||||
| 	// verifier assumes the contents to be immutable. | ||||
| 	b, err := unix.Mmap(fd, 0, size, unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED) | ||||
|  | ||||
| 	// If the map is frozen when an rw mapping is requested, expect EPERM. If the | ||||
| 	// map was created with BPF_F_RDONLY_PROG, expect EACCES. | ||||
| 	var ro bool | ||||
| 	if errors.Is(err, unix.EPERM) || errors.Is(err, unix.EACCES) { | ||||
| 		ro = true | ||||
| 		b, err = unix.Mmap(fd, 0, size, unix.PROT_READ, unix.MAP_SHARED) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("setting up memory-mapped region: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	mm := &Memory{ | ||||
| 		b, | ||||
| 		ro, | ||||
| 	} | ||||
| 	runtime.SetFinalizer(mm, (*Memory).close) | ||||
|  | ||||
| 	return mm, nil | ||||
| } | ||||
|  | ||||
| func (mm *Memory) close() { | ||||
| 	if err := unix.Munmap(mm.b); err != nil { | ||||
| 		panic(fmt.Errorf("unmapping memory: %w", err)) | ||||
| 	} | ||||
| 	mm.b = nil | ||||
| } | ||||
|  | ||||
| // Size returns the size of the memory-mapped region in bytes. | ||||
| func (mm *Memory) Size() int { | ||||
| 	return len(mm.b) | ||||
| } | ||||
|  | ||||
| // ReadOnly returns true if the memory-mapped region is read-only. | ||||
| func (mm *Memory) ReadOnly() bool { | ||||
| 	return mm.ro | ||||
| } | ||||
|  | ||||
| // bounds returns true if an access at off of the given size is within bounds. | ||||
| func (mm *Memory) bounds(off uint64, size uint64) bool { | ||||
| 	return off+size < uint64(len(mm.b)) | ||||
| } | ||||
|  | ||||
| // ReadAt implements [io.ReaderAt]. Useful for creating a new [io.OffsetWriter]. | ||||
| // | ||||
| // See [Memory] for details around memory coherence. | ||||
| func (mm *Memory) ReadAt(p []byte, off int64) (int, error) { | ||||
| 	if mm.b == nil { | ||||
| 		return 0, fmt.Errorf("memory-mapped region closed") | ||||
| 	} | ||||
|  | ||||
| 	if p == nil { | ||||
| 		return 0, fmt.Errorf("input buffer p is nil") | ||||
| 	} | ||||
|  | ||||
| 	if off < 0 || off >= int64(len(mm.b)) { | ||||
| 		return 0, fmt.Errorf("read offset out of range") | ||||
| 	} | ||||
|  | ||||
| 	n := copy(p, mm.b[off:]) | ||||
| 	if n < len(p) { | ||||
| 		return n, io.EOF | ||||
| 	} | ||||
|  | ||||
| 	return n, nil | ||||
| } | ||||
|  | ||||
| // WriteAt implements [io.WriterAt]. Useful for creating a new | ||||
| // [io.SectionReader]. | ||||
| // | ||||
| // See [Memory] for details around memory coherence. | ||||
| func (mm *Memory) WriteAt(p []byte, off int64) (int, error) { | ||||
| 	if mm.b == nil { | ||||
| 		return 0, fmt.Errorf("memory-mapped region closed") | ||||
| 	} | ||||
| 	if mm.ro { | ||||
| 		return 0, fmt.Errorf("memory-mapped region not writable: %w", ErrReadOnly) | ||||
| 	} | ||||
|  | ||||
| 	if p == nil { | ||||
| 		return 0, fmt.Errorf("output buffer p is nil") | ||||
| 	} | ||||
|  | ||||
| 	if off < 0 || off >= int64(len(mm.b)) { | ||||
| 		return 0, fmt.Errorf("write offset out of range") | ||||
| 	} | ||||
|  | ||||
| 	n := copy(mm.b[off:], p) | ||||
| 	if n < len(p) { | ||||
| 		return n, io.EOF | ||||
| 	} | ||||
|  | ||||
| 	return n, nil | ||||
| } | ||||
							
								
								
									
										102
									
								
								vendor/github.com/cilium/ebpf/prog.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										102
									
								
								vendor/github.com/cilium/ebpf/prog.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -16,6 +16,7 @@ import ( | ||||
| 	"github.com/cilium/ebpf/btf" | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/kallsyms" | ||||
| 	"github.com/cilium/ebpf/internal/linux" | ||||
| 	"github.com/cilium/ebpf/internal/sys" | ||||
| 	"github.com/cilium/ebpf/internal/sysenc" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| @@ -46,14 +47,15 @@ const ( | ||||
| 	outputPad = 256 + 2 | ||||
| ) | ||||
|  | ||||
| // Deprecated: the correct log size is now detected automatically and this | ||||
| // constant is unused. | ||||
| const DefaultVerifierLogSize = 64 * 1024 | ||||
|  | ||||
| // minVerifierLogSize is the default number of bytes allocated for the | ||||
| // verifier log. | ||||
| const minVerifierLogSize = 64 * 1024 | ||||
|  | ||||
| // maxVerifierLogSize is the maximum size of verifier log buffer the kernel | ||||
| // will accept before returning EINVAL. May be increased to MaxUint32 in the | ||||
| // future, but avoid the unnecessary EINVAL for now. | ||||
| const maxVerifierLogSize = math.MaxUint32 >> 2 | ||||
|  | ||||
| // ProgramOptions control loading a program into the kernel. | ||||
| type ProgramOptions struct { | ||||
| 	// Bitmap controlling the detail emitted by the kernel's eBPF verifier log. | ||||
| @@ -73,9 +75,10 @@ type ProgramOptions struct { | ||||
| 	// attempt at loading the program. | ||||
| 	LogLevel LogLevel | ||||
|  | ||||
| 	// Deprecated: the correct log buffer size is determined automatically | ||||
| 	// and this field is ignored. | ||||
| 	LogSize int | ||||
| 	// Starting size of the verifier log buffer. If the verifier log is larger | ||||
| 	// than this size, the buffer will be grown to fit the entire log. Leave at | ||||
| 	// its default value unless troubleshooting. | ||||
| 	LogSizeStart uint32 | ||||
|  | ||||
| 	// Disables the verifier log completely, regardless of other options. | ||||
| 	LogDisabled bool | ||||
| @@ -162,26 +165,35 @@ func (ps *ProgramSpec) Tag() (string, error) { | ||||
| 	return ps.Instructions.Tag(internal.NativeEndian) | ||||
| } | ||||
|  | ||||
| // KernelModule returns the kernel module, if any, the AttachTo function is contained in. | ||||
| func (ps *ProgramSpec) KernelModule() (string, error) { | ||||
| // kernelModule returns the kernel module providing the symbol in | ||||
| // ProgramSpec.AttachTo, if any. Returns an empty string if the symbol is not | ||||
| // present or not part of a kernel module. | ||||
| func (ps *ProgramSpec) kernelModule() (string, error) { | ||||
| 	if ps.AttachTo == "" && ps.targetsKernelModule() { | ||||
| 		return kallsyms.Module(ps.AttachTo) | ||||
| 	} | ||||
|  | ||||
| 	return "", nil | ||||
| } | ||||
|  | ||||
| // targetsKernelModule returns true if the program supports being attached to a | ||||
| // symbol provided by a kernel module. | ||||
| func (ps *ProgramSpec) targetsKernelModule() bool { | ||||
| 	if ps.AttachTo == "" { | ||||
| 		return "", nil | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	switch ps.Type { | ||||
| 	default: | ||||
| 		return "", nil | ||||
| 	case Tracing: | ||||
| 		switch ps.AttachType { | ||||
| 		default: | ||||
| 			return "", nil | ||||
| 		case AttachTraceFEntry: | ||||
| 		case AttachTraceFExit: | ||||
| 		case AttachTraceFEntry, AttachTraceFExit: | ||||
| 			return true | ||||
| 		} | ||||
| 		fallthrough | ||||
| 	case Kprobe: | ||||
| 		return kallsyms.KernelModule(ps.AttachTo) | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // VerifierError is returned by [NewProgram] and [NewProgramWithOptions] if a | ||||
| @@ -261,7 +273,7 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er | ||||
| 	// Overwrite Kprobe program version if set to zero or the magic version constant. | ||||
| 	kv := spec.KernelVersion | ||||
| 	if spec.Type == Kprobe && (kv == 0 || kv == internal.MagicKernelVersion) { | ||||
| 		v, err := internal.KernelVersion() | ||||
| 		v, err := linux.KernelVersion() | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("detecting kernel version: %w", err) | ||||
| 		} | ||||
| @@ -283,7 +295,7 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er | ||||
| 	insns := make(asm.Instructions, len(spec.Instructions)) | ||||
| 	copy(insns, spec.Instructions) | ||||
|  | ||||
| 	kmodName, err := spec.KernelModule() | ||||
| 	kmodName, err := spec.kernelModule() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("kernel module search: %w", err) | ||||
| 	} | ||||
| @@ -344,6 +356,10 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er | ||||
| 	} | ||||
| 	defer kconfig.Close() | ||||
|  | ||||
| 	if err := resolveKsymReferences(insns); err != nil { | ||||
| 		return nil, fmt.Errorf("resolve .ksyms: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	if err := fixupAndValidate(insns); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -395,9 +411,10 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er | ||||
|  | ||||
| 	// The caller requested a specific verifier log level. Set up the log buffer | ||||
| 	// so that there is a chance of loading the program in a single shot. | ||||
| 	logSize := internal.Between(opts.LogSizeStart, minVerifierLogSize, maxVerifierLogSize) | ||||
| 	var logBuf []byte | ||||
| 	if !opts.LogDisabled && opts.LogLevel != 0 { | ||||
| 		logBuf = make([]byte, minVerifierLogSize) | ||||
| 		logBuf = make([]byte, logSize) | ||||
| 		attr.LogLevel = opts.LogLevel | ||||
| 		attr.LogSize = uint32(len(logBuf)) | ||||
| 		attr.LogBuf = sys.NewSlicePointer(logBuf) | ||||
| @@ -431,12 +448,11 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er | ||||
| 			attr.LogLevel = LogLevelBranch | ||||
| 		} | ||||
|  | ||||
| 		// Make an educated guess how large the buffer should be. Start | ||||
| 		// at minVerifierLogSize and then double the size. | ||||
| 		logSize := uint32(max(len(logBuf)*2, minVerifierLogSize)) | ||||
| 		if int(logSize) < len(logBuf) { | ||||
| 			return nil, errors.New("overflow while probing log buffer size") | ||||
| 		} | ||||
| 		// Make an educated guess how large the buffer should be by multiplying. | ||||
| 		// Ensure the size doesn't overflow. | ||||
| 		const factor = 2 | ||||
| 		logSize := internal.Between(logSize, minVerifierLogSize, maxVerifierLogSize/factor) | ||||
| 		logSize *= factor | ||||
|  | ||||
| 		if attr.LogTrueSize != 0 { | ||||
| 			// The kernel has given us a hint how large the log buffer has to be. | ||||
| @@ -462,6 +478,12 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er | ||||
| 			return nil, fmt.Errorf("load program: %w (MEMLOCK may be too low, consider rlimit.RemoveMemlock)", err) | ||||
| 		} | ||||
|  | ||||
| 	case errors.Is(err, unix.EFAULT): | ||||
| 		// EFAULT is returned when the kernel hits a verifier bug, and always | ||||
| 		// overrides ENOSPC, defeating the buffer growth strategy. Warn the user | ||||
| 		// that they may need to increase the buffer size manually. | ||||
| 		return nil, fmt.Errorf("load program: %w (hit verifier bug, increase LogSizeStart to fit the log and check dmesg)", err) | ||||
|  | ||||
| 	case errors.Is(err, unix.EINVAL): | ||||
| 		if bytes.Contains(tail, coreBadCall) { | ||||
| 			err = errBadRelocation | ||||
| @@ -598,7 +620,7 @@ func (p *Program) Clone() (*Program, error) { | ||||
| // This requires bpffs to be mounted above fileName. | ||||
| // See https://docs.cilium.io/en/stable/network/kubernetes/configuration/#mounting-bpffs-with-systemd | ||||
| func (p *Program) Pin(fileName string) error { | ||||
| 	if err := internal.Pin(p.pinnedPath, fileName, p.fd); err != nil { | ||||
| 	if err := sys.Pin(p.pinnedPath, fileName, p.fd); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	p.pinnedPath = fileName | ||||
| @@ -611,7 +633,7 @@ func (p *Program) Pin(fileName string) error { | ||||
| // | ||||
| // Unpinning an unpinned Program returns nil. | ||||
| func (p *Program) Unpin() error { | ||||
| 	if err := internal.Unpin(p.pinnedPath); err != nil { | ||||
| 	if err := sys.Unpin(p.pinnedPath); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	p.pinnedPath = "" | ||||
| @@ -699,6 +721,10 @@ func (p *Program) Test(in []byte) (uint32, []byte, error) { | ||||
| // | ||||
| // Note: the same restrictions from Test apply. | ||||
| func (p *Program) Run(opts *RunOptions) (uint32, error) { | ||||
| 	if opts == nil { | ||||
| 		opts = &RunOptions{} | ||||
| 	} | ||||
|  | ||||
| 	ret, _, err := p.run(opts) | ||||
| 	if err != nil { | ||||
| 		return ret, fmt.Errorf("run program: %w", err) | ||||
| @@ -732,7 +758,7 @@ func (p *Program) Benchmark(in []byte, repeat int, reset func()) (uint32, time.D | ||||
| 	return ret, total, nil | ||||
| } | ||||
|  | ||||
| var haveProgRun = internal.NewFeatureTest("BPF_PROG_RUN", "4.12", func() error { | ||||
| var haveProgRun = internal.NewFeatureTest("BPF_PROG_RUN", func() error { | ||||
| 	prog, err := NewProgram(&ProgramSpec{ | ||||
| 		// SocketFilter does not require privileges on newer kernels. | ||||
| 		Type: SocketFilter, | ||||
| @@ -774,7 +800,7 @@ var haveProgRun = internal.NewFeatureTest("BPF_PROG_RUN", "4.12", func() error { | ||||
| 	} | ||||
|  | ||||
| 	return err | ||||
| }) | ||||
| }, "4.12") | ||||
|  | ||||
| func (p *Program) run(opts *RunOptions) (uint32, time.Duration, error) { | ||||
| 	if uint(len(opts.Data)) > math.MaxUint32 { | ||||
| @@ -883,6 +909,10 @@ func unmarshalProgram(buf sysenc.Buffer) (*Program, error) { | ||||
| } | ||||
|  | ||||
| func marshalProgram(p *Program, length int) ([]byte, error) { | ||||
| 	if p == nil { | ||||
| 		return nil, errors.New("can't marshal a nil Program") | ||||
| 	} | ||||
|  | ||||
| 	if length != 4 { | ||||
| 		return nil, fmt.Errorf("can't marshal program to %d bytes", length) | ||||
| 	} | ||||
| @@ -892,11 +922,12 @@ func marshalProgram(p *Program, length int) ([]byte, error) { | ||||
| 	return buf, nil | ||||
| } | ||||
|  | ||||
| // LoadPinnedProgram loads a Program from a BPF file. | ||||
| // LoadPinnedProgram loads a Program from a pin (file) on the BPF virtual | ||||
| // filesystem. | ||||
| // | ||||
| // Requires at least Linux 4.11. | ||||
| func LoadPinnedProgram(fileName string, opts *LoadPinOptions) (*Program, error) { | ||||
| 	fd, err := sys.ObjGet(&sys.ObjGetAttr{ | ||||
| 	fd, typ, err := sys.ObjGetTyped(&sys.ObjGetAttr{ | ||||
| 		Pathname:  sys.NewStringPointer(fileName), | ||||
| 		FileFlags: opts.Marshal(), | ||||
| 	}) | ||||
| @@ -904,6 +935,11 @@ func LoadPinnedProgram(fileName string, opts *LoadPinOptions) (*Program, error) | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if typ != sys.BPF_TYPE_PROG { | ||||
| 		_ = fd.Close() | ||||
| 		return nil, fmt.Errorf("%s is not a Program", fileName) | ||||
| 	} | ||||
|  | ||||
| 	info, err := newProgramInfoFromFd(fd) | ||||
| 	if err != nil { | ||||
| 		_ = fd.Close() | ||||
|   | ||||
							
								
								
									
										80
									
								
								vendor/github.com/cilium/ebpf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										80
									
								
								vendor/github.com/cilium/ebpf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -10,6 +10,7 @@ import ( | ||||
|  | ||||
| 	"github.com/cilium/ebpf/asm" | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/linux" | ||||
| 	"github.com/cilium/ebpf/internal/sys" | ||||
| 	"github.com/cilium/ebpf/internal/tracefs" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| @@ -60,7 +61,7 @@ func progLoad(insns asm.Instructions, typ ProgramType, license string) (*sys.FD, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| var haveNestedMaps = internal.NewFeatureTest("nested maps", "4.12", func() error { | ||||
| var haveNestedMaps = internal.NewFeatureTest("nested maps", func() error { | ||||
| 	_, err := sys.MapCreate(&sys.MapCreateAttr{ | ||||
| 		MapType:    sys.MapType(ArrayOfMaps), | ||||
| 		KeySize:    4, | ||||
| @@ -76,9 +77,9 @@ var haveNestedMaps = internal.NewFeatureTest("nested maps", "4.12", func() error | ||||
| 		return nil | ||||
| 	} | ||||
| 	return err | ||||
| }) | ||||
| }, "4.12") | ||||
|  | ||||
| var haveMapMutabilityModifiers = internal.NewFeatureTest("read- and write-only maps", "5.2", func() error { | ||||
| var haveMapMutabilityModifiers = internal.NewFeatureTest("read- and write-only maps", func() 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 := sys.MapCreate(&sys.MapCreateAttr{ | ||||
| @@ -86,39 +87,39 @@ var haveMapMutabilityModifiers = internal.NewFeatureTest("read- and write-only m | ||||
| 		KeySize:    4, | ||||
| 		ValueSize:  4, | ||||
| 		MaxEntries: 1, | ||||
| 		MapFlags:   unix.BPF_F_RDONLY_PROG, | ||||
| 		MapFlags:   sys.BPF_F_RDONLY_PROG, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	_ = m.Close() | ||||
| 	return nil | ||||
| }) | ||||
| }, "5.2") | ||||
|  | ||||
| var haveMmapableMaps = internal.NewFeatureTest("mmapable maps", "5.5", func() error { | ||||
| var haveMmapableMaps = internal.NewFeatureTest("mmapable maps", func() error { | ||||
| 	// This checks BPF_F_MMAPABLE, which appeared in 5.5 for array maps. | ||||
| 	m, err := sys.MapCreate(&sys.MapCreateAttr{ | ||||
| 		MapType:    sys.MapType(Array), | ||||
| 		KeySize:    4, | ||||
| 		ValueSize:  4, | ||||
| 		MaxEntries: 1, | ||||
| 		MapFlags:   unix.BPF_F_MMAPABLE, | ||||
| 		MapFlags:   sys.BPF_F_MMAPABLE, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	_ = m.Close() | ||||
| 	return nil | ||||
| }) | ||||
| }, "5.5") | ||||
|  | ||||
| var haveInnerMaps = internal.NewFeatureTest("inner maps", "5.10", func() error { | ||||
| var haveInnerMaps = internal.NewFeatureTest("inner maps", func() error { | ||||
| 	// This checks BPF_F_INNER_MAP, which appeared in 5.10. | ||||
| 	m, err := sys.MapCreate(&sys.MapCreateAttr{ | ||||
| 		MapType:    sys.MapType(Array), | ||||
| 		KeySize:    4, | ||||
| 		ValueSize:  4, | ||||
| 		MaxEntries: 1, | ||||
| 		MapFlags:   unix.BPF_F_INNER_MAP, | ||||
| 		MapFlags:   sys.BPF_F_INNER_MAP, | ||||
| 	}) | ||||
|  | ||||
| 	if err != nil { | ||||
| @@ -126,16 +127,16 @@ var haveInnerMaps = internal.NewFeatureTest("inner maps", "5.10", func() error { | ||||
| 	} | ||||
| 	_ = m.Close() | ||||
| 	return nil | ||||
| }) | ||||
| }, "5.10") | ||||
|  | ||||
| var haveNoPreallocMaps = internal.NewFeatureTest("prealloc maps", "4.6", func() error { | ||||
| var haveNoPreallocMaps = internal.NewFeatureTest("prealloc maps", func() error { | ||||
| 	// This checks BPF_F_NO_PREALLOC, which appeared in 4.6. | ||||
| 	m, err := sys.MapCreate(&sys.MapCreateAttr{ | ||||
| 		MapType:    sys.MapType(Hash), | ||||
| 		KeySize:    4, | ||||
| 		ValueSize:  4, | ||||
| 		MaxEntries: 1, | ||||
| 		MapFlags:   unix.BPF_F_NO_PREALLOC, | ||||
| 		MapFlags:   sys.BPF_F_NO_PREALLOC, | ||||
| 	}) | ||||
|  | ||||
| 	if err != nil { | ||||
| @@ -143,7 +144,7 @@ var haveNoPreallocMaps = internal.NewFeatureTest("prealloc maps", "4.6", func() | ||||
| 	} | ||||
| 	_ = m.Close() | ||||
| 	return nil | ||||
| }) | ||||
| }, "4.6") | ||||
|  | ||||
| func wrapMapError(err error) error { | ||||
| 	if err == nil { | ||||
| @@ -169,7 +170,7 @@ func wrapMapError(err error) error { | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| var haveObjName = internal.NewFeatureTest("object names", "4.15", func() error { | ||||
| var haveObjName = internal.NewFeatureTest("object names", func() error { | ||||
| 	attr := sys.MapCreateAttr{ | ||||
| 		MapType:    sys.MapType(Array), | ||||
| 		KeySize:    4, | ||||
| @@ -178,16 +179,24 @@ var haveObjName = internal.NewFeatureTest("object names", "4.15", func() error { | ||||
| 		MapName:    sys.NewObjName("feature_test"), | ||||
| 	} | ||||
|  | ||||
| 	// Tolerate EPERM as this runs during ELF loading which is potentially | ||||
| 	// unprivileged. Only EINVAL is conclusive, thrown from CHECK_ATTR. | ||||
| 	fd, err := sys.MapCreate(&attr) | ||||
| 	if err != nil { | ||||
| 	if errors.Is(err, unix.EPERM) { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if errors.Is(err, unix.EINVAL) { | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	_ = fd.Close() | ||||
| 	return nil | ||||
| }) | ||||
| }, "4.15") | ||||
|  | ||||
| var objNameAllowsDot = internal.NewFeatureTest("dot in object names", "5.2", func() error { | ||||
| var objNameAllowsDot = internal.NewFeatureTest("dot in object names", func() error { | ||||
| 	if err := haveObjName(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -200,16 +209,25 @@ var objNameAllowsDot = internal.NewFeatureTest("dot in object names", "5.2", fun | ||||
| 		MapName:    sys.NewObjName(".test"), | ||||
| 	} | ||||
|  | ||||
| 	// Tolerate EPERM, otherwise MapSpec.Name has its dots removed when run by | ||||
| 	// unprivileged tools. (bpf2go, other code gen). Only EINVAL is conclusive, | ||||
| 	// thrown from bpf_obj_name_cpy(). | ||||
| 	fd, err := sys.MapCreate(&attr) | ||||
| 	if err != nil { | ||||
| 	if errors.Is(err, unix.EPERM) { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if errors.Is(err, unix.EINVAL) { | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	_ = fd.Close() | ||||
| 	return nil | ||||
| }) | ||||
| }, "5.2") | ||||
|  | ||||
| var haveBatchAPI = internal.NewFeatureTest("map batch api", "5.6", func() error { | ||||
| var haveBatchAPI = internal.NewFeatureTest("map batch api", func() error { | ||||
| 	var maxEntries uint32 = 2 | ||||
| 	attr := sys.MapCreateAttr{ | ||||
| 		MapType:    sys.MapType(Hash), | ||||
| @@ -239,9 +257,9 @@ var haveBatchAPI = internal.NewFeatureTest("map batch api", "5.6", func() error | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	return nil | ||||
| }) | ||||
| }, "5.6") | ||||
|  | ||||
| var haveProbeReadKernel = internal.NewFeatureTest("bpf_probe_read_kernel", "5.5", func() error { | ||||
| var haveProbeReadKernel = internal.NewFeatureTest("bpf_probe_read_kernel", func() error { | ||||
| 	insns := asm.Instructions{ | ||||
| 		asm.Mov.Reg(asm.R1, asm.R10), | ||||
| 		asm.Add.Imm(asm.R1, -8), | ||||
| @@ -257,9 +275,9 @@ var haveProbeReadKernel = internal.NewFeatureTest("bpf_probe_read_kernel", "5.5" | ||||
| 	} | ||||
| 	_ = fd.Close() | ||||
| 	return nil | ||||
| }) | ||||
| }, "5.5") | ||||
|  | ||||
| var haveBPFToBPFCalls = internal.NewFeatureTest("bpf2bpf calls", "4.16", func() error { | ||||
| var haveBPFToBPFCalls = internal.NewFeatureTest("bpf2bpf calls", func() error { | ||||
| 	insns := asm.Instructions{ | ||||
| 		asm.Call.Label("prog2").WithSymbol("prog1"), | ||||
| 		asm.Return(), | ||||
| @@ -273,10 +291,10 @@ var haveBPFToBPFCalls = internal.NewFeatureTest("bpf2bpf calls", "4.16", func() | ||||
| 	} | ||||
| 	_ = fd.Close() | ||||
| 	return nil | ||||
| }) | ||||
| }, "4.16") | ||||
|  | ||||
| var haveSyscallWrapper = internal.NewFeatureTest("syscall wrapper", "4.17", func() error { | ||||
| 	prefix := internal.PlatformPrefix() | ||||
| var haveSyscallWrapper = internal.NewFeatureTest("syscall wrapper", func() error { | ||||
| 	prefix := linux.PlatformPrefix() | ||||
| 	if prefix == "" { | ||||
| 		return fmt.Errorf("unable to find the platform prefix for (%s)", runtime.GOARCH) | ||||
| 	} | ||||
| @@ -302,9 +320,9 @@ var haveSyscallWrapper = internal.NewFeatureTest("syscall wrapper", "4.17", func | ||||
| 	} | ||||
|  | ||||
| 	return evt.Close() | ||||
| }) | ||||
| }, "4.17") | ||||
|  | ||||
| var haveProgramExtInfos = internal.NewFeatureTest("program ext_infos", "5.0", func() error { | ||||
| var haveProgramExtInfos = internal.NewFeatureTest("program ext_infos", func() error { | ||||
| 	insns := asm.Instructions{ | ||||
| 		asm.Mov.Imm(asm.R0, 0), | ||||
| 		asm.Return(), | ||||
| @@ -334,4 +352,4 @@ var haveProgramExtInfos = internal.NewFeatureTest("program ext_infos", "5.0", fu | ||||
| 	} | ||||
|  | ||||
| 	return err | ||||
| }) | ||||
| }, "5.0") | ||||
|   | ||||
							
								
								
									
										28
									
								
								vendor/github.com/cilium/ebpf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/cilium/ebpf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,7 +2,6 @@ package ebpf | ||||
|  | ||||
| import ( | ||||
| 	"github.com/cilium/ebpf/internal/sys" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
|  | ||||
| //go:generate go run golang.org/x/tools/cmd/stringer@latest -output types_string.go -type=MapType,ProgramType,PinType | ||||
| @@ -95,6 +94,14 @@ const ( | ||||
| 	InodeStorage | ||||
| 	// TaskStorage - Specialized local storage map for task_struct. | ||||
| 	TaskStorage | ||||
| 	// BloomFilter - Space-efficient data structure to quickly test whether an element exists in a set. | ||||
| 	BloomFilter | ||||
| 	// UserRingbuf - The reverse of RingBuf, used to send messages from user space to BPF programs. | ||||
| 	UserRingbuf | ||||
| 	// CgroupStorage - Store data keyed on a cgroup. If the cgroup disappears, the key is automatically removed. | ||||
| 	CgroupStorage | ||||
| 	// Arena - Sparse shared memory region between a BPF program and user space. | ||||
| 	Arena | ||||
| ) | ||||
|  | ||||
| // hasPerCPUValue returns true if the Map stores a value per CPU. | ||||
| @@ -120,6 +127,21 @@ func (mt MapType) canStoreProgram() bool { | ||||
| 	return mt == ProgramArray | ||||
| } | ||||
|  | ||||
| // canHaveValueSize returns true if the map type supports setting a value size. | ||||
| func (mt MapType) canHaveValueSize() bool { | ||||
| 	switch mt { | ||||
| 	case RingBuf, Arena: | ||||
| 		return false | ||||
|  | ||||
| 	// Special-case perf events since they require a value size of either 0 or 4 | ||||
| 	// for historical reasons. Let the library fix this up later. | ||||
| 	case PerfEventArray: | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // ProgramType of the eBPF program | ||||
| type ProgramType uint32 | ||||
|  | ||||
| @@ -263,10 +285,10 @@ func (lpo *LoadPinOptions) Marshal() uint32 { | ||||
|  | ||||
| 	flags := lpo.Flags | ||||
| 	if lpo.ReadOnly { | ||||
| 		flags |= unix.BPF_F_RDONLY | ||||
| 		flags |= sys.BPF_F_RDONLY | ||||
| 	} | ||||
| 	if lpo.WriteOnly { | ||||
| 		flags |= unix.BPF_F_WRONLY | ||||
| 		flags |= sys.BPF_F_WRONLY | ||||
| 	} | ||||
| 	return flags | ||||
| } | ||||
|   | ||||
							
								
								
									
										8
									
								
								vendor/github.com/cilium/ebpf/types_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/cilium/ebpf/types_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -38,11 +38,15 @@ func _() { | ||||
| 	_ = x[RingBuf-27] | ||||
| 	_ = x[InodeStorage-28] | ||||
| 	_ = x[TaskStorage-29] | ||||
| 	_ = x[BloomFilter-30] | ||||
| 	_ = x[UserRingbuf-31] | ||||
| 	_ = x[CgroupStorage-32] | ||||
| 	_ = x[Arena-33] | ||||
| } | ||||
|  | ||||
| const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOpsMapRingBufInodeStorageTaskStorage" | ||||
| const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOpsMapRingBufInodeStorageTaskStorageBloomFilterUserRingbufCgroupStorageArena" | ||||
|  | ||||
| var _MapType_index = [...]uint16{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248, 260, 267, 279, 290} | ||||
| var _MapType_index = [...]uint16{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248, 260, 267, 279, 290, 301, 312, 325, 330} | ||||
|  | ||||
| func (i MapType) String() string { | ||||
| 	if i >= MapType(len(_MapType_index)-1) { | ||||
|   | ||||
							
								
								
									
										230
									
								
								vendor/github.com/cilium/ebpf/variable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								vendor/github.com/cilium/ebpf/variable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,230 @@ | ||||
| package ebpf | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/btf" | ||||
| 	"github.com/cilium/ebpf/internal/sysenc" | ||||
| ) | ||||
|  | ||||
| // VariableSpec is a convenience wrapper for modifying global variables of a | ||||
| // CollectionSpec before loading it into the kernel. | ||||
| // | ||||
| // All operations on a VariableSpec's underlying MapSpec are performed in the | ||||
| // host's native endianness. | ||||
| type VariableSpec struct { | ||||
| 	name   string | ||||
| 	offset uint64 | ||||
| 	size   uint64 | ||||
|  | ||||
| 	m *MapSpec | ||||
| 	t *btf.Var | ||||
| } | ||||
|  | ||||
| // Set sets the value of the VariableSpec to the provided input using the host's | ||||
| // native endianness. | ||||
| func (s *VariableSpec) Set(in any) error { | ||||
| 	buf, err := sysenc.Marshal(in, int(s.size)) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("marshaling value %s: %w", s.name, err) | ||||
| 	} | ||||
|  | ||||
| 	b, _, err := s.m.dataSection() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("getting data section of map %s: %w", s.m.Name, err) | ||||
| 	} | ||||
|  | ||||
| 	if int(s.offset+s.size) > len(b) { | ||||
| 		return fmt.Errorf("offset %d(+%d) for variable %s is out of bounds", s.offset, s.size, s.name) | ||||
| 	} | ||||
|  | ||||
| 	// MapSpec.Copy() performs a shallow copy. Fully copy the byte slice | ||||
| 	// to avoid any changes affecting other copies of the MapSpec. | ||||
| 	cpy := make([]byte, len(b)) | ||||
| 	copy(cpy, b) | ||||
|  | ||||
| 	buf.CopyTo(cpy[s.offset : s.offset+s.size]) | ||||
|  | ||||
| 	s.m.Contents[0] = MapKV{Key: uint32(0), Value: cpy} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Get writes the value of the VariableSpec to the provided output using the | ||||
| // host's native endianness. | ||||
| func (s *VariableSpec) Get(out any) error { | ||||
| 	b, _, err := s.m.dataSection() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("getting data section of map %s: %w", s.m.Name, err) | ||||
| 	} | ||||
|  | ||||
| 	if int(s.offset+s.size) > len(b) { | ||||
| 		return fmt.Errorf("offset %d(+%d) for variable %s is out of bounds", s.offset, s.size, s.name) | ||||
| 	} | ||||
|  | ||||
| 	if err := sysenc.Unmarshal(out, b[s.offset:s.offset+s.size]); err != nil { | ||||
| 		return fmt.Errorf("unmarshaling value: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Size returns the size of the variable in bytes. | ||||
| func (s *VariableSpec) Size() uint64 { | ||||
| 	return s.size | ||||
| } | ||||
|  | ||||
| // MapName returns the name of the underlying MapSpec. | ||||
| func (s *VariableSpec) MapName() string { | ||||
| 	return s.m.Name | ||||
| } | ||||
|  | ||||
| // Offset returns the offset of the variable in the underlying MapSpec. | ||||
| func (s *VariableSpec) Offset() uint64 { | ||||
| 	return s.offset | ||||
| } | ||||
|  | ||||
| // Constant returns true if the VariableSpec represents a variable that is | ||||
| // read-only from the perspective of the BPF program. | ||||
| func (s *VariableSpec) Constant() bool { | ||||
| 	return s.m.readOnly() | ||||
| } | ||||
|  | ||||
| // Type returns the [btf.Var] representing the variable in its data section. | ||||
| // This is useful for inspecting the variable's decl tags and the type | ||||
| // information of the inner type. | ||||
| // | ||||
| // Returns nil if the original ELF object did not contain BTF information. | ||||
| func (s *VariableSpec) Type() *btf.Var { | ||||
| 	return s.t | ||||
| } | ||||
|  | ||||
| func (s *VariableSpec) String() string { | ||||
| 	return fmt.Sprintf("%s (type=%v, map=%s, offset=%d, size=%d)", s.name, s.t, s.m.Name, s.offset, s.size) | ||||
| } | ||||
|  | ||||
| // copy returns a new VariableSpec with the same values as the original, | ||||
| // but with a different underlying MapSpec. This is useful when copying a | ||||
| // CollectionSpec. Returns nil if a MapSpec with the same name is not found. | ||||
| func (s *VariableSpec) copy(cpy *CollectionSpec) *VariableSpec { | ||||
| 	out := &VariableSpec{ | ||||
| 		name:   s.name, | ||||
| 		offset: s.offset, | ||||
| 		size:   s.size, | ||||
| 	} | ||||
| 	if s.t != nil { | ||||
| 		out.t = btf.Copy(s.t).(*btf.Var) | ||||
| 	} | ||||
|  | ||||
| 	// Attempt to find a MapSpec with the same name in the copied CollectionSpec. | ||||
| 	for _, m := range cpy.Maps { | ||||
| 		if m.Name == s.m.Name { | ||||
| 			out.m = m | ||||
| 			return out | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Variable is a convenience wrapper for modifying global variables of a | ||||
| // Collection after loading it into the kernel. Operations on a Variable are | ||||
| // performed using direct memory access, bypassing the BPF map syscall API. | ||||
| // | ||||
| // On kernels older than 5.5, most interactions with Variable return | ||||
| // [ErrNotSupported]. | ||||
| type Variable struct { | ||||
| 	name   string | ||||
| 	offset uint64 | ||||
| 	size   uint64 | ||||
| 	t      *btf.Var | ||||
|  | ||||
| 	mm *Memory | ||||
| } | ||||
|  | ||||
| func newVariable(name string, offset, size uint64, t *btf.Var, mm *Memory) (*Variable, error) { | ||||
| 	if mm != nil { | ||||
| 		if int(offset+size) > mm.Size() { | ||||
| 			return nil, fmt.Errorf("offset %d(+%d) is out of bounds", offset, size) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return &Variable{ | ||||
| 		name:   name, | ||||
| 		offset: offset, | ||||
| 		size:   size, | ||||
| 		t:      t, | ||||
| 		mm:     mm, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // Size returns the size of the variable. | ||||
| func (v *Variable) Size() uint64 { | ||||
| 	return v.size | ||||
| } | ||||
|  | ||||
| // ReadOnly returns true if the Variable represents a variable that is read-only | ||||
| // after loading the Collection into the kernel. | ||||
| // | ||||
| // On systems without BPF_F_MMAPABLE support, ReadOnly always returns true. | ||||
| func (v *Variable) ReadOnly() bool { | ||||
| 	if v.mm == nil { | ||||
| 		return true | ||||
| 	} | ||||
| 	return v.mm.ReadOnly() | ||||
| } | ||||
|  | ||||
| // Type returns the [btf.Var] representing the variable in its data section. | ||||
| // This is useful for inspecting the variable's decl tags and the type | ||||
| // information of the inner type. | ||||
| // | ||||
| // Returns nil if the original ELF object did not contain BTF information. | ||||
| func (v *Variable) Type() *btf.Var { | ||||
| 	return v.t | ||||
| } | ||||
|  | ||||
| func (v *Variable) String() string { | ||||
| 	return fmt.Sprintf("%s (type=%v)", v.name, v.t) | ||||
| } | ||||
|  | ||||
| // Set the value of the Variable to the provided input. The input must marshal | ||||
| // to the same length as the size of the Variable. | ||||
| func (v *Variable) Set(in any) error { | ||||
| 	if v.mm == nil { | ||||
| 		return fmt.Errorf("variable %s: direct access requires Linux 5.5 or later: %w", v.name, ErrNotSupported) | ||||
| 	} | ||||
|  | ||||
| 	if v.ReadOnly() { | ||||
| 		return fmt.Errorf("variable %s: %w", v.name, ErrReadOnly) | ||||
| 	} | ||||
|  | ||||
| 	buf, err := sysenc.Marshal(in, int(v.size)) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("marshaling value %s: %w", v.name, err) | ||||
| 	} | ||||
|  | ||||
| 	if _, err := v.mm.WriteAt(buf.Bytes(), int64(v.offset)); err != nil { | ||||
| 		return fmt.Errorf("writing value to %s: %w", v.name, err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Get writes the value of the Variable to the provided output. The output must | ||||
| // be a pointer to a value whose size matches the Variable. | ||||
| func (v *Variable) Get(out any) error { | ||||
| 	if v.mm == nil { | ||||
| 		return fmt.Errorf("variable %s: direct access requires Linux 5.5 or later: %w", v.name, ErrNotSupported) | ||||
| 	} | ||||
|  | ||||
| 	if !v.mm.bounds(v.offset, v.size) { | ||||
| 		return fmt.Errorf("variable %s: access out of bounds: %w", v.name, io.EOF) | ||||
| 	} | ||||
|  | ||||
| 	if err := sysenc.Unmarshal(out, v.mm.b[v.offset:v.offset+v.size]); err != nil { | ||||
| 		return fmt.Errorf("unmarshaling value %s: %w", v.name, err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										27
									
								
								vendor/golang.org/x/exp/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/golang.org/x/exp/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,27 +0,0 @@ | ||||
| Copyright (c) 2009 The Go Authors. All rights reserved. | ||||
|  | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are | ||||
| met: | ||||
|  | ||||
|    * Redistributions of source code must retain the above copyright | ||||
| notice, this list of conditions and the following disclaimer. | ||||
|    * Redistributions in binary form must reproduce the above | ||||
| copyright notice, this list of conditions and the following disclaimer | ||||
| in the documentation and/or other materials provided with the | ||||
| distribution. | ||||
|    * Neither the name of Google Inc. nor the names of its | ||||
| contributors may be used to endorse or promote products derived from | ||||
| this software without specific prior written permission. | ||||
|  | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										22
									
								
								vendor/golang.org/x/exp/PATENTS
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/golang.org/x/exp/PATENTS
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,22 +0,0 @@ | ||||
| Additional IP Rights Grant (Patents) | ||||
|  | ||||
| "This implementation" means the copyrightable works distributed by | ||||
| Google as part of the Go project. | ||||
|  | ||||
| Google hereby grants to You a perpetual, worldwide, non-exclusive, | ||||
| no-charge, royalty-free, irrevocable (except as stated in this section) | ||||
| patent license to make, have made, use, offer to sell, sell, import, | ||||
| transfer and otherwise run, modify and propagate the contents of this | ||||
| implementation of Go, where such license applies only to those patent | ||||
| claims, both currently owned or controlled by Google and acquired in | ||||
| the future, licensable by Google that are necessarily infringed by this | ||||
| implementation of Go.  This grant does not include claims that would be | ||||
| infringed only as a consequence of further modification of this | ||||
| implementation.  If you or your agent or exclusive licensee institute or | ||||
| order or agree to the institution of patent litigation against any | ||||
| entity (including a cross-claim or counterclaim in a lawsuit) alleging | ||||
| that this implementation of Go or any code incorporated within this | ||||
| implementation of Go constitutes direct or contributory patent | ||||
| infringement, or inducement of patent infringement, then any patent | ||||
| rights granted to you under this License for this implementation of Go | ||||
| shall terminate as of the date such litigation is filed. | ||||
							
								
								
									
										50
									
								
								vendor/golang.org/x/exp/constraints/constraints.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										50
									
								
								vendor/golang.org/x/exp/constraints/constraints.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,50 +0,0 @@ | ||||
| // Copyright 2021 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| // Package constraints defines a set of useful constraints to be used | ||||
| // with type parameters. | ||||
| package constraints | ||||
|  | ||||
| // Signed is a constraint that permits any signed integer type. | ||||
| // If future releases of Go add new predeclared signed integer types, | ||||
| // this constraint will be modified to include them. | ||||
| type Signed interface { | ||||
| 	~int | ~int8 | ~int16 | ~int32 | ~int64 | ||||
| } | ||||
|  | ||||
| // Unsigned is a constraint that permits any unsigned integer type. | ||||
| // If future releases of Go add new predeclared unsigned integer types, | ||||
| // this constraint will be modified to include them. | ||||
| type Unsigned interface { | ||||
| 	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ||||
| } | ||||
|  | ||||
| // Integer is a constraint that permits any integer type. | ||||
| // If future releases of Go add new predeclared integer types, | ||||
| // this constraint will be modified to include them. | ||||
| type Integer interface { | ||||
| 	Signed | Unsigned | ||||
| } | ||||
|  | ||||
| // Float is a constraint that permits any floating-point type. | ||||
| // If future releases of Go add new predeclared floating-point types, | ||||
| // this constraint will be modified to include them. | ||||
| type Float interface { | ||||
| 	~float32 | ~float64 | ||||
| } | ||||
|  | ||||
| // Complex is a constraint that permits any complex numeric type. | ||||
| // If future releases of Go add new predeclared complex numeric types, | ||||
| // this constraint will be modified to include them. | ||||
| type Complex interface { | ||||
| 	~complex64 | ~complex128 | ||||
| } | ||||
|  | ||||
| // Ordered is a constraint that permits any ordered type: any type | ||||
| // that supports the operators < <= >= >. | ||||
| // If future releases of Go add new ordered types, | ||||
| // this constraint will be modified to include them. | ||||
| type Ordered interface { | ||||
| 	Integer | Float | ~string | ||||
| } | ||||
							
								
								
									
										9
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							| @@ -2,16 +2,18 @@ | ||||
| ## explicit; go 1.16 | ||||
| github.com/checkpoint-restore/go-criu/v6 | ||||
| github.com/checkpoint-restore/go-criu/v6/rpc | ||||
| # github.com/cilium/ebpf v0.16.0 | ||||
| ## explicit; go 1.21 | ||||
| # github.com/cilium/ebpf v0.17.0 | ||||
| ## explicit; go 1.22 | ||||
| github.com/cilium/ebpf | ||||
| github.com/cilium/ebpf/asm | ||||
| github.com/cilium/ebpf/btf | ||||
| github.com/cilium/ebpf/internal | ||||
| github.com/cilium/ebpf/internal/kallsyms | ||||
| github.com/cilium/ebpf/internal/kconfig | ||||
| github.com/cilium/ebpf/internal/linux | ||||
| github.com/cilium/ebpf/internal/sys | ||||
| github.com/cilium/ebpf/internal/sysenc | ||||
| github.com/cilium/ebpf/internal/testutils/fdtrace | ||||
| github.com/cilium/ebpf/internal/tracefs | ||||
| github.com/cilium/ebpf/internal/unix | ||||
| github.com/cilium/ebpf/link | ||||
| @@ -78,9 +80,6 @@ github.com/vishvananda/netlink/nl | ||||
| # github.com/vishvananda/netns v0.0.4 | ||||
| ## explicit; go 1.17 | ||||
| github.com/vishvananda/netns | ||||
| # golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 | ||||
| ## explicit; go 1.18 | ||||
| golang.org/x/exp/constraints | ||||
| # golang.org/x/net v0.33.0 | ||||
| ## explicit; go 1.18 | ||||
| golang.org/x/net/bpf | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	![49699333+dependabot[bot]@users.noreply.github.com](/assets/img/avatar_default.png) dependabot[bot]
					dependabot[bot]