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