vendor: cilium/ebbf 4032b1d8aae306b7bb94a2a11002932caf88c644
full diff: 60c3aa43f4...4032b1d8aa
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
			
			
This commit is contained in:
		
							
								
								
									
										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"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
 | 
			
		||||
	"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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Cause(err) == syscall.EINVAL {
 | 
			
		||||
@@ -50,7 +51,7 @@ func newMapABIFromFd(fd *bpfFD) (string, *MapABI, error) {
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMapABIFromProc(fd *bpfFD) (*MapABI, error) {
 | 
			
		||||
func newMapABIFromProc(fd *internal.FD) (*MapABI, error) {
 | 
			
		||||
	var abi MapABI
 | 
			
		||||
	err := scanFdInfo(fd, map[string]interface{}{
 | 
			
		||||
		"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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Cause(err) == syscall.EINVAL {
 | 
			
		||||
@@ -105,10 +106,10 @@ func newProgramABIFromFd(fd *bpfFD) (string, *ProgramABI, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var name string
 | 
			
		||||
	if bpfName := convertCString(info.name[:]); bpfName != "" {
 | 
			
		||||
	if bpfName := internal.CString(info.name[:]); bpfName != "" {
 | 
			
		||||
		name = bpfName
 | 
			
		||||
	} else {
 | 
			
		||||
		name = convertCString(info.tag[:])
 | 
			
		||||
		name = internal.CString(info.tag[:])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return name, &ProgramABI{
 | 
			
		||||
@@ -116,7 +117,7 @@ func newProgramABIFromFd(fd *bpfFD) (string, *ProgramABI, error) {
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newProgramABIFromProc(fd *bpfFD) (string, *ProgramABI, error) {
 | 
			
		||||
func newProgramABIFromProc(fd *internal.FD) (string, *ProgramABI, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		abi  ProgramABI
 | 
			
		||||
		name string
 | 
			
		||||
@@ -139,8 +140,8 @@ func newProgramABIFromProc(fd *bpfFD) (string, *ProgramABI, error) {
 | 
			
		||||
	return name, &abi, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanFdInfo(fd *bpfFD, fields map[string]interface{}) error {
 | 
			
		||||
	raw, err := fd.value()
 | 
			
		||||
func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error {
 | 
			
		||||
	raw, err := fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		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 (
 | 
			
		||||
	"github.com/cilium/ebpf/asm"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -55,17 +56,61 @@ func NewCollection(spec *CollectionSpec) (*Collection, error) {
 | 
			
		||||
// NewCollectionWithOptions creates a Collection from a specification.
 | 
			
		||||
//
 | 
			
		||||
// Only maps referenced by at least one of the programs are initialized.
 | 
			
		||||
func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error) {
 | 
			
		||||
	maps := make(map[string]*Map)
 | 
			
		||||
func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (coll *Collection, err error) {
 | 
			
		||||
	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 {
 | 
			
		||||
		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 {
 | 
			
		||||
			return nil, errors.Wrapf(err, "map %s", mapName)
 | 
			
		||||
		}
 | 
			
		||||
		maps[mapName] = m
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	progs := make(map[string]*Program)
 | 
			
		||||
	for progName, origProgSpec := range spec.Programs {
 | 
			
		||||
		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 {
 | 
			
		||||
			return nil, errors.Wrapf(err, "program %s", progName)
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										297
									
								
								vendor/github.com/cilium/ebpf/elf_reader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										297
									
								
								vendor/github.com/cilium/ebpf/elf_reader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -4,12 +4,13 @@ import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"debug/elf"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/asm"
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
@@ -18,6 +19,8 @@ type elfCode struct {
 | 
			
		||||
	*elf.File
 | 
			
		||||
	symbols           []elf.Symbol
 | 
			
		||||
	symbolsPerSection map[elf.SectionIndex]map[uint64]string
 | 
			
		||||
	license           string
 | 
			
		||||
	version           uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
func LoadCollectionSpecFromReader(code io.ReaderAt) (*CollectionSpec, error) {
 | 
			
		||||
	f, err := elf.NewFile(code)
 | 
			
		||||
func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
 | 
			
		||||
	f, err := elf.NewFile(rd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -45,12 +48,17 @@ func LoadCollectionSpecFromReader(code io.ReaderAt) (*CollectionSpec, error) {
 | 
			
		||||
		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 {
 | 
			
		||||
		switch {
 | 
			
		||||
		case strings.HasPrefix(sec.Name, "license"):
 | 
			
		||||
@@ -59,6 +67,8 @@ func LoadCollectionSpecFromReader(code io.ReaderAt) (*CollectionSpec, error) {
 | 
			
		||||
			versionSection = sec
 | 
			
		||||
		case strings.HasPrefix(sec.Name, "maps"):
 | 
			
		||||
			mapSections[elf.SectionIndex(i)] = sec
 | 
			
		||||
		case sec.Name == ".maps":
 | 
			
		||||
			btfMaps[elf.SectionIndex(i)] = sec
 | 
			
		||||
		case sec.Type == elf.SHT_REL:
 | 
			
		||||
			if int(sec.Info) >= len(ec.Sections) {
 | 
			
		||||
				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
 | 
			
		||||
			idx := elf.SectionIndex(sec.Info)
 | 
			
		||||
			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
 | 
			
		||||
		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 {
 | 
			
		||||
		return nil, errors.Wrap(err, "load license")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	version, err := loadVersion(versionSection, ec.ByteOrder)
 | 
			
		||||
	ec.version, err = loadVersion(versionSection, ec.ByteOrder)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "load version")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	maps, err := ec.loadMaps(mapSections)
 | 
			
		||||
	btf, err := btf.LoadSpecFromReader(rd)
 | 
			
		||||
	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")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	progs, libs, err := ec.loadPrograms(progSections, relSections, license, version)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "load programs")
 | 
			
		||||
	if len(btfMaps) > 0 {
 | 
			
		||||
		if err := ec.loadBTFMaps(maps, btfMaps, btf); err != nil {
 | 
			
		||||
			return nil, errors.Wrap(err, "load BTF maps")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(libs) > 0 {
 | 
			
		||||
		for name, prog := range progs {
 | 
			
		||||
			prog.Instructions, err = link(prog.Instructions, libs...)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, errors.Wrapf(err, "program %s", name)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	progs, err := ec.loadPrograms(progSections, relSections, btf)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "load programs")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 (
 | 
			
		||||
		progs = make(map[string]*ProgramSpec)
 | 
			
		||||
		libs  []asm.Instructions
 | 
			
		||||
		progs []*ProgramSpec
 | 
			
		||||
		libs  []*ProgramSpec
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	for idx, prog := range progSections {
 | 
			
		||||
		syms := ec.symbolsPerSection[idx]
 | 
			
		||||
		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]
 | 
			
		||||
		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])
 | 
			
		||||
		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 {
 | 
			
		||||
			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)
 | 
			
		||||
 | 
			
		||||
		spec := &ProgramSpec{
 | 
			
		||||
			Name:          funcSym,
 | 
			
		||||
			Type:          progType,
 | 
			
		||||
			AttachType:    attachType,
 | 
			
		||||
			License:       ec.license,
 | 
			
		||||
			KernelVersion: ec.version,
 | 
			
		||||
			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)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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, insns)
 | 
			
		||||
			libs = append(libs, spec)
 | 
			
		||||
		} else {
 | 
			
		||||
			progs[funcSym] = &ProgramSpec{
 | 
			
		||||
				Name:          funcSym,
 | 
			
		||||
				Type:          progType,
 | 
			
		||||
				AttachType:    attachType,
 | 
			
		||||
				License:       license,
 | 
			
		||||
				KernelVersion: version,
 | 
			
		||||
				Instructions:  insns,
 | 
			
		||||
			}
 | 
			
		||||
			progs = append(progs, spec)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return progs, libs, nil
 | 
			
		||||
 | 
			
		||||
	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, error) {
 | 
			
		||||
func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations map[uint64]string) (asm.Instructions, uint64, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		r      = section.Open()
 | 
			
		||||
		insns  asm.Instructions
 | 
			
		||||
@@ -183,10 +218,10 @@ func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations m
 | 
			
		||||
	for {
 | 
			
		||||
		n, err := ins.Unmarshal(r, ec.ByteOrder)
 | 
			
		||||
		if err == io.EOF {
 | 
			
		||||
			return insns, nil
 | 
			
		||||
			return insns, offset, 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]
 | 
			
		||||
@@ -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) {
 | 
			
		||||
	var (
 | 
			
		||||
		maps = make(map[string]*MapSpec)
 | 
			
		||||
		b    = make([]byte, 1)
 | 
			
		||||
	)
 | 
			
		||||
func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.SectionIndex]*elf.Section) error {
 | 
			
		||||
	for idx, sec := range mapSections {
 | 
			
		||||
		syms := ec.symbolsPerSection[idx]
 | 
			
		||||
		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 {
 | 
			
		||||
			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 (
 | 
			
		||||
@@ -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 {
 | 
			
		||||
			mapSym := syms[offset]
 | 
			
		||||
			if mapSym == "" {
 | 
			
		||||
				fmt.Println(syms)
 | 
			
		||||
				return nil, errors.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset)
 | 
			
		||||
				return errors.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			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))
 | 
			
		||||
@@ -232,51 +262,152 @@ func (ec *elfCode) loadMaps(mapSections map[elf.SectionIndex]*elf.Section) (map[
 | 
			
		||||
			var spec MapSpec
 | 
			
		||||
			switch {
 | 
			
		||||
			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:
 | 
			
		||||
				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:
 | 
			
		||||
				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:
 | 
			
		||||
				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:
 | 
			
		||||
				return nil, errors.Errorf("map %v: missing flags", mapSym)
 | 
			
		||||
				return errors.Errorf("map %v: missing flags", mapSym)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for {
 | 
			
		||||
				_, err := lr.Read(b)
 | 
			
		||||
				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)
 | 
			
		||||
				}
 | 
			
		||||
			if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil {
 | 
			
		||||
				return errors.Errorf("map %v: unknown and non-zero fields in definition", mapSym)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			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) {
 | 
			
		||||
	types := map[string]ProgramType{
 | 
			
		||||
		// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c#n3568
 | 
			
		||||
		"socket":         SocketFilter,
 | 
			
		||||
		"seccomp":        SocketFilter,
 | 
			
		||||
		"kprobe/":        Kprobe,
 | 
			
		||||
		"kretprobe/":     Kprobe,
 | 
			
		||||
		"tracepoint/":    TracePoint,
 | 
			
		||||
		"xdp":            XDP,
 | 
			
		||||
		"perf_event":     PerfEvent,
 | 
			
		||||
		"sockops":        SockOps,
 | 
			
		||||
		"sk_skb":         SkSKB,
 | 
			
		||||
		"sk_msg":         SkMsg,
 | 
			
		||||
		"lirc_mode2":     LircMode2,
 | 
			
		||||
		"flow_dissector": FlowDissector,
 | 
			
		||||
		"socket":          SocketFilter,
 | 
			
		||||
		"seccomp":         SocketFilter,
 | 
			
		||||
		"kprobe/":         Kprobe,
 | 
			
		||||
		"uprobe/":         Kprobe,
 | 
			
		||||
		"kretprobe/":      Kprobe,
 | 
			
		||||
		"uretprobe/":      Kprobe,
 | 
			
		||||
		"tracepoint/":     TracePoint,
 | 
			
		||||
		"raw_tracepoint/": RawTracepoint,
 | 
			
		||||
		"xdp":             XDP,
 | 
			
		||||
		"perf_event":      PerfEvent,
 | 
			
		||||
		"lwt_in":          LWTIn,
 | 
			
		||||
		"lwt_out":         LWTOut,
 | 
			
		||||
		"lwt_xmit":        LWTXmit,
 | 
			
		||||
		"lwt_seg6local":   LWTSeg6Local,
 | 
			
		||||
		"sockops":         SockOps,
 | 
			
		||||
		"sk_skb":          SkSKB,
 | 
			
		||||
		"sk_msg":          SkMsg,
 | 
			
		||||
		"lirc_mode2":      LircMode2,
 | 
			
		||||
		"flow_dissector":  FlowDissector,
 | 
			
		||||
 | 
			
		||||
		"cgroup_skb/":       CGroupSKB,
 | 
			
		||||
		"cgroup/dev":        CGroupDevice,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
 | 
			
		||||
package ebpf
 | 
			
		||||
package internal
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ptr wraps an unsafe.Pointer to be 64bit to
 | 
			
		||||
// Pointer wraps an unsafe.Pointer to be 64bit to
 | 
			
		||||
// conform to the syscall specification.
 | 
			
		||||
type syscallPtr struct {
 | 
			
		||||
type Pointer struct {
 | 
			
		||||
	pad uint32
 | 
			
		||||
	ptr unsafe.Pointer
 | 
			
		||||
}
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
// +build 386 amd64p32 arm mipsle mips64p32le
 | 
			
		||||
 | 
			
		||||
package ebpf
 | 
			
		||||
package internal
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ptr wraps an unsafe.Pointer to be 64bit to
 | 
			
		||||
// Pointer wraps an unsafe.Pointer to be 64bit to
 | 
			
		||||
// conform to the syscall specification.
 | 
			
		||||
type syscallPtr struct {
 | 
			
		||||
type Pointer struct {
 | 
			
		||||
	ptr unsafe.Pointer
 | 
			
		||||
	pad uint32
 | 
			
		||||
}
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
// +build !386,!amd64p32,!arm,!mipsle,!mips64p32le
 | 
			
		||||
// +build !armbe,!mips,!mips64p32
 | 
			
		||||
 | 
			
		||||
package ebpf
 | 
			
		||||
package internal
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ptr wraps an unsafe.Pointer to be 64bit to
 | 
			
		||||
// Pointer wraps an unsafe.Pointer to be 64bit to
 | 
			
		||||
// conform to the syscall specification.
 | 
			
		||||
type syscallPtr struct {
 | 
			
		||||
type Pointer struct {
 | 
			
		||||
	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 (
 | 
			
		||||
	"github.com/cilium/ebpf/asm"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
//
 | 
			
		||||
// Sections must not require linking themselves.
 | 
			
		||||
func link(insns asm.Instructions, sections ...asm.Instructions) (asm.Instructions, error) {
 | 
			
		||||
	for _, section := range sections {
 | 
			
		||||
		var err error
 | 
			
		||||
		insns, err = linkSection(insns, section)
 | 
			
		||||
// Libraries must not require linking themselves.
 | 
			
		||||
func link(prog *ProgramSpec, libs []*ProgramSpec) error {
 | 
			
		||||
	for _, lib := range libs {
 | 
			
		||||
		insns, err := linkSection(prog.Instructions, lib.Instructions)
 | 
			
		||||
		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) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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 (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
@@ -20,8 +20,12 @@ type MapSpec struct {
 | 
			
		||||
	ValueSize  uint32
 | 
			
		||||
	MaxEntries uint32
 | 
			
		||||
	Flags      uint32
 | 
			
		||||
 | 
			
		||||
	// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
 | 
			
		||||
	InnerMap *MapSpec
 | 
			
		||||
 | 
			
		||||
	// The BTF associated with this map.
 | 
			
		||||
	BTF *btf.Map
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ms *MapSpec) String() string {
 | 
			
		||||
@@ -50,7 +54,7 @@ func (ms *MapSpec) Copy() *MapSpec {
 | 
			
		||||
// if you require custom encoding.
 | 
			
		||||
type Map struct {
 | 
			
		||||
	name string
 | 
			
		||||
	fd   *bpfFD
 | 
			
		||||
	fd   *internal.FD
 | 
			
		||||
	abi  MapABI
 | 
			
		||||
	// Per CPU maps return values larger than the size in the spec
 | 
			
		||||
	fullValueSize int
 | 
			
		||||
@@ -63,11 +67,11 @@ func NewMapFromFD(fd int) (*Map, error) {
 | 
			
		||||
	if fd < 0 {
 | 
			
		||||
		return nil, errors.New("invalid fd")
 | 
			
		||||
	}
 | 
			
		||||
	bpfFd := newBPFFD(uint32(fd))
 | 
			
		||||
	bpfFd := internal.NewFD(uint32(fd))
 | 
			
		||||
 | 
			
		||||
	name, abi, err := newMapABIFromFd(bpfFd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		bpfFd.forget()
 | 
			
		||||
		bpfFd.Forget()
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	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
 | 
			
		||||
// by creating small, temporary maps.
 | 
			
		||||
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 {
 | 
			
		||||
		return createMap(spec, nil)
 | 
			
		||||
		return createMap(spec, nil, handle)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if spec.InnerMap == nil {
 | 
			
		||||
		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 {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	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()
 | 
			
		||||
 | 
			
		||||
	switch spec.Type {
 | 
			
		||||
@@ -140,12 +157,18 @@ func createMap(spec *MapSpec, inner *bpfFD) (*Map, error) {
 | 
			
		||||
 | 
			
		||||
	if inner != nil {
 | 
			
		||||
		var err error
 | 
			
		||||
		attr.innerMapFd, err = inner.value()
 | 
			
		||||
		attr.innerMapFd, err = inner.Value()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		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))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMap(fd *bpfFD, name string, abi *MapABI) (*Map, error) {
 | 
			
		||||
func newMap(fd *internal.FD, name string, abi *MapABI) (*Map, error) {
 | 
			
		||||
	m := &Map{
 | 
			
		||||
		name,
 | 
			
		||||
		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.
 | 
			
		||||
//
 | 
			
		||||
// Returns a nil value if a key doesn't exist.
 | 
			
		||||
func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
 | 
			
		||||
	valueBytes := make([]byte, m.fullValueSize)
 | 
			
		||||
	valuePtr := newPtr(unsafe.Pointer(&valueBytes[0]))
 | 
			
		||||
	valuePtr := internal.NewSlicePointer(valueBytes)
 | 
			
		||||
 | 
			
		||||
	err := m.lookup(key, valuePtr)
 | 
			
		||||
	if IsNotExist(err) {
 | 
			
		||||
@@ -266,7 +305,7 @@ func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
 | 
			
		||||
	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))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		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")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var valuePtr syscallPtr
 | 
			
		||||
	var valuePtr internal.Pointer
 | 
			
		||||
	if m.abi.Type.hasPerCPUValue() {
 | 
			
		||||
		valuePtr, err = marshalPerCPUValue(value, int(m.abi.ValueSize))
 | 
			
		||||
	} 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.
 | 
			
		||||
func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) {
 | 
			
		||||
	nextKey := make([]byte, m.abi.KeySize)
 | 
			
		||||
	nextKeyPtr := newPtr(unsafe.Pointer(&nextKey[0]))
 | 
			
		||||
	nextKeyPtr := internal.NewSlicePointer(nextKey)
 | 
			
		||||
 | 
			
		||||
	err := m.nextKey(key, nextKeyPtr)
 | 
			
		||||
	if IsNotExist(err) {
 | 
			
		||||
@@ -365,9 +404,9 @@ func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) {
 | 
			
		||||
	return nextKey, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Map) nextKey(key interface{}, nextKeyOut syscallPtr) error {
 | 
			
		||||
func (m *Map) nextKey(key interface{}, nextKeyOut internal.Pointer) error {
 | 
			
		||||
	var (
 | 
			
		||||
		keyPtr syscallPtr
 | 
			
		||||
		keyPtr internal.Pointer
 | 
			
		||||
		err    error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
@@ -400,14 +439,14 @@ func (m *Map) Close() error {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return m.fd.close()
 | 
			
		||||
	return m.fd.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FD gets the file descriptor of the Map.
 | 
			
		||||
//
 | 
			
		||||
// Calling this function is invalid after Close has been called.
 | 
			
		||||
func (m *Map) FD() int {
 | 
			
		||||
	fd, err := m.fd.value()
 | 
			
		||||
	fd, err := m.fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// Best effort: -1 is the number most likely to be an
 | 
			
		||||
		// invalid file descriptor.
 | 
			
		||||
@@ -428,7 +467,7 @@ func (m *Map) Clone() (*Map, error) {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dup, err := m.fd.dup()
 | 
			
		||||
	dup, err := m.fd.Dup()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "can't clone map")
 | 
			
		||||
	}
 | 
			
		||||
@@ -454,7 +493,7 @@ func LoadPinnedMap(fileName string) (*Map, error) {
 | 
			
		||||
	}
 | 
			
		||||
	name, abi, err := newMapABIFromFd(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		_ = fd.close()
 | 
			
		||||
		_ = fd.Close()
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return newMap(fd, name, abi)
 | 
			
		||||
@@ -484,7 +523,7 @@ func unmarshalMap(buf []byte) (*Map, error) {
 | 
			
		||||
 | 
			
		||||
	name, abi, err := newMapABIFromFd(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		_ = fd.close()
 | 
			
		||||
		_ = fd.Close()
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -493,7 +532,7 @@ func unmarshalMap(buf []byte) (*Map, error) {
 | 
			
		||||
 | 
			
		||||
// MarshalBinary implements BinaryMarshaler.
 | 
			
		||||
func (m *Map) MarshalBinary() ([]byte, error) {
 | 
			
		||||
	fd, err := m.fd.value()
 | 
			
		||||
	fd, err := m.fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		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"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
		return newPtr(ptr), nil
 | 
			
		||||
		return internal.NewPointer(ptr), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf, err := marshalBytes(data, length)
 | 
			
		||||
	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) {
 | 
			
		||||
@@ -52,13 +59,13 @@ func marshalBytes(data interface{}, length int) (buf []byte, err error) {
 | 
			
		||||
	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 {
 | 
			
		||||
		return newPtr(ptr), nil
 | 
			
		||||
		return internal.NewPointer(ptr), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf := make([]byte, length)
 | 
			
		||||
	return newPtr(unsafe.Pointer(&buf[0])), buf
 | 
			
		||||
	return internal.NewSlicePointer(buf), buf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
//
 | 
			
		||||
// 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)
 | 
			
		||||
	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()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return syscallPtr{}, err
 | 
			
		||||
		return internal.Pointer{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sliceValue := reflect.ValueOf(slice)
 | 
			
		||||
	sliceLen := sliceValue.Len()
 | 
			
		||||
	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)
 | 
			
		||||
@@ -123,14 +130,14 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (syscallPtr, error) {
 | 
			
		||||
		elem := sliceValue.Index(i).Interface()
 | 
			
		||||
		elemBytes, err := marshalBytes(elem, elemLength)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return syscallPtr{}, err
 | 
			
		||||
			return internal.Pointer{}, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		offset := i * alignedElemLength
 | 
			
		||||
		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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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/internal"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
@@ -46,6 +47,11 @@ type ProgramSpec struct {
 | 
			
		||||
	Instructions  asm.Instructions
 | 
			
		||||
	License       string
 | 
			
		||||
	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.
 | 
			
		||||
@@ -68,7 +74,7 @@ type Program struct {
 | 
			
		||||
	// otherwise it is empty.
 | 
			
		||||
	VerifierLog string
 | 
			
		||||
 | 
			
		||||
	fd   *bpfFD
 | 
			
		||||
	fd   *internal.FD
 | 
			
		||||
	name string
 | 
			
		||||
	abi  ProgramABI
 | 
			
		||||
}
 | 
			
		||||
@@ -86,7 +92,20 @@ func NewProgram(spec *ProgramSpec) (*Program, error) {
 | 
			
		||||
// Loading a program for the first time will perform
 | 
			
		||||
// feature detection by loading small, temporary programs.
 | 
			
		||||
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 {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -101,34 +120,28 @@ func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er
 | 
			
		||||
		logBuf = make([]byte, logSize)
 | 
			
		||||
		attr.logLevel = opts.LogLevel
 | 
			
		||||
		attr.logSize = uint32(len(logBuf))
 | 
			
		||||
		attr.logBuf = newPtr(unsafe.Pointer(&logBuf[0]))
 | 
			
		||||
		attr.logBuf = internal.NewSlicePointer(logBuf)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fd, err := bpfProgLoad(attr)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		prog := newProgram(fd, spec.Name, &ProgramABI{spec.Type})
 | 
			
		||||
		prog.VerifierLog = convertCString(logBuf)
 | 
			
		||||
		prog.VerifierLog = internal.CString(logBuf)
 | 
			
		||||
		return prog, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	truncated := errors.Cause(err) == unix.ENOSPC
 | 
			
		||||
	if opts.LogLevel == 0 {
 | 
			
		||||
		// Re-run with the verifier enabled to get better error messages.
 | 
			
		||||
		logBuf = make([]byte, logSize)
 | 
			
		||||
		attr.logLevel = 1
 | 
			
		||||
		attr.logSize = uint32(len(logBuf))
 | 
			
		||||
		attr.logBuf = newPtr(unsafe.Pointer(&logBuf[0]))
 | 
			
		||||
		attr.logBuf = internal.NewSlicePointer(logBuf)
 | 
			
		||||
 | 
			
		||||
		_, nerr := bpfProgLoad(attr)
 | 
			
		||||
		truncated = errors.Cause(nerr) == unix.ENOSPC
 | 
			
		||||
		_, logErr := bpfProgLoad(attr)
 | 
			
		||||
		err = internal.ErrorWithLog(err, logBuf, logErr)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	logs := convertCString(logBuf)
 | 
			
		||||
	if truncated {
 | 
			
		||||
		logs += "\n(truncated...)"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, &loadError{err, logs}
 | 
			
		||||
	return nil, errors.Wrap(err, "can't load program")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewProgramFromFD creates a program from a raw fd.
 | 
			
		||||
@@ -140,18 +153,18 @@ func NewProgramFromFD(fd int) (*Program, error) {
 | 
			
		||||
	if fd < 0 {
 | 
			
		||||
		return nil, errors.New("invalid fd")
 | 
			
		||||
	}
 | 
			
		||||
	bpfFd := newBPFFD(uint32(fd))
 | 
			
		||||
	bpfFd := internal.NewFD(uint32(fd))
 | 
			
		||||
 | 
			
		||||
	name, abi, err := newProgramABIFromFd(bpfFd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		bpfFd.forget()
 | 
			
		||||
		bpfFd.Forget()
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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{
 | 
			
		||||
		name: name,
 | 
			
		||||
		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 {
 | 
			
		||||
		return nil, errors.New("Instructions cannot be empty")
 | 
			
		||||
	}
 | 
			
		||||
@@ -176,13 +189,12 @@ func convertProgramSpec(spec *ProgramSpec) (*bpfProgLoadAttr, error) {
 | 
			
		||||
 | 
			
		||||
	bytecode := buf.Bytes()
 | 
			
		||||
	insCount := uint32(len(bytecode) / asm.InstructionSize)
 | 
			
		||||
	lic := []byte(spec.License)
 | 
			
		||||
	attr := &bpfProgLoadAttr{
 | 
			
		||||
		progType:           spec.Type,
 | 
			
		||||
		expectedAttachType: spec.AttachType,
 | 
			
		||||
		insCount:           insCount,
 | 
			
		||||
		instructions:       newPtr(unsafe.Pointer(&bytecode[0])),
 | 
			
		||||
		license:            newPtr(unsafe.Pointer(&lic[0])),
 | 
			
		||||
		instructions:       internal.NewSlicePointer(bytecode),
 | 
			
		||||
		license:            internal.NewStringPointer(spec.License),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name, err := newBPFObjName(spec.Name)
 | 
			
		||||
@@ -194,6 +206,26 @@ func convertProgramSpec(spec *ProgramSpec) (*bpfProgLoadAttr, error) {
 | 
			
		||||
		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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -213,7 +245,7 @@ func (p *Program) ABI() ProgramABI {
 | 
			
		||||
//
 | 
			
		||||
// It is invalid to call this function after Close has been called.
 | 
			
		||||
func (p *Program) FD() int {
 | 
			
		||||
	fd, err := p.fd.value()
 | 
			
		||||
	fd, err := p.fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// Best effort: -1 is the number most likely to be an
 | 
			
		||||
		// invalid file descriptor.
 | 
			
		||||
@@ -233,7 +265,7 @@ func (p *Program) Clone() (*Program, error) {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dup, err := p.fd.dup()
 | 
			
		||||
	dup, err := p.fd.Dup()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "can't clone program")
 | 
			
		||||
	}
 | 
			
		||||
@@ -254,7 +286,7 @@ func (p *Program) Close() error {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return p.fd.close()
 | 
			
		||||
	return p.fd.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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()
 | 
			
		||||
 | 
			
		||||
	fd, err := prog.fd.value()
 | 
			
		||||
	fd, err := prog.fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
@@ -306,10 +338,10 @@ var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() b
 | 
			
		||||
	attr := bpfProgTestRunAttr{
 | 
			
		||||
		fd:         fd,
 | 
			
		||||
		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
 | 
			
		||||
	// 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/
 | 
			
		||||
	out := make([]byte, len(in)+outputPad)
 | 
			
		||||
 | 
			
		||||
	fd, err := p.fd.value()
 | 
			
		||||
	fd, err := p.fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, nil, 0, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -349,12 +381,12 @@ func (p *Program) testRun(in []byte, repeat int) (uint32, []byte, time.Duration,
 | 
			
		||||
		fd:          fd,
 | 
			
		||||
		dataSizeIn:  uint32(len(in)),
 | 
			
		||||
		dataSizeOut: uint32(len(out)),
 | 
			
		||||
		dataIn:      newPtr(unsafe.Pointer(&in[0])),
 | 
			
		||||
		dataOut:     newPtr(unsafe.Pointer(&out[0])),
 | 
			
		||||
		dataIn:      internal.NewSlicePointer(in),
 | 
			
		||||
		dataOut:     internal.NewSlicePointer(out),
 | 
			
		||||
		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 {
 | 
			
		||||
		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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		_ = fd.close()
 | 
			
		||||
		_ = fd.Close()
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -394,7 +426,7 @@ func unmarshalProgram(buf []byte) (*Program, error) {
 | 
			
		||||
 | 
			
		||||
// MarshalBinary implements BinaryMarshaler.
 | 
			
		||||
func (p *Program) MarshalBinary() ([]byte, error) {
 | 
			
		||||
	value, err := p.fd.value()
 | 
			
		||||
	value, err := p.fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -410,7 +442,7 @@ func (p *Program) Attach(fd int, typ AttachType, flags AttachFlags) error {
 | 
			
		||||
		return errors.New("invalid fd")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pfd, err := p.fd.value()
 | 
			
		||||
	pfd, err := p.fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -431,7 +463,7 @@ func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error {
 | 
			
		||||
		return errors.New("invalid fd")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pfd, err := p.fd.value()
 | 
			
		||||
	pfd, err := p.fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -457,7 +489,7 @@ func LoadPinnedProgram(fileName string) (*Program, error) {
 | 
			
		||||
 | 
			
		||||
	name, abi, err := newProgramABIFromFd(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		_ = fd.close()
 | 
			
		||||
		_ = fd.Close()
 | 
			
		||||
		return nil, errors.Wrapf(err, "can't get ABI for %s", fileName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -480,22 +512,6 @@ func SanitizeName(name string, replacement rune) string {
 | 
			
		||||
	}, 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
 | 
			
		||||
// the kernel does not have support for a specific feature.
 | 
			
		||||
func IsNotSupported(err error) bool {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										235
									
								
								vendor/github.com/cilium/ebpf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										235
									
								
								vendor/github.com/cilium/ebpf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,72 +1,17 @@
 | 
			
		||||
package ebpf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/btf"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
 | 
			
		||||
	"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
 | 
			
		||||
// 'A-Za-z0-9_' characters.
 | 
			
		||||
type bpfObjName [unix.BPF_OBJ_NAME_LEN]byte
 | 
			
		||||
@@ -99,21 +44,25 @@ func invalidBPFObjNameChar(char rune) bool {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfMapCreateAttr struct {
 | 
			
		||||
	mapType    MapType
 | 
			
		||||
	keySize    uint32
 | 
			
		||||
	valueSize  uint32
 | 
			
		||||
	maxEntries uint32
 | 
			
		||||
	flags      uint32
 | 
			
		||||
	innerMapFd uint32     // since 4.12 56f668dfe00d
 | 
			
		||||
	numaNode   uint32     // since 4.14 96eabe7a40aa
 | 
			
		||||
	mapName    bpfObjName // since 4.15 ad5b177bd73f
 | 
			
		||||
	mapType        MapType
 | 
			
		||||
	keySize        uint32
 | 
			
		||||
	valueSize      uint32
 | 
			
		||||
	maxEntries     uint32
 | 
			
		||||
	flags          uint32
 | 
			
		||||
	innerMapFd     uint32     // since 4.12 56f668dfe00d
 | 
			
		||||
	numaNode       uint32     // since 4.14 96eabe7a40aa
 | 
			
		||||
	mapName        bpfObjName // since 4.15 ad5b177bd73f
 | 
			
		||||
	mapIfIndex     uint32
 | 
			
		||||
	btfFd          uint32
 | 
			
		||||
	btfKeyTypeID   btf.TypeID
 | 
			
		||||
	btfValueTypeID btf.TypeID
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfMapOpAttr struct {
 | 
			
		||||
	mapFd   uint32
 | 
			
		||||
	padding uint32
 | 
			
		||||
	key     syscallPtr
 | 
			
		||||
	value   syscallPtr
 | 
			
		||||
	key     internal.Pointer
 | 
			
		||||
	value   internal.Pointer
 | 
			
		||||
	flags   uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -128,7 +77,7 @@ type bpfMapInfo struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfPinObjAttr struct {
 | 
			
		||||
	fileName syscallPtr
 | 
			
		||||
	fileName internal.Pointer
 | 
			
		||||
	fd       uint32
 | 
			
		||||
	padding  uint32
 | 
			
		||||
}
 | 
			
		||||
@@ -136,16 +85,23 @@ type bpfPinObjAttr struct {
 | 
			
		||||
type bpfProgLoadAttr struct {
 | 
			
		||||
	progType           ProgramType
 | 
			
		||||
	insCount           uint32
 | 
			
		||||
	instructions       syscallPtr
 | 
			
		||||
	license            syscallPtr
 | 
			
		||||
	instructions       internal.Pointer
 | 
			
		||||
	license            internal.Pointer
 | 
			
		||||
	logLevel           uint32
 | 
			
		||||
	logSize            uint32
 | 
			
		||||
	logBuf             syscallPtr
 | 
			
		||||
	logBuf             internal.Pointer
 | 
			
		||||
	kernelVersion      uint32     // since 4.1  2541517c32be
 | 
			
		||||
	progFlags          uint32     // since 4.11 e07b98d9bffe
 | 
			
		||||
	progName           bpfObjName // since 4.15 067cae47771c
 | 
			
		||||
	progIfIndex        uint32     // since 4.15 1f6f4cb7ba21
 | 
			
		||||
	expectedAttachType AttachType // since 4.17 5e43f899b03a
 | 
			
		||||
	progBTFFd          uint32
 | 
			
		||||
	funcInfoRecSize    uint32
 | 
			
		||||
	funcInfo           internal.Pointer
 | 
			
		||||
	funcInfoCnt        uint32
 | 
			
		||||
	lineInfoRecSize    uint32
 | 
			
		||||
	lineInfo           internal.Pointer
 | 
			
		||||
	lineInfoCnt        uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfProgInfo struct {
 | 
			
		||||
@@ -154,12 +110,12 @@ type bpfProgInfo struct {
 | 
			
		||||
	tag          [unix.BPF_TAG_SIZE]byte
 | 
			
		||||
	jitedLen     uint32
 | 
			
		||||
	xlatedLen    uint32
 | 
			
		||||
	jited        syscallPtr
 | 
			
		||||
	xlated       syscallPtr
 | 
			
		||||
	jited        internal.Pointer
 | 
			
		||||
	xlated       internal.Pointer
 | 
			
		||||
	loadTime     uint64 // since 4.15 cb4d2b3f03d8
 | 
			
		||||
	createdByUID uint32
 | 
			
		||||
	nrMapIDs     uint32
 | 
			
		||||
	mapIds       syscallPtr
 | 
			
		||||
	mapIds       internal.Pointer
 | 
			
		||||
	name         bpfObjName
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -168,8 +124,8 @@ type bpfProgTestRunAttr struct {
 | 
			
		||||
	retval      uint32
 | 
			
		||||
	dataSizeIn  uint32
 | 
			
		||||
	dataSizeOut uint32
 | 
			
		||||
	dataIn      syscallPtr
 | 
			
		||||
	dataOut     syscallPtr
 | 
			
		||||
	dataIn      internal.Pointer
 | 
			
		||||
	dataOut     internal.Pointer
 | 
			
		||||
	repeat      uint32
 | 
			
		||||
	duration    uint32
 | 
			
		||||
}
 | 
			
		||||
@@ -184,7 +140,7 @@ type bpfProgAlterAttr struct {
 | 
			
		||||
type bpfObjGetInfoByFDAttr struct {
 | 
			
		||||
	fd      uint32
 | 
			
		||||
	infoLen uint32
 | 
			
		||||
	info    syscallPtr // May be either bpfMapInfo or bpfProgInfo
 | 
			
		||||
	info    internal.Pointer // May be either bpfMapInfo or bpfProgInfo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfGetFDByIDAttr struct {
 | 
			
		||||
@@ -192,13 +148,9 @@ type bpfGetFDByIDAttr struct {
 | 
			
		||||
	next uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newPtr(ptr unsafe.Pointer) syscallPtr {
 | 
			
		||||
	return syscallPtr{ptr: ptr}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfProgLoad(attr *bpfProgLoadAttr) (*bpfFD, error) {
 | 
			
		||||
func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) {
 | 
			
		||||
	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,
 | 
			
		||||
		// and returns EAGAIN in that case.
 | 
			
		||||
		if err == unix.EAGAIN {
 | 
			
		||||
@@ -209,22 +161,22 @@ func bpfProgLoad(attr *bpfProgLoadAttr) (*bpfFD, error) {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return newBPFFD(uint32(fd)), nil
 | 
			
		||||
		return internal.NewFD(uint32(fd)), nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfMapCreate(attr *bpfMapCreateAttr) (*bpfFD, error) {
 | 
			
		||||
	fd, err := bpfCall(_MapCreate, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) {
 | 
			
		||||
	fd, err := internal.BPF(_MapCreate, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newBPFFD(uint32(fd)), nil
 | 
			
		||||
	return internal.NewFD(uint32(fd)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	defer inner.close()
 | 
			
		||||
	defer inner.Close()
 | 
			
		||||
 | 
			
		||||
	innerFd, _ := inner.value()
 | 
			
		||||
	innerFd, _ := inner.Value()
 | 
			
		||||
	nested, err := bpfMapCreate(&bpfMapCreateAttr{
 | 
			
		||||
		mapType:    ArrayOfMaps,
 | 
			
		||||
		keySize:    4,
 | 
			
		||||
@@ -251,12 +203,12 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_ = nested.close()
 | 
			
		||||
	_ = nested.Close()
 | 
			
		||||
	return true
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
func bpfMapLookupElem(m *bpfFD, key, valueOut syscallPtr) error {
 | 
			
		||||
	fd, err := m.value()
 | 
			
		||||
func bpfMapLookupElem(m *internal.FD, key, valueOut internal.Pointer) error {
 | 
			
		||||
	fd, err := m.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -266,12 +218,27 @@ func bpfMapLookupElem(m *bpfFD, key, valueOut syscallPtr) error {
 | 
			
		||||
		key:   key,
 | 
			
		||||
		value: valueOut,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = bpfCall(_MapLookupElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	_, err = internal.BPF(_MapLookupElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfMapUpdateElem(m *bpfFD, key, valueOut syscallPtr, flags uint64) error {
 | 
			
		||||
	fd, err := m.value()
 | 
			
		||||
func bpfMapLookupAndDelete(m *internal.FD, key, valueOut internal.Pointer) error {
 | 
			
		||||
	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 {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -282,12 +249,12 @@ func bpfMapUpdateElem(m *bpfFD, key, valueOut syscallPtr, flags uint64) error {
 | 
			
		||||
		value: valueOut,
 | 
			
		||||
		flags: flags,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = bpfCall(_MapUpdateElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	_, err = internal.BPF(_MapUpdateElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfMapDeleteElem(m *bpfFD, key syscallPtr) error {
 | 
			
		||||
	fd, err := m.value()
 | 
			
		||||
func bpfMapDeleteElem(m *internal.FD, key internal.Pointer) error {
 | 
			
		||||
	fd, err := m.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -296,12 +263,12 @@ func bpfMapDeleteElem(m *bpfFD, key syscallPtr) error {
 | 
			
		||||
		mapFd: fd,
 | 
			
		||||
		key:   key,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = bpfCall(_MapDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	_, err = internal.BPF(_MapDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfMapGetNextKey(m *bpfFD, key, nextKeyOut syscallPtr) error {
 | 
			
		||||
	fd, err := m.value()
 | 
			
		||||
func bpfMapGetNextKey(m *internal.FD, key, nextKeyOut internal.Pointer) error {
 | 
			
		||||
	fd, err := m.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -311,13 +278,13 @@ func bpfMapGetNextKey(m *bpfFD, key, nextKeyOut syscallPtr) error {
 | 
			
		||||
		key:   key,
 | 
			
		||||
		value: nextKeyOut,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = bpfCall(_MapGetNextKey, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	_, err = internal.BPF(_MapGetNextKey, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const bpfFSType = 0xcafe4a11
 | 
			
		||||
 | 
			
		||||
func bpfPinObject(fileName string, fd *bpfFD) error {
 | 
			
		||||
func bpfPinObject(fileName string, fd *internal.FD) error {
 | 
			
		||||
	dirName := filepath.Dir(fileName)
 | 
			
		||||
	var statfs unix.Statfs_t
 | 
			
		||||
	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)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value, err := fd.value()
 | 
			
		||||
	value, err := fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = bpfCall(_ObjPin, unsafe.Pointer(&bpfPinObjAttr{
 | 
			
		||||
		fileName: newPtr(unsafe.Pointer(&[]byte(fileName)[0])),
 | 
			
		||||
	_, err = internal.BPF(_ObjPin, unsafe.Pointer(&bpfPinObjAttr{
 | 
			
		||||
		fileName: internal.NewStringPointer(fileName),
 | 
			
		||||
		fd:       value,
 | 
			
		||||
	}), 16)
 | 
			
		||||
	return errors.Wrapf(err, "pin object %s", fileName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfGetObject(fileName string) (*bpfFD, error) {
 | 
			
		||||
	ptr, err := bpfCall(_ObjGet, unsafe.Pointer(&bpfPinObjAttr{
 | 
			
		||||
		fileName: newPtr(unsafe.Pointer(&[]byte(fileName)[0])),
 | 
			
		||||
func bpfGetObject(fileName string) (*internal.FD, error) {
 | 
			
		||||
	ptr, err := internal.BPF(_ObjGet, unsafe.Pointer(&bpfPinObjAttr{
 | 
			
		||||
		fileName: internal.NewStringPointer(fileName),
 | 
			
		||||
	}), 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		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 {
 | 
			
		||||
	value, err := fd.value()
 | 
			
		||||
func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) error {
 | 
			
		||||
	value, err := fd.Value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -359,19 +326,19 @@ func bpfGetObjectInfoByFD(fd *bpfFD, info unsafe.Pointer, size uintptr) error {
 | 
			
		||||
	attr := bpfObjGetInfoByFDAttr{
 | 
			
		||||
		fd:      value,
 | 
			
		||||
		infoLen: uint32(size),
 | 
			
		||||
		info:    newPtr(info),
 | 
			
		||||
		info:    internal.NewPointer(info),
 | 
			
		||||
	}
 | 
			
		||||
	_, err = bpfCall(_ObjGetInfoByFD, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return errors.Wrapf(err, "fd %d", value)
 | 
			
		||||
	_, err = internal.BPF(_ObjGetInfoByFD, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return errors.Wrapf(err, "fd %d", fd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfGetProgInfoByFD(fd *bpfFD) (*bpfProgInfo, error) {
 | 
			
		||||
func bpfGetProgInfoByFD(fd *internal.FD) (*bpfProgInfo, error) {
 | 
			
		||||
	var info bpfProgInfo
 | 
			
		||||
	err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(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
 | 
			
		||||
	err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_ = fd.close()
 | 
			
		||||
	_ = fd.Close()
 | 
			
		||||
	return true
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
func bpfGetMapFDByID(id uint32) (*bpfFD, error) {
 | 
			
		||||
func bpfGetMapFDByID(id uint32) (*internal.FD, error) {
 | 
			
		||||
	// available from 4.13
 | 
			
		||||
	attr := bpfGetFDByIDAttr{
 | 
			
		||||
		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 {
 | 
			
		||||
		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
 | 
			
		||||
	attr := bpfGetFDByIDAttr{
 | 
			
		||||
		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 {
 | 
			
		||||
		return nil, errors.Wrapf(err, "can't get fd for program id %d", id)
 | 
			
		||||
	}
 | 
			
		||||
	return newBPFFD(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])
 | 
			
		||||
	return internal.NewFD(uint32(ptr)), nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
	// itself.
 | 
			
		||||
	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.
 | 
			
		||||
@@ -84,6 +108,13 @@ const (
 | 
			
		||||
	_ProgGetFDByID
 | 
			
		||||
	_MapGetFDByID
 | 
			
		||||
	_ObjGetInfoByFD
 | 
			
		||||
	_ProgQuery
 | 
			
		||||
	_RawTracepointOpen
 | 
			
		||||
	_BTFLoad
 | 
			
		||||
	_BTFGetFDByID
 | 
			
		||||
	_TaskFDQuery
 | 
			
		||||
	_MapLookupAndDeleteElem
 | 
			
		||||
	_MapFreeze
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
@@ -149,6 +180,8 @@ const (
 | 
			
		||||
	RawTracepointWritable
 | 
			
		||||
	// CGroupSockopt program
 | 
			
		||||
	CGroupSockopt
 | 
			
		||||
	// Tracing program
 | 
			
		||||
	Tracing
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// AttachType of the eBPF program, needed to differentiate allowed context accesses in
 | 
			
		||||
@@ -183,6 +216,9 @@ const (
 | 
			
		||||
	AttachCGroupUDP6Recvmsg
 | 
			
		||||
	AttachCGroupGetsockopt
 | 
			
		||||
	AttachCGroupSetsockopt
 | 
			
		||||
	AttachTraceRawTp
 | 
			
		||||
	AttachTraceFEntry
 | 
			
		||||
	AttachTraceFExit
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 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[ArrayOfMaps-12]
 | 
			
		||||
	_ = 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 {
 | 
			
		||||
	if i >= MapType(len(_MapType_index)-1) {
 | 
			
		||||
@@ -64,11 +76,12 @@ func _() {
 | 
			
		||||
	_ = x[CGroupSysctl-23]
 | 
			
		||||
	_ = x[RawTracepointWritable-24]
 | 
			
		||||
	_ = 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 {
 | 
			
		||||
	if i >= ProgramType(len(_ProgramType_index)-1) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user