go.mod: github.com/opencontainers/runc v1.1.0
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
		
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,6 +5,7 @@ | ||||
| *.so | ||||
| *.dylib | ||||
| *.o | ||||
| !*_bpf*.o | ||||
|  | ||||
| # Test binary, build with `go test -c` | ||||
| *.test | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/.golangci.yaml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/.golangci.yaml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -24,6 +24,5 @@ linters: | ||||
|  | ||||
|     # Could be enabled later: | ||||
|     # - gocyclo | ||||
|     # - prealloc | ||||
|     # - maligned | ||||
|     # - gosec | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/cilium/ebpf/ARCHITECTURE.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/cilium/ebpf/ARCHITECTURE.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -57,7 +57,7 @@ Objects | ||||
| loading a spec will fail because the kernel is too old, or a feature is not | ||||
| enabled. There are multiple ways the library deals with that: | ||||
|  | ||||
| * Fallback: older kernels don't allowing naming programs and maps. The library | ||||
| * Fallback: older kernels don't allow naming programs and maps. The library | ||||
|   automatically detects support for names, and omits them during load if | ||||
|   necessary. This works since name is primarily a debug aid. | ||||
|  | ||||
| @@ -68,7 +68,7 @@ enabled. There are multiple ways the library deals with that: | ||||
| Once program and map objects are loaded they expose the kernel's low-level API, | ||||
| e.g. `NextKey`. Often this API is awkward to use in Go, so there are safer | ||||
| wrappers on top of the low-level API, like `MapIterator`. The low-level API is | ||||
| useful as an out when our higher-level API doesn't support a particular use case. | ||||
| useful when our higher-level API doesn't support a particular use case. | ||||
|  | ||||
| Links | ||||
| --- | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/cilium/ebpf/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/cilium/ebpf/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -6,8 +6,8 @@ are welcome. Please take a look at [the architecture](ARCHITECTURE.md) to get | ||||
| a better understanding for the high-level goals. | ||||
|  | ||||
| New features must be accompanied by tests. Before starting work on any large | ||||
| feature, please [join](https://cilium.herokuapp.com/) the | ||||
| [#libbpf-go](https://cilium.slack.com/messages/libbpf-go) channel on Slack to | ||||
| feature, please [join](https://ebpf.io/slack) the | ||||
| [#ebpf-go](https://cilium.slack.com/messages/ebpf-go) channel on Slack to | ||||
| discuss the design first. | ||||
|  | ||||
| When submitting pull requests, consider writing details about what problem you | ||||
|   | ||||
							
								
								
									
										5
									
								
								vendor/github.com/cilium/ebpf/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/cilium/ebpf/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -18,11 +18,14 @@ TARGETS := \ | ||||
| 	testdata/loader-clang-7 \ | ||||
| 	testdata/loader-clang-9 \ | ||||
| 	testdata/loader-$(CLANG) \ | ||||
| 	testdata/btf_map_init \ | ||||
| 	testdata/invalid_map \ | ||||
| 	testdata/raw_tracepoint \ | ||||
| 	testdata/invalid_map_static \ | ||||
| 	testdata/initialized_btf_map \ | ||||
| 	testdata/invalid_btf_map_init \ | ||||
| 	testdata/strings \ | ||||
| 	testdata/freplace \ | ||||
| 	testdata/iproute2_map_compat \ | ||||
| 	internal/btf/testdata/relocs | ||||
|  | ||||
| .PHONY: all clean docker-all docker-shell | ||||
|   | ||||
							
								
								
									
										62
									
								
								vendor/github.com/cilium/ebpf/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								vendor/github.com/cilium/ebpf/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,28 +2,16 @@ | ||||
|  | ||||
| [](https://pkg.go.dev/github.com/cilium/ebpf) | ||||
|  | ||||
|  | ||||
|  | ||||
| eBPF is a pure Go library that provides utilities for loading, compiling, and | ||||
| debugging eBPF programs. It has minimal external dependencies and is intended to | ||||
| be used in long running processes. | ||||
|  | ||||
| * [asm](https://pkg.go.dev/github.com/cilium/ebpf/asm) contains a basic | ||||
|   assembler | ||||
| * [link](https://pkg.go.dev/github.com/cilium/ebpf/link) allows attaching eBPF | ||||
|   to various hooks | ||||
| * [perf](https://pkg.go.dev/github.com/cilium/ebpf/perf) allows reading from a | ||||
|   `PERF_EVENT_ARRAY` | ||||
| * [cmd/bpf2go](https://pkg.go.dev/github.com/cilium/ebpf/cmd/bpf2go) allows | ||||
|   compiling and embedding eBPF programs in Go code | ||||
|  | ||||
| The library is maintained by [Cloudflare](https://www.cloudflare.com) and | ||||
| [Cilium](https://www.cilium.io). Feel free to | ||||
| [join](https://cilium.herokuapp.com/) the | ||||
| [#libbpf-go](https://cilium.slack.com/messages/libbpf-go) channel on Slack. | ||||
| [Cilium](https://www.cilium.io). | ||||
|  | ||||
| ## Current status | ||||
|  | ||||
| The package is production ready, but **the API is explicitly unstable right | ||||
| now**. Expect to update your code if you want to follow along. | ||||
| See [ebpf.io](https://ebpf.io) for other projects from the eBPF ecosystem. | ||||
|  | ||||
| ## Getting Started | ||||
|  | ||||
| @@ -33,21 +21,37 @@ your own tools can be found under [examples/](examples/). | ||||
| Contributions are highly encouraged, as they highlight certain use cases of | ||||
| eBPF and the library, and help shape the future of the project. | ||||
|  | ||||
| ## Getting Help | ||||
|  | ||||
| Please | ||||
| [join](https://ebpf.io/slack) the | ||||
| [#ebpf-go](https://cilium.slack.com/messages/ebpf-go) channel on Slack if you | ||||
| have questions regarding the library. | ||||
|  | ||||
| ## Packages | ||||
|  | ||||
| This library includes the following packages:  | ||||
|  | ||||
| * [asm](https://pkg.go.dev/github.com/cilium/ebpf/asm) contains a basic | ||||
|   assembler, allowing you to write eBPF assembly instructions directly | ||||
|   within your Go code. (You don't need to use this if you prefer to write your eBPF program in C.) | ||||
| * [cmd/bpf2go](https://pkg.go.dev/github.com/cilium/ebpf/cmd/bpf2go) allows | ||||
|   compiling and embedding eBPF programs written in C within Go code. As well as | ||||
|   compiling the C code, it auto-generates Go code for loading and manipulating | ||||
|   the eBPF program and map objects.  | ||||
| * [link](https://pkg.go.dev/github.com/cilium/ebpf/link) allows attaching eBPF | ||||
|   to various hooks | ||||
| * [perf](https://pkg.go.dev/github.com/cilium/ebpf/perf) allows reading from a | ||||
|   `PERF_EVENT_ARRAY` | ||||
| * [ringbuf](https://pkg.go.dev/github.com/cilium/ebpf/ringbuf) allows reading from a | ||||
|   `BPF_MAP_TYPE_RINGBUF` map | ||||
|  | ||||
|  | ||||
| ## Requirements | ||||
|  | ||||
| * A version of Go that is [supported by | ||||
|   upstream](https://golang.org/doc/devel/release.html#policy) | ||||
| * Linux 4.9, 4.19 or 5.4 (versions in-between should work, but are not tested) | ||||
|  | ||||
| ## Useful resources | ||||
|  | ||||
| * [eBPF.io](https://ebpf.io) (recommended) | ||||
| * [Cilium eBPF documentation](https://docs.cilium.io/en/latest/bpf/#bpf-guide) | ||||
|   (recommended) | ||||
| * [Linux documentation on | ||||
|   BPF](https://www.kernel.org/doc/html/latest/networking/filter.html) | ||||
| * [eBPF features by Linux | ||||
|   version](https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md) | ||||
| * Linux >= 4.9. CI is run against LTS releases. | ||||
|  | ||||
| ## Regenerating Testdata | ||||
|  | ||||
| @@ -60,3 +64,7 @@ The toolchain image build files are kept in [testdata/docker/](testdata/docker/) | ||||
| ## License | ||||
|  | ||||
| MIT | ||||
|  | ||||
| ### eBPF Gopher | ||||
|  | ||||
| The eBPF honeygopher is based on the Go gopher designed by Renee French. | ||||
|   | ||||
							
								
								
									
										6
									
								
								vendor/github.com/cilium/ebpf/asm/func.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/cilium/ebpf/asm/func.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -184,6 +184,12 @@ const ( | ||||
| 	FnKtimeGetCoarseNs | ||||
| 	FnImaInodeHash | ||||
| 	FnSockFromFile | ||||
| 	FnCheckMtu | ||||
| 	FnForEachMapElem | ||||
| 	FnSnprintf | ||||
| 	FnSysBpf | ||||
| 	FnBtfFindByNameKind | ||||
| 	FnSysClose | ||||
| ) | ||||
|  | ||||
| // Call emits a function call. | ||||
|   | ||||
							
								
								
									
										10
									
								
								vendor/github.com/cilium/ebpf/asm/func_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/cilium/ebpf/asm/func_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -171,11 +171,17 @@ func _() { | ||||
| 	_ = x[FnKtimeGetCoarseNs-160] | ||||
| 	_ = x[FnImaInodeHash-161] | ||||
| 	_ = x[FnSockFromFile-162] | ||||
| 	_ = x[FnCheckMtu-163] | ||||
| 	_ = x[FnForEachMapElem-164] | ||||
| 	_ = x[FnSnprintf-165] | ||||
| 	_ = x[FnSysBpf-166] | ||||
| 	_ = x[FnBtfFindByNameKind-167] | ||||
| 	_ = x[FnSysClose-168] | ||||
| } | ||||
|  | ||||
| const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookieFnSkbOutputFnProbeReadUserFnProbeReadKernelFnProbeReadUserStrFnProbeReadKernelStrFnTcpSendAckFnSendSignalThreadFnJiffies64FnReadBranchRecordsFnGetNsCurrentPidTgidFnXdpOutputFnGetNetnsCookieFnGetCurrentAncestorCgroupIdFnSkAssignFnKtimeGetBootNsFnSeqPrintfFnSeqWriteFnSkCgroupIdFnSkAncestorCgroupIdFnRingbufOutputFnRingbufReserveFnRingbufSubmitFnRingbufDiscardFnRingbufQueryFnCsumLevelFnSkcToTcp6SockFnSkcToTcpSockFnSkcToTcpTimewaitSockFnSkcToTcpRequestSockFnSkcToUdp6SockFnGetTaskStackFnLoadHdrOptFnStoreHdrOptFnReserveHdrOptFnInodeStorageGetFnInodeStorageDeleteFnDPathFnCopyFromUserFnSnprintfBtfFnSeqPrintfBtfFnSkbCgroupClassidFnRedirectNeighFnPerCpuPtrFnThisCpuPtrFnRedirectPeerFnTaskStorageGetFnTaskStorageDeleteFnGetCurrentTaskBtfFnBprmOptsSetFnKtimeGetCoarseNsFnImaInodeHashFnSockFromFile" | ||||
| const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookieFnSkbOutputFnProbeReadUserFnProbeReadKernelFnProbeReadUserStrFnProbeReadKernelStrFnTcpSendAckFnSendSignalThreadFnJiffies64FnReadBranchRecordsFnGetNsCurrentPidTgidFnXdpOutputFnGetNetnsCookieFnGetCurrentAncestorCgroupIdFnSkAssignFnKtimeGetBootNsFnSeqPrintfFnSeqWriteFnSkCgroupIdFnSkAncestorCgroupIdFnRingbufOutputFnRingbufReserveFnRingbufSubmitFnRingbufDiscardFnRingbufQueryFnCsumLevelFnSkcToTcp6SockFnSkcToTcpSockFnSkcToTcpTimewaitSockFnSkcToTcpRequestSockFnSkcToUdp6SockFnGetTaskStackFnLoadHdrOptFnStoreHdrOptFnReserveHdrOptFnInodeStorageGetFnInodeStorageDeleteFnDPathFnCopyFromUserFnSnprintfBtfFnSeqPrintfBtfFnSkbCgroupClassidFnRedirectNeighFnPerCpuPtrFnThisCpuPtrFnRedirectPeerFnTaskStorageGetFnTaskStorageDeleteFnGetCurrentTaskBtfFnBprmOptsSetFnKtimeGetCoarseNsFnImaInodeHashFnSockFromFileFnCheckMtuFnForEachMapElemFnSnprintfFnSysBpfFnBtfFindByNameKindFnSysClose" | ||||
|  | ||||
| var _BuiltinFunc_index = [...]uint16{0, 8, 23, 38, 53, 64, 76, 89, 104, 123, 138, 153, 168, 178, 193, 212, 230, 246, 264, 277, 289, 306, 323, 338, 348, 363, 380, 394, 406, 416, 433, 450, 466, 481, 497, 512, 528, 544, 568, 583, 596, 608, 624, 639, 654, 669, 683, 700, 714, 723, 735, 750, 763, 778, 793, 808, 828, 847, 859, 875, 894, 910, 925, 939, 952, 958, 973, 990, 1000, 1022, 1033, 1049, 1066, 1082, 1096, 1115, 1133, 1148, 1158, 1169, 1182, 1202, 1219, 1238, 1259, 1272, 1285, 1296, 1309, 1321, 1334, 1347, 1359, 1373, 1383, 1395, 1407, 1416, 1429, 1446, 1460, 1479, 1494, 1517, 1536, 1555, 1563, 1572, 1586, 1603, 1615, 1632, 1643, 1658, 1675, 1693, 1713, 1725, 1743, 1754, 1773, 1794, 1805, 1821, 1849, 1859, 1875, 1886, 1896, 1908, 1928, 1943, 1959, 1974, 1990, 2004, 2015, 2030, 2044, 2066, 2087, 2102, 2116, 2128, 2141, 2156, 2173, 2193, 2200, 2214, 2227, 2241, 2259, 2274, 2285, 2297, 2311, 2327, 2346, 2365, 2378, 2396, 2410, 2424} | ||||
| var _BuiltinFunc_index = [...]uint16{0, 8, 23, 38, 53, 64, 76, 89, 104, 123, 138, 153, 168, 178, 193, 212, 230, 246, 264, 277, 289, 306, 323, 338, 348, 363, 380, 394, 406, 416, 433, 450, 466, 481, 497, 512, 528, 544, 568, 583, 596, 608, 624, 639, 654, 669, 683, 700, 714, 723, 735, 750, 763, 778, 793, 808, 828, 847, 859, 875, 894, 910, 925, 939, 952, 958, 973, 990, 1000, 1022, 1033, 1049, 1066, 1082, 1096, 1115, 1133, 1148, 1158, 1169, 1182, 1202, 1219, 1238, 1259, 1272, 1285, 1296, 1309, 1321, 1334, 1347, 1359, 1373, 1383, 1395, 1407, 1416, 1429, 1446, 1460, 1479, 1494, 1517, 1536, 1555, 1563, 1572, 1586, 1603, 1615, 1632, 1643, 1658, 1675, 1693, 1713, 1725, 1743, 1754, 1773, 1794, 1805, 1821, 1849, 1859, 1875, 1886, 1896, 1908, 1928, 1943, 1959, 1974, 1990, 2004, 2015, 2030, 2044, 2066, 2087, 2102, 2116, 2128, 2141, 2156, 2173, 2193, 2200, 2214, 2227, 2241, 2259, 2274, 2285, 2297, 2311, 2327, 2346, 2365, 2378, 2396, 2410, 2424, 2434, 2450, 2460, 2468, 2487, 2497} | ||||
|  | ||||
| func (i BuiltinFunc) String() string { | ||||
| 	if i < 0 || i >= BuiltinFunc(len(_BuiltinFunc_index)-1) { | ||||
|   | ||||
							
								
								
									
										5
									
								
								vendor/github.com/cilium/ebpf/asm/instruction.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/cilium/ebpf/asm/instruction.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -181,6 +181,11 @@ func (ins *Instruction) IsFunctionCall() bool { | ||||
| 	return ins.OpCode.JumpOp() == Call && ins.Src == PseudoCall | ||||
| } | ||||
|  | ||||
| // IsBuiltinCall returns true if the instruction is a built-in call, i.e. BPF helper call. | ||||
| func (ins *Instruction) IsBuiltinCall() bool { | ||||
| 	return ins.OpCode.JumpOp() == Call && ins.Src == R0 && ins.Dst == R0 | ||||
| } | ||||
|  | ||||
| // IsConstantLoad returns true if the instruction loads a constant of the | ||||
| // given size. | ||||
| func (ins *Instruction) IsConstantLoad(size Size) bool { | ||||
|   | ||||
							
								
								
									
										65
									
								
								vendor/github.com/cilium/ebpf/attachtype_string.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								vendor/github.com/cilium/ebpf/attachtype_string.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| // Code generated by "stringer -type AttachType -trimprefix Attach"; DO NOT EDIT. | ||||
|  | ||||
| package ebpf | ||||
|  | ||||
| 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[AttachNone-0] | ||||
| 	_ = x[AttachCGroupInetIngress-0] | ||||
| 	_ = x[AttachCGroupInetEgress-1] | ||||
| 	_ = x[AttachCGroupInetSockCreate-2] | ||||
| 	_ = x[AttachCGroupSockOps-3] | ||||
| 	_ = x[AttachSkSKBStreamParser-4] | ||||
| 	_ = x[AttachSkSKBStreamVerdict-5] | ||||
| 	_ = x[AttachCGroupDevice-6] | ||||
| 	_ = x[AttachSkMsgVerdict-7] | ||||
| 	_ = x[AttachCGroupInet4Bind-8] | ||||
| 	_ = x[AttachCGroupInet6Bind-9] | ||||
| 	_ = x[AttachCGroupInet4Connect-10] | ||||
| 	_ = x[AttachCGroupInet6Connect-11] | ||||
| 	_ = x[AttachCGroupInet4PostBind-12] | ||||
| 	_ = x[AttachCGroupInet6PostBind-13] | ||||
| 	_ = x[AttachCGroupUDP4Sendmsg-14] | ||||
| 	_ = x[AttachCGroupUDP6Sendmsg-15] | ||||
| 	_ = x[AttachLircMode2-16] | ||||
| 	_ = x[AttachFlowDissector-17] | ||||
| 	_ = x[AttachCGroupSysctl-18] | ||||
| 	_ = x[AttachCGroupUDP4Recvmsg-19] | ||||
| 	_ = x[AttachCGroupUDP6Recvmsg-20] | ||||
| 	_ = x[AttachCGroupGetsockopt-21] | ||||
| 	_ = x[AttachCGroupSetsockopt-22] | ||||
| 	_ = x[AttachTraceRawTp-23] | ||||
| 	_ = x[AttachTraceFEntry-24] | ||||
| 	_ = x[AttachTraceFExit-25] | ||||
| 	_ = x[AttachModifyReturn-26] | ||||
| 	_ = x[AttachLSMMac-27] | ||||
| 	_ = x[AttachTraceIter-28] | ||||
| 	_ = x[AttachCgroupInet4GetPeername-29] | ||||
| 	_ = x[AttachCgroupInet6GetPeername-30] | ||||
| 	_ = x[AttachCgroupInet4GetSockname-31] | ||||
| 	_ = x[AttachCgroupInet6GetSockname-32] | ||||
| 	_ = x[AttachXDPDevMap-33] | ||||
| 	_ = x[AttachCgroupInetSockRelease-34] | ||||
| 	_ = x[AttachXDPCPUMap-35] | ||||
| 	_ = x[AttachSkLookup-36] | ||||
| 	_ = x[AttachXDP-37] | ||||
| 	_ = x[AttachSkSKBVerdict-38] | ||||
| 	_ = x[AttachSkReuseportSelect-39] | ||||
| 	_ = x[AttachSkReuseportSelectOrMigrate-40] | ||||
| 	_ = x[AttachPerfEvent-41] | ||||
| } | ||||
|  | ||||
| const _AttachType_name = "NoneCGroupInetEgressCGroupInetSockCreateCGroupSockOpsSkSKBStreamParserSkSKBStreamVerdictCGroupDeviceSkMsgVerdictCGroupInet4BindCGroupInet6BindCGroupInet4ConnectCGroupInet6ConnectCGroupInet4PostBindCGroupInet6PostBindCGroupUDP4SendmsgCGroupUDP6SendmsgLircMode2FlowDissectorCGroupSysctlCGroupUDP4RecvmsgCGroupUDP6RecvmsgCGroupGetsockoptCGroupSetsockoptTraceRawTpTraceFEntryTraceFExitModifyReturnLSMMacTraceIterCgroupInet4GetPeernameCgroupInet6GetPeernameCgroupInet4GetSocknameCgroupInet6GetSocknameXDPDevMapCgroupInetSockReleaseXDPCPUMapSkLookupXDPSkSKBVerdictSkReuseportSelectSkReuseportSelectOrMigratePerfEvent" | ||||
|  | ||||
| var _AttachType_index = [...]uint16{0, 4, 20, 40, 53, 70, 88, 100, 112, 127, 142, 160, 178, 197, 216, 233, 250, 259, 272, 284, 301, 318, 334, 350, 360, 371, 381, 393, 399, 408, 430, 452, 474, 496, 505, 526, 535, 543, 546, 558, 575, 601, 610} | ||||
|  | ||||
| func (i AttachType) String() string { | ||||
| 	if i >= AttachType(len(_AttachType_index)-1) { | ||||
| 		return "AttachType(" + strconv.FormatInt(int64(i), 10) + ")" | ||||
| 	} | ||||
| 	return _AttachType_name[_AttachType_index[i]:_AttachType_index[i+1]] | ||||
| } | ||||
							
								
								
									
										532
									
								
								vendor/github.com/cilium/ebpf/collection.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										532
									
								
								vendor/github.com/cilium/ebpf/collection.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| package ebpf | ||||
|  | ||||
| import ( | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| @@ -25,6 +26,10 @@ type CollectionOptions struct { | ||||
| type CollectionSpec struct { | ||||
| 	Maps     map[string]*MapSpec | ||||
| 	Programs map[string]*ProgramSpec | ||||
|  | ||||
| 	// ByteOrder specifies whether the ELF was compiled for | ||||
| 	// big-endian or little-endian architectures. | ||||
| 	ByteOrder binary.ByteOrder | ||||
| } | ||||
|  | ||||
| // Copy returns a recursive copy of the spec. | ||||
| @@ -34,8 +39,9 @@ func (cs *CollectionSpec) Copy() *CollectionSpec { | ||||
| 	} | ||||
|  | ||||
| 	cpy := CollectionSpec{ | ||||
| 		Maps:     make(map[string]*MapSpec, len(cs.Maps)), | ||||
| 		Programs: make(map[string]*ProgramSpec, len(cs.Programs)), | ||||
| 		Maps:      make(map[string]*MapSpec, len(cs.Maps)), | ||||
| 		Programs:  make(map[string]*ProgramSpec, len(cs.Programs)), | ||||
| 		ByteOrder: cs.ByteOrder, | ||||
| 	} | ||||
|  | ||||
| 	for name, spec := range cs.Maps { | ||||
| @@ -123,7 +129,7 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error | ||||
| 	buf := make([]byte, len(value)) | ||||
| 	copy(buf, value) | ||||
|  | ||||
| 	err := patchValue(buf, btf.MapValue(rodata.BTF), consts) | ||||
| 	err := patchValue(buf, rodata.BTF.Value, consts) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -134,15 +140,15 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error | ||||
|  | ||||
| // Assign the contents of a CollectionSpec to a struct. | ||||
| // | ||||
| // This function is a short-cut to manually checking the presence | ||||
| // of maps and programs in a collection spec. Consider using bpf2go if this | ||||
| // sounds useful. | ||||
| // This function is a shortcut to manually checking the presence | ||||
| // of maps and programs in a CollectionSpec. Consider using bpf2go | ||||
| // if this sounds useful. | ||||
| // | ||||
| // The argument to must be a pointer to a struct. A field of the | ||||
| // '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. | ||||
| // The tag gives the name of the program or map as found in | ||||
| // the CollectionSpec. | ||||
| // The tag's value specifies the name of the program or map as | ||||
| // found in the CollectionSpec. | ||||
| // | ||||
| //    struct { | ||||
| //        Foo     *ebpf.ProgramSpec `ebpf:"xdp_foo"` | ||||
| @@ -150,42 +156,47 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error | ||||
| //        Ignored int | ||||
| //    } | ||||
| // | ||||
| // Returns an error if any of the fields can't be found, or | ||||
| // if the same map or program is assigned multiple times. | ||||
| // Returns an error if any of the eBPF objects can't be found, or | ||||
| // if the same MapSpec or ProgramSpec is assigned multiple times. | ||||
| func (cs *CollectionSpec) Assign(to interface{}) error { | ||||
| 	valueOf := func(typ reflect.Type, name string) (reflect.Value, 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)): | ||||
| 			p := cs.Programs[name] | ||||
| 			if p == nil { | ||||
| 				return reflect.Value{}, fmt.Errorf("missing program %q", name) | ||||
| 			if p := cs.Programs[name]; p != nil { | ||||
| 				return p, nil | ||||
| 			} | ||||
| 			return reflect.ValueOf(p), nil | ||||
| 			return nil, fmt.Errorf("missing program %q", name) | ||||
|  | ||||
| 		case reflect.TypeOf((*MapSpec)(nil)): | ||||
| 			m := cs.Maps[name] | ||||
| 			if m == nil { | ||||
| 				return reflect.Value{}, fmt.Errorf("missing map %q", name) | ||||
| 			if m := cs.Maps[name]; m != nil { | ||||
| 				return m, nil | ||||
| 			} | ||||
| 			return reflect.ValueOf(m), nil | ||||
| 			return nil, fmt.Errorf("missing map %q", name) | ||||
|  | ||||
| 		default: | ||||
| 			return reflect.Value{}, fmt.Errorf("unsupported type %s", typ) | ||||
| 			return nil, fmt.Errorf("unsupported type %s", typ) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return assignValues(to, valueOf) | ||||
| 	return assignValues(to, getValue) | ||||
| } | ||||
|  | ||||
| // LoadAndAssign maps and programs into the kernel and assign them to a struct. | ||||
| // LoadAndAssign loads Maps and Programs into the kernel and assigns them | ||||
| // to a struct. | ||||
| // | ||||
| // This function is a short-cut to manually checking the presence | ||||
| // of maps and programs in a collection spec. Consider using bpf2go if this | ||||
| // sounds useful. | ||||
| // This function is a shortcut to manually checking the presence | ||||
| // of maps and programs in a CollectionSpec. Consider using bpf2go | ||||
| // if this sounds useful. | ||||
| // | ||||
| // The argument 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 *Program or *Map. | ||||
| // The tag gives the name of the program or map as found in | ||||
| // the CollectionSpec. | ||||
| // 'to' must be a pointer to a struct. A field of the struct is updated with | ||||
| // a Program or Map if it has an `ebpf` tag and its type is *Program or *Map. | ||||
| // The tag's value specifies the name of the program or map as found in the | ||||
| // CollectionSpec. Before updating the struct, the requested objects and their | ||||
| // dependent resources are loaded into the kernel and populated with values if | ||||
| // specified. | ||||
| // | ||||
| //    struct { | ||||
| //        Foo     *ebpf.Program `ebpf:"xdp_foo"` | ||||
| @@ -196,39 +207,53 @@ func (cs *CollectionSpec) Assign(to interface{}) error { | ||||
| // opts may be nil. | ||||
| // | ||||
| // Returns an error if any of the fields can't be found, or | ||||
| // if the same map or program is assigned multiple times. | ||||
| // if the same Map or Program is assigned multiple times. | ||||
| func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) error { | ||||
| 	if opts == nil { | ||||
| 		opts = &CollectionOptions{} | ||||
| 	} | ||||
| 	loader := newCollectionLoader(cs, opts) | ||||
| 	defer loader.cleanup() | ||||
|  | ||||
| 	loadMap, loadProgram, done, cleanup := lazyLoadCollection(cs, opts) | ||||
| 	defer cleanup() | ||||
|  | ||||
| 	valueOf := func(typ reflect.Type, name string) (reflect.Value, error) { | ||||
| 	// Support assigning Programs and Maps, lazy-loading the required objects. | ||||
| 	assignedMaps := make(map[string]bool) | ||||
| 	getValue := func(typ reflect.Type, name string) (interface{}, error) { | ||||
| 		switch typ { | ||||
|  | ||||
| 		case reflect.TypeOf((*Program)(nil)): | ||||
| 			p, err := loadProgram(name) | ||||
| 			if err != nil { | ||||
| 				return reflect.Value{}, err | ||||
| 			} | ||||
| 			return reflect.ValueOf(p), nil | ||||
| 			return loader.loadProgram(name) | ||||
|  | ||||
| 		case reflect.TypeOf((*Map)(nil)): | ||||
| 			m, err := loadMap(name) | ||||
| 			if err != nil { | ||||
| 				return reflect.Value{}, err | ||||
| 			} | ||||
| 			return reflect.ValueOf(m), nil | ||||
| 			assignedMaps[name] = true | ||||
| 			return loader.loadMap(name) | ||||
|  | ||||
| 		default: | ||||
| 			return reflect.Value{}, fmt.Errorf("unsupported type %s", typ) | ||||
| 			return nil, fmt.Errorf("unsupported type %s", typ) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err := assignValues(to, valueOf); err != nil { | ||||
| 	// Load the Maps and Programs requested by the annotated struct. | ||||
| 	if err := assignValues(to, getValue); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	done() | ||||
| 	// Populate the requested maps. Has a chance of lazy-loading other dependent maps. | ||||
| 	if err := loader.populateMaps(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Evaluate the loader's objects after all (lazy)loading has taken place. | ||||
| 	for n, m := range loader.maps { | ||||
| 		switch m.typ { | ||||
| 		case ProgramArray: | ||||
| 			// Require all lazy-loaded ProgramArrays to be assigned to the given object. | ||||
| 			// Without any references, they will be closed on the first GC and all tail | ||||
| 			// calls into them will miss. | ||||
| 			if !assignedMaps[n] { | ||||
| 				return fmt.Errorf("ProgramArray %s must be assigned to prevent missed tail calls", n) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	loader.finalize() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -246,24 +271,32 @@ func NewCollection(spec *CollectionSpec) (*Collection, error) { | ||||
|  | ||||
| // NewCollectionWithOptions creates a Collection from a specification. | ||||
| func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error) { | ||||
| 	loadMap, loadProgram, done, cleanup := lazyLoadCollection(spec, &opts) | ||||
| 	defer cleanup() | ||||
| 	loader := newCollectionLoader(spec, &opts) | ||||
| 	defer loader.cleanup() | ||||
|  | ||||
| 	// Create maps first, as their fds need to be linked into programs. | ||||
| 	for mapName := range spec.Maps { | ||||
| 		_, err := loadMap(mapName) | ||||
| 		if err != nil { | ||||
| 		if _, err := loader.loadMap(mapName); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for progName := range spec.Programs { | ||||
| 		_, err := loadProgram(progName) | ||||
| 		if err != nil { | ||||
| 		if _, err := loader.loadProgram(progName); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	maps, progs := done() | ||||
| 	// Maps can contain Program and Map stubs, so populate them after | ||||
| 	// all Maps and Programs have been successfully loaded. | ||||
| 	if err := loader.populateMaps(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	maps, progs := loader.maps, loader.programs | ||||
|  | ||||
| 	loader.finalize() | ||||
|  | ||||
| 	return &Collection{ | ||||
| 		progs, | ||||
| 		maps, | ||||
| @@ -314,113 +347,154 @@ func (hc handleCache) close() { | ||||
| 	for _, handle := range hc.btfHandles { | ||||
| 		handle.Close() | ||||
| 	} | ||||
| 	hc.btfHandles = nil | ||||
| 	hc.btfSpecs = nil | ||||
| } | ||||
|  | ||||
| func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) ( | ||||
| 	loadMap func(string) (*Map, error), | ||||
| 	loadProgram func(string) (*Program, error), | ||||
| 	done func() (map[string]*Map, map[string]*Program), | ||||
| 	cleanup func(), | ||||
| ) { | ||||
| 	var ( | ||||
| 		maps             = make(map[string]*Map) | ||||
| 		progs            = make(map[string]*Program) | ||||
| 		handles          = newHandleCache() | ||||
| 		skipMapsAndProgs = false | ||||
| 	) | ||||
| type collectionLoader struct { | ||||
| 	coll     *CollectionSpec | ||||
| 	opts     *CollectionOptions | ||||
| 	maps     map[string]*Map | ||||
| 	programs map[string]*Program | ||||
| 	handles  *handleCache | ||||
| } | ||||
|  | ||||
| 	cleanup = func() { | ||||
| 		handles.close() | ||||
|  | ||||
| 		if skipMapsAndProgs { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		for _, m := range maps { | ||||
| 			m.Close() | ||||
| 		} | ||||
|  | ||||
| 		for _, p := range progs { | ||||
| 			p.Close() | ||||
| 		} | ||||
| func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) *collectionLoader { | ||||
| 	if opts == nil { | ||||
| 		opts = &CollectionOptions{} | ||||
| 	} | ||||
|  | ||||
| 	done = func() (map[string]*Map, map[string]*Program) { | ||||
| 		skipMapsAndProgs = true | ||||
| 		return maps, progs | ||||
| 	return &collectionLoader{ | ||||
| 		coll, | ||||
| 		opts, | ||||
| 		make(map[string]*Map), | ||||
| 		make(map[string]*Program), | ||||
| 		newHandleCache(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| 	loadMap = func(mapName string) (*Map, error) { | ||||
| 		if m := maps[mapName]; m != nil { | ||||
| 			return m, nil | ||||
| 		} | ||||
| // finalize should be called when all the collectionLoader's resources | ||||
| // have been successfully loaded into the kernel and populated with values. | ||||
| func (cl *collectionLoader) finalize() { | ||||
| 	cl.maps, cl.programs = nil, nil | ||||
| } | ||||
|  | ||||
| 		mapSpec := coll.Maps[mapName] | ||||
| 		if mapSpec == nil { | ||||
| 			return nil, fmt.Errorf("missing map %s", mapName) | ||||
| 		} | ||||
| // cleanup cleans up all resources left over in the collectionLoader. | ||||
| // Call finalize() when Map and Program creation/population is successful | ||||
| // to prevent them from getting closed. | ||||
| func (cl *collectionLoader) cleanup() { | ||||
| 	cl.handles.close() | ||||
| 	for _, m := range cl.maps { | ||||
| 		m.Close() | ||||
| 	} | ||||
| 	for _, p := range cl.programs { | ||||
| 		p.Close() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| 		m, err := newMapWithOptions(mapSpec, opts.Maps, handles) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("map %s: %w", mapName, err) | ||||
| 		} | ||||
|  | ||||
| 		maps[mapName] = m | ||||
| func (cl *collectionLoader) loadMap(mapName string) (*Map, error) { | ||||
| 	if m := cl.maps[mapName]; m != nil { | ||||
| 		return m, nil | ||||
| 	} | ||||
|  | ||||
| 	loadProgram = func(progName string) (*Program, error) { | ||||
| 		if prog := progs[progName]; prog != nil { | ||||
| 			return prog, nil | ||||
| 	mapSpec := cl.coll.Maps[mapName] | ||||
| 	if mapSpec == nil { | ||||
| 		return nil, fmt.Errorf("missing map %s", mapName) | ||||
| 	} | ||||
|  | ||||
| 	m, err := newMapWithOptions(mapSpec, cl.opts.Maps, cl.handles) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("map %s: %w", mapName, err) | ||||
| 	} | ||||
|  | ||||
| 	cl.maps[mapName] = m | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| func (cl *collectionLoader) loadProgram(progName string) (*Program, error) { | ||||
| 	if prog := cl.programs[progName]; prog != nil { | ||||
| 		return prog, nil | ||||
| 	} | ||||
|  | ||||
| 	progSpec := cl.coll.Programs[progName] | ||||
| 	if progSpec == nil { | ||||
| 		return nil, fmt.Errorf("unknown program %s", progName) | ||||
| 	} | ||||
|  | ||||
| 	progSpec = progSpec.Copy() | ||||
|  | ||||
| 	// Rewrite any reference to a valid map. | ||||
| 	for i := range progSpec.Instructions { | ||||
| 		ins := &progSpec.Instructions[i] | ||||
|  | ||||
| 		if !ins.IsLoadFromMap() || ins.Reference == "" { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		progSpec := coll.Programs[progName] | ||||
| 		if progSpec == nil { | ||||
| 			return nil, fmt.Errorf("unknown program %s", progName) | ||||
| 		if uint32(ins.Constant) != math.MaxUint32 { | ||||
| 			// Don't overwrite maps already rewritten, users can | ||||
| 			// rewrite programs in the spec themselves | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		progSpec = progSpec.Copy() | ||||
|  | ||||
| 		// Rewrite any reference to a valid map. | ||||
| 		for i := range progSpec.Instructions { | ||||
| 			ins := &progSpec.Instructions[i] | ||||
|  | ||||
| 			if !ins.IsLoadFromMap() || ins.Reference == "" { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if uint32(ins.Constant) != math.MaxUint32 { | ||||
| 				// Don't overwrite maps already rewritten, users can | ||||
| 				// rewrite programs in the spec themselves | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			m, err := loadMap(ins.Reference) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("program %s: %w", progName, err) | ||||
| 			} | ||||
|  | ||||
| 			fd := m.FD() | ||||
| 			if fd < 0 { | ||||
| 				return nil, fmt.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd) | ||||
| 			} | ||||
| 			if err := ins.RewriteMapPtr(m.FD()); err != nil { | ||||
| 				return nil, fmt.Errorf("progam %s: map %s: %w", progName, ins.Reference, err) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		prog, err := newProgramWithOptions(progSpec, opts.Programs, handles) | ||||
| 		m, err := cl.loadMap(ins.Reference) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("program %s: %w", progName, err) | ||||
| 		} | ||||
|  | ||||
| 		progs[progName] = prog | ||||
| 		return prog, nil | ||||
| 		fd := m.FD() | ||||
| 		if fd < 0 { | ||||
| 			return nil, fmt.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd) | ||||
| 		} | ||||
| 		if err := ins.RewriteMapPtr(m.FD()); err != nil { | ||||
| 			return nil, fmt.Errorf("program %s: map %s: %w", progName, ins.Reference, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| 	prog, err := newProgramWithOptions(progSpec, cl.opts.Programs, cl.handles) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("program %s: %w", progName, err) | ||||
| 	} | ||||
|  | ||||
| 	cl.programs[progName] = prog | ||||
| 	return prog, nil | ||||
| } | ||||
|  | ||||
| func (cl *collectionLoader) populateMaps() error { | ||||
| 	for mapName, m := range cl.maps { | ||||
| 		mapSpec, ok := cl.coll.Maps[mapName] | ||||
| 		if !ok { | ||||
| 			return fmt.Errorf("missing map spec %s", mapName) | ||||
| 		} | ||||
|  | ||||
| 		mapSpec = mapSpec.Copy() | ||||
|  | ||||
| 		// Replace any object stubs with loaded objects. | ||||
| 		for i, kv := range mapSpec.Contents { | ||||
| 			switch v := kv.Value.(type) { | ||||
| 			case programStub: | ||||
| 				// loadProgram is idempotent and could return an existing Program. | ||||
| 				prog, err := cl.loadProgram(string(v)) | ||||
| 				if err != nil { | ||||
| 					return fmt.Errorf("loading program %s, for map %s: %w", v, mapName, err) | ||||
| 				} | ||||
| 				mapSpec.Contents[i] = MapKV{kv.Key, prog} | ||||
|  | ||||
| 			case mapStub: | ||||
| 				// loadMap is idempotent and could return an existing Map. | ||||
| 				innerMap, err := cl.loadMap(string(v)) | ||||
| 				if err != nil { | ||||
| 					return fmt.Errorf("loading inner map %s, for map %s: %w", v, mapName, err) | ||||
| 				} | ||||
| 				mapSpec.Contents[i] = MapKV{kv.Key, innerMap} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Populate and freeze the map if specified. | ||||
| 		if err := m.finalize(mapSpec); err != nil { | ||||
| 			return fmt.Errorf("populating map %s: %w", mapName, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // LoadCollection parses an object file and converts it to a collection. | ||||
| @@ -466,108 +540,81 @@ func (coll *Collection) DetachProgram(name string) *Program { | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| // Assign the contents of a collection to a struct. | ||||
| // | ||||
| // Deprecated: use CollectionSpec.Assign instead. It provides the same | ||||
| // functionality but creates only the maps and programs requested. | ||||
| func (coll *Collection) Assign(to interface{}) error { | ||||
| 	assignedMaps := make(map[string]struct{}) | ||||
| 	assignedPrograms := make(map[string]struct{}) | ||||
| 	valueOf := func(typ reflect.Type, name string) (reflect.Value, error) { | ||||
| 		switch typ { | ||||
| 		case reflect.TypeOf((*Program)(nil)): | ||||
| 			p := coll.Programs[name] | ||||
| 			if p == nil { | ||||
| 				return reflect.Value{}, fmt.Errorf("missing program %q", name) | ||||
| 			} | ||||
| 			assignedPrograms[name] = struct{}{} | ||||
| 			return reflect.ValueOf(p), nil | ||||
| 		case reflect.TypeOf((*Map)(nil)): | ||||
| 			m := coll.Maps[name] | ||||
| 			if m == nil { | ||||
| 				return reflect.Value{}, fmt.Errorf("missing map %q", name) | ||||
| 			} | ||||
| 			assignedMaps[name] = struct{}{} | ||||
| 			return reflect.ValueOf(m), nil | ||||
| 		default: | ||||
| 			return reflect.Value{}, fmt.Errorf("unsupported type %s", typ) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err := assignValues(to, valueOf); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for name := range assignedPrograms { | ||||
| 		coll.DetachProgram(name) | ||||
| 	} | ||||
|  | ||||
| 	for name := range assignedMaps { | ||||
| 		coll.DetachMap(name) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| // structField represents a struct field containing the ebpf struct tag. | ||||
| type structField struct { | ||||
| 	reflect.StructField | ||||
| 	value reflect.Value | ||||
| } | ||||
|  | ||||
| func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Value, error)) error { | ||||
| 	type structField struct { | ||||
| 		reflect.StructField | ||||
| 		value reflect.Value | ||||
| // ebpfFields extracts field names tagged with 'ebpf' from a struct type. | ||||
| // Keep track of visited types to avoid infinite recursion. | ||||
| func ebpfFields(structVal reflect.Value, visited map[reflect.Type]bool) ([]structField, error) { | ||||
| 	if visited == nil { | ||||
| 		visited = make(map[reflect.Type]bool) | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		fields        []structField | ||||
| 		visitedTypes  = make(map[reflect.Type]bool) | ||||
| 		flattenStruct func(reflect.Value) error | ||||
| 	) | ||||
| 	structType := structVal.Type() | ||||
| 	if structType.Kind() != reflect.Struct { | ||||
| 		return nil, fmt.Errorf("%s is not a struct", structType) | ||||
| 	} | ||||
|  | ||||
| 	flattenStruct = func(structVal reflect.Value) error { | ||||
| 		structType := structVal.Type() | ||||
| 		if structType.Kind() != reflect.Struct { | ||||
| 			return fmt.Errorf("%s is not a struct", structType) | ||||
| 	if visited[structType] { | ||||
| 		return nil, fmt.Errorf("recursion on type %s", structType) | ||||
| 	} | ||||
|  | ||||
| 	fields := make([]structField, 0, structType.NumField()) | ||||
| 	for i := 0; i < structType.NumField(); i++ { | ||||
| 		field := structField{structType.Field(i), structVal.Field(i)} | ||||
|  | ||||
| 		// If the field is tagged, gather it and move on. | ||||
| 		name := field.Tag.Get("ebpf") | ||||
| 		if name != "" { | ||||
| 			fields = append(fields, field) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if visitedTypes[structType] { | ||||
| 			return fmt.Errorf("recursion on type %s", structType) | ||||
| 		} | ||||
|  | ||||
| 		for i := 0; i < structType.NumField(); i++ { | ||||
| 			field := structField{structType.Field(i), structVal.Field(i)} | ||||
|  | ||||
| 			name := field.Tag.Get("ebpf") | ||||
| 			if name != "" { | ||||
| 				fields = append(fields, field) | ||||
| 		// If the field does not have an ebpf tag, but is a struct or a pointer | ||||
| 		// to a struct, attempt to gather its fields as well. | ||||
| 		var v reflect.Value | ||||
| 		switch field.Type.Kind() { | ||||
| 		case reflect.Ptr: | ||||
| 			if field.Type.Elem().Kind() != reflect.Struct { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			var err error | ||||
| 			switch field.Type.Kind() { | ||||
| 			case reflect.Ptr: | ||||
| 				if field.Type.Elem().Kind() != reflect.Struct { | ||||
| 					continue | ||||
| 				} | ||||
|  | ||||
| 				if field.value.IsNil() { | ||||
| 					return fmt.Errorf("nil pointer to %s", structType) | ||||
| 				} | ||||
|  | ||||
| 				err = flattenStruct(field.value.Elem()) | ||||
|  | ||||
| 			case reflect.Struct: | ||||
| 				err = flattenStruct(field.value) | ||||
|  | ||||
| 			default: | ||||
| 				continue | ||||
| 			if field.value.IsNil() { | ||||
| 				return nil, fmt.Errorf("nil pointer to %s", structType) | ||||
| 			} | ||||
|  | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("field %s: %w", field.Name, err) | ||||
| 			} | ||||
| 			// Obtain the destination type of the pointer. | ||||
| 			v = field.value.Elem() | ||||
|  | ||||
| 		case reflect.Struct: | ||||
| 			// Reference the value's type directly. | ||||
| 			v = field.value | ||||
|  | ||||
| 		default: | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
| 		inner, err := ebpfFields(v, visited) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("field %s: %w", field.Name, err) | ||||
| 		} | ||||
|  | ||||
| 		fields = append(fields, inner...) | ||||
| 	} | ||||
|  | ||||
| 	return fields, nil | ||||
| } | ||||
|  | ||||
| // assignValues attempts to populate all fields of 'to' tagged with 'ebpf'. | ||||
| // | ||||
| // getValue is called for every tagged field of 'to' and must return the value | ||||
| // to be assigned to the field with the given typ and name. | ||||
| func assignValues(to interface{}, | ||||
| 	getValue func(typ reflect.Type, name string) (interface{}, error)) error { | ||||
|  | ||||
| 	toValue := reflect.ValueOf(to) | ||||
| 	if toValue.Type().Kind() != reflect.Ptr { | ||||
| 		return fmt.Errorf("%T is not a pointer to struct", to) | ||||
| @@ -577,7 +624,8 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va | ||||
| 		return fmt.Errorf("nil pointer to %T", to) | ||||
| 	} | ||||
|  | ||||
| 	if err := flattenStruct(toValue.Elem()); err != nil { | ||||
| 	fields, err := ebpfFields(toValue.Elem(), nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| @@ -587,19 +635,23 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va | ||||
| 		name string | ||||
| 	} | ||||
|  | ||||
| 	assignedTo := make(map[elem]string) | ||||
| 	assigned := make(map[elem]string) | ||||
| 	for _, field := range fields { | ||||
| 		name := field.Tag.Get("ebpf") | ||||
| 		if strings.Contains(name, ",") { | ||||
| 		// Get string value the field is tagged with. | ||||
| 		tag := field.Tag.Get("ebpf") | ||||
| 		if strings.Contains(tag, ",") { | ||||
| 			return fmt.Errorf("field %s: ebpf tag contains a comma", field.Name) | ||||
| 		} | ||||
|  | ||||
| 		e := elem{field.Type, name} | ||||
| 		if assignedField := assignedTo[e]; assignedField != "" { | ||||
| 			return fmt.Errorf("field %s: %q was already assigned to %s", field.Name, name, assignedField) | ||||
| 		// Check if the eBPF object with the requested | ||||
| 		// type and tag was already assigned elsewhere. | ||||
| 		e := elem{field.Type, tag} | ||||
| 		if af := assigned[e]; af != "" { | ||||
| 			return fmt.Errorf("field %s: object %q was already assigned to %s", field.Name, tag, af) | ||||
| 		} | ||||
|  | ||||
| 		value, err := valueOf(field.Type, name) | ||||
| 		// Get the eBPF object referred to by the tag. | ||||
| 		value, err := getValue(field.Type, tag) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("field %s: %w", field.Name, err) | ||||
| 		} | ||||
| @@ -607,9 +659,9 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va | ||||
| 		if !field.value.CanSet() { | ||||
| 			return fmt.Errorf("field %s: can't set value", field.Name) | ||||
| 		} | ||||
| 		field.value.Set(reflect.ValueOf(value)) | ||||
|  | ||||
| 		field.value.Set(value) | ||||
| 		assignedTo[e] = field.Name | ||||
| 		assigned[e] = field.Name | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
|   | ||||
							
								
								
									
										180
									
								
								vendor/github.com/cilium/ebpf/elf_reader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										180
									
								
								vendor/github.com/cilium/ebpf/elf_reader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -19,7 +19,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| // elfCode is a convenience to reduce the amount of arguments that have to | ||||
| // be passed around explicitly. You should treat it's contents as immutable. | ||||
| // be passed around explicitly. You should treat its contents as immutable. | ||||
| type elfCode struct { | ||||
| 	*internal.SafeELFFile | ||||
| 	sections map[elf.SectionIndex]*elfSection | ||||
| @@ -188,7 +188,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) { | ||||
| 		return nil, fmt.Errorf("load programs: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return &CollectionSpec{maps, progs}, nil | ||||
| 	return &CollectionSpec{maps, progs, ec.ByteOrder}, nil | ||||
| } | ||||
|  | ||||
| func loadLicense(sec *elf.Section) (string, error) { | ||||
| @@ -520,8 +520,12 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec) error { | ||||
| 				return fmt.Errorf("map %s: missing flags", mapName) | ||||
| 			} | ||||
|  | ||||
| 			if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil { | ||||
| 				return fmt.Errorf("map %s: unknown and non-zero fields in definition", mapName) | ||||
| 			extra, err := io.ReadAll(lr) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("map %s: reading map tail: %w", mapName, err) | ||||
| 			} | ||||
| 			if len(extra) > 0 { | ||||
| 				spec.Extra = *bytes.NewReader(extra) | ||||
| 			} | ||||
|  | ||||
| 			if err := spec.clampPerfEventArraySize(); err != nil { | ||||
| @@ -535,6 +539,9 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // loadBTFMaps iterates over all ELF sections marked as BTF map sections | ||||
| // (like .maps) and parses them into MapSpecs. Dump the .maps section and | ||||
| // any relocations with `readelf -x .maps -r <elf_file>`. | ||||
| func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error { | ||||
| 	for _, sec := range ec.sections { | ||||
| 		if sec.kind != btfMapSection { | ||||
| @@ -545,33 +552,46 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error { | ||||
| 			return fmt.Errorf("missing BTF") | ||||
| 		} | ||||
|  | ||||
| 		_, err := io.Copy(internal.DiscardZeroes{}, bufio.NewReader(sec.Open())) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("section %v: initializing BTF map definitions: %w", sec.Name, internal.ErrNotSupported) | ||||
| 		} | ||||
|  | ||||
| 		var ds btf.Datasec | ||||
| 		// Each section must appear as a DataSec in the ELF's BTF blob. | ||||
| 		var ds *btf.Datasec | ||||
| 		if err := ec.btf.FindType(sec.Name, &ds); err != nil { | ||||
| 			return fmt.Errorf("cannot find section '%s' in BTF: %w", sec.Name, err) | ||||
| 		} | ||||
|  | ||||
| 		// Open a Reader to the ELF's raw section bytes so we can assert that all | ||||
| 		// of them are zero on a per-map (per-Var) basis. For now, the section's | ||||
| 		// sole purpose is to receive relocations, so all must be zero. | ||||
| 		rs := sec.Open() | ||||
|  | ||||
| 		for _, vs := range ds.Vars { | ||||
| 			// BPF maps are declared as and assigned to global variables, | ||||
| 			// so iterate over each Var in the DataSec and validate their types. | ||||
| 			v, ok := vs.Type.(*btf.Var) | ||||
| 			if !ok { | ||||
| 				return fmt.Errorf("section %v: unexpected type %s", sec.Name, vs.Type) | ||||
| 			} | ||||
| 			name := string(v.Name) | ||||
|  | ||||
| 			// The BTF metadata for each Var contains the full length of the map | ||||
| 			// declaration, so read the corresponding amount of bytes from the ELF. | ||||
| 			// This way, we can pinpoint which map declaration contains unexpected | ||||
| 			// (and therefore unsupported) data. | ||||
| 			_, err := io.Copy(internal.DiscardZeroes{}, io.LimitReader(rs, int64(vs.Size))) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("section %v: map %s: initializing BTF map definitions: %w", sec.Name, name, internal.ErrNotSupported) | ||||
| 			} | ||||
|  | ||||
| 			if maps[name] != nil { | ||||
| 				return fmt.Errorf("section %v: map %s already exists", sec.Name, name) | ||||
| 			} | ||||
|  | ||||
| 			// Each Var representing a BTF map definition contains a Struct. | ||||
| 			mapStruct, ok := v.Type.(*btf.Struct) | ||||
| 			if !ok { | ||||
| 				return fmt.Errorf("expected struct, got %s", v.Type) | ||||
| 			} | ||||
|  | ||||
| 			mapSpec, err := mapSpecFromBTF(name, mapStruct, false, ec.btf) | ||||
| 			mapSpec, err := mapSpecFromBTF(sec, &vs, mapStruct, ec.btf, name, false) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("map %v: %w", name, err) | ||||
| 			} | ||||
| @@ -582,32 +602,52 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error { | ||||
|  | ||||
| 			maps[name] = mapSpec | ||||
| 		} | ||||
|  | ||||
| 		// Drain the ELF section reader to make sure all bytes are accounted for | ||||
| 		// with BTF metadata. | ||||
| 		i, err := io.Copy(io.Discard, rs) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("section %v: unexpected error reading remainder of ELF section: %w", sec.Name, err) | ||||
| 		} | ||||
| 		if i > 0 { | ||||
| 			return fmt.Errorf("section %v: %d unexpected remaining bytes in ELF section, invalid BTF?", sec.Name, i) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // A programStub is a placeholder for a Program to be inserted at a certain map key. | ||||
| // It needs to be resolved into a Program later on in the loader process. | ||||
| type programStub string | ||||
|  | ||||
| // A mapStub is a placeholder for a Map to be inserted at a certain map key. | ||||
| // It needs to be resolved into a Map later on in the loader process. | ||||
| type mapStub string | ||||
|  | ||||
| // mapSpecFromBTF produces a MapSpec based on a btf.Struct def representing | ||||
| // a BTF map definition. The name and spec arguments will be copied to the | ||||
| // resulting MapSpec, and inner must be true on any resursive invocations. | ||||
| func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*MapSpec, error) { | ||||
|  | ||||
| func mapSpecFromBTF(es *elfSection, vs *btf.VarSecinfo, def *btf.Struct, spec *btf.Spec, name string, inner bool) (*MapSpec, error) { | ||||
| 	var ( | ||||
| 		key, value                 btf.Type | ||||
| 		keySize, valueSize         uint32 | ||||
| 		mapType, flags, maxEntries uint32 | ||||
| 		pinType                    PinType | ||||
| 		innerMapSpec               *MapSpec | ||||
| 		err                        error | ||||
| 		key, value         btf.Type | ||||
| 		keySize, valueSize uint32 | ||||
| 		mapType            MapType | ||||
| 		flags, maxEntries  uint32 | ||||
| 		pinType            PinType | ||||
| 		innerMapSpec       *MapSpec | ||||
| 		contents           []MapKV | ||||
| 		err                error | ||||
| 	) | ||||
|  | ||||
| 	for i, member := range def.Members { | ||||
| 		switch member.Name { | ||||
| 		case "type": | ||||
| 			mapType, err = uintFromBTF(member.Type) | ||||
| 			mt, err := uintFromBTF(member.Type) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("can't get type: %w", err) | ||||
| 			} | ||||
| 			mapType = MapType(mt) | ||||
|  | ||||
| 		case "map_flags": | ||||
| 			flags, err = uintFromBTF(member.Type) | ||||
| @@ -717,7 +757,7 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (* | ||||
| 			case *btf.Struct: | ||||
| 				// The values member pointing to an array of structs means we're expecting | ||||
| 				// a map-in-map declaration. | ||||
| 				if MapType(mapType) != ArrayOfMaps && MapType(mapType) != HashOfMaps { | ||||
| 				if mapType != ArrayOfMaps && mapType != HashOfMaps { | ||||
| 					return nil, errors.New("outer map needs to be an array or a hash of maps") | ||||
| 				} | ||||
| 				if inner { | ||||
| @@ -731,21 +771,38 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (* | ||||
| 				// on kernels 5.2 and up) | ||||
| 				// Pass the BTF spec from the parent object, since both parent and | ||||
| 				// child must be created from the same BTF blob (on kernels that support BTF). | ||||
| 				innerMapSpec, err = mapSpecFromBTF(name+"_inner", t, true, spec) | ||||
| 				innerMapSpec, err = mapSpecFromBTF(es, vs, t, spec, name+"_inner", true) | ||||
| 				if err != nil { | ||||
| 					return nil, fmt.Errorf("can't parse BTF map definition of inner map: %w", err) | ||||
| 				} | ||||
|  | ||||
| 			case *btf.FuncProto: | ||||
| 				// The values member contains an array of function pointers, meaning an | ||||
| 				// autopopulated PROG_ARRAY. | ||||
| 				if mapType != ProgramArray { | ||||
| 					return nil, errors.New("map needs to be a program array") | ||||
| 				} | ||||
|  | ||||
| 			default: | ||||
| 				return nil, fmt.Errorf("unsupported value type %q in 'values' field", t) | ||||
| 			} | ||||
|  | ||||
| 			contents, err = resolveBTFValuesContents(es, vs, member) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("resolving values contents: %w", err) | ||||
| 			} | ||||
|  | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("unrecognized field %s in BTF map definition", member.Name) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	bm := btf.NewMap(spec, key, value) | ||||
| 	if key == nil { | ||||
| 		key = &btf.Void{} | ||||
| 	} | ||||
| 	if value == nil { | ||||
| 		value = &btf.Void{} | ||||
| 	} | ||||
|  | ||||
| 	return &MapSpec{ | ||||
| 		Name:       SanitizeName(name, -1), | ||||
| @@ -754,9 +811,10 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (* | ||||
| 		ValueSize:  valueSize, | ||||
| 		MaxEntries: maxEntries, | ||||
| 		Flags:      flags, | ||||
| 		BTF:        &bm, | ||||
| 		BTF:        &btf.Map{Spec: spec, Key: key, Value: value}, | ||||
| 		Pinning:    pinType, | ||||
| 		InnerMap:   innerMapSpec, | ||||
| 		Contents:   contents, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| @@ -793,6 +851,64 @@ func resolveBTFArrayMacro(typ btf.Type) (btf.Type, error) { | ||||
| 	return ptr.Target, nil | ||||
| } | ||||
|  | ||||
| // resolveBTFValuesContents resolves relocations into ELF sections belonging | ||||
| // to btf.VarSecinfo's. This can be used on the 'values' member in BTF map | ||||
| // definitions to extract static declarations of map contents. | ||||
| func resolveBTFValuesContents(es *elfSection, vs *btf.VarSecinfo, member btf.Member) ([]MapKV, error) { | ||||
| 	// The elements of a .values pointer array are not encoded in BTF. | ||||
| 	// Instead, relocations are generated into each array index. | ||||
| 	// However, it's possible to leave certain array indices empty, so all | ||||
| 	// indices' offsets need to be checked for emitted relocations. | ||||
|  | ||||
| 	// The offset of the 'values' member within the _struct_ (in bits) | ||||
| 	// is the starting point of the array. Convert to bytes. Add VarSecinfo | ||||
| 	// offset to get the absolute position in the ELF blob. | ||||
| 	start := (member.OffsetBits / 8) + vs.Offset | ||||
| 	// 'values' is encoded in BTF as a zero (variable) length struct | ||||
| 	// member, and its contents run until the end of the VarSecinfo. | ||||
| 	// Add VarSecinfo offset to get the absolute position in the ELF blob. | ||||
| 	end := vs.Size + vs.Offset | ||||
| 	// The size of an address in this section. This determines the width of | ||||
| 	// an index in the array. | ||||
| 	align := uint32(es.SectionHeader.Addralign) | ||||
|  | ||||
| 	// Check if variable-length section is aligned. | ||||
| 	if (end-start)%align != 0 { | ||||
| 		return nil, errors.New("unaligned static values section") | ||||
| 	} | ||||
| 	elems := (end - start) / align | ||||
|  | ||||
| 	if elems == 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	contents := make([]MapKV, 0, elems) | ||||
|  | ||||
| 	// k is the array index, off is its corresponding ELF section offset. | ||||
| 	for k, off := uint32(0), start; k < elems; k, off = k+1, off+align { | ||||
| 		r, ok := es.relocations[uint64(off)] | ||||
| 		if !ok { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// Relocation exists for the current offset in the ELF section. | ||||
| 		// Emit a value stub based on the type of relocation to be replaced by | ||||
| 		// a real fd later in the pipeline before populating the map. | ||||
| 		// Map keys are encoded in MapKV entries, so empty array indices are | ||||
| 		// skipped here. | ||||
| 		switch t := elf.ST_TYPE(r.Info); t { | ||||
| 		case elf.STT_FUNC: | ||||
| 			contents = append(contents, MapKV{uint32(k), programStub(r.Name)}) | ||||
| 		case elf.STT_OBJECT: | ||||
| 			contents = append(contents, MapKV{uint32(k), mapStub(r.Name)}) | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("unknown relocation type %v", t) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return contents, nil | ||||
| } | ||||
|  | ||||
| func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error { | ||||
| 	for _, sec := range ec.sections { | ||||
| 		if sec.kind != dataSection { | ||||
| @@ -809,9 +925,9 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error { | ||||
| 			return errors.New("data sections require BTF, make sure all consts are marked as static") | ||||
| 		} | ||||
|  | ||||
| 		btfMap, err := ec.btf.Datasec(sec.Name) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		var datasec *btf.Datasec | ||||
| 		if err := ec.btf.FindType(sec.Name, &datasec); err != nil { | ||||
| 			return fmt.Errorf("data section %s: can't get BTF: %w", sec.Name, err) | ||||
| 		} | ||||
|  | ||||
| 		data, err := sec.Data() | ||||
| @@ -830,7 +946,7 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error { | ||||
| 			ValueSize:  uint32(len(data)), | ||||
| 			MaxEntries: 1, | ||||
| 			Contents:   []MapKV{{uint32(0), data}}, | ||||
| 			BTF:        btfMap, | ||||
| 			BTF:        &btf.Map{Spec: ec.btf, Key: &btf.Void{}, Value: datasec}, | ||||
| 		} | ||||
|  | ||||
| 		switch sec.Name { | ||||
| @@ -855,6 +971,8 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) { | ||||
| 	}{ | ||||
| 		// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c | ||||
| 		"socket":                {SocketFilter, AttachNone, 0}, | ||||
| 		"sk_reuseport/migrate":  {SkReuseport, AttachSkReuseportSelectOrMigrate, 0}, | ||||
| 		"sk_reuseport":          {SkReuseport, AttachSkReuseportSelect, 0}, | ||||
| 		"seccomp":               {SocketFilter, AttachNone, 0}, | ||||
| 		"kprobe/":               {Kprobe, AttachNone, 0}, | ||||
| 		"uprobe/":               {Kprobe, AttachNone, 0}, | ||||
| @@ -884,6 +1002,7 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) { | ||||
| 		"fmod_ret.s/":           {Tracing, AttachModifyReturn, unix.BPF_F_SLEEPABLE}, | ||||
| 		"fexit.s/":              {Tracing, AttachTraceFExit, unix.BPF_F_SLEEPABLE}, | ||||
| 		"sk_lookup/":            {SkLookup, AttachSkLookup, 0}, | ||||
| 		"freplace/":             {Extension, AttachNone, 0}, | ||||
| 		"lsm/":                  {LSM, AttachLSMMac, 0}, | ||||
| 		"lsm.s/":                {LSM, AttachLSMMac, unix.BPF_F_SLEEPABLE}, | ||||
|  | ||||
| @@ -907,6 +1026,11 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) { | ||||
| 		"cgroup/setsockopt":  {CGroupSockopt, AttachCGroupSetsockopt, 0}, | ||||
| 		"classifier":         {SchedCLS, AttachNone, 0}, | ||||
| 		"action":             {SchedACT, AttachNone, 0}, | ||||
|  | ||||
| 		"cgroup/getsockname4": {CGroupSockAddr, AttachCgroupInet4GetSockname, 0}, | ||||
| 		"cgroup/getsockname6": {CGroupSockAddr, AttachCgroupInet6GetSockname, 0}, | ||||
| 		"cgroup/getpeername4": {CGroupSockAddr, AttachCgroupInet4GetPeername, 0}, | ||||
| 		"cgroup/getpeername6": {CGroupSockAddr, AttachCgroupInet6GetPeername, 0}, | ||||
| 	} | ||||
|  | ||||
| 	for prefix, t := range types { | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/elf_reader_fuzz.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/elf_reader_fuzz.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build gofuzz | ||||
| // +build gofuzz | ||||
|  | ||||
| // Use with https://github.com/dvyukov/go-fuzz | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/cilium/ebpf/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/cilium/ebpf/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,9 +1,9 @@ | ||||
| module github.com/cilium/ebpf | ||||
|  | ||||
| go 1.15 | ||||
| go 1.16 | ||||
|  | ||||
| require ( | ||||
| 	github.com/frankban/quicktest v1.11.3 | ||||
| 	github.com/google/go-cmp v0.5.4 | ||||
| 	golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c | ||||
| 	golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 | ||||
| ) | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/cilium/ebpf/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/cilium/ebpf/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -7,7 +7,7 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn | ||||
| github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||||
| github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= | ||||
| github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||||
| golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= | ||||
| golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI= | ||||
| golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
|   | ||||
							
								
								
									
										36
									
								
								vendor/github.com/cilium/ebpf/info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/cilium/ebpf/info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -12,6 +12,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/btf" | ||||
| ) | ||||
|  | ||||
| // MapInfo describes a map. | ||||
| @@ -87,12 +88,16 @@ type ProgramInfo struct { | ||||
| 	Tag string | ||||
| 	// Name as supplied by user space at load time. | ||||
| 	Name string | ||||
| 	// BTF for the program. | ||||
| 	btf btf.ID | ||||
| 	// IDS map ids related to program. | ||||
| 	ids []MapID | ||||
|  | ||||
| 	stats *programStats | ||||
| } | ||||
|  | ||||
| func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) { | ||||
| 	info, err := bpfGetProgInfoByFD(fd) | ||||
| 	info, err := bpfGetProgInfoByFD(fd, nil) | ||||
| 	if errors.Is(err, syscall.EINVAL) { | ||||
| 		return newProgramInfoFromProc(fd) | ||||
| 	} | ||||
| @@ -100,6 +105,15 @@ func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var mapIDs []MapID | ||||
| 	if info.nr_map_ids > 0 { | ||||
| 		mapIDs = make([]MapID, info.nr_map_ids) | ||||
| 		info, err = bpfGetProgInfoByFD(fd, mapIDs) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return &ProgramInfo{ | ||||
| 		Type: ProgramType(info.prog_type), | ||||
| 		id:   ProgramID(info.id), | ||||
| @@ -107,6 +121,8 @@ func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) { | ||||
| 		Tag: hex.EncodeToString(info.tag[:]), | ||||
| 		// name is available from 4.15. | ||||
| 		Name: internal.CString(info.name[:]), | ||||
| 		btf:  btf.ID(info.btf_id), | ||||
| 		ids:  mapIDs, | ||||
| 		stats: &programStats{ | ||||
| 			runtime:  time.Duration(info.run_time_ns), | ||||
| 			runCount: info.run_cnt, | ||||
| @@ -142,6 +158,17 @@ func (pi *ProgramInfo) ID() (ProgramID, bool) { | ||||
| 	return pi.id, pi.id > 0 | ||||
| } | ||||
|  | ||||
| // BTFID returns the BTF ID associated with the program. | ||||
| // | ||||
| // Available from 5.0. | ||||
| // | ||||
| // The bool return value indicates whether this optional field is available and | ||||
| // populated. (The field may be available but not populated if the kernel | ||||
| // supports the field but the program was loaded without BTF information.) | ||||
| func (pi *ProgramInfo) BTFID() (btf.ID, bool) { | ||||
| 	return pi.btf, pi.btf > 0 | ||||
| } | ||||
|  | ||||
| // RunCount returns the total number of times the program was called. | ||||
| // | ||||
| // Can return 0 if the collection of statistics is not enabled. See EnableStats(). | ||||
| @@ -164,6 +191,13 @@ func (pi *ProgramInfo) Runtime() (time.Duration, bool) { | ||||
| 	return time.Duration(0), false | ||||
| } | ||||
|  | ||||
| // MapIDs returns the maps related to the program. | ||||
| // | ||||
| // The bool return value indicates whether this optional field is available. | ||||
| func (pi *ProgramInfo) MapIDs() ([]MapID, bool) { | ||||
| 	return pi.ids, pi.ids != nil | ||||
| } | ||||
|  | ||||
| func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error { | ||||
| 	raw, err := fd.Value() | ||||
| 	if err != nil { | ||||
|   | ||||
							
								
								
									
										6
									
								
								vendor/github.com/cilium/ebpf/internal/align.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/cilium/ebpf/internal/align.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| package internal | ||||
|  | ||||
| // Align returns 'n' updated to 'alignment' boundary. | ||||
| func Align(n, alignment int) int { | ||||
| 	return (int(n) + alignment - 1) / alignment * alignment | ||||
| } | ||||
							
								
								
									
										293
									
								
								vendor/github.com/cilium/ebpf/internal/btf/btf.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										293
									
								
								vendor/github.com/cilium/ebpf/internal/btf/btf.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -7,7 +7,6 @@ import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"math" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| @@ -27,12 +26,15 @@ var ( | ||||
| 	ErrNoExtendedInfo = errors.New("no extended info") | ||||
| ) | ||||
|  | ||||
| // ID represents the unique ID of a BTF object. | ||||
| type ID uint32 | ||||
|  | ||||
| // Spec represents decoded BTF. | ||||
| type Spec struct { | ||||
| 	rawTypes   []rawType | ||||
| 	strings    stringTable | ||||
| 	types      []Type | ||||
| 	namedTypes map[string][]namedType | ||||
| 	namedTypes map[string][]NamedType | ||||
| 	funcInfos  map[string]extInfo | ||||
| 	lineInfos  map[string]extInfo | ||||
| 	coreRelos  map[string]coreRelos | ||||
| @@ -61,15 +63,6 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) { | ||||
| 	} | ||||
| 	defer file.Close() | ||||
|  | ||||
| 	btfSection, btfExtSection, sectionSizes, err := findBtfSections(file) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if btfSection == nil { | ||||
| 		return nil, fmt.Errorf("btf: %w", ErrNotFound) | ||||
| 	} | ||||
|  | ||||
| 	symbols, err := file.Symbols() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("can't read symbols: %v", err) | ||||
| @@ -87,10 +80,6 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) { | ||||
| 		} | ||||
|  | ||||
| 		secName := file.Sections[symbol.Section].Name | ||||
| 		if _, ok := sectionSizes[secName]; !ok { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if symbol.Value > math.MaxUint32 { | ||||
| 			return nil, fmt.Errorf("section %s: symbol %s: size exceeds maximum", secName, symbol.Name) | ||||
| 		} | ||||
| @@ -98,24 +87,10 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) { | ||||
| 		variableOffsets[variable{secName, symbol.Name}] = uint32(symbol.Value) | ||||
| 	} | ||||
|  | ||||
| 	spec, err := loadNakedSpec(btfSection.Open(), file.ByteOrder, sectionSizes, variableOffsets) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if btfExtSection == nil { | ||||
| 		return spec, nil | ||||
| 	} | ||||
|  | ||||
| 	spec.funcInfos, spec.lineInfos, spec.coreRelos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("can't read ext info: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return spec, nil | ||||
| 	return loadSpecFromELF(file, variableOffsets) | ||||
| } | ||||
|  | ||||
| func findBtfSections(file *internal.SafeELFFile) (*elf.Section, *elf.Section, map[string]uint32, error) { | ||||
| func loadSpecFromELF(file *internal.SafeELFFile, variableOffsets map[variable]uint32) (*Spec, error) { | ||||
| 	var ( | ||||
| 		btfSection    *elf.Section | ||||
| 		btfExtSection *elf.Section | ||||
| @@ -134,33 +109,45 @@ func findBtfSections(file *internal.SafeELFFile) (*elf.Section, *elf.Section, ma | ||||
| 			} | ||||
|  | ||||
| 			if sec.Size > math.MaxUint32 { | ||||
| 				return nil, nil, nil, fmt.Errorf("section %s exceeds maximum size", sec.Name) | ||||
| 				return nil, fmt.Errorf("section %s exceeds maximum size", sec.Name) | ||||
| 			} | ||||
|  | ||||
| 			sectionSizes[sec.Name] = uint32(sec.Size) | ||||
| 		} | ||||
| 	} | ||||
| 	return btfSection, btfExtSection, sectionSizes, nil | ||||
| } | ||||
|  | ||||
| func loadSpecFromVmlinux(rd io.ReaderAt) (*Spec, error) { | ||||
| 	file, err := internal.NewSafeELFFile(rd) | ||||
| 	if btfSection == nil { | ||||
| 		return nil, fmt.Errorf("btf: %w", ErrNotFound) | ||||
| 	} | ||||
|  | ||||
| 	spec, err := loadRawSpec(btfSection.Open(), file.ByteOrder, sectionSizes, variableOffsets) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer file.Close() | ||||
|  | ||||
| 	btfSection, _, _, err := findBtfSections(file) | ||||
| 	if btfExtSection == nil { | ||||
| 		return spec, nil | ||||
| 	} | ||||
|  | ||||
| 	spec.funcInfos, spec.lineInfos, spec.coreRelos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf(".BTF ELF section: %s", err) | ||||
| 		return nil, fmt.Errorf("can't read ext info: %w", err) | ||||
| 	} | ||||
| 	if btfSection == nil { | ||||
| 		return nil, fmt.Errorf("unable to find .BTF ELF section") | ||||
| 	} | ||||
| 	return loadNakedSpec(btfSection.Open(), file.ByteOrder, nil, nil) | ||||
|  | ||||
| 	return spec, nil | ||||
| } | ||||
|  | ||||
| func loadNakedSpec(btf io.ReadSeeker, bo binary.ByteOrder, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) (*Spec, error) { | ||||
| // LoadRawSpec reads a blob of BTF data that isn't wrapped in an ELF file. | ||||
| // | ||||
| // Prefer using LoadSpecFromReader, since this function only supports a subset | ||||
| // of BTF. | ||||
| func LoadRawSpec(btf io.Reader, bo binary.ByteOrder) (*Spec, error) { | ||||
| 	// This will return an error if we encounter a Datasec, since we can't fix | ||||
| 	// it up. | ||||
| 	return loadRawSpec(btf, bo, nil, nil) | ||||
| } | ||||
|  | ||||
| func loadRawSpec(btf io.Reader, bo binary.ByteOrder, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) (*Spec, error) { | ||||
| 	rawTypes, rawStrings, err := parseBTF(btf, bo) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -217,7 +204,7 @@ func loadKernelSpec() (*Spec, error) { | ||||
| 	if err == nil { | ||||
| 		defer fh.Close() | ||||
|  | ||||
| 		return loadNakedSpec(fh, internal.NativeEndian, nil, nil) | ||||
| 		return LoadRawSpec(fh, internal.NativeEndian) | ||||
| 	} | ||||
|  | ||||
| 	// use same list of locations as libbpf | ||||
| @@ -241,14 +228,20 @@ func loadKernelSpec() (*Spec, error) { | ||||
| 		} | ||||
| 		defer fh.Close() | ||||
|  | ||||
| 		return loadSpecFromVmlinux(fh) | ||||
| 		file, err := internal.NewSafeELFFile(fh) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		defer file.Close() | ||||
|  | ||||
| 		return loadSpecFromELF(file, nil) | ||||
| 	} | ||||
|  | ||||
| 	return nil, fmt.Errorf("no BTF for kernel version %s: %w", release, internal.ErrNotSupported) | ||||
| } | ||||
|  | ||||
| func parseBTF(btf io.ReadSeeker, bo binary.ByteOrder) ([]rawType, stringTable, error) { | ||||
| 	rawBTF, err := ioutil.ReadAll(btf) | ||||
| func parseBTF(btf io.Reader, bo binary.ByteOrder) ([]rawType, stringTable, error) { | ||||
| 	rawBTF, err := io.ReadAll(btf) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, fmt.Errorf("can't read BTF: %v", err) | ||||
| 	} | ||||
| @@ -357,6 +350,30 @@ func fixupDatasec(rawTypes []rawType, rawStrings stringTable, sectionSizes map[s | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Copy creates a copy of Spec. | ||||
| func (s *Spec) Copy() *Spec { | ||||
| 	types, _ := copyTypes(s.types, nil) | ||||
| 	namedTypes := make(map[string][]NamedType) | ||||
| 	for _, typ := range types { | ||||
| 		if named, ok := typ.(NamedType); ok { | ||||
| 			name := essentialName(named.TypeName()) | ||||
| 			namedTypes[name] = append(namedTypes[name], named) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// NB: Other parts of spec are not copied since they are immutable. | ||||
| 	return &Spec{ | ||||
| 		s.rawTypes, | ||||
| 		s.strings, | ||||
| 		types, | ||||
| 		namedTypes, | ||||
| 		s.funcInfos, | ||||
| 		s.lineInfos, | ||||
| 		s.coreRelos, | ||||
| 		s.byteOrder, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type marshalOpts struct { | ||||
| 	ByteOrder        binary.ByteOrder | ||||
| 	StripFuncLinkage bool | ||||
| @@ -447,36 +464,37 @@ func (s *Spec) Program(name string, length uint64) (*Program, error) { | ||||
| 	return &Program{s, length, funcInfos, lineInfos, relos}, nil | ||||
| } | ||||
|  | ||||
| // Datasec returns the BTF required to create maps which represent data sections. | ||||
| func (s *Spec) Datasec(name string) (*Map, error) { | ||||
| 	var datasec Datasec | ||||
| 	if err := s.FindType(name, &datasec); err != nil { | ||||
| 		return nil, fmt.Errorf("data section %s: can't get BTF: %w", name, err) | ||||
| 	} | ||||
|  | ||||
| 	m := NewMap(s, &Void{}, &datasec) | ||||
| 	return &m, nil | ||||
| } | ||||
|  | ||||
| // FindType searches for a type with a specific name. | ||||
| // | ||||
| // hint determines the type of the returned Type. | ||||
| // Called T a type that satisfies Type, typ must be a non-nil **T. | ||||
| // On success, the address of the found type will be copied in typ. | ||||
| // | ||||
| // Returns an error wrapping ErrNotFound if no matching | ||||
| // type exists in spec. | ||||
| func (s *Spec) FindType(name string, typ Type) error { | ||||
| 	var ( | ||||
| 		wanted    = reflect.TypeOf(typ) | ||||
| 		candidate Type | ||||
| 	) | ||||
| func (s *Spec) FindType(name string, typ interface{}) error { | ||||
| 	typValue := reflect.ValueOf(typ) | ||||
| 	if typValue.Kind() != reflect.Ptr { | ||||
| 		return fmt.Errorf("%T is not a pointer", typ) | ||||
| 	} | ||||
|  | ||||
| 	typPtr := typValue.Elem() | ||||
| 	if !typPtr.CanSet() { | ||||
| 		return fmt.Errorf("%T cannot be set", typ) | ||||
| 	} | ||||
|  | ||||
| 	wanted := typPtr.Type() | ||||
| 	if !wanted.AssignableTo(reflect.TypeOf((*Type)(nil)).Elem()) { | ||||
| 		return fmt.Errorf("%T does not satisfy Type interface", typ) | ||||
| 	} | ||||
|  | ||||
| 	var candidate Type | ||||
| 	for _, typ := range s.namedTypes[essentialName(name)] { | ||||
| 		if reflect.TypeOf(typ) != wanted { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// Match against the full name, not just the essential one. | ||||
| 		if typ.name() != name { | ||||
| 		if typ.TypeName() != name { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| @@ -491,15 +509,15 @@ func (s *Spec) FindType(name string, typ Type) error { | ||||
| 		return fmt.Errorf("type %s: %w", name, ErrNotFound) | ||||
| 	} | ||||
|  | ||||
| 	cpy, _ := copyType(candidate, nil) | ||||
| 	value := reflect.Indirect(reflect.ValueOf(cpy)) | ||||
| 	reflect.Indirect(reflect.ValueOf(typ)).Set(value) | ||||
| 	typPtr.Set(reflect.ValueOf(candidate)) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Handle is a reference to BTF loaded into the kernel. | ||||
| type Handle struct { | ||||
| 	fd *internal.FD | ||||
| 	spec *Spec | ||||
| 	fd   *internal.FD | ||||
| } | ||||
|  | ||||
| // NewHandle loads BTF into the kernel. | ||||
| @@ -541,7 +559,32 @@ func NewHandle(spec *Spec) (*Handle, error) { | ||||
| 		return nil, internal.ErrorWithLog(err, logBuf, logErr) | ||||
| 	} | ||||
|  | ||||
| 	return &Handle{fd}, nil | ||||
| 	return &Handle{spec.Copy(), fd}, nil | ||||
| } | ||||
|  | ||||
| // NewHandleFromID returns the BTF handle for a given id. | ||||
| // | ||||
| // Returns ErrNotExist, if there is no BTF with the given id. | ||||
| // | ||||
| // Requires CAP_SYS_ADMIN. | ||||
| func NewHandleFromID(id ID) (*Handle, error) { | ||||
| 	fd, err := internal.BPFObjGetFDByID(internal.BPF_BTF_GET_FD_BY_ID, uint32(id)) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("get BTF by id: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	info, err := newInfoFromFd(fd) | ||||
| 	if err != nil { | ||||
| 		_ = fd.Close() | ||||
| 		return nil, fmt.Errorf("get BTF spec for handle: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return &Handle{info.BTF, fd}, nil | ||||
| } | ||||
|  | ||||
| // Spec returns the Spec that defined the BTF loaded into the kernel. | ||||
| func (h *Handle) Spec() *Spec { | ||||
| 	return h.spec | ||||
| } | ||||
|  | ||||
| // Close destroys the handle. | ||||
| @@ -563,43 +606,8 @@ func (h *Handle) FD() int { | ||||
|  | ||||
| // Map is the BTF for a map. | ||||
| type Map struct { | ||||
| 	spec       *Spec | ||||
| 	key, value Type | ||||
| } | ||||
|  | ||||
| // NewMap returns a new Map containing the given values. | ||||
| // The key and value arguments are initialized to Void if nil values are given. | ||||
| func NewMap(spec *Spec, key Type, value Type) Map { | ||||
| 	if key == nil { | ||||
| 		key = &Void{} | ||||
| 	} | ||||
| 	if value == nil { | ||||
| 		value = &Void{} | ||||
| 	} | ||||
|  | ||||
| 	return Map{ | ||||
| 		spec:  spec, | ||||
| 		key:   key, | ||||
| 		value: value, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // MapSpec should be a method on Map, but is a free function | ||||
| // to hide it from users of the ebpf package. | ||||
| func MapSpec(m *Map) *Spec { | ||||
| 	return m.spec | ||||
| } | ||||
|  | ||||
| // MapKey should be a method on Map, but is a free function | ||||
| // to hide it from users of the ebpf package. | ||||
| func MapKey(m *Map) Type { | ||||
| 	return m.key | ||||
| } | ||||
|  | ||||
| // MapValue should be a method on Map, but is a free function | ||||
| // to hide it from users of the ebpf package. | ||||
| func MapValue(m *Map) Type { | ||||
| 	return m.value | ||||
| 	Spec       *Spec | ||||
| 	Key, Value Type | ||||
| } | ||||
|  | ||||
| // Program is the BTF information for a stream of instructions. | ||||
| @@ -610,68 +618,59 @@ type Program struct { | ||||
| 	coreRelos            coreRelos | ||||
| } | ||||
|  | ||||
| // ProgramSpec returns the Spec needed for loading function and line infos into the kernel. | ||||
| // | ||||
| // This is a free function instead of a method to hide it from users | ||||
| // of package ebpf. | ||||
| func ProgramSpec(s *Program) *Spec { | ||||
| 	return s.spec | ||||
| // Spec returns the BTF spec of this program. | ||||
| func (p *Program) Spec() *Spec { | ||||
| 	return p.spec | ||||
| } | ||||
|  | ||||
| // ProgramAppend the information from other to the Program. | ||||
| // | ||||
| // This is a free function instead of a method to hide it from users | ||||
| // of package ebpf. | ||||
| func ProgramAppend(s, other *Program) error { | ||||
| 	funcInfos, err := s.funcInfos.append(other.funcInfos, s.length) | ||||
| // Append the information from other to the Program. | ||||
| func (p *Program) Append(other *Program) error { | ||||
| 	if other.spec != p.spec { | ||||
| 		return fmt.Errorf("can't append program with different BTF specs") | ||||
| 	} | ||||
|  | ||||
| 	funcInfos, err := p.funcInfos.append(other.funcInfos, p.length) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("func infos: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	lineInfos, err := s.lineInfos.append(other.lineInfos, s.length) | ||||
| 	lineInfos, err := p.lineInfos.append(other.lineInfos, p.length) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("line infos: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	s.funcInfos = funcInfos | ||||
| 	s.lineInfos = lineInfos | ||||
| 	s.coreRelos = s.coreRelos.append(other.coreRelos, s.length) | ||||
| 	s.length += other.length | ||||
| 	p.funcInfos = funcInfos | ||||
| 	p.lineInfos = lineInfos | ||||
| 	p.coreRelos = p.coreRelos.append(other.coreRelos, p.length) | ||||
| 	p.length += other.length | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ProgramFuncInfos returns the binary form of BTF function infos. | ||||
| // | ||||
| // This is a free function instead of a method to hide it from users | ||||
| // of package ebpf. | ||||
| func ProgramFuncInfos(s *Program) (recordSize uint32, bytes []byte, err error) { | ||||
| 	bytes, err = s.funcInfos.MarshalBinary() | ||||
| // FuncInfos returns the binary form of BTF function infos. | ||||
| func (p *Program) FuncInfos() (recordSize uint32, bytes []byte, err error) { | ||||
| 	bytes, err = p.funcInfos.MarshalBinary() | ||||
| 	if err != nil { | ||||
| 		return 0, nil, err | ||||
| 		return 0, nil, fmt.Errorf("func infos: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return s.funcInfos.recordSize, bytes, nil | ||||
| 	return p.funcInfos.recordSize, bytes, nil | ||||
| } | ||||
|  | ||||
| // ProgramLineInfos returns the binary form of BTF line infos. | ||||
| // | ||||
| // This is a free function instead of a method to hide it from users | ||||
| // of package ebpf. | ||||
| func ProgramLineInfos(s *Program) (recordSize uint32, bytes []byte, err error) { | ||||
| 	bytes, err = s.lineInfos.MarshalBinary() | ||||
| // LineInfos returns the binary form of BTF line infos. | ||||
| func (p *Program) LineInfos() (recordSize uint32, bytes []byte, err error) { | ||||
| 	bytes, err = p.lineInfos.MarshalBinary() | ||||
| 	if err != nil { | ||||
| 		return 0, nil, err | ||||
| 		return 0, nil, fmt.Errorf("line infos: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return s.lineInfos.recordSize, bytes, nil | ||||
| 	return p.lineInfos.recordSize, bytes, nil | ||||
| } | ||||
|  | ||||
| // ProgramFixups returns the changes required to adjust the program to the target. | ||||
| // Fixups returns the changes required to adjust the program to the target. | ||||
| // | ||||
| // This is a free function instead of a method to hide it from users | ||||
| // of package ebpf. | ||||
| func ProgramFixups(s *Program, target *Spec) (COREFixups, error) { | ||||
| 	if len(s.coreRelos) == 0 { | ||||
| // Passing a nil target will relocate against the running kernel. | ||||
| func (p *Program) Fixups(target *Spec) (COREFixups, error) { | ||||
| 	if len(p.coreRelos) == 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| @@ -683,7 +682,7 @@ func ProgramFixups(s *Program, target *Spec) (COREFixups, error) { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return coreRelocate(s.spec, target, s.coreRelos) | ||||
| 	return coreRelocate(p.spec, target, p.coreRelos) | ||||
| } | ||||
|  | ||||
| type bpfLoadBTFAttr struct { | ||||
|   | ||||
							
								
								
									
										11
									
								
								vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -31,6 +31,8 @@ const ( | ||||
| 	// Added ~5.1 | ||||
| 	kindVar | ||||
| 	kindDatasec | ||||
| 	// Added ~5.13 | ||||
| 	kindFloat | ||||
| ) | ||||
|  | ||||
| // FuncLinkage describes BTF function linkage metadata. | ||||
| @@ -54,7 +56,7 @@ const ( | ||||
|  | ||||
| const ( | ||||
| 	btfTypeKindShift     = 24 | ||||
| 	btfTypeKindLen       = 4 | ||||
| 	btfTypeKindLen       = 5 | ||||
| 	btfTypeVlenShift     = 0 | ||||
| 	btfTypeVlenMask      = 16 | ||||
| 	btfTypeKindFlagShift = 31 | ||||
| @@ -67,8 +69,8 @@ type btfType struct { | ||||
| 	/* "info" bits arrangement | ||||
| 	 * bits  0-15: vlen (e.g. # of struct's members), linkage | ||||
| 	 * bits 16-23: unused | ||||
| 	 * bits 24-27: kind (e.g. int, ptr, array...etc) | ||||
| 	 * bits 28-30: unused | ||||
| 	 * bits 24-28: kind (e.g. int, ptr, array...etc) | ||||
| 	 * bits 29-30: unused | ||||
| 	 * bit     31: kind_flag, currently used by | ||||
| 	 *             struct, union and fwd | ||||
| 	 */ | ||||
| @@ -117,6 +119,8 @@ func (k btfKind) String() string { | ||||
| 		return "Variable" | ||||
| 	case kindDatasec: | ||||
| 		return "Section" | ||||
| 	case kindFloat: | ||||
| 		return "Float" | ||||
| 	default: | ||||
| 		return fmt.Sprintf("Unknown (%d)", k) | ||||
| 	} | ||||
| @@ -260,6 +264,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) { | ||||
| 			data = new(btfVariable) | ||||
| 		case kindDatasec: | ||||
| 			data = make([]btfVarSecinfo, header.Vlen()) | ||||
| 		case kindFloat: | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind()) | ||||
| 		} | ||||
|   | ||||
							
								
								
									
										33
									
								
								vendor/github.com/cilium/ebpf/internal/btf/core.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								vendor/github.com/cilium/ebpf/internal/btf/core.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -234,13 +234,13 @@ func coreRelocate(local, target *Spec, relos coreRelos) (COREFixups, error) { | ||||
| 		} | ||||
|  | ||||
| 		localType := local.types[id] | ||||
| 		named, ok := localType.(namedType) | ||||
| 		if !ok || named.name() == "" { | ||||
| 		named, ok := localType.(NamedType) | ||||
| 		if !ok || named.TypeName() == "" { | ||||
| 			return nil, fmt.Errorf("relocate unnamed or anonymous type %s: %w", localType, ErrNotSupported) | ||||
| 		} | ||||
|  | ||||
| 		relos := relosByID[id] | ||||
| 		targets := target.namedTypes[named.essentialName()] | ||||
| 		targets := target.namedTypes[essentialName(named.TypeName())] | ||||
| 		fixups, err := coreCalculateFixups(localType, targets, relos) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("relocate %s: %w", localType, err) | ||||
| @@ -262,7 +262,7 @@ var errImpossibleRelocation = errors.New("impossible relocation") | ||||
| // | ||||
| // The best target is determined by scoring: the less poisoning we have to do | ||||
| // the better the target is. | ||||
| func coreCalculateFixups(local Type, targets []namedType, relos coreRelos) ([]COREFixup, error) { | ||||
| func coreCalculateFixups(local Type, targets []NamedType, relos coreRelos) ([]COREFixup, error) { | ||||
| 	localID := local.ID() | ||||
| 	local, err := copyType(local, skipQualifierAndTypedef) | ||||
| 	if err != nil { | ||||
| @@ -467,8 +467,8 @@ func parseCoreAccessor(accessor string) (coreAccessor, error) { | ||||
| 		return nil, fmt.Errorf("empty accessor") | ||||
| 	} | ||||
|  | ||||
| 	var result coreAccessor | ||||
| 	parts := strings.Split(accessor, ":") | ||||
| 	result := make(coreAccessor, 0, len(parts)) | ||||
| 	for _, part := range parts { | ||||
| 		// 31 bits to avoid overflowing int on 32 bit platforms. | ||||
| 		index, err := strconv.ParseUint(part, 10, 31) | ||||
| @@ -564,7 +564,7 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie | ||||
|  | ||||
| 				// This is an anonymous struct or union, ignore it. | ||||
| 				local = localMember.Type | ||||
| 				localOffset += localMember.Offset | ||||
| 				localOffset += localMember.OffsetBits | ||||
| 				localMaybeFlex = false | ||||
| 				continue | ||||
| 			} | ||||
| @@ -585,10 +585,10 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie | ||||
|  | ||||
| 			local = localMember.Type | ||||
| 			localMaybeFlex = acc == len(localMembers)-1 | ||||
| 			localOffset += localMember.Offset | ||||
| 			localOffset += localMember.OffsetBits | ||||
| 			target = targetMember.Type | ||||
| 			targetMaybeFlex = last | ||||
| 			targetOffset += targetMember.Offset | ||||
| 			targetOffset += targetMember.OffsetBits | ||||
|  | ||||
| 		case *Array: | ||||
| 			// For arrays, acc is the index in the target. | ||||
| @@ -639,7 +639,7 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie | ||||
|  | ||||
| // coreFindMember finds a member in a composite type while handling anonymous | ||||
| // structs and unions. | ||||
| func coreFindMember(typ composite, name Name) (Member, bool, error) { | ||||
| func coreFindMember(typ composite, name string) (Member, bool, error) { | ||||
| 	if name == "" { | ||||
| 		return Member{}, false, errors.New("can't search for anonymous member") | ||||
| 	} | ||||
| @@ -670,7 +670,7 @@ func coreFindMember(typ composite, name Name) (Member, bool, error) { | ||||
| 		for j, member := range members { | ||||
| 			if member.Name == name { | ||||
| 				// NB: This is safe because member is a copy. | ||||
| 				member.Offset += target.offset | ||||
| 				member.OffsetBits += target.offset | ||||
| 				return member, j == len(members)-1, nil | ||||
| 			} | ||||
|  | ||||
| @@ -685,7 +685,7 @@ func coreFindMember(typ composite, name Name) (Member, bool, error) { | ||||
| 				return Member{}, false, fmt.Errorf("anonymous non-composite type %T not allowed", member.Type) | ||||
| 			} | ||||
|  | ||||
| 			targets = append(targets, offsetTarget{comp, target.offset + member.Offset}) | ||||
| 			targets = append(targets, offsetTarget{comp, target.offset + member.OffsetBits}) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -704,9 +704,9 @@ func coreFindEnumValue(local Type, localAcc coreAccessor, target Type) (localVal | ||||
| 		return nil, nil, errImpossibleRelocation | ||||
| 	} | ||||
|  | ||||
| 	localName := localValue.Name.essentialName() | ||||
| 	localName := essentialName(localValue.Name) | ||||
| 	for i, targetValue := range targetEnum.Values { | ||||
| 		if targetValue.Name.essentialName() != localName { | ||||
| 		if essentialName(targetValue.Name) != localName { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| @@ -813,6 +813,7 @@ func coreAreTypesCompatible(localType Type, targetType Type) error { | ||||
|  *     least one of enums should be anonymous; | ||||
|  *   - for ENUMs, check sizes, names are ignored; | ||||
|  *   - for INT, size and signedness are ignored; | ||||
|  *   - any two FLOATs are always compatible; | ||||
|  *   - for ARRAY, dimensionality is ignored, element types are checked for | ||||
|  *     compatibility recursively; | ||||
|  *     [ NB: coreAreMembersCompatible doesn't recurse, this check is done | ||||
| @@ -848,16 +849,16 @@ func coreAreMembersCompatible(localType Type, targetType Type) error { | ||||
| 	} | ||||
|  | ||||
| 	switch lv := localType.(type) { | ||||
| 	case *Array, *Pointer: | ||||
| 	case *Array, *Pointer, *Float: | ||||
| 		return nil | ||||
|  | ||||
| 	case *Enum: | ||||
| 		tv := targetType.(*Enum) | ||||
| 		return doNamesMatch(lv.name(), tv.name()) | ||||
| 		return doNamesMatch(lv.Name, tv.Name) | ||||
|  | ||||
| 	case *Fwd: | ||||
| 		tv := targetType.(*Fwd) | ||||
| 		return doNamesMatch(lv.name(), tv.name()) | ||||
| 		return doNamesMatch(lv.Name, tv.Name) | ||||
|  | ||||
| 	case *Int: | ||||
| 		tv := targetType.(*Int) | ||||
|   | ||||
							
								
								
									
										15
									
								
								vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -7,7 +7,6 @@ import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/asm" | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| @@ -64,7 +63,7 @@ func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (f | ||||
|  | ||||
| 	// Of course, the .BTF.ext header has different semantics than the | ||||
| 	// .BTF ext header. We need to ignore non-null values. | ||||
| 	_, err = io.CopyN(ioutil.Discard, r, remainder) | ||||
| 	_, err = io.CopyN(io.Discard, r, remainder) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, nil, fmt.Errorf("header padding: %v", err) | ||||
| 	} | ||||
| @@ -114,11 +113,16 @@ type extInfoRecord struct { | ||||
| } | ||||
|  | ||||
| type extInfo struct { | ||||
| 	byteOrder  binary.ByteOrder | ||||
| 	recordSize uint32 | ||||
| 	records    []extInfoRecord | ||||
| } | ||||
|  | ||||
| func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) { | ||||
| 	if other.byteOrder != ei.byteOrder { | ||||
| 		return extInfo{}, fmt.Errorf("ext_info byte order mismatch, want %v (got %v)", ei.byteOrder, other.byteOrder) | ||||
| 	} | ||||
|  | ||||
| 	if other.recordSize != ei.recordSize { | ||||
| 		return extInfo{}, fmt.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize) | ||||
| 	} | ||||
| @@ -131,10 +135,14 @@ func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) { | ||||
| 			Opaque:  info.Opaque, | ||||
| 		}) | ||||
| 	} | ||||
| 	return extInfo{ei.recordSize, records}, nil | ||||
| 	return extInfo{ei.byteOrder, ei.recordSize, records}, nil | ||||
| } | ||||
|  | ||||
| func (ei extInfo) MarshalBinary() ([]byte, error) { | ||||
| 	if ei.byteOrder != internal.NativeEndian { | ||||
| 		return nil, fmt.Errorf("%s is not the native byte order", ei.byteOrder) | ||||
| 	} | ||||
|  | ||||
| 	if len(ei.records) == 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| @@ -197,6 +205,7 @@ func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[st | ||||
| 		} | ||||
|  | ||||
| 		result[secName] = extInfo{ | ||||
| 			bo, | ||||
| 			recordSize, | ||||
| 			records, | ||||
| 		} | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/btf/fuzz.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/btf/fuzz.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build gofuzz | ||||
| // +build gofuzz | ||||
|  | ||||
| // Use with https://github.com/dvyukov/go-fuzz | ||||
|   | ||||
							
								
								
									
										48
									
								
								vendor/github.com/cilium/ebpf/internal/btf/info.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/cilium/ebpf/internal/btf/info.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| package btf | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| ) | ||||
|  | ||||
| // info describes a BTF object. | ||||
| type info struct { | ||||
| 	BTF *Spec | ||||
| 	ID  ID | ||||
| 	// Name is an identifying name for the BTF, currently only used by the | ||||
| 	// kernel. | ||||
| 	Name string | ||||
| 	// KernelBTF is true if the BTf originated with the kernel and not | ||||
| 	// userspace. | ||||
| 	KernelBTF bool | ||||
| } | ||||
|  | ||||
| func newInfoFromFd(fd *internal.FD) (*info, error) { | ||||
| 	// We invoke the syscall once with a empty BTF and name buffers to get size | ||||
| 	// information to allocate buffers. Then we invoke it a second time with | ||||
| 	// buffers to receive the data. | ||||
| 	bpfInfo, err := bpfGetBTFInfoByFD(fd, nil, nil) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	btfBuffer := make([]byte, bpfInfo.btfSize) | ||||
| 	nameBuffer := make([]byte, bpfInfo.nameLen) | ||||
| 	bpfInfo, err = bpfGetBTFInfoByFD(fd, btfBuffer, nameBuffer) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	spec, err := loadRawSpec(bytes.NewReader(btfBuffer), internal.NativeEndian, nil, nil) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &info{ | ||||
| 		BTF:       spec, | ||||
| 		ID:        ID(bpfInfo.id), | ||||
| 		Name:      internal.CString(nameBuffer), | ||||
| 		KernelBTF: bpfInfo.kernelBTF != 0, | ||||
| 	}, nil | ||||
| } | ||||
							
								
								
									
										8
									
								
								vendor/github.com/cilium/ebpf/internal/btf/strings.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/cilium/ebpf/internal/btf/strings.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,13 +5,12 @@ import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| ) | ||||
|  | ||||
| type stringTable []byte | ||||
|  | ||||
| func readStringTable(r io.Reader) (stringTable, error) { | ||||
| 	contents, err := ioutil.ReadAll(r) | ||||
| 	contents, err := io.ReadAll(r) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("can't read string table: %v", err) | ||||
| 	} | ||||
| @@ -53,8 +52,3 @@ func (st stringTable) Lookup(offset uint32) (string, error) { | ||||
|  | ||||
| 	return string(str[:end]), nil | ||||
| } | ||||
|  | ||||
| func (st stringTable) LookupName(offset uint32) (Name, error) { | ||||
| 	str, err := st.Lookup(offset) | ||||
| 	return Name(str), err | ||||
| } | ||||
|   | ||||
							
								
								
									
										31
									
								
								vendor/github.com/cilium/ebpf/internal/btf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/cilium/ebpf/internal/btf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| package btf | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| ) | ||||
|  | ||||
| type bpfBTFInfo struct { | ||||
| 	btf       internal.Pointer | ||||
| 	btfSize   uint32 | ||||
| 	id        uint32 | ||||
| 	name      internal.Pointer | ||||
| 	nameLen   uint32 | ||||
| 	kernelBTF uint32 | ||||
| } | ||||
|  | ||||
| func bpfGetBTFInfoByFD(fd *internal.FD, btf, name []byte) (*bpfBTFInfo, error) { | ||||
| 	info := bpfBTFInfo{ | ||||
| 		btf:     internal.NewSlicePointer(btf), | ||||
| 		btfSize: uint32(len(btf)), | ||||
| 		name:    internal.NewSlicePointer(name), | ||||
| 		nameLen: uint32(len(name)), | ||||
| 	} | ||||
| 	if err := internal.BPFObjGetInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil { | ||||
| 		return nil, fmt.Errorf("can't get program info: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return &info, nil | ||||
| } | ||||
							
								
								
									
										190
									
								
								vendor/github.com/cilium/ebpf/internal/btf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										190
									
								
								vendor/github.com/cilium/ebpf/internal/btf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -30,27 +30,26 @@ type Type interface { | ||||
| 	walk(*typeDeque) | ||||
| } | ||||
|  | ||||
| // namedType is a type with a name. | ||||
| // | ||||
| // Most named types simply embed Name. | ||||
| type namedType interface { | ||||
| // NamedType is a type with a name. | ||||
| type NamedType interface { | ||||
| 	Type | ||||
| 	name() string | ||||
| 	essentialName() string | ||||
|  | ||||
| 	// Name of the type, empty for anonymous types. | ||||
| 	TypeName() string | ||||
| } | ||||
|  | ||||
| // Name identifies a type. | ||||
| // | ||||
| // Anonymous types have an empty name. | ||||
| type Name string | ||||
|  | ||||
| func (n Name) name() string { | ||||
| 	return string(n) | ||||
| } | ||||
|  | ||||
| func (n Name) essentialName() string { | ||||
| 	return essentialName(string(n)) | ||||
| } | ||||
| var ( | ||||
| 	_ NamedType = (*Int)(nil) | ||||
| 	_ NamedType = (*Struct)(nil) | ||||
| 	_ NamedType = (*Union)(nil) | ||||
| 	_ NamedType = (*Enum)(nil) | ||||
| 	_ NamedType = (*Fwd)(nil) | ||||
| 	_ NamedType = (*Func)(nil) | ||||
| 	_ NamedType = (*Typedef)(nil) | ||||
| 	_ NamedType = (*Var)(nil) | ||||
| 	_ NamedType = (*Datasec)(nil) | ||||
| 	_ NamedType = (*Float)(nil) | ||||
| ) | ||||
|  | ||||
| // Void is the unit type of BTF. | ||||
| type Void struct{} | ||||
| @@ -72,19 +71,17 @@ const ( | ||||
| // Int is an integer of a given length. | ||||
| type Int struct { | ||||
| 	TypeID | ||||
| 	Name | ||||
| 	Name string | ||||
|  | ||||
| 	// The size of the integer in bytes. | ||||
| 	Size     uint32 | ||||
| 	Encoding IntEncoding | ||||
| 	// Offset is the starting bit offset. Currently always 0. | ||||
| 	// OffsetBits is the starting bit offset. Currently always 0. | ||||
| 	// See https://www.kernel.org/doc/html/latest/bpf/btf.html#btf-kind-int | ||||
| 	Offset uint32 | ||||
| 	Bits   byte | ||||
| 	OffsetBits uint32 | ||||
| 	Bits       byte | ||||
| } | ||||
|  | ||||
| var _ namedType = (*Int)(nil) | ||||
|  | ||||
| func (i *Int) String() string { | ||||
| 	var s strings.Builder | ||||
|  | ||||
| @@ -110,15 +107,16 @@ func (i *Int) String() string { | ||||
| 	return s.String() | ||||
| } | ||||
|  | ||||
| func (i *Int) size() uint32    { return i.Size } | ||||
| func (i *Int) walk(*typeDeque) {} | ||||
| func (i *Int) TypeName() string { return i.Name } | ||||
| func (i *Int) size() uint32     { return i.Size } | ||||
| func (i *Int) walk(*typeDeque)  {} | ||||
| func (i *Int) copy() Type { | ||||
| 	cpy := *i | ||||
| 	return &cpy | ||||
| } | ||||
|  | ||||
| func (i *Int) isBitfield() bool { | ||||
| 	return i.Offset > 0 | ||||
| 	return i.OffsetBits > 0 | ||||
| } | ||||
|  | ||||
| // Pointer is a pointer to another type. | ||||
| @@ -158,7 +156,7 @@ func (arr *Array) copy() Type { | ||||
| // Struct is a compound type of consecutive members. | ||||
| type Struct struct { | ||||
| 	TypeID | ||||
| 	Name | ||||
| 	Name string | ||||
| 	// The size of the struct including padding, in bytes | ||||
| 	Size    uint32 | ||||
| 	Members []Member | ||||
| @@ -168,6 +166,8 @@ func (s *Struct) String() string { | ||||
| 	return fmt.Sprintf("struct#%d[%q]", s.TypeID, s.Name) | ||||
| } | ||||
|  | ||||
| func (s *Struct) TypeName() string { return s.Name } | ||||
|  | ||||
| func (s *Struct) size() uint32 { return s.Size } | ||||
|  | ||||
| func (s *Struct) walk(tdq *typeDeque) { | ||||
| @@ -189,7 +189,7 @@ func (s *Struct) members() []Member { | ||||
| // Union is a compound type where members occupy the same memory. | ||||
| type Union struct { | ||||
| 	TypeID | ||||
| 	Name | ||||
| 	Name string | ||||
| 	// The size of the union including padding, in bytes. | ||||
| 	Size    uint32 | ||||
| 	Members []Member | ||||
| @@ -199,6 +199,8 @@ func (u *Union) String() string { | ||||
| 	return fmt.Sprintf("union#%d[%q]", u.TypeID, u.Name) | ||||
| } | ||||
|  | ||||
| func (u *Union) TypeName() string { return u.Name } | ||||
|  | ||||
| func (u *Union) size() uint32 { return u.Size } | ||||
|  | ||||
| func (u *Union) walk(tdq *typeDeque) { | ||||
| @@ -236,17 +238,17 @@ var ( | ||||
| // | ||||
| // It is not a valid Type. | ||||
| type Member struct { | ||||
| 	Name | ||||
| 	Name string | ||||
| 	Type Type | ||||
| 	// Offset is the bit offset of this member | ||||
| 	Offset       uint32 | ||||
| 	// OffsetBits is the bit offset of this member. | ||||
| 	OffsetBits   uint32 | ||||
| 	BitfieldSize uint32 | ||||
| } | ||||
|  | ||||
| // Enum lists possible values. | ||||
| type Enum struct { | ||||
| 	TypeID | ||||
| 	Name | ||||
| 	Name   string | ||||
| 	Values []EnumValue | ||||
| } | ||||
|  | ||||
| @@ -254,11 +256,13 @@ func (e *Enum) String() string { | ||||
| 	return fmt.Sprintf("enum#%d[%q]", e.TypeID, e.Name) | ||||
| } | ||||
|  | ||||
| func (e *Enum) TypeName() string { return e.Name } | ||||
|  | ||||
| // EnumValue is part of an Enum | ||||
| // | ||||
| // Is is not a valid Type | ||||
| type EnumValue struct { | ||||
| 	Name | ||||
| 	Name  string | ||||
| 	Value int32 | ||||
| } | ||||
|  | ||||
| @@ -294,7 +298,7 @@ func (fk FwdKind) String() string { | ||||
| // Fwd is a forward declaration of a Type. | ||||
| type Fwd struct { | ||||
| 	TypeID | ||||
| 	Name | ||||
| 	Name string | ||||
| 	Kind FwdKind | ||||
| } | ||||
|  | ||||
| @@ -302,6 +306,8 @@ func (f *Fwd) String() string { | ||||
| 	return fmt.Sprintf("fwd#%d[%s %q]", f.TypeID, f.Kind, f.Name) | ||||
| } | ||||
|  | ||||
| func (f *Fwd) TypeName() string { return f.Name } | ||||
|  | ||||
| func (f *Fwd) walk(*typeDeque) {} | ||||
| func (f *Fwd) copy() Type { | ||||
| 	cpy := *f | ||||
| @@ -311,7 +317,7 @@ func (f *Fwd) copy() Type { | ||||
| // Typedef is an alias of a Type. | ||||
| type Typedef struct { | ||||
| 	TypeID | ||||
| 	Name | ||||
| 	Name string | ||||
| 	Type Type | ||||
| } | ||||
|  | ||||
| @@ -319,6 +325,8 @@ func (td *Typedef) String() string { | ||||
| 	return fmt.Sprintf("typedef#%d[%q #%d]", td.TypeID, td.Name, td.Type.ID()) | ||||
| } | ||||
|  | ||||
| func (td *Typedef) TypeName() string { return td.Name } | ||||
|  | ||||
| func (td *Typedef) walk(tdq *typeDeque) { tdq.push(&td.Type) } | ||||
| func (td *Typedef) copy() Type { | ||||
| 	cpy := *td | ||||
| @@ -379,7 +387,7 @@ func (r *Restrict) copy() Type { | ||||
| // Func is a function definition. | ||||
| type Func struct { | ||||
| 	TypeID | ||||
| 	Name | ||||
| 	Name    string | ||||
| 	Type    Type | ||||
| 	Linkage FuncLinkage | ||||
| } | ||||
| @@ -388,6 +396,8 @@ func (f *Func) String() string { | ||||
| 	return fmt.Sprintf("func#%d[%s %q proto=#%d]", f.TypeID, f.Linkage, f.Name, f.Type.ID()) | ||||
| } | ||||
|  | ||||
| func (f *Func) TypeName() string { return f.Name } | ||||
|  | ||||
| func (f *Func) walk(tdq *typeDeque) { tdq.push(&f.Type) } | ||||
| func (f *Func) copy() Type { | ||||
| 	cpy := *f | ||||
| @@ -426,14 +436,14 @@ func (fp *FuncProto) copy() Type { | ||||
| } | ||||
|  | ||||
| type FuncParam struct { | ||||
| 	Name | ||||
| 	Name string | ||||
| 	Type Type | ||||
| } | ||||
|  | ||||
| // Var is a global variable. | ||||
| type Var struct { | ||||
| 	TypeID | ||||
| 	Name | ||||
| 	Name    string | ||||
| 	Type    Type | ||||
| 	Linkage VarLinkage | ||||
| } | ||||
| @@ -442,6 +452,8 @@ func (v *Var) String() string { | ||||
| 	return fmt.Sprintf("var#%d[%s %q]", v.TypeID, v.Linkage, v.Name) | ||||
| } | ||||
|  | ||||
| func (v *Var) TypeName() string { return v.Name } | ||||
|  | ||||
| func (v *Var) walk(tdq *typeDeque) { tdq.push(&v.Type) } | ||||
| func (v *Var) copy() Type { | ||||
| 	cpy := *v | ||||
| @@ -451,7 +463,7 @@ func (v *Var) copy() Type { | ||||
| // Datasec is a global program section containing data. | ||||
| type Datasec struct { | ||||
| 	TypeID | ||||
| 	Name | ||||
| 	Name string | ||||
| 	Size uint32 | ||||
| 	Vars []VarSecinfo | ||||
| } | ||||
| @@ -460,6 +472,8 @@ func (ds *Datasec) String() string { | ||||
| 	return fmt.Sprintf("section#%d[%q]", ds.TypeID, ds.Name) | ||||
| } | ||||
|  | ||||
| func (ds *Datasec) TypeName() string { return ds.Name } | ||||
|  | ||||
| func (ds *Datasec) size() uint32 { return ds.Size } | ||||
|  | ||||
| func (ds *Datasec) walk(tdq *typeDeque) { | ||||
| @@ -475,7 +489,7 @@ func (ds *Datasec) copy() Type { | ||||
| 	return &cpy | ||||
| } | ||||
|  | ||||
| // VarSecinfo describes variable in a Datasec | ||||
| // VarSecinfo describes variable in a Datasec. | ||||
| // | ||||
| // It is not a valid Type. | ||||
| type VarSecinfo struct { | ||||
| @@ -484,6 +498,27 @@ type VarSecinfo struct { | ||||
| 	Size   uint32 | ||||
| } | ||||
|  | ||||
| // Float is a float of a given length. | ||||
| type Float struct { | ||||
| 	TypeID | ||||
| 	Name string | ||||
|  | ||||
| 	// The size of the float in bytes. | ||||
| 	Size uint32 | ||||
| } | ||||
|  | ||||
| func (f *Float) String() string { | ||||
| 	return fmt.Sprintf("float%d#%d[%q]", f.Size*8, f.TypeID, f.Name) | ||||
| } | ||||
|  | ||||
| func (f *Float) TypeName() string { return f.Name } | ||||
| func (f *Float) size() uint32     { return f.Size } | ||||
| func (f *Float) walk(*typeDeque)  {} | ||||
| func (f *Float) copy() Type { | ||||
| 	cpy := *f | ||||
| 	return &cpy | ||||
| } | ||||
|  | ||||
| type sizer interface { | ||||
| 	size() uint32 | ||||
| } | ||||
| @@ -565,14 +600,36 @@ func Sizeof(typ Type) (int, error) { | ||||
| // | ||||
| // Returns any errors from transform verbatim. | ||||
| func copyType(typ Type, transform func(Type) (Type, error)) (Type, error) { | ||||
| 	var ( | ||||
| 		copies = make(map[Type]Type) | ||||
| 		work   typeDeque | ||||
| 	) | ||||
| 	copies := make(copier) | ||||
| 	return typ, copies.copy(&typ, transform) | ||||
| } | ||||
|  | ||||
| 	for t := &typ; t != nil; t = work.pop() { | ||||
| // copy a slice of Types recursively. | ||||
| // | ||||
| // Types may form a cycle. | ||||
| // | ||||
| // Returns any errors from transform verbatim. | ||||
| func copyTypes(types []Type, transform func(Type) (Type, error)) ([]Type, error) { | ||||
| 	result := make([]Type, len(types)) | ||||
| 	copy(result, types) | ||||
|  | ||||
| 	copies := make(copier) | ||||
| 	for i := range result { | ||||
| 		if err := copies.copy(&result[i], transform); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
|  | ||||
| type copier map[Type]Type | ||||
|  | ||||
| func (c copier) copy(typ *Type, transform func(Type) (Type, error)) error { | ||||
| 	var work typeDeque | ||||
| 	for t := typ; t != nil; t = work.pop() { | ||||
| 		// *t is the identity of the type. | ||||
| 		if cpy := copies[*t]; cpy != nil { | ||||
| 		if cpy := c[*t]; cpy != nil { | ||||
| 			*t = cpy | ||||
| 			continue | ||||
| 		} | ||||
| @@ -581,21 +638,21 @@ func copyType(typ Type, transform func(Type) (Type, error)) (Type, error) { | ||||
| 		if transform != nil { | ||||
| 			tf, err := transform(*t) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("copy %s: %w", typ, err) | ||||
| 				return fmt.Errorf("copy %s: %w", *t, err) | ||||
| 			} | ||||
| 			cpy = tf.copy() | ||||
| 		} else { | ||||
| 			cpy = (*t).copy() | ||||
| 		} | ||||
|  | ||||
| 		copies[*t] = cpy | ||||
| 		c[*t] = cpy | ||||
| 		*t = cpy | ||||
|  | ||||
| 		// Mark any nested types for copying. | ||||
| 		cpy.walk(&work) | ||||
| 	} | ||||
|  | ||||
| 	return typ, nil | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // typeDeque keeps track of pointers to types which still | ||||
| @@ -606,6 +663,10 @@ type typeDeque struct { | ||||
| 	mask        uint64 | ||||
| } | ||||
|  | ||||
| func (dq *typeDeque) empty() bool { | ||||
| 	return dq.read == dq.write | ||||
| } | ||||
|  | ||||
| // push adds a type to the stack. | ||||
| func (dq *typeDeque) push(t *Type) { | ||||
| 	if dq.write-dq.read < uint64(len(dq.types)) { | ||||
| @@ -632,7 +693,7 @@ func (dq *typeDeque) push(t *Type) { | ||||
|  | ||||
| // shift returns the first element or null. | ||||
| func (dq *typeDeque) shift() *Type { | ||||
| 	if dq.read == dq.write { | ||||
| 	if dq.empty() { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| @@ -645,7 +706,7 @@ func (dq *typeDeque) shift() *Type { | ||||
|  | ||||
| // pop returns the last element or null. | ||||
| func (dq *typeDeque) pop() *Type { | ||||
| 	if dq.read == dq.write { | ||||
| 	if dq.empty() { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| @@ -674,7 +735,7 @@ func (dq *typeDeque) all() []*Type { | ||||
| // Returns a map of named types (so, where NameOff is non-zero) and a slice of types | ||||
| // indexed by TypeID. Since BTF ignores compilation units, multiple types may share | ||||
| // the same name. A Type may form a cyclic graph by pointing at itself. | ||||
| func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, namedTypes map[string][]namedType, err error) { | ||||
| func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, namedTypes map[string][]NamedType, err error) { | ||||
| 	type fixupDef struct { | ||||
| 		id           TypeID | ||||
| 		expectedKind btfKind | ||||
| @@ -691,17 +752,17 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, | ||||
| 		// work, since otherwise append might re-allocate members. | ||||
| 		members := make([]Member, 0, len(raw)) | ||||
| 		for i, btfMember := range raw { | ||||
| 			name, err := rawStrings.LookupName(btfMember.NameOff) | ||||
| 			name, err := rawStrings.Lookup(btfMember.NameOff) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("can't get name for member %d: %w", i, err) | ||||
| 			} | ||||
| 			m := Member{ | ||||
| 				Name:   name, | ||||
| 				Offset: btfMember.Offset, | ||||
| 				Name:       name, | ||||
| 				OffsetBits: btfMember.Offset, | ||||
| 			} | ||||
| 			if kindFlag { | ||||
| 				m.BitfieldSize = btfMember.Offset >> 24 | ||||
| 				m.Offset &= 0xffffff | ||||
| 				m.OffsetBits &= 0xffffff | ||||
| 			} | ||||
| 			members = append(members, m) | ||||
| 		} | ||||
| @@ -713,7 +774,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, | ||||
|  | ||||
| 	types = make([]Type, 0, len(rawTypes)) | ||||
| 	types = append(types, (*Void)(nil)) | ||||
| 	namedTypes = make(map[string][]namedType) | ||||
| 	namedTypes = make(map[string][]NamedType) | ||||
|  | ||||
| 	for i, raw := range rawTypes { | ||||
| 		var ( | ||||
| @@ -723,7 +784,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, | ||||
| 			typ Type | ||||
| 		) | ||||
|  | ||||
| 		name, err := rawStrings.LookupName(raw.NameOff) | ||||
| 		name, err := rawStrings.Lookup(raw.NameOff) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, fmt.Errorf("get name for type id %d: %w", id, err) | ||||
| 		} | ||||
| @@ -765,7 +826,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, | ||||
| 			rawvals := raw.data.([]btfEnum) | ||||
| 			vals := make([]EnumValue, 0, len(rawvals)) | ||||
| 			for i, btfVal := range rawvals { | ||||
| 				name, err := rawStrings.LookupName(btfVal.NameOff) | ||||
| 				name, err := rawStrings.Lookup(btfVal.NameOff) | ||||
| 				if err != nil { | ||||
| 					return nil, nil, fmt.Errorf("get name for enum value %d: %s", i, err) | ||||
| 				} | ||||
| @@ -812,7 +873,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, | ||||
| 			rawparams := raw.data.([]btfParam) | ||||
| 			params := make([]FuncParam, 0, len(rawparams)) | ||||
| 			for i, param := range rawparams { | ||||
| 				name, err := rawStrings.LookupName(param.NameOff) | ||||
| 				name, err := rawStrings.Lookup(param.NameOff) | ||||
| 				if err != nil { | ||||
| 					return nil, nil, fmt.Errorf("get name for func proto parameter %d: %s", i, err) | ||||
| 				} | ||||
| @@ -848,14 +909,17 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, | ||||
| 			} | ||||
| 			typ = &Datasec{id, name, raw.SizeType, vars} | ||||
|  | ||||
| 		case kindFloat: | ||||
| 			typ = &Float{id, name, raw.Size()} | ||||
|  | ||||
| 		default: | ||||
| 			return nil, nil, fmt.Errorf("type id %d: unknown kind: %v", id, raw.Kind()) | ||||
| 		} | ||||
|  | ||||
| 		types = append(types, typ) | ||||
|  | ||||
| 		if named, ok := typ.(namedType); ok { | ||||
| 			if name := essentialName(named.name()); name != "" { | ||||
| 		if named, ok := typ.(NamedType); ok { | ||||
| 			if name := essentialName(named.TypeName()); name != "" { | ||||
| 				namedTypes[name] = append(namedTypes[name], named) | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/cilium/ebpf/internal/cpu.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/cilium/ebpf/internal/cpu.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,7 +2,7 @@ package internal | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| ) | ||||
| @@ -24,7 +24,7 @@ func PossibleCPUs() (int, error) { | ||||
| } | ||||
|  | ||||
| func parseCPUsFromFile(path string) (int, error) { | ||||
| 	spec, err := ioutil.ReadFile(path) | ||||
| 	spec, err := os.ReadFile(path) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/ptr_32_be.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/ptr_32_be.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build armbe || mips || mips64p32 | ||||
| // +build armbe mips mips64p32 | ||||
|  | ||||
| package internal | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/ptr_32_le.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cilium/ebpf/internal/ptr_32_le.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build 386 || amd64p32 || arm || mipsle || mips64p32le | ||||
| // +build 386 amd64p32 arm mipsle mips64p32le | ||||
|  | ||||
| package internal | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/cilium/ebpf/internal/ptr_64.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/cilium/ebpf/internal/ptr_64.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| // +build !386,!amd64p32,!arm,!mipsle,!mips64p32le | ||||
| // +build !armbe,!mips,!mips64p32 | ||||
| //go:build !386 && !amd64p32 && !arm && !mipsle && !mips64p32le && !armbe && !mips && !mips64p32 | ||||
| // +build !386,!amd64p32,!arm,!mipsle,!mips64p32le,!armbe,!mips,!mips64p32 | ||||
|  | ||||
| package internal | ||||
|  | ||||
|   | ||||
							
								
								
									
										59
									
								
								vendor/github.com/cilium/ebpf/internal/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										59
									
								
								vendor/github.com/cilium/ebpf/internal/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| package internal | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
| @@ -68,6 +69,48 @@ func BPF(cmd BPFCmd, attr unsafe.Pointer, size uintptr) (uintptr, error) { | ||||
| 	return r1, err | ||||
| } | ||||
|  | ||||
| type BPFProgLoadAttr struct { | ||||
| 	ProgType           uint32 | ||||
| 	InsCount           uint32 | ||||
| 	Instructions       Pointer | ||||
| 	License            Pointer | ||||
| 	LogLevel           uint32 | ||||
| 	LogSize            uint32 | ||||
| 	LogBuf             Pointer | ||||
| 	KernelVersion      uint32     // since 4.1  2541517c32be | ||||
| 	ProgFlags          uint32     // since 4.11 e07b98d9bffe | ||||
| 	ProgName           BPFObjName // since 4.15 067cae47771c | ||||
| 	ProgIfIndex        uint32     // since 4.15 1f6f4cb7ba21 | ||||
| 	ExpectedAttachType uint32     // since 4.17 5e43f899b03a | ||||
| 	ProgBTFFd          uint32 | ||||
| 	FuncInfoRecSize    uint32 | ||||
| 	FuncInfo           Pointer | ||||
| 	FuncInfoCnt        uint32 | ||||
| 	LineInfoRecSize    uint32 | ||||
| 	LineInfo           Pointer | ||||
| 	LineInfoCnt        uint32 | ||||
| 	AttachBTFID        uint32 | ||||
| 	AttachProgFd       uint32 | ||||
| } | ||||
|  | ||||
| // BPFProgLoad wraps BPF_PROG_LOAD. | ||||
| func BPFProgLoad(attr *BPFProgLoadAttr) (*FD, error) { | ||||
| 	for { | ||||
| 		fd, err := BPF(BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) | ||||
| 		// As of ~4.20 the verifier can be interrupted by a signal, | ||||
| 		// and returns EAGAIN in that case. | ||||
| 		if errors.Is(err, unix.EAGAIN) { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		return NewFD(uint32(fd)), nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type BPFProgAttachAttr struct { | ||||
| 	TargetFd     uint32 | ||||
| 	AttachBpfFd  uint32 | ||||
| @@ -180,6 +223,22 @@ func BPFObjGetInfoByFD(fd *FD, info unsafe.Pointer, size uintptr) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type bpfGetFDByIDAttr struct { | ||||
| 	id   uint32 | ||||
| 	next uint32 | ||||
| } | ||||
|  | ||||
| // BPFObjGetInfoByFD wraps BPF_*_GET_FD_BY_ID. | ||||
| // | ||||
| // Available from 4.13. | ||||
| func BPFObjGetFDByID(cmd BPFCmd, id uint32) (*FD, error) { | ||||
| 	attr := bpfGetFDByIDAttr{ | ||||
| 		id: id, | ||||
| 	} | ||||
| 	ptr, err := BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) | ||||
| 	return NewFD(uint32(ptr)), err | ||||
| } | ||||
|  | ||||
| // BPFObjName is a null-terminated string made up of | ||||
| // 'A-Za-z0-9_' characters. | ||||
| type BPFObjName [unix.BPF_OBJ_NAME_LEN]byte | ||||
|   | ||||
							
								
								
									
										16
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build linux | ||||
| // +build linux | ||||
|  | ||||
| package unix | ||||
| @@ -20,10 +21,11 @@ const ( | ||||
| 	EPERM   = linux.EPERM | ||||
| 	ESRCH   = linux.ESRCH | ||||
| 	ENODEV  = linux.ENODEV | ||||
| 	EBADF   = linux.EBADF | ||||
| 	E2BIG   = linux.E2BIG | ||||
| 	// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP | ||||
| 	ENOTSUPP = syscall.Errno(0x20c) | ||||
|  | ||||
| 	EBADF                    = linux.EBADF | ||||
| 	BPF_F_NO_PREALLOC        = linux.BPF_F_NO_PREALLOC | ||||
| 	BPF_F_NUMA_NODE          = linux.BPF_F_NUMA_NODE | ||||
| 	BPF_F_RDONLY             = linux.BPF_F_RDONLY | ||||
| @@ -35,6 +37,9 @@ const ( | ||||
| 	BPF_F_INNER_MAP          = linux.BPF_F_INNER_MAP | ||||
| 	BPF_OBJ_NAME_LEN         = linux.BPF_OBJ_NAME_LEN | ||||
| 	BPF_TAG_SIZE             = linux.BPF_TAG_SIZE | ||||
| 	BPF_RINGBUF_BUSY_BIT     = linux.BPF_RINGBUF_BUSY_BIT | ||||
| 	BPF_RINGBUF_DISCARD_BIT  = linux.BPF_RINGBUF_DISCARD_BIT | ||||
| 	BPF_RINGBUF_HDR_SZ       = linux.BPF_RINGBUF_HDR_SZ | ||||
| 	SYS_BPF                  = linux.SYS_BPF | ||||
| 	F_DUPFD_CLOEXEC          = linux.F_DUPFD_CLOEXEC | ||||
| 	EPOLL_CTL_ADD            = linux.EPOLL_CTL_ADD | ||||
| @@ -69,11 +74,6 @@ type Statfs_t = linux.Statfs_t | ||||
| // Rlimit is a wrapper | ||||
| type Rlimit = linux.Rlimit | ||||
|  | ||||
| // Setrlimit is a wrapper | ||||
| func Setrlimit(resource int, rlim *Rlimit) (err error) { | ||||
| 	return linux.Setrlimit(resource, rlim) | ||||
| } | ||||
|  | ||||
| // Syscall is a wrapper | ||||
| func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { | ||||
| 	return linux.Syscall(trap, a1, a2, a3) | ||||
| @@ -202,3 +202,7 @@ func KernelRelease() (string, error) { | ||||
| 	release := string(uname.Release[:end]) | ||||
| 	return release, nil | ||||
| } | ||||
|  | ||||
| func Prlimit(pid, resource int, new, old *Rlimit) error { | ||||
| 	return linux.Prlimit(pid, resource, new, old) | ||||
| } | ||||
|   | ||||
							
								
								
									
										14
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/cilium/ebpf/internal/unix/types_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build !linux | ||||
| // +build !linux | ||||
|  | ||||
| package unix | ||||
| @@ -21,6 +22,7 @@ const ( | ||||
| 	ESRCH  = syscall.ESRCH | ||||
| 	ENODEV = syscall.ENODEV | ||||
| 	EBADF  = syscall.Errno(0) | ||||
| 	E2BIG  = syscall.Errno(0) | ||||
| 	// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP | ||||
| 	ENOTSUPP = syscall.Errno(0x20c) | ||||
|  | ||||
| @@ -35,6 +37,9 @@ const ( | ||||
| 	BPF_F_INNER_MAP          = 0 | ||||
| 	BPF_OBJ_NAME_LEN         = 0x10 | ||||
| 	BPF_TAG_SIZE             = 0x8 | ||||
| 	BPF_RINGBUF_BUSY_BIT     = 0 | ||||
| 	BPF_RINGBUF_DISCARD_BIT  = 0 | ||||
| 	BPF_RINGBUF_HDR_SZ       = 0 | ||||
| 	SYS_BPF                  = 321 | ||||
| 	F_DUPFD_CLOEXEC          = 0x406 | ||||
| 	EPOLLIN                  = 0x1 | ||||
| @@ -86,11 +91,6 @@ type Rlimit struct { | ||||
| 	Max uint64 | ||||
| } | ||||
|  | ||||
| // Setrlimit is a wrapper | ||||
| func Setrlimit(resource int, rlim *Rlimit) (err error) { | ||||
| 	return errNonLinux | ||||
| } | ||||
|  | ||||
| // Syscall is a wrapper | ||||
| func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { | ||||
| 	return 0, 0, syscall.Errno(1) | ||||
| @@ -261,3 +261,7 @@ func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags | ||||
| func KernelRelease() (string, error) { | ||||
| 	return "", errNonLinux | ||||
| } | ||||
|  | ||||
| func Prlimit(pid, resource int, new, old *Rlimit) error { | ||||
| 	return errNonLinux | ||||
| } | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/cilium/ebpf/internal/version.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/cilium/ebpf/internal/version.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,7 +2,7 @@ package internal | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"regexp" | ||||
| 	"sync" | ||||
|  | ||||
| @@ -109,7 +109,7 @@ func detectKernelVersion() (Version, error) { | ||||
| 	// Example format: Ubuntu 4.15.0-91.92-generic 4.15.18 | ||||
| 	// This method exists in the kernel itself, see d18acd15c | ||||
| 	// ("perf tools: Fix kernel version error in ubuntu"). | ||||
| 	if pvs, err := ioutil.ReadFile("/proc/version_signature"); err == nil { | ||||
| 	if pvs, err := os.ReadFile("/proc/version_signature"); err == nil { | ||||
| 		// If /proc/version_signature exists, failing to parse it is an error. | ||||
| 		// It only exists on Ubuntu, where the real patch level is not obtainable | ||||
| 		// through any other method. | ||||
|   | ||||
							
								
								
									
										88
									
								
								vendor/github.com/cilium/ebpf/link/freplace.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								vendor/github.com/cilium/ebpf/link/freplace.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| package link | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/cilium/ebpf" | ||||
| 	"github.com/cilium/ebpf/internal/btf" | ||||
| ) | ||||
|  | ||||
| type FreplaceLink struct { | ||||
| 	RawLink | ||||
| } | ||||
|  | ||||
| // AttachFreplace attaches the given eBPF program to the function it replaces. | ||||
| // | ||||
| // The program and name can either be provided at link time, or can be provided | ||||
| // at program load time. If they were provided at load time, they should be nil | ||||
| // and empty respectively here, as they will be ignored by the kernel. | ||||
| // Examples: | ||||
| // | ||||
| //	AttachFreplace(dispatcher, "function", replacement) | ||||
| //	AttachFreplace(nil, "", replacement) | ||||
| func AttachFreplace(targetProg *ebpf.Program, name string, prog *ebpf.Program) (*FreplaceLink, error) { | ||||
| 	if (name == "") != (targetProg == nil) { | ||||
| 		return nil, fmt.Errorf("must provide both or neither of name and targetProg: %w", errInvalidInput) | ||||
| 	} | ||||
| 	if prog == nil { | ||||
| 		return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput) | ||||
| 	} | ||||
| 	if prog.Type() != ebpf.Extension { | ||||
| 		return nil, fmt.Errorf("eBPF program type %s is not an Extension: %w", prog.Type(), errInvalidInput) | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		target int | ||||
| 		typeID btf.TypeID | ||||
| 	) | ||||
| 	if targetProg != nil { | ||||
| 		info, err := targetProg.Info() | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		btfID, ok := info.BTFID() | ||||
| 		if !ok { | ||||
| 			return nil, fmt.Errorf("could not get BTF ID for program %s: %w", info.Name, errInvalidInput) | ||||
| 		} | ||||
| 		btfHandle, err := btf.NewHandleFromID(btfID) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		defer btfHandle.Close() | ||||
|  | ||||
| 		var function *btf.Func | ||||
| 		if err := btfHandle.Spec().FindType(name, &function); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		target = targetProg.FD() | ||||
| 		typeID = function.ID() | ||||
| 	} | ||||
|  | ||||
| 	link, err := AttachRawLink(RawLinkOptions{ | ||||
| 		Target:  target, | ||||
| 		Program: prog, | ||||
| 		Attach:  ebpf.AttachNone, | ||||
| 		BTF:     typeID, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &FreplaceLink{*link}, nil | ||||
| } | ||||
|  | ||||
| // Update implements the Link interface. | ||||
| func (f *FreplaceLink) Update(new *ebpf.Program) error { | ||||
| 	return fmt.Errorf("freplace update: %w", ErrNotSupported) | ||||
| } | ||||
|  | ||||
| // LoadPinnedFreplace loads a pinned iterator from a bpffs. | ||||
| func LoadPinnedFreplace(fileName string, opts *ebpf.LoadPinOptions) (*FreplaceLink, error) { | ||||
| 	link, err := LoadPinnedRawLink(fileName, TracingType, opts) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &FreplaceLink{*link}, err | ||||
| } | ||||
							
								
								
									
										38
									
								
								vendor/github.com/cilium/ebpf/link/kprobe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								vendor/github.com/cilium/ebpf/link/kprobe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,7 +5,6 @@ import ( | ||||
| 	"crypto/rand" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
| @@ -72,10 +71,11 @@ func (pt probeType) RetprobeBit() (uint64, error) { | ||||
| // given kernel symbol starts executing. See /proc/kallsyms for available | ||||
| // symbols. For example, printk(): | ||||
| // | ||||
| //	Kprobe("printk", prog) | ||||
| //	kp, err := Kprobe("printk", prog) | ||||
| // | ||||
| // The resulting Link must be Closed during program shutdown to avoid leaking | ||||
| // system resources. | ||||
| // Losing the reference to the resulting Link (kp) will close the Kprobe | ||||
| // and prevent further execution of prog. The Link must be Closed during | ||||
| // program shutdown to avoid leaking system resources. | ||||
| func Kprobe(symbol string, prog *ebpf.Program) (Link, error) { | ||||
| 	k, err := kprobe(symbol, prog, false) | ||||
| 	if err != nil { | ||||
| @@ -95,10 +95,11 @@ func Kprobe(symbol string, prog *ebpf.Program) (Link, error) { | ||||
| // before the given kernel symbol exits, with the function stack left intact. | ||||
| // See /proc/kallsyms for available symbols. For example, printk(): | ||||
| // | ||||
| //	Kretprobe("printk", prog) | ||||
| //	kp, err := Kretprobe("printk", prog) | ||||
| // | ||||
| // The resulting Link must be Closed during program shutdown to avoid leaking | ||||
| // system resources. | ||||
| // Losing the reference to the resulting Link (kp) will close the Kretprobe | ||||
| // and prevent further execution of prog. The Link must be Closed during | ||||
| // program shutdown to avoid leaking system resources. | ||||
| func Kretprobe(symbol string, prog *ebpf.Program) (Link, error) { | ||||
| 	k, err := kprobe(symbol, prog, true) | ||||
| 	if err != nil { | ||||
| @@ -157,7 +158,7 @@ func kprobe(symbol string, prog *ebpf.Program, ret bool) (*perfEvent, error) { | ||||
| // pmuKprobe opens a perf event based on the kprobe PMU. | ||||
| // Returns os.ErrNotExist if the given symbol does not exist in the kernel. | ||||
| func pmuKprobe(symbol string, ret bool) (*perfEvent, error) { | ||||
| 	return pmuProbe(kprobeType, symbol, "", 0, ret) | ||||
| 	return pmuProbe(kprobeType, symbol, "", 0, perfAllThreads, ret) | ||||
| } | ||||
|  | ||||
| // pmuProbe opens a perf event based on a Performance Monitoring Unit. | ||||
| @@ -167,7 +168,7 @@ func pmuKprobe(symbol string, ret bool) (*perfEvent, error) { | ||||
| // 33ea4b24277b "perf/core: Implement the 'perf_uprobe' PMU" | ||||
| // | ||||
| // Returns ErrNotSupported if the kernel doesn't support perf_[k,u]probe PMU | ||||
| func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*perfEvent, error) { | ||||
| func pmuProbe(typ probeType, symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) { | ||||
| 	// Getting the PMU type will fail if the kernel doesn't support | ||||
| 	// the perf_[k,u]probe PMU. | ||||
| 	et, err := getPMUEventType(typ) | ||||
| @@ -191,7 +192,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per | ||||
| 	switch typ { | ||||
| 	case kprobeType: | ||||
| 		// Create a pointer to a NUL-terminated string for the kernel. | ||||
| 		sp, err := unsafeStringPtr(symbol) | ||||
| 		sp, err = unsafeStringPtr(symbol) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| @@ -202,7 +203,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per | ||||
| 			Config: config,              // Retprobe flag | ||||
| 		} | ||||
| 	case uprobeType: | ||||
| 		sp, err := unsafeStringPtr(path) | ||||
| 		sp, err = unsafeStringPtr(path) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| @@ -220,7 +221,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC) | ||||
| 	fd, err := unix.PerfEventOpen(&attr, pid, 0, -1, unix.PERF_FLAG_FD_CLOEXEC) | ||||
|  | ||||
| 	// Since commit 97c753e62e6c, ENOENT is correctly returned instead of EINVAL | ||||
| 	// when trying to create a kretprobe for a missing symbol. Make sure ENOENT | ||||
| @@ -228,6 +229,11 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per | ||||
| 	if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) { | ||||
| 		return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, os.ErrNotExist) | ||||
| 	} | ||||
| 	// Since at least commit cb9a19fe4aa51, ENOTSUPP is returned | ||||
| 	// when attempting to set a uprobe on a trap instruction. | ||||
| 	if errors.Is(err, unix.ENOTSUPP) { | ||||
| 		return nil, fmt.Errorf("failed setting uprobe on offset %#x (possible trap insn): %w", offset, err) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("opening perf event: %w", err) | ||||
| 	} | ||||
| @@ -246,7 +252,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per | ||||
|  | ||||
| // tracefsKprobe creates a Kprobe tracefs entry. | ||||
| func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) { | ||||
| 	return tracefsProbe(kprobeType, symbol, "", 0, ret) | ||||
| 	return tracefsProbe(kprobeType, symbol, "", 0, perfAllThreads, ret) | ||||
| } | ||||
|  | ||||
| // tracefsProbe creates a trace event by writing an entry to <tracefs>/[k,u]probe_events. | ||||
| @@ -255,7 +261,7 @@ func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) { | ||||
| // Path and offset are only set in the case of uprobe(s) and are used to set | ||||
| // the executable/library path on the filesystem and the offset where the probe is inserted. | ||||
| // A perf event is then opened on the newly-created trace event and returned to the caller. | ||||
| func tracefsProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*perfEvent, error) { | ||||
| func tracefsProbe(typ probeType, symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) { | ||||
| 	// Generate a random string for each trace event we attempt to create. | ||||
| 	// This value is used as the 'group' token in tracefs to allow creating | ||||
| 	// multiple kprobe trace events with the same name. | ||||
| @@ -288,7 +294,7 @@ func tracefsProbe(typ probeType, symbol, path string, offset uint64, ret bool) ( | ||||
| 	} | ||||
|  | ||||
| 	// Kprobes are ephemeral tracepoints and share the same perf event type. | ||||
| 	fd, err := openTracepointPerfEvent(tid) | ||||
| 	fd, err := openTracepointPerfEvent(tid, pid) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -413,7 +419,7 @@ func probePrefix(ret bool) string { | ||||
| func determineRetprobeBit(typ probeType) (uint64, error) { | ||||
| 	p := filepath.Join("/sys/bus/event_source/devices/", typ.String(), "/format/retprobe") | ||||
|  | ||||
| 	data, err := ioutil.ReadFile(p) | ||||
| 	data, err := os.ReadFile(p) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										14
									
								
								vendor/github.com/cilium/ebpf/link/link.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/cilium/ebpf/link/link.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -6,6 +6,7 @@ import ( | ||||
|  | ||||
| 	"github.com/cilium/ebpf" | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/btf" | ||||
| ) | ||||
|  | ||||
| var ErrNotSupported = internal.ErrNotSupported | ||||
| @@ -29,8 +30,8 @@ type Link interface { | ||||
|  | ||||
| 	// Close frees resources. | ||||
| 	// | ||||
| 	// The link will be broken unless it has been pinned. A link | ||||
| 	// may continue past the lifetime of the process if Close is | ||||
| 	// The link will be broken unless it has been successfully pinned. | ||||
| 	// A link may continue past the lifetime of the process if Close is | ||||
| 	// not called. | ||||
| 	Close() error | ||||
|  | ||||
| @@ -49,6 +50,8 @@ type RawLinkOptions struct { | ||||
| 	Program *ebpf.Program | ||||
| 	// Attach must match the attach type of Program. | ||||
| 	Attach ebpf.AttachType | ||||
| 	// BTF is the BTF of the attachment target. | ||||
| 	BTF btf.TypeID | ||||
| } | ||||
|  | ||||
| // RawLinkInfo contains metadata on a link. | ||||
| @@ -83,9 +86,10 @@ func AttachRawLink(opts RawLinkOptions) (*RawLink, error) { | ||||
| 	} | ||||
|  | ||||
| 	attr := bpfLinkCreateAttr{ | ||||
| 		targetFd:   uint32(opts.Target), | ||||
| 		progFd:     uint32(progFd), | ||||
| 		attachType: opts.Attach, | ||||
| 		targetFd:    uint32(opts.Target), | ||||
| 		progFd:      uint32(progFd), | ||||
| 		attachType:  opts.Attach, | ||||
| 		targetBTFID: uint32(opts.BTF), | ||||
| 	} | ||||
| 	fd, err := bpfLinkCreate(&attr) | ||||
| 	if err != nil { | ||||
|   | ||||
							
								
								
									
										7
									
								
								vendor/github.com/cilium/ebpf/link/perf_event.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/cilium/ebpf/link/perf_event.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -4,7 +4,6 @@ import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"regexp" | ||||
| @@ -236,7 +235,7 @@ func getPMUEventType(typ probeType) (uint64, error) { | ||||
| // openTracepointPerfEvent opens a tracepoint-type perf event. System-wide | ||||
| // [k,u]probes created by writing to <tracefs>/[k,u]probe_events are tracepoints | ||||
| // behind the scenes, and can be attached to using these perf events. | ||||
| func openTracepointPerfEvent(tid uint64) (*internal.FD, error) { | ||||
| func openTracepointPerfEvent(tid uint64, pid int) (*internal.FD, error) { | ||||
| 	attr := unix.PerfEventAttr{ | ||||
| 		Type:        unix.PERF_TYPE_TRACEPOINT, | ||||
| 		Config:      tid, | ||||
| @@ -245,7 +244,7 @@ func openTracepointPerfEvent(tid uint64) (*internal.FD, error) { | ||||
| 		Wakeup:      1, | ||||
| 	} | ||||
|  | ||||
| 	fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC) | ||||
| 	fd, err := unix.PerfEventOpen(&attr, pid, 0, -1, unix.PERF_FLAG_FD_CLOEXEC) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("opening tracepoint perf event: %w", err) | ||||
| 	} | ||||
| @@ -263,7 +262,7 @@ func uint64FromFile(base string, path ...string) (uint64, error) { | ||||
| 		return 0, fmt.Errorf("path '%s' attempts to escape base path '%s': %w", l, base, errInvalidInput) | ||||
| 	} | ||||
|  | ||||
| 	data, err := ioutil.ReadFile(p) | ||||
| 	data, err := os.ReadFile(p) | ||||
| 	if err != nil { | ||||
| 		return 0, fmt.Errorf("reading file %s: %w", p, err) | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										9
									
								
								vendor/github.com/cilium/ebpf/link/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/cilium/ebpf/link/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -88,10 +88,11 @@ var haveProgAttachReplace = internal.FeatureTest("BPF_PROG_ATTACH atomic replace | ||||
| }) | ||||
|  | ||||
| type bpfLinkCreateAttr struct { | ||||
| 	progFd     uint32 | ||||
| 	targetFd   uint32 | ||||
| 	attachType ebpf.AttachType | ||||
| 	flags      uint32 | ||||
| 	progFd      uint32 | ||||
| 	targetFd    uint32 | ||||
| 	attachType  ebpf.AttachType | ||||
| 	flags       uint32 | ||||
| 	targetBTFID uint32 | ||||
| } | ||||
|  | ||||
| func bpfLinkCreate(attr *bpfLinkCreateAttr) (*internal.FD, error) { | ||||
|   | ||||
							
								
								
									
										8
									
								
								vendor/github.com/cilium/ebpf/link/tracepoint.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/cilium/ebpf/link/tracepoint.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -11,7 +11,11 @@ import ( | ||||
| // tracepoints. The top-level directory is the group, the event's subdirectory | ||||
| // is the name. Example: | ||||
| // | ||||
| //	Tracepoint("syscalls", "sys_enter_fork", prog) | ||||
| //	tp, err := Tracepoint("syscalls", "sys_enter_fork", prog) | ||||
| // | ||||
| // Losing the reference to the resulting Link (tp) will close the Tracepoint | ||||
| // and prevent further execution of prog. The Link must be Closed during | ||||
| // program shutdown to avoid leaking system resources. | ||||
| // | ||||
| // Note that attaching eBPF programs to syscalls (sys_enter_*/sys_exit_*) is | ||||
| // only possible as of kernel 4.14 (commit cf5f5ce). | ||||
| @@ -34,7 +38,7 @@ func Tracepoint(group, name string, prog *ebpf.Program) (Link, error) { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	fd, err := openTracepointPerfEvent(tid) | ||||
| 	fd, err := openTracepointPerfEvent(tid, perfAllThreads) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										135
									
								
								vendor/github.com/cilium/ebpf/link/uprobe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										135
									
								
								vendor/github.com/cilium/ebpf/link/uprobe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -25,14 +25,18 @@ var ( | ||||
| 		value uint64 | ||||
| 		err   error | ||||
| 	}{} | ||||
|  | ||||
| 	// ErrNoSymbol indicates that the given symbol was not found | ||||
| 	// in the ELF symbols table. | ||||
| 	ErrNoSymbol = errors.New("not found") | ||||
| ) | ||||
|  | ||||
| // Executable defines an executable program on the filesystem. | ||||
| type Executable struct { | ||||
| 	// Path of the executable on the filesystem. | ||||
| 	path string | ||||
| 	// Parsed ELF symbols and dynamic symbols. | ||||
| 	symbols map[string]elf.Symbol | ||||
| 	// Parsed ELF symbols and dynamic symbols offsets. | ||||
| 	offsets map[string]uint64 | ||||
| } | ||||
|  | ||||
| // UprobeOptions defines additional parameters that will be used | ||||
| @@ -41,6 +45,9 @@ type UprobeOptions struct { | ||||
| 	// Symbol offset. Must be provided in case of external symbols (shared libs). | ||||
| 	// If set, overrides the offset eventually parsed from the executable. | ||||
| 	Offset uint64 | ||||
| 	// Only set the uprobe on the given process ID. Useful when tracing | ||||
| 	// shared library calls or programs that have many running instances. | ||||
| 	PID int | ||||
| } | ||||
|  | ||||
| // To open a new Executable, use: | ||||
| @@ -64,42 +71,84 @@ func OpenExecutable(path string) (*Executable, error) { | ||||
| 		return nil, fmt.Errorf("parse ELF file: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	var ex = Executable{ | ||||
| 		path:    path, | ||||
| 		symbols: make(map[string]elf.Symbol), | ||||
| 	} | ||||
| 	if err := ex.addSymbols(se.Symbols); err != nil { | ||||
| 		return nil, err | ||||
| 	if se.Type != elf.ET_EXEC && se.Type != elf.ET_DYN { | ||||
| 		// ELF is not an executable or a shared object. | ||||
| 		return nil, errors.New("the given file is not an executable or a shared object") | ||||
| 	} | ||||
|  | ||||
| 	if err := ex.addSymbols(se.DynamicSymbols); err != nil { | ||||
| 	ex := Executable{ | ||||
| 		path:    path, | ||||
| 		offsets: make(map[string]uint64), | ||||
| 	} | ||||
|  | ||||
| 	if err := ex.load(se); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &ex, nil | ||||
| } | ||||
|  | ||||
| func (ex *Executable) addSymbols(f func() ([]elf.Symbol, error)) error { | ||||
| 	// elf.Symbols and elf.DynamicSymbols return ErrNoSymbols if the section is not found. | ||||
| 	syms, err := f() | ||||
| func (ex *Executable) load(f *internal.SafeELFFile) error { | ||||
| 	syms, err := f.Symbols() | ||||
| 	if err != nil && !errors.Is(err, elf.ErrNoSymbols) { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	dynsyms, err := f.DynamicSymbols() | ||||
| 	if err != nil && !errors.Is(err, elf.ErrNoSymbols) { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	syms = append(syms, dynsyms...) | ||||
|  | ||||
| 	for _, s := range syms { | ||||
| 		if elf.ST_TYPE(s.Info) != elf.STT_FUNC { | ||||
| 			// Symbol not associated with a function or other executable code. | ||||
| 			continue | ||||
| 		} | ||||
| 		ex.symbols[s.Name] = s | ||||
|  | ||||
| 		off := s.Value | ||||
|  | ||||
| 		// Loop over ELF segments. | ||||
| 		for _, prog := range f.Progs { | ||||
| 			// Skip uninteresting segments. | ||||
| 			if prog.Type != elf.PT_LOAD || (prog.Flags&elf.PF_X) == 0 { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if prog.Vaddr <= s.Value && s.Value < (prog.Vaddr+prog.Memsz) { | ||||
| 				// If the symbol value is contained in the segment, calculate | ||||
| 				// the symbol offset. | ||||
| 				// | ||||
| 				// fn symbol offset = fn symbol VA - .text VA + .text offset | ||||
| 				// | ||||
| 				// stackoverflow.com/a/40249502 | ||||
| 				off = s.Value - prog.Vaddr + prog.Off | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		ex.offsets[s.Name] = off | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (ex *Executable) symbol(symbol string) (*elf.Symbol, error) { | ||||
| 	if s, ok := ex.symbols[symbol]; ok { | ||||
| 		return &s, nil | ||||
| func (ex *Executable) offset(symbol string) (uint64, error) { | ||||
| 	if off, ok := ex.offsets[symbol]; ok { | ||||
| 		// Symbols with location 0 from section undef are shared library calls and | ||||
| 		// are relocated before the binary is executed. Dynamic linking is not | ||||
| 		// implemented by the library, so mark this as unsupported for now. | ||||
| 		// | ||||
| 		// Since only offset values are stored and not elf.Symbol, if the value is 0, | ||||
| 		// assume it's an external symbol. | ||||
| 		if off == 0 { | ||||
| 			return 0, fmt.Errorf("cannot resolve %s library call '%s', "+ | ||||
| 				"consider providing the offset via options: %w", ex.path, symbol, ErrNotSupported) | ||||
| 		} | ||||
| 		return off, nil | ||||
| 	} | ||||
| 	return nil, fmt.Errorf("symbol %s not found", symbol) | ||||
| 	return 0, fmt.Errorf("symbol %s: %w", symbol, ErrNoSymbol) | ||||
| } | ||||
|  | ||||
| // Uprobe attaches the given eBPF program to a perf event that fires when the | ||||
| @@ -112,11 +161,14 @@ func (ex *Executable) symbol(symbol string) (*elf.Symbol, error) { | ||||
| // When using symbols which belongs to shared libraries, | ||||
| // an offset must be provided via options: | ||||
| // | ||||
| //  ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123}) | ||||
| //	up, err := ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123}) | ||||
| // | ||||
| // The resulting Link must be Closed during program shutdown to avoid leaking | ||||
| // system resources. Functions provided by shared libraries can currently not | ||||
| // be traced and will result in an ErrNotSupported. | ||||
| // Losing the reference to the resulting Link (up) will close the Uprobe | ||||
| // and prevent further execution of prog. The Link must be Closed during | ||||
| // program shutdown to avoid leaking system resources. | ||||
| // | ||||
| // Functions provided by shared libraries can currently not be traced and | ||||
| // will result in an ErrNotSupported. | ||||
| func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) { | ||||
| 	u, err := ex.uprobe(symbol, prog, opts, false) | ||||
| 	if err != nil { | ||||
| @@ -141,11 +193,14 @@ func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti | ||||
| // When using symbols which belongs to shared libraries, | ||||
| // an offset must be provided via options: | ||||
| // | ||||
| //  ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123}) | ||||
| //	up, err := ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123}) | ||||
| // | ||||
| // The resulting Link must be Closed during program shutdown to avoid leaking | ||||
| // system resources. Functions provided by shared libraries can currently not | ||||
| // be traced and will result in an ErrNotSupported. | ||||
| // Losing the reference to the resulting Link (up) will close the Uprobe | ||||
| // and prevent further execution of prog. The Link must be Closed during | ||||
| // program shutdown to avoid leaking system resources. | ||||
| // | ||||
| // Functions provided by shared libraries can currently not be traced and | ||||
| // will result in an ErrNotSupported. | ||||
| func (ex *Executable) Uretprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) { | ||||
| 	u, err := ex.uprobe(symbol, prog, opts, true) | ||||
| 	if err != nil { | ||||
| @@ -175,24 +230,20 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti | ||||
| 	if opts != nil && opts.Offset != 0 { | ||||
| 		offset = opts.Offset | ||||
| 	} else { | ||||
| 		sym, err := ex.symbol(symbol) | ||||
| 		off, err := ex.offset(symbol) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, err) | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		offset = off | ||||
| 	} | ||||
|  | ||||
| 		// Symbols with location 0 from section undef are shared library calls and | ||||
| 		// are relocated before the binary is executed. Dynamic linking is not | ||||
| 		// implemented by the library, so mark this as unsupported for now. | ||||
| 		if sym.Section == elf.SHN_UNDEF && sym.Value == 0 { | ||||
| 			return nil, fmt.Errorf("cannot resolve %s library call '%s', "+ | ||||
| 				"consider providing the offset via options: %w", ex.path, symbol, ErrNotSupported) | ||||
| 		} | ||||
|  | ||||
| 		offset = sym.Value | ||||
| 	pid := perfAllThreads | ||||
| 	if opts != nil && opts.PID != 0 { | ||||
| 		pid = opts.PID | ||||
| 	} | ||||
|  | ||||
| 	// Use uprobe PMU if the kernel has it available. | ||||
| 	tp, err := pmuUprobe(symbol, ex.path, offset, ret) | ||||
| 	tp, err := pmuUprobe(symbol, ex.path, offset, pid, ret) | ||||
| 	if err == nil { | ||||
| 		return tp, nil | ||||
| 	} | ||||
| @@ -201,7 +252,7 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti | ||||
| 	} | ||||
|  | ||||
| 	// Use tracefs if uprobe PMU is missing. | ||||
| 	tp, err = tracefsUprobe(uprobeSanitizedSymbol(symbol), ex.path, offset, ret) | ||||
| 	tp, err = tracefsUprobe(uprobeSanitizedSymbol(symbol), ex.path, offset, pid, ret) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("creating trace event '%s:%s' in tracefs: %w", ex.path, symbol, err) | ||||
| 	} | ||||
| @@ -210,13 +261,13 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti | ||||
| } | ||||
|  | ||||
| // pmuUprobe opens a perf event based on the uprobe PMU. | ||||
| func pmuUprobe(symbol, path string, offset uint64, ret bool) (*perfEvent, error) { | ||||
| 	return pmuProbe(uprobeType, symbol, path, offset, ret) | ||||
| func pmuUprobe(symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) { | ||||
| 	return pmuProbe(uprobeType, symbol, path, offset, pid, ret) | ||||
| } | ||||
|  | ||||
| // tracefsUprobe creates a Uprobe tracefs entry. | ||||
| func tracefsUprobe(symbol, path string, offset uint64, ret bool) (*perfEvent, error) { | ||||
| 	return tracefsProbe(uprobeType, symbol, path, offset, ret) | ||||
| func tracefsUprobe(symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) { | ||||
| 	return tracefsProbe(uprobeType, symbol, path, offset, pid, ret) | ||||
| } | ||||
|  | ||||
| // uprobeSanitizedSymbol replaces every invalid characted for the tracefs api with an underscore. | ||||
|   | ||||
							
								
								
									
										23
									
								
								vendor/github.com/cilium/ebpf/linker.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/cilium/ebpf/linker.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -4,7 +4,6 @@ import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/asm" | ||||
| 	"github.com/cilium/ebpf/internal/btf" | ||||
| ) | ||||
|  | ||||
| // link resolves bpf-to-bpf calls. | ||||
| @@ -40,7 +39,7 @@ func link(prog *ProgramSpec, libs []*ProgramSpec) error { | ||||
| 			pending = append(pending, lib.Instructions) | ||||
|  | ||||
| 			if prog.BTF != nil && lib.BTF != nil { | ||||
| 				if err := btf.ProgramAppend(prog.BTF, lib.BTF); err != nil { | ||||
| 				if err := prog.BTF.Append(lib.BTF); err != nil { | ||||
| 					return fmt.Errorf("linking BTF of %s: %w", lib.Name, err) | ||||
| 				} | ||||
| 			} | ||||
| @@ -136,5 +135,25 @@ func fixupJumpsAndCalls(insns asm.Instructions) error { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// fixupBPFCalls replaces bpf_probe_read_{kernel,user}[_str] with bpf_probe_read[_str] on older kernels | ||||
| 	// https://github.com/libbpf/libbpf/blob/master/src/libbpf.c#L6009 | ||||
| 	iter = insns.Iterate() | ||||
| 	for iter.Next() { | ||||
| 		ins := iter.Ins | ||||
| 		if !ins.IsBuiltinCall() { | ||||
| 			continue | ||||
| 		} | ||||
| 		switch asm.BuiltinFunc(ins.Constant) { | ||||
| 		case asm.FnProbeReadKernel, asm.FnProbeReadUser: | ||||
| 			if err := haveProbeReadKernel(); err != nil { | ||||
| 				ins.Constant = int64(asm.FnProbeRead) | ||||
| 			} | ||||
| 		case asm.FnProbeReadKernelStr, asm.FnProbeReadUserStr: | ||||
| 			if err := haveProbeReadKernel(); err != nil { | ||||
| 				ins.Constant = int64(asm.FnProbeReadStr) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
							
								
								
									
										95
									
								
								vendor/github.com/cilium/ebpf/map.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										95
									
								
								vendor/github.com/cilium/ebpf/map.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| package ebpf | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| @@ -65,6 +66,11 @@ type MapSpec struct { | ||||
| 	// InnerMap is used as a template for ArrayOfMaps and HashOfMaps | ||||
| 	InnerMap *MapSpec | ||||
|  | ||||
| 	// Extra trailing bytes found in the ELF map definition when using structs | ||||
| 	// larger than libbpf's bpf_map_def. Must be empty before instantiating | ||||
| 	// the MapSpec into a Map. | ||||
| 	Extra bytes.Reader | ||||
|  | ||||
| 	// The BTF associated with this map. | ||||
| 	BTF *btf.Map | ||||
| } | ||||
| @@ -82,9 +88,12 @@ func (ms *MapSpec) Copy() *MapSpec { | ||||
| 	} | ||||
|  | ||||
| 	cpy := *ms | ||||
|  | ||||
| 	cpy.Contents = make([]MapKV, len(ms.Contents)) | ||||
| 	copy(cpy.Contents, ms.Contents) | ||||
|  | ||||
| 	cpy.InnerMap = ms.InnerMap.Copy() | ||||
|  | ||||
| 	return &cpy | ||||
| } | ||||
|  | ||||
| @@ -188,14 +197,24 @@ func NewMap(spec *MapSpec) (*Map, error) { | ||||
| // | ||||
| // The caller is responsible for ensuring the process' rlimit is set | ||||
| // sufficiently high for locking memory during map creation. This can be done | ||||
| // by calling unix.Setrlimit with unix.RLIMIT_MEMLOCK prior to calling NewMapWithOptions. | ||||
| // by calling rlimit.RemoveMemlock() prior to calling NewMapWithOptions. | ||||
| // | ||||
| // May return an error wrapping ErrMapIncompatible. | ||||
| func NewMapWithOptions(spec *MapSpec, opts MapOptions) (*Map, error) { | ||||
| 	handles := newHandleCache() | ||||
| 	defer handles.close() | ||||
|  | ||||
| 	return newMapWithOptions(spec, opts, handles) | ||||
| 	m, err := newMapWithOptions(spec, opts, handles) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("creating map: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	err = m.finalize(spec) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("populating map: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ *Map, err error) { | ||||
| @@ -207,8 +226,12 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ | ||||
|  | ||||
| 	switch spec.Pinning { | ||||
| 	case PinByName: | ||||
| 		if spec.Name == "" || opts.PinPath == "" { | ||||
| 			return nil, fmt.Errorf("pin by name: missing Name or PinPath") | ||||
| 		if spec.Name == "" { | ||||
| 			return nil, fmt.Errorf("pin by name: missing Name") | ||||
| 		} | ||||
|  | ||||
| 		if opts.PinPath == "" { | ||||
| 			return nil, fmt.Errorf("pin by name: missing MapOptions.PinPath") | ||||
| 		} | ||||
|  | ||||
| 		path := filepath.Join(opts.PinPath, spec.Name) | ||||
| @@ -244,16 +267,19 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ | ||||
| 			return nil, errors.New("inner maps cannot be pinned") | ||||
| 		} | ||||
|  | ||||
| 		template, err := createMap(spec.InnerMap, nil, opts, handles) | ||||
| 		template, err := spec.InnerMap.createMap(nil, opts, handles) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 			return nil, fmt.Errorf("inner map: %w", err) | ||||
| 		} | ||||
| 		defer template.Close() | ||||
|  | ||||
| 		// Intentionally skip populating and freezing (finalizing) | ||||
| 		// the inner map template since it will be removed shortly. | ||||
|  | ||||
| 		innerFd = template.fd | ||||
| 	} | ||||
|  | ||||
| 	m, err := createMap(spec, innerFd, opts, handles) | ||||
| 	m, err := spec.createMap(innerFd, opts, handles) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -269,7 +295,9 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *handleCache) (_ *Map, err error) { | ||||
| // 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 *internal.FD, opts MapOptions, handles *handleCache) (_ *Map, err error) { | ||||
| 	closeOnError := func(closer io.Closer) { | ||||
| 		if err != nil { | ||||
| 			closer.Close() | ||||
| @@ -278,10 +306,16 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand | ||||
|  | ||||
| 	spec = spec.Copy() | ||||
|  | ||||
| 	// Kernels 4.13 through 5.4 used a struct bpf_map_def that contained | ||||
| 	// additional 'inner_map_idx' and later 'numa_node' fields. | ||||
| 	// In order to support loading these definitions, tolerate the presence of | ||||
| 	// extra bytes, but require them to be zeroes. | ||||
| 	if _, err := io.Copy(internal.DiscardZeroes{}, &spec.Extra); err != nil { | ||||
| 		return nil, errors.New("extra contains unhandled non-zero bytes, drain before creating map") | ||||
| 	} | ||||
|  | ||||
| 	switch spec.Type { | ||||
| 	case ArrayOfMaps: | ||||
| 		fallthrough | ||||
| 	case HashOfMaps: | ||||
| 	case ArrayOfMaps, HashOfMaps: | ||||
| 		if err := haveNestedMaps(); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| @@ -350,7 +384,7 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand | ||||
|  | ||||
| 	var btfDisabled bool | ||||
| 	if spec.BTF != nil { | ||||
| 		handle, err := handles.btfHandle(btf.MapSpec(spec.BTF)) | ||||
| 		handle, err := handles.btfHandle(spec.BTF.Spec) | ||||
| 		btfDisabled = errors.Is(err, btf.ErrNotSupported) | ||||
| 		if err != nil && !btfDisabled { | ||||
| 			return nil, fmt.Errorf("load BTF: %w", err) | ||||
| @@ -358,15 +392,15 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand | ||||
|  | ||||
| 		if handle != nil { | ||||
| 			attr.BTFFd = uint32(handle.FD()) | ||||
| 			attr.BTFKeyTypeID = uint32(btf.MapKey(spec.BTF).ID()) | ||||
| 			attr.BTFValueTypeID = uint32(btf.MapValue(spec.BTF).ID()) | ||||
| 			attr.BTFKeyTypeID = uint32(spec.BTF.Key.ID()) | ||||
| 			attr.BTFValueTypeID = uint32(spec.BTF.Value.ID()) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	fd, err := internal.BPFMapCreate(&attr) | ||||
| 	if err != nil { | ||||
| 		if errors.Is(err, unix.EPERM) { | ||||
| 			return nil, fmt.Errorf("map create: RLIMIT_MEMLOCK may be too low: %w", err) | ||||
| 			return nil, fmt.Errorf("map create: %w (MEMLOCK bay be too low, consider rlimit.RemoveMemlock)", err) | ||||
| 		} | ||||
| 		if btfDisabled { | ||||
| 			return nil, fmt.Errorf("map create without BTF: %w", err) | ||||
| @@ -380,19 +414,11 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand | ||||
| 		return nil, fmt.Errorf("map create: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	if err := m.populate(spec.Contents); err != nil { | ||||
| 		return nil, fmt.Errorf("map create: can't set initial contents: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	if spec.Freeze { | ||||
| 		if err := m.Freeze(); err != nil { | ||||
| 			return nil, fmt.Errorf("can't freeze map: %w", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| // newMap allocates and returns a new Map structure. | ||||
| // Sets the fullValueSize on per-CPU maps. | ||||
| func newMap(fd *internal.FD, name string, typ MapType, keySize, valueSize, maxEntries, flags uint32) (*Map, error) { | ||||
| 	m := &Map{ | ||||
| 		name, | ||||
| @@ -415,7 +441,7 @@ func newMap(fd *internal.FD, name string, typ MapType, keySize, valueSize, maxEn | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	m.fullValueSize = align(int(valueSize), 8) * possibleCPUs | ||||
| 	m.fullValueSize = internal.Align(int(valueSize), 8) * possibleCPUs | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| @@ -892,12 +918,21 @@ func (m *Map) Freeze() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *Map) populate(contents []MapKV) error { | ||||
| 	for _, kv := range contents { | ||||
| // finalize populates the Map according to the Contents specified | ||||
| // in spec and freezes the Map if requested by spec. | ||||
| func (m *Map) finalize(spec *MapSpec) error { | ||||
| 	for _, kv := range spec.Contents { | ||||
| 		if err := m.Put(kv.Key, kv.Value); err != nil { | ||||
| 			return fmt.Errorf("key %v: %w", kv.Key, err) | ||||
| 			return fmt.Errorf("putting value: key %v: %w", kv.Key, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if spec.Freeze { | ||||
| 		if err := m.Freeze(); err != nil { | ||||
| 			return fmt.Errorf("freezing map: %w", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -1212,7 +1247,7 @@ func MapGetNextID(startID MapID) (MapID, error) { | ||||
| // | ||||
| // Returns ErrNotExist, if there is no eBPF map with the given id. | ||||
| func NewMapFromID(id MapID) (*Map, error) { | ||||
| 	fd, err := bpfObjGetFDByID(internal.BPF_MAP_GET_FD_BY_ID, uint32(id)) | ||||
| 	fd, err := internal.BPFObjGetFDByID(internal.BPF_MAP_GET_FD_BY_ID, uint32(id)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										63
									
								
								vendor/github.com/cilium/ebpf/marshalers.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										63
									
								
								vendor/github.com/cilium/ebpf/marshalers.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -8,6 +8,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"runtime" | ||||
| 	"sync" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| @@ -39,6 +40,10 @@ func marshalPtr(data interface{}, length int) (internal.Pointer, error) { | ||||
| // Returns an error if the given value isn't representable in exactly | ||||
| // length bytes. | ||||
| func marshalBytes(data interface{}, length int) (buf []byte, err error) { | ||||
| 	if data == nil { | ||||
| 		return nil, errors.New("can't marshal a nil value") | ||||
| 	} | ||||
|  | ||||
| 	switch value := data.(type) { | ||||
| 	case encoding.BinaryMarshaler: | ||||
| 		buf, err = value.MarshalBinary() | ||||
| @@ -77,22 +82,30 @@ func makeBuffer(dst interface{}, length int) (internal.Pointer, []byte) { | ||||
| 	return internal.NewSlicePointer(buf), buf | ||||
| } | ||||
|  | ||||
| var bytesReaderPool = sync.Pool{ | ||||
| 	New: func() interface{} { | ||||
| 		return new(bytes.Reader) | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| // unmarshalBytes converts a byte buffer into an arbitrary value. | ||||
| // | ||||
| // Prefer using Map.unmarshalKey and Map.unmarshalValue if possible, since | ||||
| // those have special cases that allow more types to be encoded. | ||||
| // | ||||
| // The common int32 and int64 types are directly handled to avoid | ||||
| // unnecessary heap allocations as happening in the default case. | ||||
| func unmarshalBytes(data interface{}, buf []byte) error { | ||||
| 	switch value := data.(type) { | ||||
| 	case unsafe.Pointer: | ||||
| 		// This could be solved in Go 1.17 by unsafe.Slice instead. (https://github.com/golang/go/issues/19367) | ||||
| 		// We could opt for removing unsafe.Pointer support in the lib as well. | ||||
| 		sh := &reflect.SliceHeader{ //nolint:govet | ||||
| 			Data: uintptr(value), | ||||
| 			Len:  len(buf), | ||||
| 			Cap:  len(buf), | ||||
| 		} | ||||
| 		var dst []byte | ||||
| 		// Use unsafe.Slice when we drop support for pre1.17 (https://github.com/golang/go/issues/19367) | ||||
| 		// We could opt for removing unsafe.Pointer support in the lib as well | ||||
| 		sh := (*reflect.SliceHeader)(unsafe.Pointer(&dst)) | ||||
| 		sh.Data = uintptr(value) | ||||
| 		sh.Len = len(buf) | ||||
| 		sh.Cap = len(buf) | ||||
|  | ||||
| 		dst := *(*[]byte)(unsafe.Pointer(sh)) | ||||
| 		copy(dst, buf) | ||||
| 		runtime.KeepAlive(value) | ||||
| 		return nil | ||||
| @@ -106,12 +119,38 @@ func unmarshalBytes(data interface{}, buf []byte) error { | ||||
| 	case *[]byte: | ||||
| 		*value = buf | ||||
| 		return nil | ||||
| 	case *int32: | ||||
| 		if len(buf) < 4 { | ||||
| 			return errors.New("int32 requires 4 bytes") | ||||
| 		} | ||||
| 		*value = int32(internal.NativeEndian.Uint32(buf)) | ||||
| 		return nil | ||||
| 	case *uint32: | ||||
| 		if len(buf) < 4 { | ||||
| 			return errors.New("uint32 requires 4 bytes") | ||||
| 		} | ||||
| 		*value = internal.NativeEndian.Uint32(buf) | ||||
| 		return nil | ||||
| 	case *int64: | ||||
| 		if len(buf) < 8 { | ||||
| 			return errors.New("int64 requires 8 bytes") | ||||
| 		} | ||||
| 		*value = int64(internal.NativeEndian.Uint64(buf)) | ||||
| 		return nil | ||||
| 	case *uint64: | ||||
| 		if len(buf) < 8 { | ||||
| 			return errors.New("uint64 requires 8 bytes") | ||||
| 		} | ||||
| 		*value = internal.NativeEndian.Uint64(buf) | ||||
| 		return nil | ||||
| 	case string: | ||||
| 		return errors.New("require pointer to string") | ||||
| 	case []byte: | ||||
| 		return errors.New("require pointer to []byte") | ||||
| 	default: | ||||
| 		rd := bytes.NewReader(buf) | ||||
| 		rd := bytesReaderPool.Get().(*bytes.Reader) | ||||
| 		rd.Reset(buf) | ||||
| 		defer bytesReaderPool.Put(rd) | ||||
| 		if err := binary.Read(rd, internal.NativeEndian, value); err != nil { | ||||
| 			return fmt.Errorf("decoding %T: %v", value, err) | ||||
| 		} | ||||
| @@ -142,7 +181,7 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, er | ||||
| 		return internal.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs") | ||||
| 	} | ||||
|  | ||||
| 	alignedElemLength := align(elemLength, 8) | ||||
| 	alignedElemLength := internal.Align(elemLength, 8) | ||||
| 	buf := make([]byte, alignedElemLength*possibleCPUs) | ||||
|  | ||||
| 	for i := 0; i < sliceLen; i++ { | ||||
| @@ -212,7 +251,3 @@ func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) erro | ||||
| 	reflect.ValueOf(slicePtr).Elem().Set(slice) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func align(n, alignment int) int { | ||||
| 	return (int(n) + alignment - 1) / alignment * alignment | ||||
| } | ||||
|   | ||||
							
								
								
									
										123
									
								
								vendor/github.com/cilium/ebpf/prog.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										123
									
								
								vendor/github.com/cilium/ebpf/prog.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -57,16 +57,21 @@ type ProgramSpec struct { | ||||
| 	// Name is passed to the kernel as a debug aid. Must only contain | ||||
| 	// alpha numeric and '_' characters. | ||||
| 	Name string | ||||
|  | ||||
| 	// Type determines at which hook in the kernel a program will run. | ||||
| 	Type       ProgramType | ||||
| 	AttachType AttachType | ||||
| 	// Name of a kernel data structure to attach to. It's interpretation | ||||
| 	// depends on Type and AttachType. | ||||
| 	AttachTo     string | ||||
| 	// Name of a kernel data structure or function to attach to. Its | ||||
| 	// interpretation depends on Type and AttachType. | ||||
| 	AttachTo string | ||||
| 	// The program to attach to. Must be provided manually. | ||||
| 	AttachTarget *Program | ||||
| 	Instructions asm.Instructions | ||||
|  | ||||
| 	// Flags is passed to the kernel and specifies additional program | ||||
| 	// load attributes. | ||||
| 	Flags uint32 | ||||
|  | ||||
| 	// License of the program. Some helpers are only available if | ||||
| 	// the license is deemed compatible with the GPL. | ||||
| 	// | ||||
| @@ -146,7 +151,7 @@ func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er | ||||
|  | ||||
| func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *handleCache) (*Program, error) { | ||||
| 	if len(spec.Instructions) == 0 { | ||||
| 		return nil, errors.New("Instructions cannot be empty") | ||||
| 		return nil, errors.New("instructions cannot be empty") | ||||
| 	} | ||||
|  | ||||
| 	if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian { | ||||
| @@ -166,16 +171,16 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand | ||||
| 		kv = v.Kernel() | ||||
| 	} | ||||
|  | ||||
| 	attr := &bpfProgLoadAttr{ | ||||
| 		progType:           spec.Type, | ||||
| 		progFlags:          spec.Flags, | ||||
| 		expectedAttachType: spec.AttachType, | ||||
| 		license:            internal.NewStringPointer(spec.License), | ||||
| 		kernelVersion:      kv, | ||||
| 	attr := &internal.BPFProgLoadAttr{ | ||||
| 		ProgType:           uint32(spec.Type), | ||||
| 		ProgFlags:          spec.Flags, | ||||
| 		ExpectedAttachType: uint32(spec.AttachType), | ||||
| 		License:            internal.NewStringPointer(spec.License), | ||||
| 		KernelVersion:      kv, | ||||
| 	} | ||||
|  | ||||
| 	if haveObjName() == nil { | ||||
| 		attr.progName = internal.NewBPFObjName(spec.Name) | ||||
| 		attr.ProgName = internal.NewBPFObjName(spec.Name) | ||||
| 	} | ||||
|  | ||||
| 	var err error | ||||
| @@ -190,35 +195,35 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand | ||||
| 	var btfDisabled bool | ||||
| 	var core btf.COREFixups | ||||
| 	if spec.BTF != nil { | ||||
| 		core, err = btf.ProgramFixups(spec.BTF, targetBTF) | ||||
| 		core, err = spec.BTF.Fixups(targetBTF) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("CO-RE relocations: %w", err) | ||||
| 		} | ||||
|  | ||||
| 		handle, err := handles.btfHandle(btf.ProgramSpec(spec.BTF)) | ||||
| 		handle, err := handles.btfHandle(spec.BTF.Spec()) | ||||
| 		btfDisabled = errors.Is(err, btf.ErrNotSupported) | ||||
| 		if err != nil && !btfDisabled { | ||||
| 			return nil, fmt.Errorf("load BTF: %w", err) | ||||
| 		} | ||||
|  | ||||
| 		if handle != nil { | ||||
| 			attr.progBTFFd = uint32(handle.FD()) | ||||
| 			attr.ProgBTFFd = uint32(handle.FD()) | ||||
|  | ||||
| 			recSize, bytes, err := btf.ProgramLineInfos(spec.BTF) | ||||
| 			recSize, bytes, err := spec.BTF.LineInfos() | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("get BTF line infos: %w", err) | ||||
| 			} | ||||
| 			attr.lineInfoRecSize = recSize | ||||
| 			attr.lineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize)) | ||||
| 			attr.lineInfo = internal.NewSlicePointer(bytes) | ||||
| 			attr.LineInfoRecSize = recSize | ||||
| 			attr.LineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize)) | ||||
| 			attr.LineInfo = internal.NewSlicePointer(bytes) | ||||
|  | ||||
| 			recSize, bytes, err = btf.ProgramFuncInfos(spec.BTF) | ||||
| 			recSize, bytes, err = spec.BTF.FuncInfos() | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("get BTF function infos: %w", err) | ||||
| 			} | ||||
| 			attr.funcInfoRecSize = recSize | ||||
| 			attr.funcInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize)) | ||||
| 			attr.funcInfo = internal.NewSlicePointer(bytes) | ||||
| 			attr.FuncInfoRecSize = recSize | ||||
| 			attr.FuncInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize)) | ||||
| 			attr.FuncInfo = internal.NewSlicePointer(bytes) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -238,16 +243,41 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand | ||||
| 	} | ||||
|  | ||||
| 	bytecode := buf.Bytes() | ||||
| 	attr.instructions = internal.NewSlicePointer(bytecode) | ||||
| 	attr.insCount = uint32(len(bytecode) / asm.InstructionSize) | ||||
| 	attr.Instructions = internal.NewSlicePointer(bytecode) | ||||
| 	attr.InsCount = uint32(len(bytecode) / asm.InstructionSize) | ||||
|  | ||||
| 	if spec.AttachTo != "" { | ||||
| 		if spec.AttachTarget != nil { | ||||
| 			info, err := spec.AttachTarget.Info() | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("load target BTF: %w", err) | ||||
| 			} | ||||
|  | ||||
| 			btfID, ok := info.BTFID() | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("load target BTF: no BTF info available") | ||||
| 			} | ||||
| 			btfHandle, err := btf.NewHandleFromID(btfID) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("load target BTF: %w", err) | ||||
| 			} | ||||
| 			defer btfHandle.Close() | ||||
|  | ||||
| 			targetBTF = btfHandle.Spec() | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("load target BTF: %w", err) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		target, err := resolveBTFType(targetBTF, spec.AttachTo, spec.Type, spec.AttachType) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if target != nil { | ||||
| 			attr.attachBTFID = target.ID() | ||||
| 			attr.AttachBTFID = uint32(target.ID()) | ||||
| 		} | ||||
| 		if spec.AttachTarget != nil { | ||||
| 			attr.AttachProgFd = uint32(spec.AttachTarget.FD()) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -259,12 +289,12 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand | ||||
| 	var logBuf []byte | ||||
| 	if opts.LogLevel > 0 { | ||||
| 		logBuf = make([]byte, logSize) | ||||
| 		attr.logLevel = opts.LogLevel | ||||
| 		attr.logSize = uint32(len(logBuf)) | ||||
| 		attr.logBuf = internal.NewSlicePointer(logBuf) | ||||
| 		attr.LogLevel = opts.LogLevel | ||||
| 		attr.LogSize = uint32(len(logBuf)) | ||||
| 		attr.LogBuf = internal.NewSlicePointer(logBuf) | ||||
| 	} | ||||
|  | ||||
| 	fd, err := bpfProgLoad(attr) | ||||
| 	fd, err := internal.BPFProgLoad(attr) | ||||
| 	if err == nil { | ||||
| 		return &Program{internal.CString(logBuf), fd, spec.Name, "", spec.Type}, nil | ||||
| 	} | ||||
| @@ -273,17 +303,20 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand | ||||
| 	if opts.LogLevel == 0 && opts.LogSize >= 0 { | ||||
| 		// Re-run with the verifier enabled to get better error messages. | ||||
| 		logBuf = make([]byte, logSize) | ||||
| 		attr.logLevel = 1 | ||||
| 		attr.logSize = uint32(len(logBuf)) | ||||
| 		attr.logBuf = internal.NewSlicePointer(logBuf) | ||||
| 		attr.LogLevel = 1 | ||||
| 		attr.LogSize = uint32(len(logBuf)) | ||||
| 		attr.LogBuf = internal.NewSlicePointer(logBuf) | ||||
|  | ||||
| 		_, logErr = bpfProgLoad(attr) | ||||
| 		fd, logErr = internal.BPFProgLoad(attr) | ||||
| 		if logErr == nil { | ||||
| 			fd.Close() | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if errors.Is(logErr, unix.EPERM) && logBuf[0] == 0 { | ||||
| 		// EPERM due to RLIMIT_MEMLOCK happens before the verifier, so we can | ||||
| 		// check that the log is empty to reduce false positives. | ||||
| 		return nil, fmt.Errorf("load program: RLIMIT_MEMLOCK may be too low: %w", logErr) | ||||
| 		return nil, fmt.Errorf("load program: %w (MEMLOCK bay be too low, consider rlimit.RemoveMemlock)", logErr) | ||||
| 	} | ||||
|  | ||||
| 	err = internal.ErrorWithLog(err, logBuf, logErr) | ||||
| @@ -310,7 +343,7 @@ func NewProgramFromFD(fd int) (*Program, error) { | ||||
| // | ||||
| // Returns ErrNotExist, if there is no eBPF program with the given id. | ||||
| func NewProgramFromID(id ProgramID) (*Program, error) { | ||||
| 	fd, err := bpfObjGetFDByID(internal.BPF_PROG_GET_FD_BY_ID, uint32(id)) | ||||
| 	fd, err := internal.BPFObjGetFDByID(internal.BPF_PROG_GET_FD_BY_ID, uint32(id)) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("get program by id: %w", err) | ||||
| 	} | ||||
| @@ -677,45 +710,44 @@ func ProgramGetNextID(startID ProgramID) (ProgramID, error) { | ||||
| // | ||||
| // Deprecated: use ProgramInfo.ID() instead. | ||||
| func (p *Program) ID() (ProgramID, error) { | ||||
| 	info, err := bpfGetProgInfoByFD(p.fd) | ||||
| 	info, err := bpfGetProgInfoByFD(p.fd, nil) | ||||
| 	if err != nil { | ||||
| 		return ProgramID(0), err | ||||
| 	} | ||||
| 	return ProgramID(info.id), nil | ||||
| } | ||||
|  | ||||
| func resolveBTFType(kernel *btf.Spec, name string, progType ProgramType, attachType AttachType) (btf.Type, error) { | ||||
| func resolveBTFType(spec *btf.Spec, name string, progType ProgramType, attachType AttachType) (btf.Type, error) { | ||||
| 	type match struct { | ||||
| 		p ProgramType | ||||
| 		a AttachType | ||||
| 	} | ||||
|  | ||||
| 	var target btf.Type | ||||
| 	var typeName, featureName string | ||||
| 	switch (match{progType, attachType}) { | ||||
| 	case match{LSM, AttachLSMMac}: | ||||
| 		target = new(btf.Func) | ||||
| 		typeName = "bpf_lsm_" + name | ||||
| 		featureName = name + " LSM hook" | ||||
|  | ||||
| 	case match{Tracing, AttachTraceIter}: | ||||
| 		target = new(btf.Func) | ||||
| 		typeName = "bpf_iter_" + name | ||||
| 		featureName = name + " iterator" | ||||
|  | ||||
| 	case match{Extension, AttachNone}: | ||||
| 		typeName = name | ||||
| 		featureName = fmt.Sprintf("freplace %s", name) | ||||
| 	default: | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	if kernel == nil { | ||||
| 	if spec == nil { | ||||
| 		var err error | ||||
| 		kernel, err = btf.LoadKernelSpec() | ||||
| 		spec, err = btf.LoadKernelSpec() | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("load kernel spec: %w", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	err := kernel.FindType(typeName, target) | ||||
| 	var target *btf.Func | ||||
| 	err := spec.FindType(typeName, &target) | ||||
| 	if errors.Is(err, btf.ErrNotFound) { | ||||
| 		return nil, &internal.UnsupportedFeatureError{ | ||||
| 			Name: featureName, | ||||
| @@ -724,5 +756,6 @@ func resolveBTFType(kernel *btf.Spec, name string, progType ProgramType, attachT | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("resolve BTF for %s: %w", featureName, err) | ||||
| 	} | ||||
|  | ||||
| 	return target, nil | ||||
| } | ||||
|   | ||||
							
								
								
									
										22
									
								
								vendor/github.com/cilium/ebpf/run-tests.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/cilium/ebpf/run-tests.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,7 +5,7 @@ | ||||
| #     Run all tests on a 5.4 kernel | ||||
| #     $ ./run-tests.sh 5.4 | ||||
| #     Run a subset of tests: | ||||
| #     $ ./run-tests.sh 5.4 go test ./link | ||||
| #     $ ./run-tests.sh 5.4 ./link | ||||
|  | ||||
| set -euo pipefail | ||||
|  | ||||
| @@ -48,15 +48,17 @@ if [[ "${1:-}" = "--exec-vm" ]]; then | ||||
|     rm "${output}/fake-stdin" | ||||
|   fi | ||||
|  | ||||
|   $sudo virtme-run --kimg "${input}/bzImage" --memory 768M --pwd \ | ||||
|   --rwdir="${testdir}=${testdir}" \ | ||||
|   --rodir=/run/input="${input}" \ | ||||
|   --rwdir=/run/output="${output}" \ | ||||
|   --script-sh "PATH=\"$PATH\" \"$script\" --exec-test $cmd" \ | ||||
|   --qemu-opts -smp 2 # need at least two CPUs for some tests | ||||
|   if ! $sudo virtme-run --kimg "${input}/bzImage" --memory 768M --pwd \ | ||||
|     --rwdir="${testdir}=${testdir}" \ | ||||
|     --rodir=/run/input="${input}" \ | ||||
|     --rwdir=/run/output="${output}" \ | ||||
|     --script-sh "PATH=\"$PATH\" \"$script\" --exec-test $cmd" \ | ||||
|     --kopt possible_cpus=2; then # need at least two CPUs for some tests | ||||
|     exit 23 | ||||
|   fi | ||||
|  | ||||
|   if [[ ! -e "${output}/success" ]]; then | ||||
|     exit 1 | ||||
|     exit 42 | ||||
|   fi | ||||
|  | ||||
|   $sudo rm -r "$output" | ||||
| @@ -74,7 +76,7 @@ elif [[ "${1:-}" = "--exec-test" ]]; then | ||||
|   dmesg -C | ||||
|   if ! "$@"; then | ||||
|     dmesg | ||||
|     exit 1 | ||||
|     exit 1 # this return code is "swallowed" by qemu | ||||
|   fi | ||||
|   touch "/run/output/success" | ||||
|   exit 0 | ||||
| @@ -108,7 +110,7 @@ else | ||||
|   echo "No selftests found, disabling" | ||||
| fi | ||||
|  | ||||
| args=(-v -short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...) | ||||
| args=(-short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...) | ||||
| if (( $# > 0 )); then | ||||
|   args=("$@") | ||||
| fi | ||||
|   | ||||
							
								
								
									
										94
									
								
								vendor/github.com/cilium/ebpf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										94
									
								
								vendor/github.com/cilium/ebpf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,13 +1,14 @@ | ||||
| package ebpf | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/cilium/ebpf/asm" | ||||
| 	"github.com/cilium/ebpf/internal" | ||||
| 	"github.com/cilium/ebpf/internal/btf" | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
|  | ||||
| @@ -73,30 +74,6 @@ type bpfMapInfo struct { | ||||
| 	btf_value_type_id         uint32 | ||||
| } | ||||
|  | ||||
| type bpfProgLoadAttr struct { | ||||
| 	progType           ProgramType | ||||
| 	insCount           uint32 | ||||
| 	instructions       internal.Pointer | ||||
| 	license            internal.Pointer | ||||
| 	logLevel           uint32 | ||||
| 	logSize            uint32 | ||||
| 	logBuf             internal.Pointer | ||||
| 	kernelVersion      uint32              // since 4.1  2541517c32be | ||||
| 	progFlags          uint32              // since 4.11 e07b98d9bffe | ||||
| 	progName           internal.BPFObjName // since 4.15 067cae47771c | ||||
| 	progIfIndex        uint32              // since 4.15 1f6f4cb7ba21 | ||||
| 	expectedAttachType AttachType          // since 4.17 5e43f899b03a | ||||
| 	progBTFFd          uint32 | ||||
| 	funcInfoRecSize    uint32 | ||||
| 	funcInfo           internal.Pointer | ||||
| 	funcInfoCnt        uint32 | ||||
| 	lineInfoRecSize    uint32 | ||||
| 	lineInfo           internal.Pointer | ||||
| 	lineInfoCnt        uint32 | ||||
| 	attachBTFID        btf.TypeID | ||||
| 	attachProgFd       uint32 | ||||
| } | ||||
|  | ||||
| type bpfProgInfo struct { | ||||
| 	prog_type                uint32 | ||||
| 	id                       uint32 | ||||
| @@ -107,7 +84,7 @@ type bpfProgInfo struct { | ||||
| 	xlated_prog_insns        internal.Pointer | ||||
| 	load_time                uint64 // since 4.15 cb4d2b3f03d8 | ||||
| 	created_by_uid           uint32 | ||||
| 	nr_map_ids               uint32 | ||||
| 	nr_map_ids               uint32 // since 4.15 cb4d2b3f03d8 | ||||
| 	map_ids                  internal.Pointer | ||||
| 	name                     internal.BPFObjName // since 4.15 067cae47771c | ||||
| 	ifindex                  uint32 | ||||
| @@ -145,11 +122,6 @@ type bpfProgTestRunAttr struct { | ||||
| 	duration    uint32 | ||||
| } | ||||
|  | ||||
| type bpfGetFDByIDAttr struct { | ||||
| 	id   uint32 | ||||
| 	next uint32 | ||||
| } | ||||
|  | ||||
| type bpfMapFreezeAttr struct { | ||||
| 	mapFd uint32 | ||||
| } | ||||
| @@ -160,23 +132,6 @@ type bpfObjGetNextIDAttr struct { | ||||
| 	openFlags uint32 | ||||
| } | ||||
|  | ||||
| func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) { | ||||
| 	for { | ||||
| 		fd, err := internal.BPF(internal.BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) | ||||
| 		// As of ~4.20 the verifier can be interrupted by a signal, | ||||
| 		// and returns EAGAIN in that case. | ||||
| 		if errors.Is(err, unix.EAGAIN) { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		return internal.NewFD(uint32(fd)), nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func bpfProgTestRun(attr *bpfProgTestRunAttr) error { | ||||
| 	_, err := internal.BPF(internal.BPF_PROG_TEST_RUN, unsafe.Pointer(attr), unsafe.Sizeof(*attr)) | ||||
| 	return err | ||||
| @@ -372,6 +327,10 @@ func wrapMapError(err error) error { | ||||
| 		return internal.SyscallError(ErrNotSupported, unix.ENOTSUPP) | ||||
| 	} | ||||
|  | ||||
| 	if errors.Is(err, unix.E2BIG) { | ||||
| 		return fmt.Errorf("key too big for map: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| @@ -388,8 +347,13 @@ func bpfMapFreeze(m *internal.FD) error { | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func bpfGetProgInfoByFD(fd *internal.FD) (*bpfProgInfo, error) { | ||||
| func bpfGetProgInfoByFD(fd *internal.FD, ids []MapID) (*bpfProgInfo, error) { | ||||
| 	var info bpfProgInfo | ||||
| 	if len(ids) > 0 { | ||||
| 		info.nr_map_ids = uint32(len(ids)) | ||||
| 		info.map_ids = internal.NewPointer(unsafe.Pointer(&ids[0])) | ||||
| 	} | ||||
|  | ||||
| 	if err := internal.BPFObjGetInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil { | ||||
| 		return nil, fmt.Errorf("can't get program info: %w", err) | ||||
| 	} | ||||
| @@ -471,10 +435,30 @@ var haveBatchAPI = internal.FeatureTest("map batch api", "5.6", func() error { | ||||
| 	return nil | ||||
| }) | ||||
|  | ||||
| func bpfObjGetFDByID(cmd internal.BPFCmd, id uint32) (*internal.FD, error) { | ||||
| 	attr := bpfGetFDByIDAttr{ | ||||
| 		id: id, | ||||
| var haveProbeReadKernel = internal.FeatureTest("bpf_probe_read_kernel", "5.5", func() error { | ||||
| 	insns := asm.Instructions{ | ||||
| 		asm.Mov.Reg(asm.R1, asm.R10), | ||||
| 		asm.Add.Imm(asm.R1, -8), | ||||
| 		asm.Mov.Imm(asm.R2, 8), | ||||
| 		asm.Mov.Imm(asm.R3, 0), | ||||
| 		asm.FnProbeReadKernel.Call(), | ||||
| 		asm.Return(), | ||||
| 	} | ||||
| 	ptr, err := internal.BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr)) | ||||
| 	return internal.NewFD(uint32(ptr)), err | ||||
| } | ||||
| 	buf := bytes.NewBuffer(make([]byte, 0, len(insns)*asm.InstructionSize)) | ||||
| 	if err := insns.Marshal(buf, internal.NativeEndian); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	bytecode := buf.Bytes() | ||||
|  | ||||
| 	fd, err := internal.BPFProgLoad(&internal.BPFProgLoadAttr{ | ||||
| 		ProgType:     uint32(Kprobe), | ||||
| 		License:      internal.NewStringPointer("GPL"), | ||||
| 		Instructions: internal.NewSlicePointer(bytecode), | ||||
| 		InsCount:     uint32(len(bytecode) / asm.InstructionSize), | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return internal.ErrNotSupported | ||||
| 	} | ||||
| 	_ = fd.Close() | ||||
| 	return nil | ||||
| }) | ||||
|   | ||||
							
								
								
									
										36
									
								
								vendor/github.com/cilium/ebpf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/cilium/ebpf/types.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -4,12 +4,17 @@ import ( | ||||
| 	"github.com/cilium/ebpf/internal/unix" | ||||
| ) | ||||
|  | ||||
| //go:generate stringer -output types_string.go -type=MapType,ProgramType,AttachType,PinType | ||||
| //go:generate stringer -output types_string.go -type=MapType,ProgramType,PinType | ||||
|  | ||||
| // MapType indicates the type map structure | ||||
| // that will be initialized in the kernel. | ||||
| type MapType uint32 | ||||
|  | ||||
| // Max returns the latest supported MapType. | ||||
| func (_ MapType) Max() MapType { | ||||
| 	return maxMapType - 1 | ||||
| } | ||||
|  | ||||
| // All the various map types that can be created | ||||
| const ( | ||||
| 	UnspecifiedMap MapType = iota | ||||
| @@ -85,15 +90,28 @@ const ( | ||||
| 	SkStorage | ||||
| 	// DevMapHash - Hash-based indexing scheme for references to network devices. | ||||
| 	DevMapHash | ||||
| 	StructOpts | ||||
| 	// StructOpsMap - This map holds a kernel struct with its function pointer implemented in a BPF | ||||
| 	// program. | ||||
| 	StructOpsMap | ||||
| 	// RingBuf - Similar to PerfEventArray, but shared across all CPUs. | ||||
| 	RingBuf | ||||
| 	// InodeStorage - Specialized local storage map for inodes. | ||||
| 	InodeStorage | ||||
| 	// TaskStorage - Specialized local storage map for task_struct. | ||||
| 	TaskStorage | ||||
| 	// maxMapType - Bound enum of MapTypes, has to be last in enum. | ||||
| 	maxMapType | ||||
| ) | ||||
|  | ||||
| // Deprecated: StructOpts was a typo, use StructOpsMap instead. | ||||
| // | ||||
| // Declared as a variable to prevent stringer from picking it up | ||||
| // as an enum value. | ||||
| var StructOpts MapType = StructOpsMap | ||||
|  | ||||
| // hasPerCPUValue returns true if the Map stores a value per CPU. | ||||
| func (mt MapType) hasPerCPUValue() bool { | ||||
| 	return mt == PerCPUHash || mt == PerCPUArray || mt == LRUCPUHash | ||||
| 	return mt == PerCPUHash || mt == PerCPUArray || mt == LRUCPUHash || mt == PerCPUCGroupStorage | ||||
| } | ||||
|  | ||||
| // canStoreMap returns true if the map type accepts a map fd | ||||
| @@ -111,6 +129,11 @@ func (mt MapType) canStoreProgram() bool { | ||||
| // ProgramType of the eBPF program | ||||
| type ProgramType uint32 | ||||
|  | ||||
| // Max return the latest supported ProgramType. | ||||
| func (_ ProgramType) Max() ProgramType { | ||||
| 	return maxProgramType - 1 | ||||
| } | ||||
|  | ||||
| // eBPF program types | ||||
| const ( | ||||
| 	UnspecifiedProgram ProgramType = iota | ||||
| @@ -144,6 +167,7 @@ const ( | ||||
| 	Extension | ||||
| 	LSM | ||||
| 	SkLookup | ||||
| 	maxProgramType | ||||
| ) | ||||
|  | ||||
| // AttachType of the eBPF program, needed to differentiate allowed context accesses in | ||||
| @@ -151,6 +175,8 @@ const ( | ||||
| // Will cause invalid argument (EINVAL) at program load time if set incorrectly. | ||||
| type AttachType uint32 | ||||
|  | ||||
| //go:generate stringer -type AttachType -trimprefix Attach | ||||
|  | ||||
| // AttachNone is an alias for AttachCGroupInetIngress for readability reasons. | ||||
| const AttachNone AttachType = 0 | ||||
|  | ||||
| @@ -193,6 +219,10 @@ const ( | ||||
| 	AttachXDPCPUMap | ||||
| 	AttachSkLookup | ||||
| 	AttachXDP | ||||
| 	AttachSkSKBVerdict | ||||
| 	AttachSkReuseportSelect | ||||
| 	AttachSkReuseportSelectOrMigrate | ||||
| 	AttachPerfEvent | ||||
| ) | ||||
|  | ||||
| // AttachFlags of the eBPF program used in BPF_PROG_ATTACH command | ||||
|   | ||||
							
								
								
									
										69
									
								
								vendor/github.com/cilium/ebpf/types_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										69
									
								
								vendor/github.com/cilium/ebpf/types_string.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| // Code generated by "stringer -output types_string.go -type=MapType,ProgramType,AttachType,PinType"; DO NOT EDIT. | ||||
| // Code generated by "stringer -output types_string.go -type=MapType,ProgramType,PinType"; DO NOT EDIT. | ||||
|  | ||||
| package ebpf | ||||
|  | ||||
| @@ -34,15 +34,16 @@ func _() { | ||||
| 	_ = x[Stack-23] | ||||
| 	_ = x[SkStorage-24] | ||||
| 	_ = x[DevMapHash-25] | ||||
| 	_ = x[StructOpts-26] | ||||
| 	_ = x[StructOpsMap-26] | ||||
| 	_ = x[RingBuf-27] | ||||
| 	_ = x[InodeStorage-28] | ||||
| 	_ = x[TaskStorage-29] | ||||
| 	_ = x[maxMapType-30] | ||||
| } | ||||
|  | ||||
| const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOptsRingBufInodeStorageTaskStorage" | ||||
| const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOpsMapRingBufInodeStorageTaskStoragemaxMapType" | ||||
|  | ||||
| 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, 258, 265, 277, 288} | ||||
| 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, 300} | ||||
|  | ||||
| func (i MapType) String() string { | ||||
| 	if i >= MapType(len(_MapType_index)-1) { | ||||
| @@ -85,11 +86,12 @@ func _() { | ||||
| 	_ = x[Extension-28] | ||||
| 	_ = x[LSM-29] | ||||
| 	_ = x[SkLookup-30] | ||||
| 	_ = x[maxProgramType-31] | ||||
| } | ||||
|  | ||||
| const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockoptTracingStructOpsExtensionLSMSkLookup" | ||||
| const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockoptTracingStructOpsExtensionLSMSkLookupmaxProgramType" | ||||
|  | ||||
| var _ProgramType_index = [...]uint16{0, 18, 30, 36, 44, 52, 62, 65, 74, 83, 93, 98, 104, 111, 118, 123, 135, 140, 153, 167, 179, 188, 199, 212, 224, 245, 258, 265, 274, 283, 286, 294} | ||||
| var _ProgramType_index = [...]uint16{0, 18, 30, 36, 44, 52, 62, 65, 74, 83, 93, 98, 104, 111, 118, 123, 135, 140, 153, 167, 179, 188, 199, 212, 224, 245, 258, 265, 274, 283, 286, 294, 308} | ||||
|  | ||||
| func (i ProgramType) String() string { | ||||
| 	if i >= ProgramType(len(_ProgramType_index)-1) { | ||||
| @@ -97,61 +99,6 @@ func (i ProgramType) String() string { | ||||
| 	} | ||||
| 	return _ProgramType_name[_ProgramType_index[i]:_ProgramType_index[i+1]] | ||||
| } | ||||
| func _() { | ||||
| 	// An "invalid array index" compiler error signifies that the constant values have changed. | ||||
| 	// Re-run the stringer command to generate them again. | ||||
| 	var x [1]struct{} | ||||
| 	_ = x[AttachNone-0] | ||||
| 	_ = x[AttachCGroupInetIngress-0] | ||||
| 	_ = x[AttachCGroupInetEgress-1] | ||||
| 	_ = x[AttachCGroupInetSockCreate-2] | ||||
| 	_ = x[AttachCGroupSockOps-3] | ||||
| 	_ = x[AttachSkSKBStreamParser-4] | ||||
| 	_ = x[AttachSkSKBStreamVerdict-5] | ||||
| 	_ = x[AttachCGroupDevice-6] | ||||
| 	_ = x[AttachSkMsgVerdict-7] | ||||
| 	_ = x[AttachCGroupInet4Bind-8] | ||||
| 	_ = x[AttachCGroupInet6Bind-9] | ||||
| 	_ = x[AttachCGroupInet4Connect-10] | ||||
| 	_ = x[AttachCGroupInet6Connect-11] | ||||
| 	_ = x[AttachCGroupInet4PostBind-12] | ||||
| 	_ = x[AttachCGroupInet6PostBind-13] | ||||
| 	_ = x[AttachCGroupUDP4Sendmsg-14] | ||||
| 	_ = x[AttachCGroupUDP6Sendmsg-15] | ||||
| 	_ = x[AttachLircMode2-16] | ||||
| 	_ = x[AttachFlowDissector-17] | ||||
| 	_ = x[AttachCGroupSysctl-18] | ||||
| 	_ = x[AttachCGroupUDP4Recvmsg-19] | ||||
| 	_ = x[AttachCGroupUDP6Recvmsg-20] | ||||
| 	_ = x[AttachCGroupGetsockopt-21] | ||||
| 	_ = x[AttachCGroupSetsockopt-22] | ||||
| 	_ = x[AttachTraceRawTp-23] | ||||
| 	_ = x[AttachTraceFEntry-24] | ||||
| 	_ = x[AttachTraceFExit-25] | ||||
| 	_ = x[AttachModifyReturn-26] | ||||
| 	_ = x[AttachLSMMac-27] | ||||
| 	_ = x[AttachTraceIter-28] | ||||
| 	_ = x[AttachCgroupInet4GetPeername-29] | ||||
| 	_ = x[AttachCgroupInet6GetPeername-30] | ||||
| 	_ = x[AttachCgroupInet4GetSockname-31] | ||||
| 	_ = x[AttachCgroupInet6GetSockname-32] | ||||
| 	_ = x[AttachXDPDevMap-33] | ||||
| 	_ = x[AttachCgroupInetSockRelease-34] | ||||
| 	_ = x[AttachXDPCPUMap-35] | ||||
| 	_ = x[AttachSkLookup-36] | ||||
| 	_ = x[AttachXDP-37] | ||||
| } | ||||
|  | ||||
| const _AttachType_name = "AttachNoneAttachCGroupInetEgressAttachCGroupInetSockCreateAttachCGroupSockOpsAttachSkSKBStreamParserAttachSkSKBStreamVerdictAttachCGroupDeviceAttachSkMsgVerdictAttachCGroupInet4BindAttachCGroupInet6BindAttachCGroupInet4ConnectAttachCGroupInet6ConnectAttachCGroupInet4PostBindAttachCGroupInet6PostBindAttachCGroupUDP4SendmsgAttachCGroupUDP6SendmsgAttachLircMode2AttachFlowDissectorAttachCGroupSysctlAttachCGroupUDP4RecvmsgAttachCGroupUDP6RecvmsgAttachCGroupGetsockoptAttachCGroupSetsockoptAttachTraceRawTpAttachTraceFEntryAttachTraceFExitAttachModifyReturnAttachLSMMacAttachTraceIterAttachCgroupInet4GetPeernameAttachCgroupInet6GetPeernameAttachCgroupInet4GetSocknameAttachCgroupInet6GetSocknameAttachXDPDevMapAttachCgroupInetSockReleaseAttachXDPCPUMapAttachSkLookupAttachXDP" | ||||
|  | ||||
| var _AttachType_index = [...]uint16{0, 10, 32, 58, 77, 100, 124, 142, 160, 181, 202, 226, 250, 275, 300, 323, 346, 361, 380, 398, 421, 444, 466, 488, 504, 521, 537, 555, 567, 582, 610, 638, 666, 694, 709, 736, 751, 765, 774} | ||||
|  | ||||
| func (i AttachType) String() string { | ||||
| 	if i >= AttachType(len(_AttachType_index)-1) { | ||||
| 		return "AttachType(" + strconv.FormatInt(int64(i), 10) + ")" | ||||
| 	} | ||||
| 	return _AttachType_name[_AttachType_index[i]:_AttachType_index[i+1]] | ||||
| } | ||||
| func _() { | ||||
| 	// An "invalid array index" compiler error signifies that the constant values have changed. | ||||
| 	// Re-run the stringer command to generate them again. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Akihiro Suda
					Akihiro Suda