vendor: cilium/ebbf 4032b1d8aae306b7bb94a2a11002932caf88c644
full diff: 60c3aa43f4...4032b1d8aa
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
b0e71d7977
commit
4fb3410f65
@ -53,7 +53,7 @@ google.golang.org/grpc f495f5b15ae7ccda3b38c53a1bfc
|
|||||||
gotest.tools/v3 bb0d8a963040ea5048dcef1a14d8f8b58a33d4b3 # v3.0.2
|
gotest.tools/v3 bb0d8a963040ea5048dcef1a14d8f8b58a33d4b3 # v3.0.2
|
||||||
|
|
||||||
# cgroups dependencies
|
# cgroups dependencies
|
||||||
github.com/cilium/ebpf 60c3aa43f488292fe2ee50fb8b833b383ca8ebbb
|
github.com/cilium/ebpf 4032b1d8aae306b7bb94a2a11002932caf88c644
|
||||||
|
|
||||||
# cri dependencies
|
# cri dependencies
|
||||||
github.com/containerd/cri 92cb4ed9786a6cd271152ba1f862183d84701003 # master
|
github.com/containerd/cri 92cb4ed9786a6cd271152ba1f862183d84701003 # master
|
||||||
|
17
vendor/github.com/cilium/ebpf/abi.go
generated
vendored
17
vendor/github.com/cilium/ebpf/abi.go
generated
vendored
@ -9,6 +9,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ func newMapABIFromSpec(spec *MapSpec) *MapABI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapABIFromFd(fd *bpfFD) (string, *MapABI, error) {
|
func newMapABIFromFd(fd *internal.FD) (string, *MapABI, error) {
|
||||||
info, err := bpfGetMapInfoByFD(fd)
|
info, err := bpfGetMapInfoByFD(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) == syscall.EINVAL {
|
if errors.Cause(err) == syscall.EINVAL {
|
||||||
@ -50,7 +51,7 @@ func newMapABIFromFd(fd *bpfFD) (string, *MapABI, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapABIFromProc(fd *bpfFD) (*MapABI, error) {
|
func newMapABIFromProc(fd *internal.FD) (*MapABI, error) {
|
||||||
var abi MapABI
|
var abi MapABI
|
||||||
err := scanFdInfo(fd, map[string]interface{}{
|
err := scanFdInfo(fd, map[string]interface{}{
|
||||||
"map_type": &abi.Type,
|
"map_type": &abi.Type,
|
||||||
@ -94,7 +95,7 @@ func newProgramABIFromSpec(spec *ProgramSpec) *ProgramABI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newProgramABIFromFd(fd *bpfFD) (string, *ProgramABI, error) {
|
func newProgramABIFromFd(fd *internal.FD) (string, *ProgramABI, error) {
|
||||||
info, err := bpfGetProgInfoByFD(fd)
|
info, err := bpfGetProgInfoByFD(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) == syscall.EINVAL {
|
if errors.Cause(err) == syscall.EINVAL {
|
||||||
@ -105,10 +106,10 @@ func newProgramABIFromFd(fd *bpfFD) (string, *ProgramABI, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var name string
|
var name string
|
||||||
if bpfName := convertCString(info.name[:]); bpfName != "" {
|
if bpfName := internal.CString(info.name[:]); bpfName != "" {
|
||||||
name = bpfName
|
name = bpfName
|
||||||
} else {
|
} else {
|
||||||
name = convertCString(info.tag[:])
|
name = internal.CString(info.tag[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
return name, &ProgramABI{
|
return name, &ProgramABI{
|
||||||
@ -116,7 +117,7 @@ func newProgramABIFromFd(fd *bpfFD) (string, *ProgramABI, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newProgramABIFromProc(fd *bpfFD) (string, *ProgramABI, error) {
|
func newProgramABIFromProc(fd *internal.FD) (string, *ProgramABI, error) {
|
||||||
var (
|
var (
|
||||||
abi ProgramABI
|
abi ProgramABI
|
||||||
name string
|
name string
|
||||||
@ -139,8 +140,8 @@ func newProgramABIFromProc(fd *bpfFD) (string, *ProgramABI, error) {
|
|||||||
return name, &abi, nil
|
return name, &abi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanFdInfo(fd *bpfFD, fields map[string]interface{}) error {
|
func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error {
|
||||||
raw, err := fd.value()
|
raw, err := fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
63
vendor/github.com/cilium/ebpf/collection.go
generated
vendored
63
vendor/github.com/cilium/ebpf/collection.go
generated
vendored
@ -2,6 +2,7 @@ package ebpf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cilium/ebpf/asm"
|
"github.com/cilium/ebpf/asm"
|
||||||
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -55,17 +56,61 @@ func NewCollection(spec *CollectionSpec) (*Collection, error) {
|
|||||||
// NewCollectionWithOptions creates a Collection from a specification.
|
// NewCollectionWithOptions creates a Collection from a specification.
|
||||||
//
|
//
|
||||||
// Only maps referenced by at least one of the programs are initialized.
|
// Only maps referenced by at least one of the programs are initialized.
|
||||||
func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error) {
|
func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (coll *Collection, err error) {
|
||||||
maps := make(map[string]*Map)
|
var (
|
||||||
|
maps = make(map[string]*Map)
|
||||||
|
progs = make(map[string]*Program)
|
||||||
|
btfs = make(map[*btf.Spec]*btf.Handle)
|
||||||
|
)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
for _, btf := range btfs {
|
||||||
|
btf.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range maps {
|
||||||
|
m.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range progs {
|
||||||
|
p.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
loadBTF := func(spec *btf.Spec) (*btf.Handle, error) {
|
||||||
|
if btfs[spec] != nil {
|
||||||
|
return btfs[spec], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
handle, err := btf.NewHandle(spec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
btfs[spec] = handle
|
||||||
|
return handle, nil
|
||||||
|
}
|
||||||
|
|
||||||
for mapName, mapSpec := range spec.Maps {
|
for mapName, mapSpec := range spec.Maps {
|
||||||
m, err := NewMap(mapSpec)
|
var handle *btf.Handle
|
||||||
|
if mapSpec.BTF != nil {
|
||||||
|
handle, err = loadBTF(btf.MapSpec(mapSpec.BTF))
|
||||||
|
if err != nil && !btf.IsNotSupported(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := newMapWithBTF(mapSpec, handle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "map %s", mapName)
|
return nil, errors.Wrapf(err, "map %s", mapName)
|
||||||
}
|
}
|
||||||
maps[mapName] = m
|
maps[mapName] = m
|
||||||
}
|
}
|
||||||
|
|
||||||
progs := make(map[string]*Program)
|
|
||||||
for progName, origProgSpec := range spec.Programs {
|
for progName, origProgSpec := range spec.Programs {
|
||||||
progSpec := origProgSpec.Copy()
|
progSpec := origProgSpec.Copy()
|
||||||
|
|
||||||
@ -91,7 +136,15 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prog, err := NewProgramWithOptions(progSpec, opts.Programs)
|
var handle *btf.Handle
|
||||||
|
if progSpec.BTF != nil {
|
||||||
|
handle, err = loadBTF(btf.ProgramSpec(progSpec.BTF))
|
||||||
|
if err != nil && !btf.IsNotSupported(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prog, err := newProgramWithBTF(progSpec, handle, opts.Programs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "program %s", progName)
|
return nil, errors.Wrapf(err, "program %s", progName)
|
||||||
}
|
}
|
||||||
|
271
vendor/github.com/cilium/ebpf/elf_reader.go
generated
vendored
271
vendor/github.com/cilium/ebpf/elf_reader.go
generated
vendored
@ -4,12 +4,13 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/asm"
|
"github.com/cilium/ebpf/asm"
|
||||||
|
"github.com/cilium/ebpf/internal"
|
||||||
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -18,6 +19,8 @@ type elfCode struct {
|
|||||||
*elf.File
|
*elf.File
|
||||||
symbols []elf.Symbol
|
symbols []elf.Symbol
|
||||||
symbolsPerSection map[elf.SectionIndex]map[uint64]string
|
symbolsPerSection map[elf.SectionIndex]map[uint64]string
|
||||||
|
license string
|
||||||
|
version uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadCollectionSpec parses an ELF file into a CollectionSpec.
|
// LoadCollectionSpec parses an ELF file into a CollectionSpec.
|
||||||
@ -33,8 +36,8 @@ func LoadCollectionSpec(file string) (*CollectionSpec, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadCollectionSpecFromReader parses an ELF file into a CollectionSpec.
|
// LoadCollectionSpecFromReader parses an ELF file into a CollectionSpec.
|
||||||
func LoadCollectionSpecFromReader(code io.ReaderAt) (*CollectionSpec, error) {
|
func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
|
||||||
f, err := elf.NewFile(code)
|
f, err := elf.NewFile(rd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -45,12 +48,17 @@ func LoadCollectionSpecFromReader(code io.ReaderAt) (*CollectionSpec, error) {
|
|||||||
return nil, errors.Wrap(err, "load symbols")
|
return nil, errors.Wrap(err, "load symbols")
|
||||||
}
|
}
|
||||||
|
|
||||||
ec := &elfCode{f, symbols, symbolsPerSection(symbols)}
|
ec := &elfCode{f, symbols, symbolsPerSection(symbols), "", 0}
|
||||||
|
|
||||||
|
var (
|
||||||
|
licenseSection *elf.Section
|
||||||
|
versionSection *elf.Section
|
||||||
|
btfMaps = make(map[elf.SectionIndex]*elf.Section)
|
||||||
|
progSections = make(map[elf.SectionIndex]*elf.Section)
|
||||||
|
relSections = make(map[elf.SectionIndex]*elf.Section)
|
||||||
|
mapSections = make(map[elf.SectionIndex]*elf.Section)
|
||||||
|
)
|
||||||
|
|
||||||
var licenseSection, versionSection *elf.Section
|
|
||||||
progSections := make(map[elf.SectionIndex]*elf.Section)
|
|
||||||
relSections := make(map[elf.SectionIndex]*elf.Section)
|
|
||||||
mapSections := make(map[elf.SectionIndex]*elf.Section)
|
|
||||||
for i, sec := range ec.Sections {
|
for i, sec := range ec.Sections {
|
||||||
switch {
|
switch {
|
||||||
case strings.HasPrefix(sec.Name, "license"):
|
case strings.HasPrefix(sec.Name, "license"):
|
||||||
@ -59,6 +67,8 @@ func LoadCollectionSpecFromReader(code io.ReaderAt) (*CollectionSpec, error) {
|
|||||||
versionSection = sec
|
versionSection = sec
|
||||||
case strings.HasPrefix(sec.Name, "maps"):
|
case strings.HasPrefix(sec.Name, "maps"):
|
||||||
mapSections[elf.SectionIndex(i)] = sec
|
mapSections[elf.SectionIndex(i)] = sec
|
||||||
|
case sec.Name == ".maps":
|
||||||
|
btfMaps[elf.SectionIndex(i)] = sec
|
||||||
case sec.Type == elf.SHT_REL:
|
case sec.Type == elf.SHT_REL:
|
||||||
if int(sec.Info) >= len(ec.Sections) {
|
if int(sec.Info) >= len(ec.Sections) {
|
||||||
return nil, errors.Errorf("found relocation section %v for missing section %v", i, sec.Info)
|
return nil, errors.Errorf("found relocation section %v for missing section %v", i, sec.Info)
|
||||||
@ -67,7 +77,7 @@ func LoadCollectionSpecFromReader(code io.ReaderAt) (*CollectionSpec, error) {
|
|||||||
// Store relocations under the section index of the target
|
// Store relocations under the section index of the target
|
||||||
idx := elf.SectionIndex(sec.Info)
|
idx := elf.SectionIndex(sec.Info)
|
||||||
if relSections[idx] != nil {
|
if relSections[idx] != nil {
|
||||||
return nil, errors.Errorf("section %d has multiple relocation sections", idx)
|
return nil, errors.Errorf("section %d has multiple relocation sections", sec.Info)
|
||||||
}
|
}
|
||||||
relSections[idx] = sec
|
relSections[idx] = sec
|
||||||
case sec.Type == elf.SHT_PROGBITS && (sec.Flags&elf.SHF_EXECINSTR) != 0 && sec.Size > 0:
|
case sec.Type == elf.SHT_PROGBITS && (sec.Flags&elf.SHF_EXECINSTR) != 0 && sec.Size > 0:
|
||||||
@ -75,33 +85,36 @@ func LoadCollectionSpecFromReader(code io.ReaderAt) (*CollectionSpec, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
license, err := loadLicense(licenseSection)
|
ec.license, err = loadLicense(licenseSection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load license")
|
return nil, errors.Wrap(err, "load license")
|
||||||
}
|
}
|
||||||
|
|
||||||
version, err := loadVersion(versionSection, ec.ByteOrder)
|
ec.version, err = loadVersion(versionSection, ec.ByteOrder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load version")
|
return nil, errors.Wrap(err, "load version")
|
||||||
}
|
}
|
||||||
|
|
||||||
maps, err := ec.loadMaps(mapSections)
|
btf, err := btf.LoadSpecFromReader(rd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "load BTF")
|
||||||
|
}
|
||||||
|
|
||||||
|
maps := make(map[string]*MapSpec)
|
||||||
|
|
||||||
|
if err := ec.loadMaps(maps, mapSections); err != nil {
|
||||||
return nil, errors.Wrap(err, "load maps")
|
return nil, errors.Wrap(err, "load maps")
|
||||||
}
|
}
|
||||||
|
|
||||||
progs, libs, err := ec.loadPrograms(progSections, relSections, license, version)
|
if len(btfMaps) > 0 {
|
||||||
if err != nil {
|
if err := ec.loadBTFMaps(maps, btfMaps, btf); err != nil {
|
||||||
return nil, errors.Wrap(err, "load programs")
|
return nil, errors.Wrap(err, "load BTF maps")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(libs) > 0 {
|
progs, err := ec.loadPrograms(progSections, relSections, btf)
|
||||||
for name, prog := range progs {
|
|
||||||
prog.Instructions, err = link(prog.Instructions, libs...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "program %s", name)
|
return nil, errors.Wrap(err, "load programs")
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &CollectionSpec{maps, progs}, nil
|
return &CollectionSpec{maps, progs}, nil
|
||||||
@ -128,52 +141,74 @@ func loadVersion(sec *elf.Section, bo binary.ByteOrder) (uint32, error) {
|
|||||||
return version, errors.Wrapf(err, "section %s", sec.Name)
|
return version, errors.Wrapf(err, "section %s", sec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *elfCode) loadPrograms(progSections, relSections map[elf.SectionIndex]*elf.Section, license string, version uint32) (map[string]*ProgramSpec, []asm.Instructions, error) {
|
func (ec *elfCode) loadPrograms(progSections, relSections map[elf.SectionIndex]*elf.Section, btf *btf.Spec) (map[string]*ProgramSpec, error) {
|
||||||
var (
|
var (
|
||||||
progs = make(map[string]*ProgramSpec)
|
progs []*ProgramSpec
|
||||||
libs []asm.Instructions
|
libs []*ProgramSpec
|
||||||
)
|
)
|
||||||
|
|
||||||
for idx, prog := range progSections {
|
for idx, prog := range progSections {
|
||||||
syms := ec.symbolsPerSection[idx]
|
syms := ec.symbolsPerSection[idx]
|
||||||
if len(syms) == 0 {
|
if len(syms) == 0 {
|
||||||
return nil, nil, errors.Errorf("section %v: missing symbols", prog.Name)
|
return nil, errors.Errorf("section %v: missing symbols", prog.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
funcSym := syms[0]
|
funcSym := syms[0]
|
||||||
if funcSym == "" {
|
if funcSym == "" {
|
||||||
return nil, nil, errors.Errorf("section %v: no label at start", prog.Name)
|
return nil, errors.Errorf("section %v: no label at start", prog.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
rels, err := ec.loadRelocations(relSections[idx])
|
rels, err := ec.loadRelocations(relSections[idx])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrapf(err, "program %s: can't load relocations", funcSym)
|
return nil, errors.Wrapf(err, "program %s: can't load relocations", funcSym)
|
||||||
}
|
}
|
||||||
|
|
||||||
insns, err := ec.loadInstructions(prog, syms, rels)
|
insns, length, err := ec.loadInstructions(prog, syms, rels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrapf(err, "program %s: can't unmarshal instructions", funcSym)
|
return nil, errors.Wrapf(err, "program %s: can't unmarshal instructions", funcSym)
|
||||||
}
|
}
|
||||||
|
|
||||||
if progType, attachType := getProgType(prog.Name); progType == UnspecifiedProgram {
|
progType, attachType := getProgType(prog.Name)
|
||||||
// There is no single name we can use for "library" sections,
|
|
||||||
// since they may contain multiple functions. We'll decode the
|
spec := &ProgramSpec{
|
||||||
// labels they contain later on, and then link sections that way.
|
|
||||||
libs = append(libs, insns)
|
|
||||||
} else {
|
|
||||||
progs[funcSym] = &ProgramSpec{
|
|
||||||
Name: funcSym,
|
Name: funcSym,
|
||||||
Type: progType,
|
Type: progType,
|
||||||
AttachType: attachType,
|
AttachType: attachType,
|
||||||
License: license,
|
License: ec.license,
|
||||||
KernelVersion: version,
|
KernelVersion: ec.version,
|
||||||
Instructions: insns,
|
Instructions: insns,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if btf != nil {
|
||||||
|
spec.BTF, err = btf.Program(prog.Name, length)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "BTF for section %s (program %s)", prog.Name, funcSym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return progs, libs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations map[uint64]string) (asm.Instructions, error) {
|
if spec.Type == UnspecifiedProgram {
|
||||||
|
// There is no single name we can use for "library" sections,
|
||||||
|
// since they may contain multiple functions. We'll decode the
|
||||||
|
// labels they contain later on, and then link sections that way.
|
||||||
|
libs = append(libs, spec)
|
||||||
|
} else {
|
||||||
|
progs = append(progs, spec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res := make(map[string]*ProgramSpec, len(progs))
|
||||||
|
for _, prog := range progs {
|
||||||
|
err := link(prog, libs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "program %s", prog.Name)
|
||||||
|
}
|
||||||
|
res[prog.Name] = prog
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations map[uint64]string) (asm.Instructions, uint64, error) {
|
||||||
var (
|
var (
|
||||||
r = section.Open()
|
r = section.Open()
|
||||||
insns asm.Instructions
|
insns asm.Instructions
|
||||||
@ -183,10 +218,10 @@ func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations m
|
|||||||
for {
|
for {
|
||||||
n, err := ins.Unmarshal(r, ec.ByteOrder)
|
n, err := ins.Unmarshal(r, ec.ByteOrder)
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return insns, nil
|
return insns, offset, nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "offset %d", offset)
|
return nil, 0, errors.Wrapf(err, "offset %d", offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
ins.Symbol = symbols[offset]
|
ins.Symbol = symbols[offset]
|
||||||
@ -197,19 +232,15 @@ func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *elfCode) loadMaps(mapSections map[elf.SectionIndex]*elf.Section) (map[string]*MapSpec, error) {
|
func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.SectionIndex]*elf.Section) error {
|
||||||
var (
|
|
||||||
maps = make(map[string]*MapSpec)
|
|
||||||
b = make([]byte, 1)
|
|
||||||
)
|
|
||||||
for idx, sec := range mapSections {
|
for idx, sec := range mapSections {
|
||||||
syms := ec.symbolsPerSection[idx]
|
syms := ec.symbolsPerSection[idx]
|
||||||
if len(syms) == 0 {
|
if len(syms) == 0 {
|
||||||
return nil, errors.Errorf("section %v: no symbols", sec.Name)
|
return errors.Errorf("section %v: no symbols", sec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sec.Size%uint64(len(syms)) != 0 {
|
if sec.Size%uint64(len(syms)) != 0 {
|
||||||
return nil, errors.Errorf("section %v: map descriptors are not of equal size", sec.Name)
|
return errors.Errorf("section %v: map descriptors are not of equal size", sec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -219,12 +250,11 @@ func (ec *elfCode) loadMaps(mapSections map[elf.SectionIndex]*elf.Section) (map[
|
|||||||
for i, offset := 0, uint64(0); i < len(syms); i, offset = i+1, offset+size {
|
for i, offset := 0, uint64(0); i < len(syms); i, offset = i+1, offset+size {
|
||||||
mapSym := syms[offset]
|
mapSym := syms[offset]
|
||||||
if mapSym == "" {
|
if mapSym == "" {
|
||||||
fmt.Println(syms)
|
return errors.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset)
|
||||||
return nil, errors.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if maps[mapSym] != nil {
|
if maps[mapSym] != nil {
|
||||||
return nil, errors.Errorf("section %v: map %v already exists", sec.Name, mapSym)
|
return errors.Errorf("section %v: map %v already exists", sec.Name, mapSym)
|
||||||
}
|
}
|
||||||
|
|
||||||
lr := io.LimitReader(r, int64(size))
|
lr := io.LimitReader(r, int64(size))
|
||||||
@ -232,34 +262,128 @@ func (ec *elfCode) loadMaps(mapSections map[elf.SectionIndex]*elf.Section) (map[
|
|||||||
var spec MapSpec
|
var spec MapSpec
|
||||||
switch {
|
switch {
|
||||||
case binary.Read(lr, ec.ByteOrder, &spec.Type) != nil:
|
case binary.Read(lr, ec.ByteOrder, &spec.Type) != nil:
|
||||||
return nil, errors.Errorf("map %v: missing type", mapSym)
|
return errors.Errorf("map %v: missing type", mapSym)
|
||||||
case binary.Read(lr, ec.ByteOrder, &spec.KeySize) != nil:
|
case binary.Read(lr, ec.ByteOrder, &spec.KeySize) != nil:
|
||||||
return nil, errors.Errorf("map %v: missing key size", mapSym)
|
return errors.Errorf("map %v: missing key size", mapSym)
|
||||||
case binary.Read(lr, ec.ByteOrder, &spec.ValueSize) != nil:
|
case binary.Read(lr, ec.ByteOrder, &spec.ValueSize) != nil:
|
||||||
return nil, errors.Errorf("map %v: missing value size", mapSym)
|
return errors.Errorf("map %v: missing value size", mapSym)
|
||||||
case binary.Read(lr, ec.ByteOrder, &spec.MaxEntries) != nil:
|
case binary.Read(lr, ec.ByteOrder, &spec.MaxEntries) != nil:
|
||||||
return nil, errors.Errorf("map %v: missing max entries", mapSym)
|
return errors.Errorf("map %v: missing max entries", mapSym)
|
||||||
case binary.Read(lr, ec.ByteOrder, &spec.Flags) != nil:
|
case binary.Read(lr, ec.ByteOrder, &spec.Flags) != nil:
|
||||||
return nil, errors.Errorf("map %v: missing flags", mapSym)
|
return errors.Errorf("map %v: missing flags", mapSym)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil {
|
||||||
_, err := lr.Read(b)
|
return errors.Errorf("map %v: unknown and non-zero fields in definition", mapSym)
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if b[0] != 0 {
|
|
||||||
return nil, errors.Errorf("map %v: unknown and non-zero fields in definition", mapSym)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
maps[mapSym] = &spec
|
maps[mapSym] = &spec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return maps, nil
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec, mapSections map[elf.SectionIndex]*elf.Section, spec *btf.Spec) error {
|
||||||
|
|
||||||
|
if spec == nil {
|
||||||
|
return errors.Errorf("missing BTF")
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, sec := range mapSections {
|
||||||
|
syms := ec.symbolsPerSection[idx]
|
||||||
|
if len(syms) == 0 {
|
||||||
|
return errors.Errorf("section %v: no symbols", sec.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, sym := range syms {
|
||||||
|
if maps[sym] != nil {
|
||||||
|
return errors.Errorf("section %v: map %v already exists", sec.Name, sym)
|
||||||
|
}
|
||||||
|
|
||||||
|
btfMap, err := spec.Map(sym)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "map %v: can't get BTF", sym)
|
||||||
|
}
|
||||||
|
|
||||||
|
spec, err := mapSpecFromBTF(btfMap)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "map %v", sym)
|
||||||
|
}
|
||||||
|
|
||||||
|
maps[sym] = spec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapSpecFromBTF(btfMap *btf.Map) (*MapSpec, error) {
|
||||||
|
var (
|
||||||
|
mapType, flags, maxEntries uint32
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
for _, member := range btf.MapType(btfMap).Members {
|
||||||
|
switch member.Name {
|
||||||
|
case "type":
|
||||||
|
mapType, err = uintFromBTF(member.Type)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't get type")
|
||||||
|
}
|
||||||
|
|
||||||
|
case "map_flags":
|
||||||
|
flags, err = uintFromBTF(member.Type)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't get BTF map flags")
|
||||||
|
}
|
||||||
|
|
||||||
|
case "max_entries":
|
||||||
|
maxEntries, err = uintFromBTF(member.Type)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't get BTF map max entries")
|
||||||
|
}
|
||||||
|
|
||||||
|
case "key":
|
||||||
|
case "value":
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("unrecognized field %s in BTF map definition", member.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keySize, err := btf.Sizeof(btf.MapKey(btfMap))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't get size of BTF key")
|
||||||
|
}
|
||||||
|
|
||||||
|
valueSize, err := btf.Sizeof(btf.MapValue(btfMap))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't get size of BTF value")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &MapSpec{
|
||||||
|
Type: MapType(mapType),
|
||||||
|
KeySize: uint32(keySize),
|
||||||
|
ValueSize: uint32(valueSize),
|
||||||
|
MaxEntries: maxEntries,
|
||||||
|
Flags: flags,
|
||||||
|
BTF: btfMap,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// uintFromBTF resolves the __uint macro, which is a pointer to a sized
|
||||||
|
// array, e.g. for int (*foo)[10], this function will return 10.
|
||||||
|
func uintFromBTF(typ btf.Type) (uint32, error) {
|
||||||
|
ptr, ok := typ.(*btf.Pointer)
|
||||||
|
if !ok {
|
||||||
|
return 0, errors.Errorf("not a pointer: %v", typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
arr, ok := ptr.Target.(*btf.Array)
|
||||||
|
if !ok {
|
||||||
|
return 0, errors.Errorf("not a pointer to array: %v", typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr.Nelems, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getProgType(v string) (ProgramType, AttachType) {
|
func getProgType(v string) (ProgramType, AttachType) {
|
||||||
@ -268,10 +392,17 @@ func getProgType(v string) (ProgramType, AttachType) {
|
|||||||
"socket": SocketFilter,
|
"socket": SocketFilter,
|
||||||
"seccomp": SocketFilter,
|
"seccomp": SocketFilter,
|
||||||
"kprobe/": Kprobe,
|
"kprobe/": Kprobe,
|
||||||
|
"uprobe/": Kprobe,
|
||||||
"kretprobe/": Kprobe,
|
"kretprobe/": Kprobe,
|
||||||
|
"uretprobe/": Kprobe,
|
||||||
"tracepoint/": TracePoint,
|
"tracepoint/": TracePoint,
|
||||||
|
"raw_tracepoint/": RawTracepoint,
|
||||||
"xdp": XDP,
|
"xdp": XDP,
|
||||||
"perf_event": PerfEvent,
|
"perf_event": PerfEvent,
|
||||||
|
"lwt_in": LWTIn,
|
||||||
|
"lwt_out": LWTOut,
|
||||||
|
"lwt_xmit": LWTXmit,
|
||||||
|
"lwt_seg6local": LWTSeg6Local,
|
||||||
"sockops": SockOps,
|
"sockops": SockOps,
|
||||||
"sk_skb": SkSKB,
|
"sk_skb": SkSKB,
|
||||||
"sk_msg": SkMsg,
|
"sk_msg": SkMsg,
|
||||||
|
530
vendor/github.com/cilium/ebpf/internal/btf/btf.go
generated
vendored
Normal file
530
vendor/github.com/cilium/ebpf/internal/btf/btf.go
generated
vendored
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
package btf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"debug/elf"
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf/internal"
|
||||||
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const btfMagic = 0xeB9F
|
||||||
|
|
||||||
|
// Spec represents decoded BTF.
|
||||||
|
type Spec struct {
|
||||||
|
rawTypes []rawType
|
||||||
|
strings stringTable
|
||||||
|
types map[string][]Type
|
||||||
|
funcInfos map[string]extInfo
|
||||||
|
lineInfos map[string]extInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type btfHeader struct {
|
||||||
|
Magic uint16
|
||||||
|
Version uint8
|
||||||
|
Flags uint8
|
||||||
|
HdrLen uint32
|
||||||
|
|
||||||
|
TypeOff uint32
|
||||||
|
TypeLen uint32
|
||||||
|
StringOff uint32
|
||||||
|
StringLen uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadSpecFromReader reads BTF sections from an ELF.
|
||||||
|
//
|
||||||
|
// Returns a nil Spec and no error if no BTF was present.
|
||||||
|
func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
|
||||||
|
file, err := elf.NewFile(rd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
var (
|
||||||
|
btfSection *elf.Section
|
||||||
|
btfExtSection *elf.Section
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, sec := range file.Sections {
|
||||||
|
switch sec.Name {
|
||||||
|
case ".BTF":
|
||||||
|
btfSection = sec
|
||||||
|
case ".BTF.ext":
|
||||||
|
btfExtSection = sec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if btfSection == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
spec, err := parseBTF(btfSection.Open(), file.ByteOrder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if btfExtSection != nil {
|
||||||
|
spec.funcInfos, spec.lineInfos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't read ext info")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBTF(btf io.ReadSeeker, bo binary.ByteOrder) (*Spec, error) {
|
||||||
|
rawBTF, err := ioutil.ReadAll(btf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't read BTF")
|
||||||
|
}
|
||||||
|
|
||||||
|
rd := bytes.NewReader(rawBTF)
|
||||||
|
|
||||||
|
var header btfHeader
|
||||||
|
if err := binary.Read(rd, bo, &header); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't read header")
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Magic != btfMagic {
|
||||||
|
return nil, errors.Errorf("incorrect magic value %v", header.Magic)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Version != 1 {
|
||||||
|
return nil, errors.Errorf("unexpected version %v", header.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Flags != 0 {
|
||||||
|
return nil, errors.Errorf("unsupported flags %v", header.Flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
remainder := int64(header.HdrLen) - int64(binary.Size(&header))
|
||||||
|
if remainder < 0 {
|
||||||
|
return nil, errors.New("header is too short")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.CopyN(internal.DiscardZeroes{}, rd, remainder); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "header padding")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := rd.Seek(int64(header.HdrLen+header.StringOff), io.SeekStart); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't seek to start of string section")
|
||||||
|
}
|
||||||
|
|
||||||
|
strings, err := readStringTable(io.LimitReader(rd, int64(header.StringLen)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't read type names")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := rd.Seek(int64(header.HdrLen+header.TypeOff), io.SeekStart); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't seek to start of type section")
|
||||||
|
}
|
||||||
|
|
||||||
|
rawTypes, err := readTypes(io.LimitReader(rd, int64(header.TypeLen)), bo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't read types")
|
||||||
|
}
|
||||||
|
|
||||||
|
types, err := inflateRawTypes(rawTypes, strings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Spec{
|
||||||
|
rawTypes: rawTypes,
|
||||||
|
types: types,
|
||||||
|
strings: strings,
|
||||||
|
funcInfos: make(map[string]extInfo),
|
||||||
|
lineInfos: make(map[string]extInfo),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Spec) marshal(bo binary.ByteOrder) ([]byte, error) {
|
||||||
|
var (
|
||||||
|
buf bytes.Buffer
|
||||||
|
header = new(btfHeader)
|
||||||
|
headerLen = binary.Size(header)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reserve space for the header. We have to write it last since
|
||||||
|
// we don't know the size of the type section yet.
|
||||||
|
_, _ = buf.Write(make([]byte, headerLen))
|
||||||
|
|
||||||
|
// Write type section, just after the header.
|
||||||
|
for _, typ := range s.rawTypes {
|
||||||
|
if typ.Kind() == kindDatasec {
|
||||||
|
// Datasec requires patching with information from the ELF
|
||||||
|
// file. We don't support this at the moment, so patch
|
||||||
|
// out any Datasec by turning it into a void*.
|
||||||
|
typ = rawType{}
|
||||||
|
typ.SetKind(kindPointer)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := typ.Marshal(&buf, bo); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't marshal BTF")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeLen := uint32(buf.Len() - headerLen)
|
||||||
|
|
||||||
|
// Write string section after type section.
|
||||||
|
_, _ = buf.Write(s.strings)
|
||||||
|
|
||||||
|
// Fill out the header, and write it out.
|
||||||
|
header = &btfHeader{
|
||||||
|
Magic: btfMagic,
|
||||||
|
Version: 1,
|
||||||
|
Flags: 0,
|
||||||
|
HdrLen: uint32(headerLen),
|
||||||
|
TypeOff: 0,
|
||||||
|
TypeLen: typeLen,
|
||||||
|
StringOff: typeLen,
|
||||||
|
StringLen: uint32(len(s.strings)),
|
||||||
|
}
|
||||||
|
|
||||||
|
raw := buf.Bytes()
|
||||||
|
err := binary.Write(sliceWriter(raw[:headerLen]), bo, header)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't write header")
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type sliceWriter []byte
|
||||||
|
|
||||||
|
func (sw sliceWriter) Write(p []byte) (int, error) {
|
||||||
|
if len(p) != len(sw) {
|
||||||
|
return 0, errors.New("size doesn't match")
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy(sw, p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Program finds the BTF for a specific section.
|
||||||
|
//
|
||||||
|
// Length is the number of bytes in the raw BPF instruction stream.
|
||||||
|
//
|
||||||
|
// Returns an error if there is no BTF.
|
||||||
|
func (s *Spec) Program(name string, length uint64) (*Program, error) {
|
||||||
|
if length == 0 {
|
||||||
|
return nil, errors.New("length musn't be zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
funcInfos, funcOK := s.funcInfos[name]
|
||||||
|
lineInfos, lineOK := s.lineInfos[name]
|
||||||
|
|
||||||
|
if !funcOK && !lineOK {
|
||||||
|
return nil, errors.Errorf("no BTF for program %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Program{s, length, funcInfos, lineInfos}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map finds the BTF for a map.
|
||||||
|
//
|
||||||
|
// Returns an error if there is no BTF for the given name.
|
||||||
|
func (s *Spec) Map(name string) (*Map, error) {
|
||||||
|
var mapVar Var
|
||||||
|
if err := s.FindType(name, &mapVar); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mapStruct, ok := mapVar.Type.(*Struct)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.Errorf("expected struct, have %s", mapVar.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
var key, value Type
|
||||||
|
for _, member := range mapStruct.Members {
|
||||||
|
switch member.Name {
|
||||||
|
case "key":
|
||||||
|
key = member.Type
|
||||||
|
|
||||||
|
case "value":
|
||||||
|
value = member.Type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == nil {
|
||||||
|
return nil, errors.Errorf("map %s: missing 'key' in type", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if value == nil {
|
||||||
|
return nil, errors.Errorf("map %s: missing 'value' in type", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Map{mapStruct, s, key, value}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var errNotFound = errors.New("not found")
|
||||||
|
|
||||||
|
// FindType searches for a type with a specific name.
|
||||||
|
//
|
||||||
|
// hint determines the type of the returned Type.
|
||||||
|
//
|
||||||
|
// Returns an error if there is no or multiple matches.
|
||||||
|
func (s *Spec) FindType(name string, typ Type) error {
|
||||||
|
var (
|
||||||
|
wanted = reflect.TypeOf(typ)
|
||||||
|
candidate Type
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, typ := range s.types[name] {
|
||||||
|
if reflect.TypeOf(typ) != wanted {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if candidate != nil {
|
||||||
|
return errors.Errorf("type %s: multiple candidates for %T", name, typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
candidate = typ
|
||||||
|
}
|
||||||
|
|
||||||
|
if candidate == nil {
|
||||||
|
return errors.WithMessagef(errNotFound, "type %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
value := reflect.Indirect(reflect.ValueOf(copyType(candidate)))
|
||||||
|
reflect.Indirect(reflect.ValueOf(typ)).Set(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is a reference to BTF loaded into the kernel.
|
||||||
|
type Handle struct {
|
||||||
|
fd *internal.FD
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHandle loads BTF into the kernel.
|
||||||
|
//
|
||||||
|
// Returns an error if BTF is not supported, which can
|
||||||
|
// be checked by IsNotSupported.
|
||||||
|
func NewHandle(spec *Spec) (*Handle, error) {
|
||||||
|
if err := haveBTF(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
btf, err := spec.marshal(internal.NativeEndian)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't marshal BTF")
|
||||||
|
}
|
||||||
|
|
||||||
|
if uint64(len(btf)) > math.MaxUint32 {
|
||||||
|
return nil, errors.New("BTF exceeds the maximum size")
|
||||||
|
}
|
||||||
|
|
||||||
|
attr := &bpfLoadBTFAttr{
|
||||||
|
btf: internal.NewSlicePointer(btf),
|
||||||
|
btfSize: uint32(len(btf)),
|
||||||
|
}
|
||||||
|
|
||||||
|
fd, err := bpfLoadBTF(attr)
|
||||||
|
if err != nil {
|
||||||
|
logBuf := make([]byte, 64*1024)
|
||||||
|
attr.logBuf = internal.NewSlicePointer(logBuf)
|
||||||
|
attr.btfLogSize = uint32(len(logBuf))
|
||||||
|
attr.btfLogLevel = 1
|
||||||
|
_, logErr := bpfLoadBTF(attr)
|
||||||
|
return nil, internal.ErrorWithLog(err, logBuf, logErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Handle{fd}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close destroys the handle.
|
||||||
|
//
|
||||||
|
// Subsequent calls to FD will return an invalid value.
|
||||||
|
func (h *Handle) Close() error {
|
||||||
|
return h.fd.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FD returns the file descriptor for the handle.
|
||||||
|
func (h *Handle) FD() int {
|
||||||
|
value, err := h.fd.Value()
|
||||||
|
if err != nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map is the BTF for a map.
|
||||||
|
type Map struct {
|
||||||
|
definition *Struct
|
||||||
|
spec *Spec
|
||||||
|
key, value Type
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapSpec should be a method on Map, but is a free function
|
||||||
|
// to hide it from users of the ebpf package.
|
||||||
|
func MapSpec(m *Map) *Spec {
|
||||||
|
return m.spec
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapType should be a method on Map, but is a free function
|
||||||
|
// to hide it from users of the ebpf package.
|
||||||
|
func MapType(m *Map) *Struct {
|
||||||
|
return m.definition
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapKey should be a method on Map, but is a free function
|
||||||
|
// to hide it from users of the ebpf package.
|
||||||
|
func MapKey(m *Map) Type {
|
||||||
|
return m.key
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapValue should be a method on Map, but is a free function
|
||||||
|
// to hide it from users of the ebpf package.
|
||||||
|
func MapValue(m *Map) Type {
|
||||||
|
return m.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Program is the BTF information for a stream of instructions.
|
||||||
|
type Program struct {
|
||||||
|
spec *Spec
|
||||||
|
length uint64
|
||||||
|
funcInfos, lineInfos extInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProgramSpec returns the Spec needed for loading function and line infos into the kernel.
|
||||||
|
//
|
||||||
|
// This is a free function instead of a method to hide it from users
|
||||||
|
// of package ebpf.
|
||||||
|
func ProgramSpec(s *Program) *Spec {
|
||||||
|
return s.spec
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProgramAppend the information from other to the Program.
|
||||||
|
//
|
||||||
|
// This is a free function instead of a method to hide it from users
|
||||||
|
// of package ebpf.
|
||||||
|
func ProgramAppend(s, other *Program) error {
|
||||||
|
funcInfos, err := s.funcInfos.append(other.funcInfos, s.length)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "func infos")
|
||||||
|
}
|
||||||
|
|
||||||
|
lineInfos, err := s.lineInfos.append(other.lineInfos, s.length)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "line infos")
|
||||||
|
}
|
||||||
|
|
||||||
|
s.length += other.length
|
||||||
|
s.funcInfos = funcInfos
|
||||||
|
s.lineInfos = lineInfos
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProgramFuncInfos returns the binary form of BTF function infos.
|
||||||
|
//
|
||||||
|
// This is a free function instead of a method to hide it from users
|
||||||
|
// of package ebpf.
|
||||||
|
func ProgramFuncInfos(s *Program) (recordSize uint32, bytes []byte, err error) {
|
||||||
|
bytes, err = s.funcInfos.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.funcInfos.recordSize, bytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProgramLineInfos returns the binary form of BTF line infos.
|
||||||
|
//
|
||||||
|
// This is a free function instead of a method to hide it from users
|
||||||
|
// of package ebpf.
|
||||||
|
func ProgramLineInfos(s *Program) (recordSize uint32, bytes []byte, err error) {
|
||||||
|
bytes, err = s.lineInfos.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.lineInfos.recordSize, bytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotSupported returns true if the error indicates that the kernel
|
||||||
|
// doesn't support BTF.
|
||||||
|
func IsNotSupported(err error) bool {
|
||||||
|
ufe, ok := errors.Cause(err).(*internal.UnsupportedFeatureError)
|
||||||
|
return ok && ufe.Name == "BTF"
|
||||||
|
}
|
||||||
|
|
||||||
|
type bpfLoadBTFAttr struct {
|
||||||
|
btf internal.Pointer
|
||||||
|
logBuf internal.Pointer
|
||||||
|
btfSize uint32
|
||||||
|
btfLogSize uint32
|
||||||
|
btfLogLevel uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func bpfLoadBTF(attr *bpfLoadBTFAttr) (*internal.FD, error) {
|
||||||
|
const _BTFLoad = 18
|
||||||
|
|
||||||
|
fd, err := internal.BPF(_BTFLoad, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return internal.NewFD(uint32(fd)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func minimalBTF(bo binary.ByteOrder) []byte {
|
||||||
|
const minHeaderLength = 24
|
||||||
|
|
||||||
|
var (
|
||||||
|
types struct {
|
||||||
|
Integer btfType
|
||||||
|
Var btfType
|
||||||
|
btfVar struct{ Linkage uint32 }
|
||||||
|
}
|
||||||
|
typLen = uint32(binary.Size(&types))
|
||||||
|
strings = []byte{0, 'a', 0}
|
||||||
|
header = btfHeader{
|
||||||
|
Magic: btfMagic,
|
||||||
|
Version: 1,
|
||||||
|
HdrLen: minHeaderLength,
|
||||||
|
TypeOff: 0,
|
||||||
|
TypeLen: typLen,
|
||||||
|
StringOff: typLen,
|
||||||
|
StringLen: uint32(len(strings)),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// We use a BTF_KIND_VAR here, to make sure that
|
||||||
|
// the kernel understands BTF at least as well as we
|
||||||
|
// do. BTF_KIND_VAR was introduced ~5.1.
|
||||||
|
types.Integer.SetKind(kindPointer)
|
||||||
|
types.Var.NameOff = 1
|
||||||
|
types.Var.SetKind(kindVar)
|
||||||
|
types.Var.SizeType = 1
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
_ = binary.Write(buf, bo, &header)
|
||||||
|
_ = binary.Write(buf, bo, &types)
|
||||||
|
buf.Write(strings)
|
||||||
|
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
var haveBTF = internal.FeatureTest("BTF", "5.1", func() bool {
|
||||||
|
btf := minimalBTF(internal.NativeEndian)
|
||||||
|
fd, err := bpfLoadBTF(&bpfLoadBTFAttr{
|
||||||
|
btf: internal.NewSlicePointer(btf),
|
||||||
|
btfSize: uint32(len(btf)),
|
||||||
|
})
|
||||||
|
if err == nil {
|
||||||
|
fd.Close()
|
||||||
|
}
|
||||||
|
// Check for EINVAL specifically, rather than err != nil since we
|
||||||
|
// otherwise misdetect due to insufficient permissions.
|
||||||
|
return errors.Cause(err) != unix.EINVAL
|
||||||
|
})
|
190
vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
generated
vendored
Normal file
190
vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
generated
vendored
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
package btf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// btfKind describes a Type.
|
||||||
|
type btfKind uint8
|
||||||
|
|
||||||
|
// Equivalents of the BTF_KIND_* constants.
|
||||||
|
const (
|
||||||
|
kindUnknown btfKind = iota
|
||||||
|
kindInt
|
||||||
|
kindPointer
|
||||||
|
kindArray
|
||||||
|
kindStruct
|
||||||
|
kindUnion
|
||||||
|
kindEnum
|
||||||
|
kindForward
|
||||||
|
kindTypedef
|
||||||
|
kindVolatile
|
||||||
|
kindConst
|
||||||
|
kindRestrict
|
||||||
|
// Added ~4.20
|
||||||
|
kindFunc
|
||||||
|
kindFuncProto
|
||||||
|
// Added ~5.1
|
||||||
|
kindVar
|
||||||
|
kindDatasec
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
btfTypeKindShift = 24
|
||||||
|
btfTypeKindLen = 4
|
||||||
|
btfTypeVlenShift = 0
|
||||||
|
btfTypeVlenMask = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
// btfType is equivalent to struct btf_type in Documentation/bpf/btf.rst.
|
||||||
|
type btfType struct {
|
||||||
|
NameOff uint32
|
||||||
|
/* "info" bits arrangement
|
||||||
|
* bits 0-15: vlen (e.g. # of struct's members)
|
||||||
|
* bits 16-23: unused
|
||||||
|
* bits 24-27: kind (e.g. int, ptr, array...etc)
|
||||||
|
* bits 28-30: unused
|
||||||
|
* bit 31: kind_flag, currently used by
|
||||||
|
* struct, union and fwd
|
||||||
|
*/
|
||||||
|
Info uint32
|
||||||
|
/* "size" is used by INT, ENUM, STRUCT and UNION.
|
||||||
|
* "size" tells the size of the type it is describing.
|
||||||
|
*
|
||||||
|
* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
|
||||||
|
* FUNC and FUNC_PROTO.
|
||||||
|
* "type" is a type_id referring to another type.
|
||||||
|
*/
|
||||||
|
SizeType uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func mask(len uint32) uint32 {
|
||||||
|
return (1 << len) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bt *btfType) info(len, shift uint32) uint32 {
|
||||||
|
return (bt.Info >> shift) & mask(len)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bt *btfType) setInfo(value, len, shift uint32) {
|
||||||
|
bt.Info &^= mask(len) << shift
|
||||||
|
bt.Info |= (value & mask(len)) << shift
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bt *btfType) Kind() btfKind {
|
||||||
|
return btfKind(bt.info(btfTypeKindLen, btfTypeKindShift))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bt *btfType) SetKind(kind btfKind) {
|
||||||
|
bt.setInfo(uint32(kind), btfTypeKindLen, btfTypeKindShift)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bt *btfType) Vlen() int {
|
||||||
|
return int(bt.info(btfTypeVlenMask, btfTypeVlenShift))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bt *btfType) SetVlen(vlen int) {
|
||||||
|
bt.setInfo(uint32(vlen), btfTypeVlenMask, btfTypeVlenShift)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bt *btfType) Type() TypeID {
|
||||||
|
// TODO: Panic here if wrong kind?
|
||||||
|
return TypeID(bt.SizeType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bt *btfType) Size() uint32 {
|
||||||
|
// TODO: Panic here if wrong kind?
|
||||||
|
return bt.SizeType
|
||||||
|
}
|
||||||
|
|
||||||
|
type rawType struct {
|
||||||
|
btfType
|
||||||
|
data interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rt *rawType) Marshal(w io.Writer, bo binary.ByteOrder) error {
|
||||||
|
if err := binary.Write(w, bo, &rt.btfType); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if rt.data == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return binary.Write(w, bo, rt.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
type btfArray struct {
|
||||||
|
Type TypeID
|
||||||
|
IndexType TypeID
|
||||||
|
Nelems uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type btfMember struct {
|
||||||
|
NameOff uint32
|
||||||
|
Type TypeID
|
||||||
|
Offset uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
|
||||||
|
var (
|
||||||
|
header btfType
|
||||||
|
types []rawType
|
||||||
|
)
|
||||||
|
|
||||||
|
for id := TypeID(1); ; id++ {
|
||||||
|
if err := binary.Read(r, bo, &header); err == io.EOF {
|
||||||
|
return types, nil
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "can't read type info for id %v", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
var data interface{}
|
||||||
|
switch header.Kind() {
|
||||||
|
case kindInt:
|
||||||
|
// sizeof(uint32)
|
||||||
|
data = make([]byte, 4)
|
||||||
|
case kindPointer:
|
||||||
|
case kindArray:
|
||||||
|
data = new(btfArray)
|
||||||
|
case kindStruct:
|
||||||
|
fallthrough
|
||||||
|
case kindUnion:
|
||||||
|
data = make([]btfMember, header.Vlen())
|
||||||
|
case kindEnum:
|
||||||
|
// sizeof(struct btf_enum)
|
||||||
|
data = make([]byte, header.Vlen()*4*2)
|
||||||
|
case kindForward:
|
||||||
|
case kindTypedef:
|
||||||
|
case kindVolatile:
|
||||||
|
case kindConst:
|
||||||
|
case kindRestrict:
|
||||||
|
case kindFunc:
|
||||||
|
case kindFuncProto:
|
||||||
|
// sizeof(struct btf_param)
|
||||||
|
data = make([]byte, header.Vlen()*4*2)
|
||||||
|
case kindVar:
|
||||||
|
// sizeof(struct btf_variable)
|
||||||
|
data = make([]byte, 4)
|
||||||
|
case kindDatasec:
|
||||||
|
// sizeof(struct btf_var_secinfo)
|
||||||
|
data = make([]byte, header.Vlen()*4*3)
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("type id %v: unknown kind: %v", id, header.Kind())
|
||||||
|
}
|
||||||
|
|
||||||
|
if data == nil {
|
||||||
|
types = append(types, rawType{header, nil})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Read(r, bo, data); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "type id %d: kind %v: can't read %T", id, header.Kind(), data)
|
||||||
|
}
|
||||||
|
|
||||||
|
types = append(types, rawType{header, data})
|
||||||
|
}
|
||||||
|
}
|
8
vendor/github.com/cilium/ebpf/internal/btf/doc.go
generated
vendored
Normal file
8
vendor/github.com/cilium/ebpf/internal/btf/doc.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Package btf handles data encoded according to the BPF Type Format.
|
||||||
|
//
|
||||||
|
// The canonical documentation lives in the Linux kernel repository and is
|
||||||
|
// available at https://www.kernel.org/doc/html/latest/bpf/btf.html
|
||||||
|
//
|
||||||
|
// The API is very much unstable. You should only use this via the main
|
||||||
|
// ebpf library.
|
||||||
|
package btf
|
184
vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
generated
vendored
Normal file
184
vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package btf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf/asm"
|
||||||
|
"github.com/cilium/ebpf/internal"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type btfExtHeader struct {
|
||||||
|
Magic uint16
|
||||||
|
Version uint8
|
||||||
|
Flags uint8
|
||||||
|
HdrLen uint32
|
||||||
|
|
||||||
|
FuncInfoOff uint32
|
||||||
|
FuncInfoLen uint32
|
||||||
|
LineInfoOff uint32
|
||||||
|
LineInfoLen uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (funcInfo, lineInfo map[string]extInfo, err error) {
|
||||||
|
const expectedMagic = 0xeB9F
|
||||||
|
|
||||||
|
var header btfExtHeader
|
||||||
|
if err := binary.Read(r, bo, &header); err != nil {
|
||||||
|
return nil, nil, errors.Wrap(err, "can't read header")
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Magic != expectedMagic {
|
||||||
|
return nil, nil, errors.Errorf("incorrect magic value %v", header.Magic)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Version != 1 {
|
||||||
|
return nil, nil, errors.Errorf("unexpected version %v", header.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Flags != 0 {
|
||||||
|
return nil, nil, errors.Errorf("unsupported flags %v", header.Flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
remainder := int64(header.HdrLen) - int64(binary.Size(&header))
|
||||||
|
if remainder < 0 {
|
||||||
|
return nil, nil, errors.New("header is too short")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Of course, the .BTF.ext header has different semantics than the
|
||||||
|
// .BTF ext header. We need to ignore non-null values.
|
||||||
|
_, err = io.CopyN(ioutil.Discard, r, remainder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, errors.Wrap(err, "header padding")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := r.Seek(int64(header.HdrLen+header.FuncInfoOff), io.SeekStart); err != nil {
|
||||||
|
return nil, nil, errors.Wrap(err, "can't seek to function info section")
|
||||||
|
}
|
||||||
|
|
||||||
|
funcInfo, err = parseExtInfo(io.LimitReader(r, int64(header.FuncInfoLen)), bo, strings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, errors.Wrap(err, "function info")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := r.Seek(int64(header.HdrLen+header.LineInfoOff), io.SeekStart); err != nil {
|
||||||
|
return nil, nil, errors.Wrap(err, "can't seek to line info section")
|
||||||
|
}
|
||||||
|
|
||||||
|
lineInfo, err = parseExtInfo(io.LimitReader(r, int64(header.LineInfoLen)), bo, strings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, errors.Wrap(err, "line info")
|
||||||
|
}
|
||||||
|
|
||||||
|
return funcInfo, lineInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type btfExtInfoSec struct {
|
||||||
|
SecNameOff uint32
|
||||||
|
NumInfo uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type extInfoRecord struct {
|
||||||
|
InsnOff uint64
|
||||||
|
Opaque []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type extInfo struct {
|
||||||
|
recordSize uint32
|
||||||
|
records []extInfoRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
|
||||||
|
if other.recordSize != ei.recordSize {
|
||||||
|
return extInfo{}, errors.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
records := make([]extInfoRecord, 0, len(ei.records)+len(other.records))
|
||||||
|
records = append(records, ei.records...)
|
||||||
|
for _, info := range other.records {
|
||||||
|
records = append(records, extInfoRecord{
|
||||||
|
InsnOff: info.InsnOff + offset,
|
||||||
|
Opaque: info.Opaque,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return extInfo{ei.recordSize, records}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ei extInfo) MarshalBinary() ([]byte, error) {
|
||||||
|
if len(ei.records) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer(make([]byte, 0, int(ei.recordSize)*len(ei.records)))
|
||||||
|
for _, info := range ei.records {
|
||||||
|
// The kernel expects offsets in number of raw bpf instructions,
|
||||||
|
// while the ELF tracks it in bytes.
|
||||||
|
insnOff := uint32(info.InsnOff / asm.InstructionSize)
|
||||||
|
if err := binary.Write(buf, internal.NativeEndian, insnOff); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't write instruction offset")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.Write(info.Opaque)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[string]extInfo, error) {
|
||||||
|
var recordSize uint32
|
||||||
|
if err := binary.Read(r, bo, &recordSize); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't read record size")
|
||||||
|
}
|
||||||
|
|
||||||
|
if recordSize < 4 {
|
||||||
|
// Need at least insnOff
|
||||||
|
return nil, errors.New("record size too short")
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make(map[string]extInfo)
|
||||||
|
for {
|
||||||
|
var infoHeader btfExtInfoSec
|
||||||
|
if err := binary.Read(r, bo, &infoHeader); err == io.EOF {
|
||||||
|
return result, nil
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't read ext info header")
|
||||||
|
}
|
||||||
|
|
||||||
|
secName, err := strings.Lookup(infoHeader.SecNameOff)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't get section name")
|
||||||
|
}
|
||||||
|
|
||||||
|
if infoHeader.NumInfo == 0 {
|
||||||
|
return nil, errors.Errorf("section %s has invalid number of records", secName)
|
||||||
|
}
|
||||||
|
|
||||||
|
var records []extInfoRecord
|
||||||
|
for i := uint32(0); i < infoHeader.NumInfo; i++ {
|
||||||
|
var byteOff uint32
|
||||||
|
if err := binary.Read(r, bo, &byteOff); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "section %v: can't read extended info offset", secName)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, int(recordSize-4))
|
||||||
|
if _, err := io.ReadFull(r, buf); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "section %v: can't read record", secName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if byteOff%asm.InstructionSize != 0 {
|
||||||
|
return nil, errors.Errorf("section %v: offset %v is not aligned with instruction size", secName, byteOff)
|
||||||
|
}
|
||||||
|
|
||||||
|
records = append(records, extInfoRecord{uint64(byteOff), buf})
|
||||||
|
}
|
||||||
|
|
||||||
|
result[secName] = extInfo{
|
||||||
|
recordSize,
|
||||||
|
records,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
vendor/github.com/cilium/ebpf/internal/btf/strings.go
generated
vendored
Normal file
60
vendor/github.com/cilium/ebpf/internal/btf/strings.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package btf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type stringTable []byte
|
||||||
|
|
||||||
|
func readStringTable(r io.Reader) (stringTable, error) {
|
||||||
|
contents, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't read string table")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(contents) < 1 {
|
||||||
|
return nil, errors.New("string table is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if contents[0] != '\x00' {
|
||||||
|
return nil, errors.New("first item in string table is non-empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if contents[len(contents)-1] != '\x00' {
|
||||||
|
return nil, errors.New("string table isn't null terminated")
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringTable(contents), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st stringTable) Lookup(offset uint32) (string, error) {
|
||||||
|
if int64(offset) > int64(^uint(0)>>1) {
|
||||||
|
return "", errors.Errorf("offset %d overflows int", offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
pos := int(offset)
|
||||||
|
if pos >= len(st) {
|
||||||
|
return "", errors.Errorf("offset %d is out of bounds", offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pos > 0 && st[pos-1] != '\x00' {
|
||||||
|
return "", errors.Errorf("offset %d isn't start of a string", offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
str := st[pos:]
|
||||||
|
end := bytes.IndexByte(str, '\x00')
|
||||||
|
if end == -1 {
|
||||||
|
return "", errors.Errorf("offset %d isn't null terminated", offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(str[:end]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st stringTable) LookupName(offset uint32) (Name, error) {
|
||||||
|
str, err := st.Lookup(offset)
|
||||||
|
return Name(str), err
|
||||||
|
}
|
550
vendor/github.com/cilium/ebpf/internal/btf/types.go
generated
vendored
Normal file
550
vendor/github.com/cilium/ebpf/internal/btf/types.go
generated
vendored
Normal file
@ -0,0 +1,550 @@
|
|||||||
|
package btf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const maxTypeDepth = 32
|
||||||
|
|
||||||
|
// TypeID identifies a type in a BTF section.
|
||||||
|
type TypeID uint32
|
||||||
|
|
||||||
|
// ID implements part of the Type interface.
|
||||||
|
func (tid TypeID) ID() TypeID {
|
||||||
|
return tid
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type represents a type described by BTF.
|
||||||
|
type Type interface {
|
||||||
|
ID() TypeID
|
||||||
|
|
||||||
|
// Make a copy of the type, without copying Type members.
|
||||||
|
copy() Type
|
||||||
|
|
||||||
|
walk(*copyStack)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name identifies a type.
|
||||||
|
//
|
||||||
|
// Anonymous types have an empty name.
|
||||||
|
type Name string
|
||||||
|
|
||||||
|
func (n Name) name() string {
|
||||||
|
return string(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Void is the unit type of BTF.
|
||||||
|
type Void struct{}
|
||||||
|
|
||||||
|
func (v Void) ID() TypeID { return 0 }
|
||||||
|
func (v Void) copy() Type { return Void{} }
|
||||||
|
func (v Void) walk(*copyStack) {}
|
||||||
|
|
||||||
|
// Int is an integer of a given length.
|
||||||
|
type Int struct {
|
||||||
|
TypeID
|
||||||
|
Name
|
||||||
|
|
||||||
|
// The size of the integer in bytes.
|
||||||
|
Size uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Int) size() uint32 { return i.Size }
|
||||||
|
func (i *Int) walk(*copyStack) {}
|
||||||
|
func (i *Int) copy() Type {
|
||||||
|
cpy := *i
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pointer is a pointer to another type.
|
||||||
|
type Pointer struct {
|
||||||
|
TypeID
|
||||||
|
Target Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pointer) size() uint32 { return 8 }
|
||||||
|
func (p *Pointer) walk(cs *copyStack) { cs.push(&p.Target) }
|
||||||
|
func (p *Pointer) copy() Type {
|
||||||
|
cpy := *p
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Array is an array with a fixed number of elements.
|
||||||
|
type Array struct {
|
||||||
|
TypeID
|
||||||
|
Type Type
|
||||||
|
Nelems uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (arr *Array) walk(cs *copyStack) { cs.push(&arr.Type) }
|
||||||
|
func (arr *Array) copy() Type {
|
||||||
|
cpy := *arr
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Struct is a compound type of consecutive members.
|
||||||
|
type Struct struct {
|
||||||
|
TypeID
|
||||||
|
Name
|
||||||
|
// The size of the struct including padding, in bytes
|
||||||
|
Size uint32
|
||||||
|
Members []Member
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Struct) size() uint32 { return s.Size }
|
||||||
|
|
||||||
|
func (s *Struct) walk(cs *copyStack) {
|
||||||
|
for i := range s.Members {
|
||||||
|
cs.push(&s.Members[i].Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Struct) copy() Type {
|
||||||
|
cpy := *s
|
||||||
|
cpy.Members = copyMembers(cpy.Members)
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union is a compound type where members occupy the same memory.
|
||||||
|
type Union struct {
|
||||||
|
TypeID
|
||||||
|
Name
|
||||||
|
// The size of the union including padding, in bytes.
|
||||||
|
Size uint32
|
||||||
|
Members []Member
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Union) size() uint32 { return u.Size }
|
||||||
|
|
||||||
|
func (u *Union) walk(cs *copyStack) {
|
||||||
|
for i := range u.Members {
|
||||||
|
cs.push(&u.Members[i].Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Union) copy() Type {
|
||||||
|
cpy := *u
|
||||||
|
cpy.Members = copyMembers(cpy.Members)
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Member is part of a Struct or Union.
|
||||||
|
//
|
||||||
|
// It is not a valid Type.
|
||||||
|
type Member struct {
|
||||||
|
Name
|
||||||
|
Type Type
|
||||||
|
Offset uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyMembers(in []Member) []Member {
|
||||||
|
cpy := make([]Member, 0, len(in))
|
||||||
|
for _, member := range in {
|
||||||
|
cpy = append(cpy, member)
|
||||||
|
}
|
||||||
|
return cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enum lists possible values.
|
||||||
|
type Enum struct {
|
||||||
|
TypeID
|
||||||
|
Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Enum) size() uint32 { return 4 }
|
||||||
|
func (e *Enum) walk(*copyStack) {}
|
||||||
|
func (e *Enum) copy() Type {
|
||||||
|
cpy := *e
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fwd is a forward declaration of a Type.
|
||||||
|
type Fwd struct {
|
||||||
|
TypeID
|
||||||
|
Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fwd) walk(*copyStack) {}
|
||||||
|
func (f *Fwd) copy() Type {
|
||||||
|
cpy := *f
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typedef is an alias of a Type.
|
||||||
|
type Typedef struct {
|
||||||
|
TypeID
|
||||||
|
Name
|
||||||
|
Type Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (td *Typedef) walk(cs *copyStack) { cs.push(&td.Type) }
|
||||||
|
func (td *Typedef) copy() Type {
|
||||||
|
cpy := *td
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Volatile is a modifier.
|
||||||
|
type Volatile struct {
|
||||||
|
TypeID
|
||||||
|
Type Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Volatile) walk(cs *copyStack) { cs.push(&v.Type) }
|
||||||
|
func (v *Volatile) copy() Type {
|
||||||
|
cpy := *v
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Const is a modifier.
|
||||||
|
type Const struct {
|
||||||
|
TypeID
|
||||||
|
Type Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Const) walk(cs *copyStack) { cs.push(&c.Type) }
|
||||||
|
func (c *Const) copy() Type {
|
||||||
|
cpy := *c
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restrict is a modifier.
|
||||||
|
type Restrict struct {
|
||||||
|
TypeID
|
||||||
|
Type Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Restrict) walk(cs *copyStack) { cs.push(&r.Type) }
|
||||||
|
func (r *Restrict) copy() Type {
|
||||||
|
cpy := *r
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Func is a function definition.
|
||||||
|
type Func struct {
|
||||||
|
TypeID
|
||||||
|
Name
|
||||||
|
Type Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Func) walk(cs *copyStack) { cs.push(&f.Type) }
|
||||||
|
func (f *Func) copy() Type {
|
||||||
|
cpy := *f
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// FuncProto is a function declaration.
|
||||||
|
type FuncProto struct {
|
||||||
|
TypeID
|
||||||
|
Return Type
|
||||||
|
// Parameters not supported yet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fp *FuncProto) walk(cs *copyStack) { cs.push(&fp.Return) }
|
||||||
|
func (fp *FuncProto) copy() Type {
|
||||||
|
cpy := *fp
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Var is a global variable.
|
||||||
|
type Var struct {
|
||||||
|
TypeID
|
||||||
|
Name
|
||||||
|
Type Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Var) walk(cs *copyStack) { cs.push(&v.Type) }
|
||||||
|
func (v *Var) copy() Type {
|
||||||
|
cpy := *v
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Datasec is a global program section containing data.
|
||||||
|
type Datasec struct {
|
||||||
|
TypeID
|
||||||
|
Name
|
||||||
|
Size uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *Datasec) size() uint32 { return ds.Size }
|
||||||
|
func (ds *Datasec) walk(*copyStack) {}
|
||||||
|
func (ds *Datasec) copy() Type {
|
||||||
|
cpy := *ds
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
type sizer interface {
|
||||||
|
size() uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ sizer = (*Int)(nil)
|
||||||
|
_ sizer = (*Pointer)(nil)
|
||||||
|
_ sizer = (*Struct)(nil)
|
||||||
|
_ sizer = (*Union)(nil)
|
||||||
|
_ sizer = (*Enum)(nil)
|
||||||
|
_ sizer = (*Datasec)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sizeof returns the size of a type in bytes.
|
||||||
|
//
|
||||||
|
// Returns an error if the size can't be computed.
|
||||||
|
func Sizeof(typ Type) (int, error) {
|
||||||
|
var (
|
||||||
|
n = int64(1)
|
||||||
|
elem int64
|
||||||
|
)
|
||||||
|
|
||||||
|
for i := 0; i < maxTypeDepth; i++ {
|
||||||
|
switch v := typ.(type) {
|
||||||
|
case *Array:
|
||||||
|
if n > 0 && int64(v.Nelems) > math.MaxInt64/n {
|
||||||
|
return 0, errors.New("overflow")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arrays may be of zero length, which allows
|
||||||
|
// n to be zero as well.
|
||||||
|
n *= int64(v.Nelems)
|
||||||
|
typ = v.Type
|
||||||
|
continue
|
||||||
|
|
||||||
|
case sizer:
|
||||||
|
elem = int64(v.size())
|
||||||
|
|
||||||
|
case *Typedef:
|
||||||
|
typ = v.Type
|
||||||
|
continue
|
||||||
|
case *Volatile:
|
||||||
|
typ = v.Type
|
||||||
|
continue
|
||||||
|
case *Const:
|
||||||
|
typ = v.Type
|
||||||
|
continue
|
||||||
|
case *Restrict:
|
||||||
|
typ = v.Type
|
||||||
|
continue
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0, errors.Errorf("unrecognized type %T", typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n > 0 && elem > math.MaxInt64/n {
|
||||||
|
return 0, errors.New("overflow")
|
||||||
|
}
|
||||||
|
|
||||||
|
size := n * elem
|
||||||
|
if int64(int(size)) != size {
|
||||||
|
return 0, errors.New("overflow")
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(size), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, errors.New("exceeded type depth")
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy a Type recursively.
|
||||||
|
//
|
||||||
|
// typ may form a cycle.
|
||||||
|
func copyType(typ Type) Type {
|
||||||
|
var (
|
||||||
|
copies = make(map[Type]Type)
|
||||||
|
work copyStack
|
||||||
|
)
|
||||||
|
|
||||||
|
for t := &typ; t != nil; t = work.pop() {
|
||||||
|
// *t is the identity of the type.
|
||||||
|
if cpy := copies[*t]; cpy != nil {
|
||||||
|
*t = cpy
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cpy := (*t).copy()
|
||||||
|
copies[*t] = cpy
|
||||||
|
*t = cpy
|
||||||
|
|
||||||
|
// Mark any nested types for copying.
|
||||||
|
cpy.walk(&work)
|
||||||
|
}
|
||||||
|
|
||||||
|
return typ
|
||||||
|
}
|
||||||
|
|
||||||
|
// copyStack keeps track of pointers to types which still
|
||||||
|
// need to be copied.
|
||||||
|
type copyStack []*Type
|
||||||
|
|
||||||
|
// push adds a type to the stack.
|
||||||
|
func (cs *copyStack) push(t *Type) {
|
||||||
|
*cs = append(*cs, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// pop returns the topmost Type, or nil.
|
||||||
|
func (cs *copyStack) pop() *Type {
|
||||||
|
n := len(*cs)
|
||||||
|
if n == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
t := (*cs)[n-1]
|
||||||
|
*cs = (*cs)[:n-1]
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
type namer interface {
|
||||||
|
name() string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ namer = Name("")
|
||||||
|
|
||||||
|
// inflateRawTypes takes a list of raw btf types linked via type IDs, and turns
|
||||||
|
// it into a graph of Types connected via pointers.
|
||||||
|
//
|
||||||
|
// Returns a map of named types (so, where NameOff is non-zero). Since BTF ignores
|
||||||
|
// compilation units, multiple types may share the same name. A Type may form a
|
||||||
|
// cyclic graph by pointing at itself.
|
||||||
|
func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map[string][]Type, err error) {
|
||||||
|
type fixup struct {
|
||||||
|
id TypeID
|
||||||
|
typ *Type
|
||||||
|
}
|
||||||
|
|
||||||
|
var fixups []fixup
|
||||||
|
convertMembers := func(raw []btfMember) ([]Member, error) {
|
||||||
|
// NB: The fixup below relies on pre-allocating this array to
|
||||||
|
// work, since otherwise append might re-allocate members.
|
||||||
|
members := make([]Member, 0, len(raw))
|
||||||
|
for i, btfMember := range raw {
|
||||||
|
name, err := rawStrings.LookupName(btfMember.NameOff)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "can't get name for member %d", i)
|
||||||
|
}
|
||||||
|
members = append(members, Member{
|
||||||
|
Name: name,
|
||||||
|
Offset: btfMember.Offset,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for i := range members {
|
||||||
|
fixups = append(fixups, fixup{raw[i].Type, &members[i].Type})
|
||||||
|
}
|
||||||
|
return members, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
types := make([]Type, 0, len(rawTypes))
|
||||||
|
types = append(types, Void{})
|
||||||
|
namedTypes = make(map[string][]Type)
|
||||||
|
|
||||||
|
for i, raw := range rawTypes {
|
||||||
|
var (
|
||||||
|
// Void is defined to always be type ID 0, and is thus
|
||||||
|
// omitted from BTF.
|
||||||
|
id = TypeID(i + 1)
|
||||||
|
typ Type
|
||||||
|
)
|
||||||
|
|
||||||
|
name, err := rawStrings.LookupName(raw.NameOff)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "can't get name for type id %d", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch raw.Kind() {
|
||||||
|
case kindInt:
|
||||||
|
typ = &Int{id, name, raw.Size()}
|
||||||
|
|
||||||
|
case kindPointer:
|
||||||
|
ptr := &Pointer{id, nil}
|
||||||
|
fixups = append(fixups, fixup{raw.Type(), &ptr.Target})
|
||||||
|
typ = ptr
|
||||||
|
|
||||||
|
case kindArray:
|
||||||
|
btfArr := raw.data.(*btfArray)
|
||||||
|
|
||||||
|
// IndexType is unused according to btf.rst.
|
||||||
|
// Don't make it available right now.
|
||||||
|
arr := &Array{id, nil, btfArr.Nelems}
|
||||||
|
fixups = append(fixups, fixup{btfArr.Type, &arr.Type})
|
||||||
|
typ = arr
|
||||||
|
|
||||||
|
case kindStruct:
|
||||||
|
members, err := convertMembers(raw.data.([]btfMember))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "struct %s (id %d)", name, id)
|
||||||
|
}
|
||||||
|
typ = &Struct{id, name, raw.Size(), members}
|
||||||
|
|
||||||
|
case kindUnion:
|
||||||
|
members, err := convertMembers(raw.data.([]btfMember))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "union %s (id %d)", name, id)
|
||||||
|
}
|
||||||
|
typ = &Union{id, name, raw.Size(), members}
|
||||||
|
|
||||||
|
case kindEnum:
|
||||||
|
typ = &Enum{id, name}
|
||||||
|
|
||||||
|
case kindForward:
|
||||||
|
typ = &Fwd{id, name}
|
||||||
|
|
||||||
|
case kindTypedef:
|
||||||
|
typedef := &Typedef{id, name, nil}
|
||||||
|
fixups = append(fixups, fixup{raw.Type(), &typedef.Type})
|
||||||
|
typ = typedef
|
||||||
|
|
||||||
|
case kindVolatile:
|
||||||
|
volatile := &Volatile{id, nil}
|
||||||
|
fixups = append(fixups, fixup{raw.Type(), &volatile.Type})
|
||||||
|
typ = volatile
|
||||||
|
|
||||||
|
case kindConst:
|
||||||
|
cnst := &Const{id, nil}
|
||||||
|
fixups = append(fixups, fixup{raw.Type(), &cnst.Type})
|
||||||
|
typ = cnst
|
||||||
|
|
||||||
|
case kindRestrict:
|
||||||
|
restrict := &Restrict{id, nil}
|
||||||
|
fixups = append(fixups, fixup{raw.Type(), &restrict.Type})
|
||||||
|
typ = restrict
|
||||||
|
|
||||||
|
case kindFunc:
|
||||||
|
fn := &Func{id, name, nil}
|
||||||
|
fixups = append(fixups, fixup{raw.Type(), &fn.Type})
|
||||||
|
typ = fn
|
||||||
|
|
||||||
|
case kindFuncProto:
|
||||||
|
fp := &FuncProto{id, nil}
|
||||||
|
fixups = append(fixups, fixup{raw.Type(), &fp.Return})
|
||||||
|
typ = fp
|
||||||
|
|
||||||
|
case kindVar:
|
||||||
|
v := &Var{id, name, nil}
|
||||||
|
fixups = append(fixups, fixup{raw.Type(), &v.Type})
|
||||||
|
typ = v
|
||||||
|
|
||||||
|
case kindDatasec:
|
||||||
|
typ = &Datasec{id, name, raw.SizeType}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("type id %d: unknown kind: %v", id, raw.Kind())
|
||||||
|
}
|
||||||
|
|
||||||
|
types = append(types, typ)
|
||||||
|
|
||||||
|
if namer, ok := typ.(namer); ok {
|
||||||
|
if name := namer.name(); name != "" {
|
||||||
|
namedTypes[name] = append(namedTypes[name], typ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fixup := range fixups {
|
||||||
|
i := int(fixup.id)
|
||||||
|
if i >= len(types) {
|
||||||
|
return nil, errors.Errorf("reference to invalid type id: %d", fixup.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
*fixup.typ = types[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return namedTypes, nil
|
||||||
|
}
|
50
vendor/github.com/cilium/ebpf/internal/errors.go
generated
vendored
Normal file
50
vendor/github.com/cilium/ebpf/internal/errors.go
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrorWithLog returns an error that includes logs from the
|
||||||
|
// kernel verifier.
|
||||||
|
//
|
||||||
|
// logErr should be the error returned by the syscall that generated
|
||||||
|
// the log. It is used to check for truncation of the output.
|
||||||
|
func ErrorWithLog(err error, log []byte, logErr error) error {
|
||||||
|
logStr := strings.Trim(CString(log), "\t\r\n ")
|
||||||
|
if errors.Cause(logErr) == unix.ENOSPC {
|
||||||
|
logStr += " (truncated...)"
|
||||||
|
}
|
||||||
|
|
||||||
|
return &loadError{err, logStr}
|
||||||
|
}
|
||||||
|
|
||||||
|
type loadError struct {
|
||||||
|
cause error
|
||||||
|
log string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (le *loadError) Error() string {
|
||||||
|
if le.log == "" {
|
||||||
|
return le.cause.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s: %s", le.cause, le.log)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (le *loadError) Cause() error {
|
||||||
|
return le.cause
|
||||||
|
}
|
||||||
|
|
||||||
|
// CString turns a NUL / zero terminated byte buffer into a string.
|
||||||
|
func CString(in []byte) string {
|
||||||
|
inLen := bytes.IndexByte(in, 0)
|
||||||
|
if inLen == -1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(in[:inLen])
|
||||||
|
}
|
63
vendor/github.com/cilium/ebpf/internal/fd.go
generated
vendored
Normal file
63
vendor/github.com/cilium/ebpf/internal/fd.go
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrClosedFd = errors.New("use of closed file descriptor")
|
||||||
|
|
||||||
|
type FD struct {
|
||||||
|
raw int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFD(value uint32) *FD {
|
||||||
|
fd := &FD{int64(value)}
|
||||||
|
runtime.SetFinalizer(fd, (*FD).Close)
|
||||||
|
return fd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fd *FD) String() string {
|
||||||
|
return strconv.FormatInt(fd.raw, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fd *FD) Value() (uint32, error) {
|
||||||
|
if fd.raw < 0 {
|
||||||
|
return 0, ErrClosedFd
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint32(fd.raw), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fd *FD) Close() error {
|
||||||
|
if fd.raw < 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
value := int(fd.raw)
|
||||||
|
fd.raw = -1
|
||||||
|
|
||||||
|
fd.Forget()
|
||||||
|
return unix.Close(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fd *FD) Forget() {
|
||||||
|
runtime.SetFinalizer(fd, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fd *FD) Dup() (*FD, error) {
|
||||||
|
if fd.raw < 0 {
|
||||||
|
return nil, ErrClosedFd
|
||||||
|
}
|
||||||
|
|
||||||
|
dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't dup fd")
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewFD(uint32(dup)), nil
|
||||||
|
}
|
16
vendor/github.com/cilium/ebpf/internal/io.go
generated
vendored
Normal file
16
vendor/github.com/cilium/ebpf/internal/io.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import "github.com/pkg/errors"
|
||||||
|
|
||||||
|
// DiscardZeroes makes sure that all written bytes are zero
|
||||||
|
// before discarding them.
|
||||||
|
type DiscardZeroes struct{}
|
||||||
|
|
||||||
|
func (DiscardZeroes) Write(p []byte) (int, error) {
|
||||||
|
for _, b := range p {
|
||||||
|
if b != 0 {
|
||||||
|
return 0, errors.New("encountered non-zero byte")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(p), nil
|
||||||
|
}
|
26
vendor/github.com/cilium/ebpf/internal/ptr.go
generated
vendored
Normal file
26
vendor/github.com/cilium/ebpf/internal/ptr.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// NewPointer creates a 64-bit pointer from an unsafe Pointer.
|
||||||
|
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 {
|
||||||
|
if len(buf) == 0 {
|
||||||
|
return Pointer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pointer{ptr: unsafe.Pointer(&buf[0])}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStringPointer creates a 64-bit pointer from a string.
|
||||||
|
func NewStringPointer(str string) Pointer {
|
||||||
|
if str == "" {
|
||||||
|
return Pointer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pointer{ptr: unsafe.Pointer(&[]byte(str)[0])}
|
||||||
|
}
|
@ -1,14 +1,14 @@
|
|||||||
// +build armbe mips mips64p32
|
// +build armbe mips mips64p32
|
||||||
|
|
||||||
package ebpf
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ptr wraps an unsafe.Pointer to be 64bit to
|
// Pointer wraps an unsafe.Pointer to be 64bit to
|
||||||
// conform to the syscall specification.
|
// conform to the syscall specification.
|
||||||
type syscallPtr struct {
|
type Pointer struct {
|
||||||
pad uint32
|
pad uint32
|
||||||
ptr unsafe.Pointer
|
ptr unsafe.Pointer
|
||||||
}
|
}
|
@ -1,14 +1,14 @@
|
|||||||
// +build 386 amd64p32 arm mipsle mips64p32le
|
// +build 386 amd64p32 arm mipsle mips64p32le
|
||||||
|
|
||||||
package ebpf
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ptr wraps an unsafe.Pointer to be 64bit to
|
// Pointer wraps an unsafe.Pointer to be 64bit to
|
||||||
// conform to the syscall specification.
|
// conform to the syscall specification.
|
||||||
type syscallPtr struct {
|
type Pointer struct {
|
||||||
ptr unsafe.Pointer
|
ptr unsafe.Pointer
|
||||||
pad uint32
|
pad uint32
|
||||||
}
|
}
|
@ -1,14 +1,14 @@
|
|||||||
// +build !386,!amd64p32,!arm,!mipsle,!mips64p32le
|
// +build !386,!amd64p32,!arm,!mipsle,!mips64p32le
|
||||||
// +build !armbe,!mips,!mips64p32
|
// +build !armbe,!mips,!mips64p32
|
||||||
|
|
||||||
package ebpf
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ptr wraps an unsafe.Pointer to be 64bit to
|
// Pointer wraps an unsafe.Pointer to be 64bit to
|
||||||
// conform to the syscall specification.
|
// conform to the syscall specification.
|
||||||
type syscallPtr struct {
|
type Pointer struct {
|
||||||
ptr unsafe.Pointer
|
ptr unsafe.Pointer
|
||||||
}
|
}
|
23
vendor/github.com/cilium/ebpf/internal/syscall.go
generated
vendored
Normal file
23
vendor/github.com/cilium/ebpf/internal/syscall.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BPF wraps SYS_BPF.
|
||||||
|
//
|
||||||
|
// Any pointers contained in attr must use the Pointer type from this package.
|
||||||
|
func BPF(cmd int, attr unsafe.Pointer, size uintptr) (uintptr, error) {
|
||||||
|
r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size)
|
||||||
|
runtime.KeepAlive(attr)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if errNo != 0 {
|
||||||
|
err = errNo
|
||||||
|
}
|
||||||
|
|
||||||
|
return r1, err
|
||||||
|
}
|
28
vendor/github.com/cilium/ebpf/linker.go
generated
vendored
28
vendor/github.com/cilium/ebpf/linker.go
generated
vendored
@ -2,23 +2,35 @@ package ebpf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cilium/ebpf/asm"
|
"github.com/cilium/ebpf/asm"
|
||||||
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// link resolves bpf-to-bpf calls.
|
// link resolves bpf-to-bpf calls.
|
||||||
//
|
//
|
||||||
// Each section may contain multiple functions / labels, and is only linked
|
// Each library may contain multiple functions / labels, and is only linked
|
||||||
// if the program being edited references one of these functions.
|
// if the program being edited references one of these functions.
|
||||||
//
|
//
|
||||||
// Sections must not require linking themselves.
|
// Libraries must not require linking themselves.
|
||||||
func link(insns asm.Instructions, sections ...asm.Instructions) (asm.Instructions, error) {
|
func link(prog *ProgramSpec, libs []*ProgramSpec) error {
|
||||||
for _, section := range sections {
|
for _, lib := range libs {
|
||||||
var err error
|
insns, err := linkSection(prog.Instructions, lib.Instructions)
|
||||||
insns, err = linkSection(insns, section)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return errors.Wrapf(err, "linking %s", lib.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(insns) == len(prog.Instructions) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
prog.Instructions = insns
|
||||||
|
if prog.BTF != nil && lib.BTF != nil {
|
||||||
|
if err := btf.ProgramAppend(prog.BTF, lib.BTF); err != nil {
|
||||||
|
return errors.Wrapf(err, "linking BTF of %s", lib.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return insns, nil
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func linkSection(insns, section asm.Instructions) (asm.Instructions, error) {
|
func linkSection(insns, section asm.Instructions) (asm.Instructions, error) {
|
||||||
|
83
vendor/github.com/cilium/ebpf/map.go
generated
vendored
83
vendor/github.com/cilium/ebpf/map.go
generated
vendored
@ -2,9 +2,9 @@ package ebpf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -20,8 +20,12 @@ type MapSpec struct {
|
|||||||
ValueSize uint32
|
ValueSize uint32
|
||||||
MaxEntries uint32
|
MaxEntries uint32
|
||||||
Flags uint32
|
Flags uint32
|
||||||
|
|
||||||
// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
|
// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
|
||||||
InnerMap *MapSpec
|
InnerMap *MapSpec
|
||||||
|
|
||||||
|
// The BTF associated with this map.
|
||||||
|
BTF *btf.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *MapSpec) String() string {
|
func (ms *MapSpec) String() string {
|
||||||
@ -50,7 +54,7 @@ func (ms *MapSpec) Copy() *MapSpec {
|
|||||||
// if you require custom encoding.
|
// if you require custom encoding.
|
||||||
type Map struct {
|
type Map struct {
|
||||||
name string
|
name string
|
||||||
fd *bpfFD
|
fd *internal.FD
|
||||||
abi MapABI
|
abi MapABI
|
||||||
// Per CPU maps return values larger than the size in the spec
|
// Per CPU maps return values larger than the size in the spec
|
||||||
fullValueSize int
|
fullValueSize int
|
||||||
@ -63,11 +67,11 @@ func NewMapFromFD(fd int) (*Map, error) {
|
|||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
return nil, errors.New("invalid fd")
|
return nil, errors.New("invalid fd")
|
||||||
}
|
}
|
||||||
bpfFd := newBPFFD(uint32(fd))
|
bpfFd := internal.NewFD(uint32(fd))
|
||||||
|
|
||||||
name, abi, err := newMapABIFromFd(bpfFd)
|
name, abi, err := newMapABIFromFd(bpfFd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
bpfFd.forget()
|
bpfFd.Forget()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newMap(bpfFd, name, abi)
|
return newMap(bpfFd, name, abi)
|
||||||
@ -78,24 +82,37 @@ func NewMapFromFD(fd int) (*Map, error) {
|
|||||||
// Creating a map for the first time will perform feature detection
|
// Creating a map for the first time will perform feature detection
|
||||||
// by creating small, temporary maps.
|
// by creating small, temporary maps.
|
||||||
func NewMap(spec *MapSpec) (*Map, error) {
|
func NewMap(spec *MapSpec) (*Map, error) {
|
||||||
|
if spec.BTF == nil {
|
||||||
|
return newMapWithBTF(spec, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
handle, err := btf.NewHandle(btf.MapSpec(spec.BTF))
|
||||||
|
if err != nil && !btf.IsNotSupported(err) {
|
||||||
|
return nil, errors.Wrap(err, "can't load BTF")
|
||||||
|
}
|
||||||
|
|
||||||
|
return newMapWithBTF(spec, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMapWithBTF(spec *MapSpec, handle *btf.Handle) (*Map, error) {
|
||||||
if spec.Type != ArrayOfMaps && spec.Type != HashOfMaps {
|
if spec.Type != ArrayOfMaps && spec.Type != HashOfMaps {
|
||||||
return createMap(spec, nil)
|
return createMap(spec, nil, handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
if spec.InnerMap == nil {
|
if spec.InnerMap == nil {
|
||||||
return nil, errors.Errorf("%s requires InnerMap", spec.Type)
|
return nil, errors.Errorf("%s requires InnerMap", spec.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
template, err := createMap(spec.InnerMap, nil)
|
template, err := createMap(spec.InnerMap, nil, handle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer template.Close()
|
defer template.Close()
|
||||||
|
|
||||||
return createMap(spec, template.fd)
|
return createMap(spec, template.fd, handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMap(spec *MapSpec, inner *bpfFD) (*Map, error) {
|
func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, error) {
|
||||||
spec = spec.Copy()
|
spec = spec.Copy()
|
||||||
|
|
||||||
switch spec.Type {
|
switch spec.Type {
|
||||||
@ -140,12 +157,18 @@ func createMap(spec *MapSpec, inner *bpfFD) (*Map, error) {
|
|||||||
|
|
||||||
if inner != nil {
|
if inner != nil {
|
||||||
var err error
|
var err error
|
||||||
attr.innerMapFd, err = inner.value()
|
attr.innerMapFd, err = inner.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "map create")
|
return nil, errors.Wrap(err, "map create")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if handle != nil && spec.BTF != nil {
|
||||||
|
attr.btfFd = uint32(handle.FD())
|
||||||
|
attr.btfKeyTypeID = btf.MapKey(spec.BTF).ID()
|
||||||
|
attr.btfValueTypeID = btf.MapValue(spec.BTF).ID()
|
||||||
|
}
|
||||||
|
|
||||||
name, err := newBPFObjName(spec.Name)
|
name, err := newBPFObjName(spec.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "map create")
|
return nil, errors.Wrap(err, "map create")
|
||||||
@ -163,7 +186,7 @@ func createMap(spec *MapSpec, inner *bpfFD) (*Map, error) {
|
|||||||
return newMap(fd, spec.Name, newMapABIFromSpec(spec))
|
return newMap(fd, spec.Name, newMapABIFromSpec(spec))
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMap(fd *bpfFD, name string, abi *MapABI) (*Map, error) {
|
func newMap(fd *internal.FD, name string, abi *MapABI) (*Map, error) {
|
||||||
m := &Map{
|
m := &Map{
|
||||||
name,
|
name,
|
||||||
fd,
|
fd,
|
||||||
@ -251,12 +274,28 @@ func (m *Map) Lookup(key, valueOut interface{}) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LookupAndDelete retrieves and deletes a value from a Map.
|
||||||
|
func (m *Map) LookupAndDelete(key, valueOut interface{}) error {
|
||||||
|
valuePtr, valueBytes := makeBuffer(valueOut, m.fullValueSize)
|
||||||
|
|
||||||
|
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithMessage(err, "can't marshal key")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := bpfMapLookupAndDelete(m.fd, keyPtr, valuePtr); err != nil {
|
||||||
|
return errors.WithMessage(err, "lookup and delete and delete failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return unmarshalBytes(valueOut, valueBytes)
|
||||||
|
}
|
||||||
|
|
||||||
// LookupBytes gets a value from Map.
|
// LookupBytes gets a value from Map.
|
||||||
//
|
//
|
||||||
// Returns a nil value if a key doesn't exist.
|
// Returns a nil value if a key doesn't exist.
|
||||||
func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
|
func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
|
||||||
valueBytes := make([]byte, m.fullValueSize)
|
valueBytes := make([]byte, m.fullValueSize)
|
||||||
valuePtr := newPtr(unsafe.Pointer(&valueBytes[0]))
|
valuePtr := internal.NewSlicePointer(valueBytes)
|
||||||
|
|
||||||
err := m.lookup(key, valuePtr)
|
err := m.lookup(key, valuePtr)
|
||||||
if IsNotExist(err) {
|
if IsNotExist(err) {
|
||||||
@ -266,7 +305,7 @@ func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
|
|||||||
return valueBytes, err
|
return valueBytes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Map) lookup(key interface{}, valueOut syscallPtr) error {
|
func (m *Map) lookup(key interface{}, valueOut internal.Pointer) error {
|
||||||
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessage(err, "can't marshal key")
|
return errors.WithMessage(err, "can't marshal key")
|
||||||
@ -304,7 +343,7 @@ func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error {
|
|||||||
return errors.WithMessage(err, "can't marshal key")
|
return errors.WithMessage(err, "can't marshal key")
|
||||||
}
|
}
|
||||||
|
|
||||||
var valuePtr syscallPtr
|
var valuePtr internal.Pointer
|
||||||
if m.abi.Type.hasPerCPUValue() {
|
if m.abi.Type.hasPerCPUValue() {
|
||||||
valuePtr, err = marshalPerCPUValue(value, int(m.abi.ValueSize))
|
valuePtr, err = marshalPerCPUValue(value, int(m.abi.ValueSize))
|
||||||
} else {
|
} else {
|
||||||
@ -355,7 +394,7 @@ func (m *Map) NextKey(key, nextKeyOut interface{}) error {
|
|||||||
// Use Iterate if you want to traverse all entries in the map.
|
// Use Iterate if you want to traverse all entries in the map.
|
||||||
func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) {
|
func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) {
|
||||||
nextKey := make([]byte, m.abi.KeySize)
|
nextKey := make([]byte, m.abi.KeySize)
|
||||||
nextKeyPtr := newPtr(unsafe.Pointer(&nextKey[0]))
|
nextKeyPtr := internal.NewSlicePointer(nextKey)
|
||||||
|
|
||||||
err := m.nextKey(key, nextKeyPtr)
|
err := m.nextKey(key, nextKeyPtr)
|
||||||
if IsNotExist(err) {
|
if IsNotExist(err) {
|
||||||
@ -365,9 +404,9 @@ func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) {
|
|||||||
return nextKey, err
|
return nextKey, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Map) nextKey(key interface{}, nextKeyOut syscallPtr) error {
|
func (m *Map) nextKey(key interface{}, nextKeyOut internal.Pointer) error {
|
||||||
var (
|
var (
|
||||||
keyPtr syscallPtr
|
keyPtr internal.Pointer
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -400,14 +439,14 @@ func (m *Map) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.fd.close()
|
return m.fd.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FD gets the file descriptor of the Map.
|
// FD gets the file descriptor of the Map.
|
||||||
//
|
//
|
||||||
// Calling this function is invalid after Close has been called.
|
// Calling this function is invalid after Close has been called.
|
||||||
func (m *Map) FD() int {
|
func (m *Map) FD() int {
|
||||||
fd, err := m.fd.value()
|
fd, err := m.fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Best effort: -1 is the number most likely to be an
|
// Best effort: -1 is the number most likely to be an
|
||||||
// invalid file descriptor.
|
// invalid file descriptor.
|
||||||
@ -428,7 +467,7 @@ func (m *Map) Clone() (*Map, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
dup, err := m.fd.dup()
|
dup, err := m.fd.Dup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't clone map")
|
return nil, errors.Wrap(err, "can't clone map")
|
||||||
}
|
}
|
||||||
@ -454,7 +493,7 @@ func LoadPinnedMap(fileName string) (*Map, error) {
|
|||||||
}
|
}
|
||||||
name, abi, err := newMapABIFromFd(fd)
|
name, abi, err := newMapABIFromFd(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = fd.close()
|
_ = fd.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newMap(fd, name, abi)
|
return newMap(fd, name, abi)
|
||||||
@ -484,7 +523,7 @@ func unmarshalMap(buf []byte) (*Map, error) {
|
|||||||
|
|
||||||
name, abi, err := newMapABIFromFd(fd)
|
name, abi, err := newMapABIFromFd(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = fd.close()
|
_ = fd.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,7 +532,7 @@ func unmarshalMap(buf []byte) (*Map, error) {
|
|||||||
|
|
||||||
// MarshalBinary implements BinaryMarshaler.
|
// MarshalBinary implements BinaryMarshaler.
|
||||||
func (m *Map) MarshalBinary() ([]byte, error) {
|
func (m *Map) MarshalBinary() ([]byte, error) {
|
||||||
fd, err := m.fd.value()
|
fd, err := m.fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
33
vendor/github.com/cilium/ebpf/marshalers.go
generated
vendored
33
vendor/github.com/cilium/ebpf/marshalers.go
generated
vendored
@ -13,17 +13,24 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func marshalPtr(data interface{}, length int) (syscallPtr, error) {
|
func marshalPtr(data interface{}, length int) (internal.Pointer, error) {
|
||||||
|
if data == nil {
|
||||||
|
if length == 0 {
|
||||||
|
return internal.NewPointer(nil), nil
|
||||||
|
}
|
||||||
|
return internal.Pointer{}, errors.New("can't use nil as key of map")
|
||||||
|
}
|
||||||
|
|
||||||
if ptr, ok := data.(unsafe.Pointer); ok {
|
if ptr, ok := data.(unsafe.Pointer); ok {
|
||||||
return newPtr(ptr), nil
|
return internal.NewPointer(ptr), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, err := marshalBytes(data, length)
|
buf, err := marshalBytes(data, length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return syscallPtr{}, err
|
return internal.Pointer{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return newPtr(unsafe.Pointer(&buf[0])), nil
|
return internal.NewSlicePointer(buf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshalBytes(data interface{}, length int) (buf []byte, err error) {
|
func marshalBytes(data interface{}, length int) (buf []byte, err error) {
|
||||||
@ -52,13 +59,13 @@ func marshalBytes(data interface{}, length int) (buf []byte, err error) {
|
|||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeBuffer(dst interface{}, length int) (syscallPtr, []byte) {
|
func makeBuffer(dst interface{}, length int) (internal.Pointer, []byte) {
|
||||||
if ptr, ok := dst.(unsafe.Pointer); ok {
|
if ptr, ok := dst.(unsafe.Pointer); ok {
|
||||||
return newPtr(ptr), nil
|
return internal.NewPointer(ptr), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, length)
|
buf := make([]byte, length)
|
||||||
return newPtr(unsafe.Pointer(&buf[0])), buf
|
return internal.NewSlicePointer(buf), buf
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalBytes(data interface{}, buf []byte) error {
|
func unmarshalBytes(data interface{}, buf []byte) error {
|
||||||
@ -99,21 +106,21 @@ func unmarshalBytes(data interface{}, buf []byte) error {
|
|||||||
// Values are initialized to zero if the slice has less elements than CPUs.
|
// Values are initialized to zero if the slice has less elements than CPUs.
|
||||||
//
|
//
|
||||||
// slice must have a type like []elementType.
|
// slice must have a type like []elementType.
|
||||||
func marshalPerCPUValue(slice interface{}, elemLength int) (syscallPtr, error) {
|
func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, error) {
|
||||||
sliceType := reflect.TypeOf(slice)
|
sliceType := reflect.TypeOf(slice)
|
||||||
if sliceType.Kind() != reflect.Slice {
|
if sliceType.Kind() != reflect.Slice {
|
||||||
return syscallPtr{}, errors.New("per-CPU value requires slice")
|
return internal.Pointer{}, errors.New("per-CPU value requires slice")
|
||||||
}
|
}
|
||||||
|
|
||||||
possibleCPUs, err := internal.PossibleCPUs()
|
possibleCPUs, err := internal.PossibleCPUs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return syscallPtr{}, err
|
return internal.Pointer{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sliceValue := reflect.ValueOf(slice)
|
sliceValue := reflect.ValueOf(slice)
|
||||||
sliceLen := sliceValue.Len()
|
sliceLen := sliceValue.Len()
|
||||||
if sliceLen > possibleCPUs {
|
if sliceLen > possibleCPUs {
|
||||||
return syscallPtr{}, errors.Errorf("per-CPU value exceeds number of CPUs")
|
return internal.Pointer{}, errors.Errorf("per-CPU value exceeds number of CPUs")
|
||||||
}
|
}
|
||||||
|
|
||||||
alignedElemLength := align(elemLength, 8)
|
alignedElemLength := align(elemLength, 8)
|
||||||
@ -123,14 +130,14 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (syscallPtr, error) {
|
|||||||
elem := sliceValue.Index(i).Interface()
|
elem := sliceValue.Index(i).Interface()
|
||||||
elemBytes, err := marshalBytes(elem, elemLength)
|
elemBytes, err := marshalBytes(elem, elemLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return syscallPtr{}, err
|
return internal.Pointer{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
offset := i * alignedElemLength
|
offset := i * alignedElemLength
|
||||||
copy(buf[offset:offset+elemLength], elemBytes)
|
copy(buf[offset:offset+elemLength], elemBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newPtr(unsafe.Pointer(&buf[0])), nil
|
return internal.NewSlicePointer(buf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// unmarshalPerCPUValue decodes a buffer into a slice containing one value per
|
// unmarshalPerCPUValue decodes a buffer into a slice containing one value per
|
||||||
|
120
vendor/github.com/cilium/ebpf/prog.go
generated
vendored
120
vendor/github.com/cilium/ebpf/prog.go
generated
vendored
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/cilium/ebpf/asm"
|
"github.com/cilium/ebpf/asm"
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -46,6 +47,11 @@ type ProgramSpec struct {
|
|||||||
Instructions asm.Instructions
|
Instructions asm.Instructions
|
||||||
License string
|
License string
|
||||||
KernelVersion uint32
|
KernelVersion uint32
|
||||||
|
|
||||||
|
// The BTF associated with this program. Changing Instructions
|
||||||
|
// will most likely invalidate the contained data, and may
|
||||||
|
// result in errors when attempting to load it into the kernel.
|
||||||
|
BTF *btf.Program
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a copy of the spec.
|
// Copy returns a copy of the spec.
|
||||||
@ -68,7 +74,7 @@ type Program struct {
|
|||||||
// otherwise it is empty.
|
// otherwise it is empty.
|
||||||
VerifierLog string
|
VerifierLog string
|
||||||
|
|
||||||
fd *bpfFD
|
fd *internal.FD
|
||||||
name string
|
name string
|
||||||
abi ProgramABI
|
abi ProgramABI
|
||||||
}
|
}
|
||||||
@ -86,7 +92,20 @@ func NewProgram(spec *ProgramSpec) (*Program, error) {
|
|||||||
// Loading a program for the first time will perform
|
// Loading a program for the first time will perform
|
||||||
// feature detection by loading small, temporary programs.
|
// feature detection by loading small, temporary programs.
|
||||||
func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, error) {
|
func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, error) {
|
||||||
attr, err := convertProgramSpec(spec)
|
if spec.BTF == nil {
|
||||||
|
return newProgramWithBTF(spec, nil, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
handle, err := btf.NewHandle(btf.ProgramSpec(spec.BTF))
|
||||||
|
if err != nil && !btf.IsNotSupported(err) {
|
||||||
|
return nil, errors.Wrap(err, "can't load BTF")
|
||||||
|
}
|
||||||
|
|
||||||
|
return newProgramWithBTF(spec, handle, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newProgramWithBTF(spec *ProgramSpec, btf *btf.Handle, opts ProgramOptions) (*Program, error) {
|
||||||
|
attr, err := convertProgramSpec(spec, btf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -101,34 +120,28 @@ func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er
|
|||||||
logBuf = make([]byte, logSize)
|
logBuf = make([]byte, logSize)
|
||||||
attr.logLevel = opts.LogLevel
|
attr.logLevel = opts.LogLevel
|
||||||
attr.logSize = uint32(len(logBuf))
|
attr.logSize = uint32(len(logBuf))
|
||||||
attr.logBuf = newPtr(unsafe.Pointer(&logBuf[0]))
|
attr.logBuf = internal.NewSlicePointer(logBuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := bpfProgLoad(attr)
|
fd, err := bpfProgLoad(attr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
prog := newProgram(fd, spec.Name, &ProgramABI{spec.Type})
|
prog := newProgram(fd, spec.Name, &ProgramABI{spec.Type})
|
||||||
prog.VerifierLog = convertCString(logBuf)
|
prog.VerifierLog = internal.CString(logBuf)
|
||||||
return prog, nil
|
return prog, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
truncated := errors.Cause(err) == unix.ENOSPC
|
|
||||||
if opts.LogLevel == 0 {
|
if opts.LogLevel == 0 {
|
||||||
// Re-run with the verifier enabled to get better error messages.
|
// Re-run with the verifier enabled to get better error messages.
|
||||||
logBuf = make([]byte, logSize)
|
logBuf = make([]byte, logSize)
|
||||||
attr.logLevel = 1
|
attr.logLevel = 1
|
||||||
attr.logSize = uint32(len(logBuf))
|
attr.logSize = uint32(len(logBuf))
|
||||||
attr.logBuf = newPtr(unsafe.Pointer(&logBuf[0]))
|
attr.logBuf = internal.NewSlicePointer(logBuf)
|
||||||
|
|
||||||
_, nerr := bpfProgLoad(attr)
|
_, logErr := bpfProgLoad(attr)
|
||||||
truncated = errors.Cause(nerr) == unix.ENOSPC
|
err = internal.ErrorWithLog(err, logBuf, logErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
logs := convertCString(logBuf)
|
return nil, errors.Wrap(err, "can't load program")
|
||||||
if truncated {
|
|
||||||
logs += "\n(truncated...)"
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, &loadError{err, logs}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProgramFromFD creates a program from a raw fd.
|
// NewProgramFromFD creates a program from a raw fd.
|
||||||
@ -140,18 +153,18 @@ func NewProgramFromFD(fd int) (*Program, error) {
|
|||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
return nil, errors.New("invalid fd")
|
return nil, errors.New("invalid fd")
|
||||||
}
|
}
|
||||||
bpfFd := newBPFFD(uint32(fd))
|
bpfFd := internal.NewFD(uint32(fd))
|
||||||
|
|
||||||
name, abi, err := newProgramABIFromFd(bpfFd)
|
name, abi, err := newProgramABIFromFd(bpfFd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
bpfFd.forget()
|
bpfFd.Forget()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return newProgram(bpfFd, name, abi), nil
|
return newProgram(bpfFd, name, abi), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newProgram(fd *bpfFD, name string, abi *ProgramABI) *Program {
|
func newProgram(fd *internal.FD, name string, abi *ProgramABI) *Program {
|
||||||
return &Program{
|
return &Program{
|
||||||
name: name,
|
name: name,
|
||||||
fd: fd,
|
fd: fd,
|
||||||
@ -159,7 +172,7 @@ func newProgram(fd *bpfFD, name string, abi *ProgramABI) *Program {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertProgramSpec(spec *ProgramSpec) (*bpfProgLoadAttr, error) {
|
func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr, error) {
|
||||||
if len(spec.Instructions) == 0 {
|
if len(spec.Instructions) == 0 {
|
||||||
return nil, errors.New("Instructions cannot be empty")
|
return nil, errors.New("Instructions cannot be empty")
|
||||||
}
|
}
|
||||||
@ -176,13 +189,12 @@ func convertProgramSpec(spec *ProgramSpec) (*bpfProgLoadAttr, error) {
|
|||||||
|
|
||||||
bytecode := buf.Bytes()
|
bytecode := buf.Bytes()
|
||||||
insCount := uint32(len(bytecode) / asm.InstructionSize)
|
insCount := uint32(len(bytecode) / asm.InstructionSize)
|
||||||
lic := []byte(spec.License)
|
|
||||||
attr := &bpfProgLoadAttr{
|
attr := &bpfProgLoadAttr{
|
||||||
progType: spec.Type,
|
progType: spec.Type,
|
||||||
expectedAttachType: spec.AttachType,
|
expectedAttachType: spec.AttachType,
|
||||||
insCount: insCount,
|
insCount: insCount,
|
||||||
instructions: newPtr(unsafe.Pointer(&bytecode[0])),
|
instructions: internal.NewSlicePointer(bytecode),
|
||||||
license: newPtr(unsafe.Pointer(&lic[0])),
|
license: internal.NewStringPointer(spec.License),
|
||||||
}
|
}
|
||||||
|
|
||||||
name, err := newBPFObjName(spec.Name)
|
name, err := newBPFObjName(spec.Name)
|
||||||
@ -194,6 +206,26 @@ func convertProgramSpec(spec *ProgramSpec) (*bpfProgLoadAttr, error) {
|
|||||||
attr.progName = name
|
attr.progName = name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if handle != nil && spec.BTF != nil {
|
||||||
|
attr.progBTFFd = uint32(handle.FD())
|
||||||
|
|
||||||
|
recSize, bytes, err := btf.ProgramLineInfos(spec.BTF)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't get BTF line infos")
|
||||||
|
}
|
||||||
|
attr.lineInfoRecSize = recSize
|
||||||
|
attr.lineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
|
||||||
|
attr.lineInfo = internal.NewSlicePointer(bytes)
|
||||||
|
|
||||||
|
recSize, bytes, err = btf.ProgramFuncInfos(spec.BTF)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "can't get BTF function infos")
|
||||||
|
}
|
||||||
|
attr.funcInfoRecSize = recSize
|
||||||
|
attr.funcInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
|
||||||
|
attr.funcInfo = internal.NewSlicePointer(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
return attr, nil
|
return attr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +245,7 @@ func (p *Program) ABI() ProgramABI {
|
|||||||
//
|
//
|
||||||
// It is invalid to call this function after Close has been called.
|
// It is invalid to call this function after Close has been called.
|
||||||
func (p *Program) FD() int {
|
func (p *Program) FD() int {
|
||||||
fd, err := p.fd.value()
|
fd, err := p.fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Best effort: -1 is the number most likely to be an
|
// Best effort: -1 is the number most likely to be an
|
||||||
// invalid file descriptor.
|
// invalid file descriptor.
|
||||||
@ -233,7 +265,7 @@ func (p *Program) Clone() (*Program, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
dup, err := p.fd.dup()
|
dup, err := p.fd.Dup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't clone program")
|
return nil, errors.Wrap(err, "can't clone program")
|
||||||
}
|
}
|
||||||
@ -254,7 +286,7 @@ func (p *Program) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.fd.close()
|
return p.fd.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test runs the Program in the kernel with the given input and returns the
|
// Test runs the Program in the kernel with the given input and returns the
|
||||||
@ -296,7 +328,7 @@ var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() b
|
|||||||
}
|
}
|
||||||
defer prog.Close()
|
defer prog.Close()
|
||||||
|
|
||||||
fd, err := prog.fd.value()
|
fd, err := prog.fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -306,10 +338,10 @@ var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() b
|
|||||||
attr := bpfProgTestRunAttr{
|
attr := bpfProgTestRunAttr{
|
||||||
fd: fd,
|
fd: fd,
|
||||||
dataSizeIn: uint32(len(in)),
|
dataSizeIn: uint32(len(in)),
|
||||||
dataIn: newPtr(unsafe.Pointer(&in[0])),
|
dataIn: internal.NewSlicePointer(in),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = bpfCall(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
|
|
||||||
// Check for EINVAL specifically, rather than err != nil since we
|
// Check for EINVAL specifically, rather than err != nil since we
|
||||||
// otherwise misdetect due to insufficient permissions.
|
// otherwise misdetect due to insufficient permissions.
|
||||||
@ -340,7 +372,7 @@ func (p *Program) testRun(in []byte, repeat int) (uint32, []byte, time.Duration,
|
|||||||
// See https://patchwork.ozlabs.org/cover/1006822/
|
// See https://patchwork.ozlabs.org/cover/1006822/
|
||||||
out := make([]byte, len(in)+outputPad)
|
out := make([]byte, len(in)+outputPad)
|
||||||
|
|
||||||
fd, err := p.fd.value()
|
fd, err := p.fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, 0, err
|
return 0, nil, 0, err
|
||||||
}
|
}
|
||||||
@ -349,12 +381,12 @@ func (p *Program) testRun(in []byte, repeat int) (uint32, []byte, time.Duration,
|
|||||||
fd: fd,
|
fd: fd,
|
||||||
dataSizeIn: uint32(len(in)),
|
dataSizeIn: uint32(len(in)),
|
||||||
dataSizeOut: uint32(len(out)),
|
dataSizeOut: uint32(len(out)),
|
||||||
dataIn: newPtr(unsafe.Pointer(&in[0])),
|
dataIn: internal.NewSlicePointer(in),
|
||||||
dataOut: newPtr(unsafe.Pointer(&out[0])),
|
dataOut: internal.NewSlicePointer(out),
|
||||||
repeat: uint32(repeat),
|
repeat: uint32(repeat),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = bpfCall(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, 0, errors.Wrap(err, "can't run test")
|
return 0, nil, 0, errors.Wrap(err, "can't run test")
|
||||||
}
|
}
|
||||||
@ -385,7 +417,7 @@ func unmarshalProgram(buf []byte) (*Program, error) {
|
|||||||
|
|
||||||
name, abi, err := newProgramABIFromFd(fd)
|
name, abi, err := newProgramABIFromFd(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = fd.close()
|
_ = fd.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +426,7 @@ func unmarshalProgram(buf []byte) (*Program, error) {
|
|||||||
|
|
||||||
// MarshalBinary implements BinaryMarshaler.
|
// MarshalBinary implements BinaryMarshaler.
|
||||||
func (p *Program) MarshalBinary() ([]byte, error) {
|
func (p *Program) MarshalBinary() ([]byte, error) {
|
||||||
value, err := p.fd.value()
|
value, err := p.fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -410,7 +442,7 @@ func (p *Program) Attach(fd int, typ AttachType, flags AttachFlags) error {
|
|||||||
return errors.New("invalid fd")
|
return errors.New("invalid fd")
|
||||||
}
|
}
|
||||||
|
|
||||||
pfd, err := p.fd.value()
|
pfd, err := p.fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -431,7 +463,7 @@ func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error {
|
|||||||
return errors.New("invalid fd")
|
return errors.New("invalid fd")
|
||||||
}
|
}
|
||||||
|
|
||||||
pfd, err := p.fd.value()
|
pfd, err := p.fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -457,7 +489,7 @@ func LoadPinnedProgram(fileName string) (*Program, error) {
|
|||||||
|
|
||||||
name, abi, err := newProgramABIFromFd(fd)
|
name, abi, err := newProgramABIFromFd(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = fd.close()
|
_ = fd.Close()
|
||||||
return nil, errors.Wrapf(err, "can't get ABI for %s", fileName)
|
return nil, errors.Wrapf(err, "can't get ABI for %s", fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,22 +512,6 @@ func SanitizeName(name string, replacement rune) string {
|
|||||||
}, name)
|
}, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
type loadError struct {
|
|
||||||
cause error
|
|
||||||
verifierLog string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (le *loadError) Error() string {
|
|
||||||
if le.verifierLog == "" {
|
|
||||||
return fmt.Sprintf("failed to load program: %s", le.cause)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("failed to load program: %s: %s", le.cause, le.verifierLog)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (le *loadError) Cause() error {
|
|
||||||
return le.cause
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotSupported returns true if an error occurred because
|
// IsNotSupported returns true if an error occurred because
|
||||||
// the kernel does not have support for a specific feature.
|
// the kernel does not have support for a specific feature.
|
||||||
func IsNotSupported(err error) bool {
|
func IsNotSupported(err error) bool {
|
||||||
|
219
vendor/github.com/cilium/ebpf/syscalls.go
generated
vendored
219
vendor/github.com/cilium/ebpf/syscalls.go
generated
vendored
@ -1,72 +1,17 @@
|
|||||||
package ebpf
|
package ebpf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errClosedFd = errors.New("use of closed file descriptor")
|
|
||||||
|
|
||||||
type bpfFD struct {
|
|
||||||
raw int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBPFFD(value uint32) *bpfFD {
|
|
||||||
fd := &bpfFD{int64(value)}
|
|
||||||
runtime.SetFinalizer(fd, (*bpfFD).close)
|
|
||||||
return fd
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fd *bpfFD) String() string {
|
|
||||||
return strconv.FormatInt(fd.raw, 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fd *bpfFD) value() (uint32, error) {
|
|
||||||
if fd.raw < 0 {
|
|
||||||
return 0, errClosedFd
|
|
||||||
}
|
|
||||||
|
|
||||||
return uint32(fd.raw), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fd *bpfFD) close() error {
|
|
||||||
if fd.raw < 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
value := int(fd.raw)
|
|
||||||
fd.raw = -1
|
|
||||||
|
|
||||||
fd.forget()
|
|
||||||
return unix.Close(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fd *bpfFD) forget() {
|
|
||||||
runtime.SetFinalizer(fd, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fd *bpfFD) dup() (*bpfFD, error) {
|
|
||||||
if fd.raw < 0 {
|
|
||||||
return nil, errClosedFd
|
|
||||||
}
|
|
||||||
|
|
||||||
dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "can't dup fd")
|
|
||||||
}
|
|
||||||
|
|
||||||
return newBPFFD(uint32(dup)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// bpfObjName is a null-terminated string made up of
|
// bpfObjName is a null-terminated string made up of
|
||||||
// 'A-Za-z0-9_' characters.
|
// 'A-Za-z0-9_' characters.
|
||||||
type bpfObjName [unix.BPF_OBJ_NAME_LEN]byte
|
type bpfObjName [unix.BPF_OBJ_NAME_LEN]byte
|
||||||
@ -107,13 +52,17 @@ type bpfMapCreateAttr struct {
|
|||||||
innerMapFd uint32 // since 4.12 56f668dfe00d
|
innerMapFd uint32 // since 4.12 56f668dfe00d
|
||||||
numaNode uint32 // since 4.14 96eabe7a40aa
|
numaNode uint32 // since 4.14 96eabe7a40aa
|
||||||
mapName bpfObjName // since 4.15 ad5b177bd73f
|
mapName bpfObjName // since 4.15 ad5b177bd73f
|
||||||
|
mapIfIndex uint32
|
||||||
|
btfFd uint32
|
||||||
|
btfKeyTypeID btf.TypeID
|
||||||
|
btfValueTypeID btf.TypeID
|
||||||
}
|
}
|
||||||
|
|
||||||
type bpfMapOpAttr struct {
|
type bpfMapOpAttr struct {
|
||||||
mapFd uint32
|
mapFd uint32
|
||||||
padding uint32
|
padding uint32
|
||||||
key syscallPtr
|
key internal.Pointer
|
||||||
value syscallPtr
|
value internal.Pointer
|
||||||
flags uint64
|
flags uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +77,7 @@ type bpfMapInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type bpfPinObjAttr struct {
|
type bpfPinObjAttr struct {
|
||||||
fileName syscallPtr
|
fileName internal.Pointer
|
||||||
fd uint32
|
fd uint32
|
||||||
padding uint32
|
padding uint32
|
||||||
}
|
}
|
||||||
@ -136,16 +85,23 @@ type bpfPinObjAttr struct {
|
|||||||
type bpfProgLoadAttr struct {
|
type bpfProgLoadAttr struct {
|
||||||
progType ProgramType
|
progType ProgramType
|
||||||
insCount uint32
|
insCount uint32
|
||||||
instructions syscallPtr
|
instructions internal.Pointer
|
||||||
license syscallPtr
|
license internal.Pointer
|
||||||
logLevel uint32
|
logLevel uint32
|
||||||
logSize uint32
|
logSize uint32
|
||||||
logBuf syscallPtr
|
logBuf internal.Pointer
|
||||||
kernelVersion uint32 // since 4.1 2541517c32be
|
kernelVersion uint32 // since 4.1 2541517c32be
|
||||||
progFlags uint32 // since 4.11 e07b98d9bffe
|
progFlags uint32 // since 4.11 e07b98d9bffe
|
||||||
progName bpfObjName // since 4.15 067cae47771c
|
progName bpfObjName // since 4.15 067cae47771c
|
||||||
progIfIndex uint32 // since 4.15 1f6f4cb7ba21
|
progIfIndex uint32 // since 4.15 1f6f4cb7ba21
|
||||||
expectedAttachType AttachType // since 4.17 5e43f899b03a
|
expectedAttachType AttachType // since 4.17 5e43f899b03a
|
||||||
|
progBTFFd uint32
|
||||||
|
funcInfoRecSize uint32
|
||||||
|
funcInfo internal.Pointer
|
||||||
|
funcInfoCnt uint32
|
||||||
|
lineInfoRecSize uint32
|
||||||
|
lineInfo internal.Pointer
|
||||||
|
lineInfoCnt uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type bpfProgInfo struct {
|
type bpfProgInfo struct {
|
||||||
@ -154,12 +110,12 @@ type bpfProgInfo struct {
|
|||||||
tag [unix.BPF_TAG_SIZE]byte
|
tag [unix.BPF_TAG_SIZE]byte
|
||||||
jitedLen uint32
|
jitedLen uint32
|
||||||
xlatedLen uint32
|
xlatedLen uint32
|
||||||
jited syscallPtr
|
jited internal.Pointer
|
||||||
xlated syscallPtr
|
xlated internal.Pointer
|
||||||
loadTime uint64 // since 4.15 cb4d2b3f03d8
|
loadTime uint64 // since 4.15 cb4d2b3f03d8
|
||||||
createdByUID uint32
|
createdByUID uint32
|
||||||
nrMapIDs uint32
|
nrMapIDs uint32
|
||||||
mapIds syscallPtr
|
mapIds internal.Pointer
|
||||||
name bpfObjName
|
name bpfObjName
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,8 +124,8 @@ type bpfProgTestRunAttr struct {
|
|||||||
retval uint32
|
retval uint32
|
||||||
dataSizeIn uint32
|
dataSizeIn uint32
|
||||||
dataSizeOut uint32
|
dataSizeOut uint32
|
||||||
dataIn syscallPtr
|
dataIn internal.Pointer
|
||||||
dataOut syscallPtr
|
dataOut internal.Pointer
|
||||||
repeat uint32
|
repeat uint32
|
||||||
duration uint32
|
duration uint32
|
||||||
}
|
}
|
||||||
@ -184,7 +140,7 @@ type bpfProgAlterAttr struct {
|
|||||||
type bpfObjGetInfoByFDAttr struct {
|
type bpfObjGetInfoByFDAttr struct {
|
||||||
fd uint32
|
fd uint32
|
||||||
infoLen uint32
|
infoLen uint32
|
||||||
info syscallPtr // May be either bpfMapInfo or bpfProgInfo
|
info internal.Pointer // May be either bpfMapInfo or bpfProgInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
type bpfGetFDByIDAttr struct {
|
type bpfGetFDByIDAttr struct {
|
||||||
@ -192,13 +148,9 @@ type bpfGetFDByIDAttr struct {
|
|||||||
next uint32
|
next uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPtr(ptr unsafe.Pointer) syscallPtr {
|
func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) {
|
||||||
return syscallPtr{ptr: ptr}
|
|
||||||
}
|
|
||||||
|
|
||||||
func bpfProgLoad(attr *bpfProgLoadAttr) (*bpfFD, error) {
|
|
||||||
for {
|
for {
|
||||||
fd, err := bpfCall(_ProgLoad, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
fd, err := internal.BPF(_ProgLoad, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||||
// As of ~4.20 the verifier can be interrupted by a signal,
|
// As of ~4.20 the verifier can be interrupted by a signal,
|
||||||
// and returns EAGAIN in that case.
|
// and returns EAGAIN in that case.
|
||||||
if err == unix.EAGAIN {
|
if err == unix.EAGAIN {
|
||||||
@ -209,22 +161,22 @@ func bpfProgLoad(attr *bpfProgLoadAttr) (*bpfFD, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return newBPFFD(uint32(fd)), nil
|
return internal.NewFD(uint32(fd)), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfProgAlter(cmd int, attr *bpfProgAlterAttr) error {
|
func bpfProgAlter(cmd int, attr *bpfProgAlterAttr) error {
|
||||||
_, err := bpfCall(cmd, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
_, err := internal.BPF(cmd, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfMapCreate(attr *bpfMapCreateAttr) (*bpfFD, error) {
|
func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) {
|
||||||
fd, err := bpfCall(_MapCreate, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
fd, err := internal.BPF(_MapCreate, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return newBPFFD(uint32(fd)), nil
|
return internal.NewFD(uint32(fd)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
|
var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
|
||||||
@ -237,9 +189,9 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
defer inner.close()
|
defer inner.Close()
|
||||||
|
|
||||||
innerFd, _ := inner.value()
|
innerFd, _ := inner.Value()
|
||||||
nested, err := bpfMapCreate(&bpfMapCreateAttr{
|
nested, err := bpfMapCreate(&bpfMapCreateAttr{
|
||||||
mapType: ArrayOfMaps,
|
mapType: ArrayOfMaps,
|
||||||
keySize: 4,
|
keySize: 4,
|
||||||
@ -251,12 +203,12 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = nested.close()
|
_ = nested.Close()
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
func bpfMapLookupElem(m *bpfFD, key, valueOut syscallPtr) error {
|
func bpfMapLookupElem(m *internal.FD, key, valueOut internal.Pointer) error {
|
||||||
fd, err := m.value()
|
fd, err := m.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -266,12 +218,27 @@ func bpfMapLookupElem(m *bpfFD, key, valueOut syscallPtr) error {
|
|||||||
key: key,
|
key: key,
|
||||||
value: valueOut,
|
value: valueOut,
|
||||||
}
|
}
|
||||||
_, err = bpfCall(_MapLookupElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(_MapLookupElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfMapUpdateElem(m *bpfFD, key, valueOut syscallPtr, flags uint64) error {
|
func bpfMapLookupAndDelete(m *internal.FD, key, valueOut internal.Pointer) error {
|
||||||
fd, err := m.value()
|
fd, err := m.Value()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
attr := bpfMapOpAttr{
|
||||||
|
mapFd: fd,
|
||||||
|
key: key,
|
||||||
|
value: valueOut,
|
||||||
|
}
|
||||||
|
_, err = internal.BPF(_MapLookupAndDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func bpfMapUpdateElem(m *internal.FD, key, valueOut internal.Pointer, flags uint64) error {
|
||||||
|
fd, err := m.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -282,12 +249,12 @@ func bpfMapUpdateElem(m *bpfFD, key, valueOut syscallPtr, flags uint64) error {
|
|||||||
value: valueOut,
|
value: valueOut,
|
||||||
flags: flags,
|
flags: flags,
|
||||||
}
|
}
|
||||||
_, err = bpfCall(_MapUpdateElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(_MapUpdateElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfMapDeleteElem(m *bpfFD, key syscallPtr) error {
|
func bpfMapDeleteElem(m *internal.FD, key internal.Pointer) error {
|
||||||
fd, err := m.value()
|
fd, err := m.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -296,12 +263,12 @@ func bpfMapDeleteElem(m *bpfFD, key syscallPtr) error {
|
|||||||
mapFd: fd,
|
mapFd: fd,
|
||||||
key: key,
|
key: key,
|
||||||
}
|
}
|
||||||
_, err = bpfCall(_MapDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(_MapDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfMapGetNextKey(m *bpfFD, key, nextKeyOut syscallPtr) error {
|
func bpfMapGetNextKey(m *internal.FD, key, nextKeyOut internal.Pointer) error {
|
||||||
fd, err := m.value()
|
fd, err := m.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -311,13 +278,13 @@ func bpfMapGetNextKey(m *bpfFD, key, nextKeyOut syscallPtr) error {
|
|||||||
key: key,
|
key: key,
|
||||||
value: nextKeyOut,
|
value: nextKeyOut,
|
||||||
}
|
}
|
||||||
_, err = bpfCall(_MapGetNextKey, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(_MapGetNextKey, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
const bpfFSType = 0xcafe4a11
|
const bpfFSType = 0xcafe4a11
|
||||||
|
|
||||||
func bpfPinObject(fileName string, fd *bpfFD) error {
|
func bpfPinObject(fileName string, fd *internal.FD) error {
|
||||||
dirName := filepath.Dir(fileName)
|
dirName := filepath.Dir(fileName)
|
||||||
var statfs unix.Statfs_t
|
var statfs unix.Statfs_t
|
||||||
if err := unix.Statfs(dirName, &statfs); err != nil {
|
if err := unix.Statfs(dirName, &statfs); err != nil {
|
||||||
@ -327,30 +294,30 @@ func bpfPinObject(fileName string, fd *bpfFD) error {
|
|||||||
return errors.Errorf("%s is not on a bpf filesystem", fileName)
|
return errors.Errorf("%s is not on a bpf filesystem", fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
value, err := fd.value()
|
value, err := fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = bpfCall(_ObjPin, unsafe.Pointer(&bpfPinObjAttr{
|
_, err = internal.BPF(_ObjPin, unsafe.Pointer(&bpfPinObjAttr{
|
||||||
fileName: newPtr(unsafe.Pointer(&[]byte(fileName)[0])),
|
fileName: internal.NewStringPointer(fileName),
|
||||||
fd: value,
|
fd: value,
|
||||||
}), 16)
|
}), 16)
|
||||||
return errors.Wrapf(err, "pin object %s", fileName)
|
return errors.Wrapf(err, "pin object %s", fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfGetObject(fileName string) (*bpfFD, error) {
|
func bpfGetObject(fileName string) (*internal.FD, error) {
|
||||||
ptr, err := bpfCall(_ObjGet, unsafe.Pointer(&bpfPinObjAttr{
|
ptr, err := internal.BPF(_ObjGet, unsafe.Pointer(&bpfPinObjAttr{
|
||||||
fileName: newPtr(unsafe.Pointer(&[]byte(fileName)[0])),
|
fileName: internal.NewStringPointer(fileName),
|
||||||
}), 16)
|
}), 16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "get object %s", fileName)
|
return nil, errors.Wrapf(err, "get object %s", fileName)
|
||||||
}
|
}
|
||||||
return newBPFFD(uint32(ptr)), nil
|
return internal.NewFD(uint32(ptr)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfGetObjectInfoByFD(fd *bpfFD, info unsafe.Pointer, size uintptr) error {
|
func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) error {
|
||||||
value, err := fd.value()
|
value, err := fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -359,19 +326,19 @@ func bpfGetObjectInfoByFD(fd *bpfFD, info unsafe.Pointer, size uintptr) error {
|
|||||||
attr := bpfObjGetInfoByFDAttr{
|
attr := bpfObjGetInfoByFDAttr{
|
||||||
fd: value,
|
fd: value,
|
||||||
infoLen: uint32(size),
|
infoLen: uint32(size),
|
||||||
info: newPtr(info),
|
info: internal.NewPointer(info),
|
||||||
}
|
}
|
||||||
_, err = bpfCall(_ObjGetInfoByFD, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(_ObjGetInfoByFD, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
return errors.Wrapf(err, "fd %d", value)
|
return errors.Wrapf(err, "fd %d", fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfGetProgInfoByFD(fd *bpfFD) (*bpfProgInfo, error) {
|
func bpfGetProgInfoByFD(fd *internal.FD) (*bpfProgInfo, error) {
|
||||||
var info bpfProgInfo
|
var info bpfProgInfo
|
||||||
err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
|
err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
|
||||||
return &info, errors.Wrap(err, "can't get program info")
|
return &info, errors.Wrap(err, "can't get program info")
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfGetMapInfoByFD(fd *bpfFD) (*bpfMapInfo, error) {
|
func bpfGetMapInfoByFD(fd *internal.FD) (*bpfMapInfo, error) {
|
||||||
var info bpfMapInfo
|
var info bpfMapInfo
|
||||||
err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
|
err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
|
||||||
return &info, errors.Wrap(err, "can't get map info")
|
return &info, errors.Wrap(err, "can't get map info")
|
||||||
@ -398,50 +365,30 @@ var haveObjName = internal.FeatureTest("object names", "4.15", func() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = fd.close()
|
_ = fd.Close()
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
func bpfGetMapFDByID(id uint32) (*bpfFD, error) {
|
func bpfGetMapFDByID(id uint32) (*internal.FD, error) {
|
||||||
// available from 4.13
|
// available from 4.13
|
||||||
attr := bpfGetFDByIDAttr{
|
attr := bpfGetFDByIDAttr{
|
||||||
id: id,
|
id: id,
|
||||||
}
|
}
|
||||||
ptr, err := bpfCall(_MapGetFDByID, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
ptr, err := internal.BPF(_MapGetFDByID, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "can't get fd for map id %d", id)
|
return nil, errors.Wrapf(err, "can't get fd for map id %d", id)
|
||||||
}
|
}
|
||||||
return newBPFFD(uint32(ptr)), nil
|
return internal.NewFD(uint32(ptr)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfGetProgramFDByID(id uint32) (*bpfFD, error) {
|
func bpfGetProgramFDByID(id uint32) (*internal.FD, error) {
|
||||||
// available from 4.13
|
// available from 4.13
|
||||||
attr := bpfGetFDByIDAttr{
|
attr := bpfGetFDByIDAttr{
|
||||||
id: id,
|
id: id,
|
||||||
}
|
}
|
||||||
ptr, err := bpfCall(_ProgGetFDByID, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
ptr, err := internal.BPF(_ProgGetFDByID, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "can't get fd for program id %d", id)
|
return nil, errors.Wrapf(err, "can't get fd for program id %d", id)
|
||||||
}
|
}
|
||||||
return newBPFFD(uint32(ptr)), nil
|
return internal.NewFD(uint32(ptr)), nil
|
||||||
}
|
|
||||||
|
|
||||||
func bpfCall(cmd int, attr unsafe.Pointer, size uintptr) (uintptr, error) {
|
|
||||||
r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size)
|
|
||||||
runtime.KeepAlive(attr)
|
|
||||||
|
|
||||||
var err error
|
|
||||||
if errNo != 0 {
|
|
||||||
err = errNo
|
|
||||||
}
|
|
||||||
|
|
||||||
return r1, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertCString(in []byte) string {
|
|
||||||
inLen := bytes.IndexByte(in, 0)
|
|
||||||
if inLen == -1 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(in[:inLen])
|
|
||||||
}
|
}
|
||||||
|
36
vendor/github.com/cilium/ebpf/types.go
generated
vendored
36
vendor/github.com/cilium/ebpf/types.go
generated
vendored
@ -57,6 +57,30 @@ const (
|
|||||||
// HashOfMaps - Each item in the hash map is another map. The inner map mustn't be a map of maps
|
// HashOfMaps - Each item in the hash map is another map. The inner map mustn't be a map of maps
|
||||||
// itself.
|
// itself.
|
||||||
HashOfMaps
|
HashOfMaps
|
||||||
|
// DevMap - Specialized map to store references to network devices.
|
||||||
|
DevMap
|
||||||
|
// SockMap - Specialized map to store references to sockets.
|
||||||
|
SockMap
|
||||||
|
// CPUMap - Specialized map to store references to CPUs.
|
||||||
|
CPUMap
|
||||||
|
// XSKMap - Specialized map for XDP programs to store references to open sockets.
|
||||||
|
XSKMap
|
||||||
|
// SockHash - Specialized hash to store references to sockets.
|
||||||
|
SockHash
|
||||||
|
// CGroupStorage - Special map for CGroups.
|
||||||
|
CGroupStorage
|
||||||
|
// ReusePortSockArray - Specialized map to store references to sockets that can be reused.
|
||||||
|
ReusePortSockArray
|
||||||
|
// PerCPUCGroupStorage - Special per CPU map for CGroups.
|
||||||
|
PerCPUCGroupStorage
|
||||||
|
// Queue - FIFO storage for BPF programs.
|
||||||
|
Queue
|
||||||
|
// Stack - LIFO storage for BPF programs.
|
||||||
|
Stack
|
||||||
|
// SkStorage - Specialized map for local storage at SK for BPF programs.
|
||||||
|
SkStorage
|
||||||
|
// DevMapHash - Hash-based indexing scheme for references to network devices.
|
||||||
|
DevMapHash
|
||||||
)
|
)
|
||||||
|
|
||||||
// hasPerCPUValue returns true if the Map stores a value per CPU.
|
// hasPerCPUValue returns true if the Map stores a value per CPU.
|
||||||
@ -84,6 +108,13 @@ const (
|
|||||||
_ProgGetFDByID
|
_ProgGetFDByID
|
||||||
_MapGetFDByID
|
_MapGetFDByID
|
||||||
_ObjGetInfoByFD
|
_ObjGetInfoByFD
|
||||||
|
_ProgQuery
|
||||||
|
_RawTracepointOpen
|
||||||
|
_BTFLoad
|
||||||
|
_BTFGetFDByID
|
||||||
|
_TaskFDQuery
|
||||||
|
_MapLookupAndDeleteElem
|
||||||
|
_MapFreeze
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -149,6 +180,8 @@ const (
|
|||||||
RawTracepointWritable
|
RawTracepointWritable
|
||||||
// CGroupSockopt program
|
// CGroupSockopt program
|
||||||
CGroupSockopt
|
CGroupSockopt
|
||||||
|
// Tracing program
|
||||||
|
Tracing
|
||||||
)
|
)
|
||||||
|
|
||||||
// AttachType of the eBPF program, needed to differentiate allowed context accesses in
|
// AttachType of the eBPF program, needed to differentiate allowed context accesses in
|
||||||
@ -183,6 +216,9 @@ const (
|
|||||||
AttachCGroupUDP6Recvmsg
|
AttachCGroupUDP6Recvmsg
|
||||||
AttachCGroupGetsockopt
|
AttachCGroupGetsockopt
|
||||||
AttachCGroupSetsockopt
|
AttachCGroupSetsockopt
|
||||||
|
AttachTraceRawTp
|
||||||
|
AttachTraceFEntry
|
||||||
|
AttachTraceFExit
|
||||||
)
|
)
|
||||||
|
|
||||||
// AttachFlags of the eBPF program used in BPF_PROG_ATTACH command
|
// AttachFlags of the eBPF program used in BPF_PROG_ATTACH command
|
||||||
|
21
vendor/github.com/cilium/ebpf/types_string.go
generated
vendored
21
vendor/github.com/cilium/ebpf/types_string.go
generated
vendored
@ -22,11 +22,23 @@ func _() {
|
|||||||
_ = x[LPMTrie-11]
|
_ = x[LPMTrie-11]
|
||||||
_ = x[ArrayOfMaps-12]
|
_ = x[ArrayOfMaps-12]
|
||||||
_ = x[HashOfMaps-13]
|
_ = x[HashOfMaps-13]
|
||||||
|
_ = x[DevMap-14]
|
||||||
|
_ = x[SockMap-15]
|
||||||
|
_ = x[CPUMap-16]
|
||||||
|
_ = x[XSKMap-17]
|
||||||
|
_ = x[SockHash-18]
|
||||||
|
_ = x[CGroupStorage-19]
|
||||||
|
_ = x[ReusePortSockArray-20]
|
||||||
|
_ = x[PerCPUCGroupStorage-21]
|
||||||
|
_ = x[Queue-22]
|
||||||
|
_ = x[Stack-23]
|
||||||
|
_ = x[SkStorage-24]
|
||||||
|
_ = x[DevMapHash-25]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMaps"
|
const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHash"
|
||||||
|
|
||||||
var _MapType_index = [...]uint8{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136}
|
var _MapType_index = [...]uint8{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}
|
||||||
|
|
||||||
func (i MapType) String() string {
|
func (i MapType) String() string {
|
||||||
if i >= MapType(len(_MapType_index)-1) {
|
if i >= MapType(len(_MapType_index)-1) {
|
||||||
@ -64,11 +76,12 @@ func _() {
|
|||||||
_ = x[CGroupSysctl-23]
|
_ = x[CGroupSysctl-23]
|
||||||
_ = x[RawTracepointWritable-24]
|
_ = x[RawTracepointWritable-24]
|
||||||
_ = x[CGroupSockopt-25]
|
_ = x[CGroupSockopt-25]
|
||||||
|
_ = x[Tracing-26]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockopt"
|
const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockoptTracing"
|
||||||
|
|
||||||
var _ProgramType_index = [...]uint16{0, 18, 30, 36, 44, 52, 62, 65, 74, 83, 93, 98, 104, 111, 118, 123, 135, 140, 153, 167, 179, 188, 199, 212, 224, 245, 258}
|
var _ProgramType_index = [...]uint16{0, 18, 30, 36, 44, 52, 62, 65, 74, 83, 93, 98, 104, 111, 118, 123, 135, 140, 153, 167, 179, 188, 199, 212, 224, 245, 258, 265}
|
||||||
|
|
||||||
func (i ProgramType) String() string {
|
func (i ProgramType) String() string {
|
||||||
if i >= ProgramType(len(_ProgramType_index)-1) {
|
if i >= ProgramType(len(_ProgramType_index)-1) {
|
||||||
|
Loading…
Reference in New Issue
Block a user