summaryrefslogtreecommitdiff
path: root/vendor/github.com/cilium/ebpf/btf/handle.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/cilium/ebpf/btf/handle.go')
-rw-r--r--vendor/github.com/cilium/ebpf/btf/handle.go121
1 files changed, 121 insertions, 0 deletions
diff --git a/vendor/github.com/cilium/ebpf/btf/handle.go b/vendor/github.com/cilium/ebpf/btf/handle.go
new file mode 100644
index 000000000..128e9b35c
--- /dev/null
+++ b/vendor/github.com/cilium/ebpf/btf/handle.go
@@ -0,0 +1,121 @@
+package btf
+
+import (
+ "errors"
+ "fmt"
+ "os"
+
+ "github.com/cilium/ebpf/internal/sys"
+ "github.com/cilium/ebpf/internal/unix"
+)
+
+// HandleInfo describes a Handle.
+type HandleInfo struct {
+ // ID of this handle in the kernel. The ID is only valid as long as the
+ // associated handle is kept alive.
+ ID ID
+
+ // Name is an identifying name for the BTF, currently only used by the
+ // kernel.
+ Name string
+
+ // IsKernel is true if the BTF originated with the kernel and not
+ // userspace.
+ IsKernel bool
+
+ // Size of the raw BTF in bytes.
+ size uint32
+}
+
+func newHandleInfoFromFD(fd *sys.FD) (*HandleInfo, error) {
+ // We invoke the syscall once with a empty BTF and name buffers to get size
+ // information to allocate buffers. Then we invoke it a second time with
+ // buffers to receive the data.
+ var btfInfo sys.BtfInfo
+ if err := sys.ObjInfo(fd, &btfInfo); err != nil {
+ return nil, fmt.Errorf("get BTF info for fd %s: %w", fd, err)
+ }
+
+ if btfInfo.NameLen > 0 {
+ // NameLen doesn't account for the terminating NUL.
+ btfInfo.NameLen++
+ }
+
+ // Don't pull raw BTF by default, since it may be quite large.
+ btfSize := btfInfo.BtfSize
+ btfInfo.BtfSize = 0
+
+ nameBuffer := make([]byte, btfInfo.NameLen)
+ btfInfo.Name, btfInfo.NameLen = sys.NewSlicePointerLen(nameBuffer)
+ if err := sys.ObjInfo(fd, &btfInfo); err != nil {
+ return nil, err
+ }
+
+ return &HandleInfo{
+ ID: ID(btfInfo.Id),
+ Name: unix.ByteSliceToString(nameBuffer),
+ IsKernel: btfInfo.KernelBtf != 0,
+ size: btfSize,
+ }, nil
+}
+
+// IsModule returns true if the BTF is for the kernel itself.
+func (i *HandleInfo) IsVmlinux() bool {
+ return i.IsKernel && i.Name == "vmlinux"
+}
+
+// IsModule returns true if the BTF is for a kernel module.
+func (i *HandleInfo) IsModule() bool {
+ return i.IsKernel && i.Name != "vmlinux"
+}
+
+// HandleIterator allows enumerating BTF blobs loaded into the kernel.
+type HandleIterator struct {
+ // The ID of the last retrieved handle. Only valid after a call to Next.
+ ID ID
+ err error
+}
+
+// Next retrieves a handle for the next BTF blob.
+//
+// [Handle.Close] is called if *handle is non-nil to avoid leaking fds.
+//
+// Returns true if another BTF blob was found. Call [HandleIterator.Err] after
+// the function returns false.
+func (it *HandleIterator) Next(handle **Handle) bool {
+ if *handle != nil {
+ (*handle).Close()
+ *handle = nil
+ }
+
+ id := it.ID
+ for {
+ attr := &sys.BtfGetNextIdAttr{Id: id}
+ err := sys.BtfGetNextId(attr)
+ if errors.Is(err, os.ErrNotExist) {
+ // There are no more BTF objects.
+ return false
+ } else if err != nil {
+ it.err = fmt.Errorf("get next BTF ID: %w", err)
+ return false
+ }
+
+ id = attr.NextId
+ *handle, err = NewHandleFromID(id)
+ if errors.Is(err, os.ErrNotExist) {
+ // Try again with the next ID.
+ continue
+ } else if err != nil {
+ it.err = fmt.Errorf("retrieve handle for ID %d: %w", id, err)
+ return false
+ }
+
+ it.ID = id
+ return true
+ }
+}
+
+// Err returns an error if iteration failed for some reason.
+func (it *HandleIterator) Err() error {
+ return it.err
+}