summaryrefslogtreecommitdiff
path: root/vendor/github.com/cilium/ebpf/asm/instruction.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/cilium/ebpf/asm/instruction.go')
-rw-r--r--vendor/github.com/cilium/ebpf/asm/instruction.go859
1 files changed, 0 insertions, 859 deletions
diff --git a/vendor/github.com/cilium/ebpf/asm/instruction.go b/vendor/github.com/cilium/ebpf/asm/instruction.go
deleted file mode 100644
index f17d88b51..000000000
--- a/vendor/github.com/cilium/ebpf/asm/instruction.go
+++ /dev/null
@@ -1,859 +0,0 @@
-package asm
-
-import (
- "crypto/sha1"
- "encoding/binary"
- "encoding/hex"
- "errors"
- "fmt"
- "io"
- "math"
- "sort"
- "strings"
-
- "github.com/cilium/ebpf/internal/sys"
- "github.com/cilium/ebpf/internal/unix"
-)
-
-// InstructionSize is the size of a BPF instruction in bytes
-const InstructionSize = 8
-
-// RawInstructionOffset is an offset in units of raw BPF instructions.
-type RawInstructionOffset uint64
-
-var ErrUnreferencedSymbol = errors.New("unreferenced symbol")
-var ErrUnsatisfiedMapReference = errors.New("unsatisfied map reference")
-var ErrUnsatisfiedProgramReference = errors.New("unsatisfied program reference")
-
-// Bytes returns the offset of an instruction in bytes.
-func (rio RawInstructionOffset) Bytes() uint64 {
- return uint64(rio) * InstructionSize
-}
-
-// Instruction is a single eBPF instruction.
-type Instruction struct {
- OpCode OpCode
- Dst Register
- Src Register
- Offset int16
- Constant int64
-
- // Metadata contains optional metadata about this instruction.
- Metadata Metadata
-}
-
-// Unmarshal decodes a BPF instruction.
-func (ins *Instruction) Unmarshal(r io.Reader, bo binary.ByteOrder) (uint64, error) {
- data := make([]byte, InstructionSize)
- if _, err := io.ReadFull(r, data); err != nil {
- return 0, err
- }
-
- ins.OpCode = OpCode(data[0])
-
- regs := data[1]
- switch bo {
- case binary.LittleEndian:
- ins.Dst, ins.Src = Register(regs&0xF), Register(regs>>4)
- case binary.BigEndian:
- ins.Dst, ins.Src = Register(regs>>4), Register(regs&0xf)
- }
-
- ins.Offset = int16(bo.Uint16(data[2:4]))
- // Convert to int32 before widening to int64
- // to ensure the signed bit is carried over.
- ins.Constant = int64(int32(bo.Uint32(data[4:8])))
-
- if !ins.OpCode.IsDWordLoad() {
- return InstructionSize, nil
- }
-
- // Pull another instruction from the stream to retrieve the second
- // half of the 64-bit immediate value.
- if _, err := io.ReadFull(r, data); err != nil {
- // No Wrap, to avoid io.EOF clash
- return 0, errors.New("64bit immediate is missing second half")
- }
-
- // Require that all fields other than the value are zero.
- if bo.Uint32(data[0:4]) != 0 {
- return 0, errors.New("64bit immediate has non-zero fields")
- }
-
- cons1 := uint32(ins.Constant)
- cons2 := int32(bo.Uint32(data[4:8]))
- ins.Constant = int64(cons2)<<32 | int64(cons1)
-
- return 2 * InstructionSize, nil
-}
-
-// Marshal encodes a BPF instruction.
-func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error) {
- if ins.OpCode == InvalidOpCode {
- return 0, errors.New("invalid opcode")
- }
-
- isDWordLoad := ins.OpCode.IsDWordLoad()
-
- cons := int32(ins.Constant)
- if isDWordLoad {
- // Encode least significant 32bit first for 64bit operations.
- cons = int32(uint32(ins.Constant))
- }
-
- regs, err := newBPFRegisters(ins.Dst, ins.Src, bo)
- if err != nil {
- return 0, fmt.Errorf("can't marshal registers: %s", err)
- }
-
- data := make([]byte, InstructionSize)
- data[0] = byte(ins.OpCode)
- data[1] = byte(regs)
- bo.PutUint16(data[2:4], uint16(ins.Offset))
- bo.PutUint32(data[4:8], uint32(cons))
- if _, err := w.Write(data); err != nil {
- return 0, err
- }
-
- if !isDWordLoad {
- return InstructionSize, nil
- }
-
- // The first half of the second part of a double-wide instruction
- // must be zero. The second half carries the value.
- bo.PutUint32(data[0:4], 0)
- bo.PutUint32(data[4:8], uint32(ins.Constant>>32))
- if _, err := w.Write(data); err != nil {
- return 0, err
- }
-
- return 2 * InstructionSize, nil
-}
-
-// AssociateMap associates a Map with this Instruction.
-//
-// Implicitly clears the Instruction's Reference field.
-//
-// Returns an error if the Instruction is not a map load.
-func (ins *Instruction) AssociateMap(m FDer) error {
- if !ins.IsLoadFromMap() {
- return errors.New("not a load from a map")
- }
-
- ins.Metadata.Set(referenceMeta{}, nil)
- ins.Metadata.Set(mapMeta{}, m)
-
- return nil
-}
-
-// RewriteMapPtr changes an instruction to use a new map fd.
-//
-// Returns an error if the instruction doesn't load a map.
-//
-// Deprecated: use AssociateMap instead. If you cannot provide a Map,
-// wrap an fd in a type implementing FDer.
-func (ins *Instruction) RewriteMapPtr(fd int) error {
- if !ins.IsLoadFromMap() {
- return errors.New("not a load from a map")
- }
-
- ins.encodeMapFD(fd)
-
- return nil
-}
-
-func (ins *Instruction) encodeMapFD(fd int) {
- // Preserve the offset value for direct map loads.
- offset := uint64(ins.Constant) & (math.MaxUint32 << 32)
- rawFd := uint64(uint32(fd))
- ins.Constant = int64(offset | rawFd)
-}
-
-// MapPtr returns the map fd for this instruction.
-//
-// The result is undefined if the instruction is not a load from a map,
-// see IsLoadFromMap.
-//
-// Deprecated: use Map() instead.
-func (ins *Instruction) MapPtr() int {
- // If there is a map associated with the instruction, return its FD.
- if fd := ins.Metadata.Get(mapMeta{}); fd != nil {
- return fd.(FDer).FD()
- }
-
- // Fall back to the fd stored in the Constant field
- return ins.mapFd()
-}
-
-// mapFd returns the map file descriptor stored in the 32 least significant
-// bits of ins' Constant field.
-func (ins *Instruction) mapFd() int {
- return int(int32(ins.Constant))
-}
-
-// RewriteMapOffset changes the offset of a direct load from a map.
-//
-// Returns an error if the instruction is not a direct load.
-func (ins *Instruction) RewriteMapOffset(offset uint32) error {
- if !ins.OpCode.IsDWordLoad() {
- return fmt.Errorf("%s is not a 64 bit load", ins.OpCode)
- }
-
- if ins.Src != PseudoMapValue {
- return errors.New("not a direct load from a map")
- }
-
- fd := uint64(ins.Constant) & math.MaxUint32
- ins.Constant = int64(uint64(offset)<<32 | fd)
- return nil
-}
-
-func (ins *Instruction) mapOffset() uint32 {
- return uint32(uint64(ins.Constant) >> 32)
-}
-
-// IsLoadFromMap returns true if the instruction loads from a map.
-//
-// This covers both loading the map pointer and direct map value loads.
-func (ins *Instruction) IsLoadFromMap() bool {
- return ins.OpCode == LoadImmOp(DWord) && (ins.Src == PseudoMapFD || ins.Src == PseudoMapValue)
-}
-
-// IsFunctionCall returns true if the instruction calls another BPF function.
-//
-// This is not the same thing as a BPF helper call.
-func (ins *Instruction) IsFunctionCall() bool {
- return ins.OpCode.JumpOp() == Call && ins.Src == PseudoCall
-}
-
-// IsLoadOfFunctionPointer returns true if the instruction loads a function pointer.
-func (ins *Instruction) IsLoadOfFunctionPointer() bool {
- return ins.OpCode.IsDWordLoad() && ins.Src == PseudoFunc
-}
-
-// IsFunctionReference returns true if the instruction references another BPF
-// function, either by invoking a Call jump operation or by loading a function
-// pointer.
-func (ins *Instruction) IsFunctionReference() bool {
- return ins.IsFunctionCall() || ins.IsLoadOfFunctionPointer()
-}
-
-// IsBuiltinCall returns true if the instruction is a built-in call, i.e. BPF helper call.
-func (ins *Instruction) IsBuiltinCall() bool {
- return ins.OpCode.JumpOp() == Call && ins.Src == R0 && ins.Dst == R0
-}
-
-// IsConstantLoad returns true if the instruction loads a constant of the
-// given size.
-func (ins *Instruction) IsConstantLoad(size Size) bool {
- return ins.OpCode == LoadImmOp(size) && ins.Src == R0 && ins.Offset == 0
-}
-
-// Format implements fmt.Formatter.
-func (ins Instruction) Format(f fmt.State, c rune) {
- if c != 'v' {
- fmt.Fprintf(f, "{UNRECOGNIZED: %c}", c)
- return
- }
-
- op := ins.OpCode
-
- if op == InvalidOpCode {
- fmt.Fprint(f, "INVALID")
- return
- }
-
- // Omit trailing space for Exit
- if op.JumpOp() == Exit {
- fmt.Fprint(f, op)
- return
- }
-
- if ins.IsLoadFromMap() {
- fd := ins.mapFd()
- m := ins.Map()
- switch ins.Src {
- case PseudoMapFD:
- if m != nil {
- fmt.Fprintf(f, "LoadMapPtr dst: %s map: %s", ins.Dst, m)
- } else {
- fmt.Fprintf(f, "LoadMapPtr dst: %s fd: %d", ins.Dst, fd)
- }
-
- case PseudoMapValue:
- if m != nil {
- fmt.Fprintf(f, "LoadMapValue dst: %s, map: %s off: %d", ins.Dst, m, ins.mapOffset())
- } else {
- fmt.Fprintf(f, "LoadMapValue dst: %s, fd: %d off: %d", ins.Dst, fd, ins.mapOffset())
- }
- }
-
- goto ref
- }
-
- fmt.Fprintf(f, "%v ", op)
- switch cls := op.Class(); {
- case cls.isLoadOrStore():
- switch op.Mode() {
- case ImmMode:
- fmt.Fprintf(f, "dst: %s imm: %d", ins.Dst, ins.Constant)
- case AbsMode:
- fmt.Fprintf(f, "imm: %d", ins.Constant)
- case IndMode:
- fmt.Fprintf(f, "dst: %s src: %s imm: %d", ins.Dst, ins.Src, ins.Constant)
- case MemMode:
- fmt.Fprintf(f, "dst: %s src: %s off: %d imm: %d", ins.Dst, ins.Src, ins.Offset, ins.Constant)
- case XAddMode:
- fmt.Fprintf(f, "dst: %s src: %s", ins.Dst, ins.Src)
- }
-
- case cls.IsALU():
- fmt.Fprintf(f, "dst: %s ", ins.Dst)
- if op.ALUOp() == Swap || op.Source() == ImmSource {
- fmt.Fprintf(f, "imm: %d", ins.Constant)
- } else {
- fmt.Fprintf(f, "src: %s", ins.Src)
- }
-
- case cls.IsJump():
- switch jop := op.JumpOp(); jop {
- case Call:
- if ins.Src == PseudoCall {
- // bpf-to-bpf call
- fmt.Fprint(f, ins.Constant)
- } else {
- fmt.Fprint(f, BuiltinFunc(ins.Constant))
- }
-
- default:
- fmt.Fprintf(f, "dst: %s off: %d ", ins.Dst, ins.Offset)
- if op.Source() == ImmSource {
- fmt.Fprintf(f, "imm: %d", ins.Constant)
- } else {
- fmt.Fprintf(f, "src: %s", ins.Src)
- }
- }
- }
-
-ref:
- if ins.Reference() != "" {
- fmt.Fprintf(f, " <%s>", ins.Reference())
- }
-}
-
-func (ins Instruction) equal(other Instruction) bool {
- return ins.OpCode == other.OpCode &&
- ins.Dst == other.Dst &&
- ins.Src == other.Src &&
- ins.Offset == other.Offset &&
- ins.Constant == other.Constant
-}
-
-// Size returns the amount of bytes ins would occupy in binary form.
-func (ins Instruction) Size() uint64 {
- return uint64(InstructionSize * ins.OpCode.rawInstructions())
-}
-
-type symbolMeta struct{}
-
-// WithSymbol marks the Instruction as a Symbol, which other Instructions
-// can point to using corresponding calls to WithReference.
-func (ins Instruction) WithSymbol(name string) Instruction {
- ins.Metadata.Set(symbolMeta{}, name)
- return ins
-}
-
-// Sym creates a symbol.
-//
-// Deprecated: use WithSymbol instead.
-func (ins Instruction) Sym(name string) Instruction {
- return ins.WithSymbol(name)
-}
-
-// Symbol returns the value ins has been marked with using WithSymbol,
-// otherwise returns an empty string. A symbol is often an Instruction
-// at the start of a function body.
-func (ins Instruction) Symbol() string {
- sym, _ := ins.Metadata.Get(symbolMeta{}).(string)
- return sym
-}
-
-type referenceMeta struct{}
-
-// WithReference makes ins reference another Symbol or map by name.
-func (ins Instruction) WithReference(ref string) Instruction {
- ins.Metadata.Set(referenceMeta{}, ref)
- return ins
-}
-
-// Reference returns the Symbol or map name referenced by ins, if any.
-func (ins Instruction) Reference() string {
- ref, _ := ins.Metadata.Get(referenceMeta{}).(string)
- return ref
-}
-
-type mapMeta struct{}
-
-// Map returns the Map referenced by ins, if any.
-// An Instruction will contain a Map if e.g. it references an existing,
-// pinned map that was opened during ELF loading.
-func (ins Instruction) Map() FDer {
- fd, _ := ins.Metadata.Get(mapMeta{}).(FDer)
- return fd
-}
-
-type sourceMeta struct{}
-
-// WithSource adds source information about the Instruction.
-func (ins Instruction) WithSource(src fmt.Stringer) Instruction {
- ins.Metadata.Set(sourceMeta{}, src)
- return ins
-}
-
-// Source returns source information about the Instruction. The field is
-// present when the compiler emits BTF line info about the Instruction and
-// usually contains the line of source code responsible for it.
-func (ins Instruction) Source() fmt.Stringer {
- str, _ := ins.Metadata.Get(sourceMeta{}).(fmt.Stringer)
- return str
-}
-
-// A Comment can be passed to Instruction.WithSource to add a comment
-// to an instruction.
-type Comment string
-
-func (s Comment) String() string {
- return string(s)
-}
-
-// FDer represents a resource tied to an underlying file descriptor.
-// Used as a stand-in for e.g. ebpf.Map since that type cannot be
-// imported here and FD() is the only method we rely on.
-type FDer interface {
- FD() int
-}
-
-// Instructions is an eBPF program.
-type Instructions []Instruction
-
-// Unmarshal unmarshals an Instructions from a binary instruction stream.
-// All instructions in insns are replaced by instructions decoded from r.
-func (insns *Instructions) Unmarshal(r io.Reader, bo binary.ByteOrder) error {
- if len(*insns) > 0 {
- *insns = nil
- }
-
- var offset uint64
- for {
- var ins Instruction
- n, err := ins.Unmarshal(r, bo)
- if errors.Is(err, io.EOF) {
- break
- }
- if err != nil {
- return fmt.Errorf("offset %d: %w", offset, err)
- }
-
- *insns = append(*insns, ins)
- offset += n
- }
-
- return nil
-}
-
-// Name returns the name of the function insns belongs to, if any.
-func (insns Instructions) Name() string {
- if len(insns) == 0 {
- return ""
- }
- return insns[0].Symbol()
-}
-
-func (insns Instructions) String() string {
- return fmt.Sprint(insns)
-}
-
-// Size returns the amount of bytes insns would occupy in binary form.
-func (insns Instructions) Size() uint64 {
- var sum uint64
- for _, ins := range insns {
- sum += ins.Size()
- }
- return sum
-}
-
-// AssociateMap updates all Instructions that Reference the given symbol
-// to point to an existing Map m instead.
-//
-// Returns ErrUnreferencedSymbol error if no references to symbol are found
-// in insns. If symbol is anything else than the symbol name of map (e.g.
-// a bpf2bpf subprogram), an error is returned.
-func (insns Instructions) AssociateMap(symbol string, m FDer) error {
- if symbol == "" {
- return errors.New("empty symbol")
- }
-
- var found bool
- for i := range insns {
- ins := &insns[i]
- if ins.Reference() != symbol {
- continue
- }
-
- if err := ins.AssociateMap(m); err != nil {
- return err
- }
-
- found = true
- }
-
- if !found {
- return fmt.Errorf("symbol %s: %w", symbol, ErrUnreferencedSymbol)
- }
-
- return nil
-}
-
-// RewriteMapPtr rewrites all loads of a specific map pointer to a new fd.
-//
-// Returns ErrUnreferencedSymbol if the symbol isn't used.
-//
-// Deprecated: use AssociateMap instead.
-func (insns Instructions) RewriteMapPtr(symbol string, fd int) error {
- if symbol == "" {
- return errors.New("empty symbol")
- }
-
- var found bool
- for i := range insns {
- ins := &insns[i]
- if ins.Reference() != symbol {
- continue
- }
-
- if !ins.IsLoadFromMap() {
- return errors.New("not a load from a map")
- }
-
- ins.encodeMapFD(fd)
-
- found = true
- }
-
- if !found {
- return fmt.Errorf("symbol %s: %w", symbol, ErrUnreferencedSymbol)
- }
-
- return nil
-}
-
-// SymbolOffsets returns the set of symbols and their offset in
-// the instructions.
-func (insns Instructions) SymbolOffsets() (map[string]int, error) {
- offsets := make(map[string]int)
-
- for i, ins := range insns {
- if ins.Symbol() == "" {
- continue
- }
-
- if _, ok := offsets[ins.Symbol()]; ok {
- return nil, fmt.Errorf("duplicate symbol %s", ins.Symbol())
- }
-
- offsets[ins.Symbol()] = i
- }
-
- return offsets, nil
-}
-
-// FunctionReferences returns a set of symbol names these Instructions make
-// bpf-to-bpf calls to.
-func (insns Instructions) FunctionReferences() []string {
- calls := make(map[string]struct{})
- for _, ins := range insns {
- if ins.Constant != -1 {
- // BPF-to-BPF calls have -1 constants.
- continue
- }
-
- if ins.Reference() == "" {
- continue
- }
-
- if !ins.IsFunctionReference() {
- continue
- }
-
- calls[ins.Reference()] = struct{}{}
- }
-
- result := make([]string, 0, len(calls))
- for call := range calls {
- result = append(result, call)
- }
-
- sort.Strings(result)
- return result
-}
-
-// ReferenceOffsets returns the set of references and their offset in
-// the instructions.
-func (insns Instructions) ReferenceOffsets() map[string][]int {
- offsets := make(map[string][]int)
-
- for i, ins := range insns {
- if ins.Reference() == "" {
- continue
- }
-
- offsets[ins.Reference()] = append(offsets[ins.Reference()], i)
- }
-
- return offsets
-}
-
-// Format implements fmt.Formatter.
-//
-// You can control indentation of symbols by
-// specifying a width. Setting a precision controls the indentation of
-// instructions.
-// The default character is a tab, which can be overridden by specifying
-// the ' ' space flag.
-func (insns Instructions) Format(f fmt.State, c rune) {
- if c != 's' && c != 'v' {
- fmt.Fprintf(f, "{UNKNOWN FORMAT '%c'}", c)
- return
- }
-
- // Precision is better in this case, because it allows
- // specifying 0 padding easily.
- padding, ok := f.Precision()
- if !ok {
- padding = 1
- }
-
- indent := strings.Repeat("\t", padding)
- if f.Flag(' ') {
- indent = strings.Repeat(" ", padding)
- }
-
- symPadding, ok := f.Width()
- if !ok {
- symPadding = padding - 1
- }
- if symPadding < 0 {
- symPadding = 0
- }
-
- symIndent := strings.Repeat("\t", symPadding)
- if f.Flag(' ') {
- symIndent = strings.Repeat(" ", symPadding)
- }
-
- // Guess how many digits we need at most, by assuming that all instructions
- // are double wide.
- highestOffset := len(insns) * 2
- offsetWidth := int(math.Ceil(math.Log10(float64(highestOffset))))
-
- iter := insns.Iterate()
- for iter.Next() {
- if iter.Ins.Symbol() != "" {
- fmt.Fprintf(f, "%s%s:\n", symIndent, iter.Ins.Symbol())
- }
- if src := iter.Ins.Source(); src != nil {
- line := strings.TrimSpace(src.String())
- if line != "" {
- fmt.Fprintf(f, "%s%*s; %s\n", indent, offsetWidth, " ", line)
- }
- }
- fmt.Fprintf(f, "%s%*d: %v\n", indent, offsetWidth, iter.Offset, iter.Ins)
- }
-}
-
-// Marshal encodes a BPF program into the kernel format.
-//
-// insns may be modified if there are unresolved jumps or bpf2bpf calls.
-//
-// Returns ErrUnsatisfiedProgramReference if there is a Reference Instruction
-// without a matching Symbol Instruction within insns.
-func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error {
- if err := insns.encodeFunctionReferences(); err != nil {
- return err
- }
-
- if err := insns.encodeMapPointers(); err != nil {
- return err
- }
-
- for i, ins := range insns {
- if _, err := ins.Marshal(w, bo); err != nil {
- return fmt.Errorf("instruction %d: %w", i, err)
- }
- }
- return nil
-}
-
-// Tag calculates the kernel tag for a series of instructions.
-//
-// It mirrors bpf_prog_calc_tag in the kernel and so can be compared
-// to ProgramInfo.Tag to figure out whether a loaded program matches
-// certain instructions.
-func (insns Instructions) Tag(bo binary.ByteOrder) (string, error) {
- h := sha1.New()
- for i, ins := range insns {
- if ins.IsLoadFromMap() {
- ins.Constant = 0
- }
- _, err := ins.Marshal(h, bo)
- if err != nil {
- return "", fmt.Errorf("instruction %d: %w", i, err)
- }
- }
- return hex.EncodeToString(h.Sum(nil)[:unix.BPF_TAG_SIZE]), nil
-}
-
-// encodeFunctionReferences populates the Offset (or Constant, depending on
-// the instruction type) field of instructions with a Reference field to point
-// to the offset of the corresponding instruction with a matching Symbol field.
-//
-// Only Reference Instructions that are either jumps or BPF function references
-// (calls or function pointer loads) are populated.
-//
-// Returns ErrUnsatisfiedProgramReference if there is a Reference Instruction
-// without at least one corresponding Symbol Instruction within insns.
-func (insns Instructions) encodeFunctionReferences() error {
- // Index the offsets of instructions tagged as a symbol.
- symbolOffsets := make(map[string]RawInstructionOffset)
- iter := insns.Iterate()
- for iter.Next() {
- ins := iter.Ins
-
- if ins.Symbol() == "" {
- continue
- }
-
- if _, ok := symbolOffsets[ins.Symbol()]; ok {
- return fmt.Errorf("duplicate symbol %s", ins.Symbol())
- }
-
- symbolOffsets[ins.Symbol()] = iter.Offset
- }
-
- // Find all instructions tagged as references to other symbols.
- // Depending on the instruction type, populate their constant or offset
- // fields to point to the symbol they refer to within the insn stream.
- iter = insns.Iterate()
- for iter.Next() {
- i := iter.Index
- offset := iter.Offset
- ins := iter.Ins
-
- if ins.Reference() == "" {
- continue
- }
-
- switch {
- case ins.IsFunctionReference() && ins.Constant == -1:
- symOffset, ok := symbolOffsets[ins.Reference()]
- if !ok {
- return fmt.Errorf("%s at insn %d: symbol %q: %w", ins.OpCode, i, ins.Reference(), ErrUnsatisfiedProgramReference)
- }
-
- ins.Constant = int64(symOffset - offset - 1)
-
- case ins.OpCode.Class().IsJump() && ins.Offset == -1:
- symOffset, ok := symbolOffsets[ins.Reference()]
- if !ok {
- return fmt.Errorf("%s at insn %d: symbol %q: %w", ins.OpCode, i, ins.Reference(), ErrUnsatisfiedProgramReference)
- }
-
- ins.Offset = int16(symOffset - offset - 1)
- }
- }
-
- return nil
-}
-
-// encodeMapPointers finds all Map Instructions and encodes their FDs
-// into their Constant fields.
-func (insns Instructions) encodeMapPointers() error {
- iter := insns.Iterate()
- for iter.Next() {
- ins := iter.Ins
-
- if !ins.IsLoadFromMap() {
- continue
- }
-
- m := ins.Map()
- if m == nil {
- continue
- }
-
- fd := m.FD()
- if fd < 0 {
- return fmt.Errorf("map %s: %w", m, sys.ErrClosedFd)
- }
-
- ins.encodeMapFD(m.FD())
- }
-
- return nil
-}
-
-// Iterate allows iterating a BPF program while keeping track of
-// various offsets.
-//
-// Modifying the instruction slice will lead to undefined behaviour.
-func (insns Instructions) Iterate() *InstructionIterator {
- return &InstructionIterator{insns: insns}
-}
-
-// InstructionIterator iterates over a BPF program.
-type InstructionIterator struct {
- insns Instructions
- // The instruction in question.
- Ins *Instruction
- // The index of the instruction in the original instruction slice.
- Index int
- // The offset of the instruction in raw BPF instructions. This accounts
- // for double-wide instructions.
- Offset RawInstructionOffset
-}
-
-// Next returns true as long as there are any instructions remaining.
-func (iter *InstructionIterator) Next() bool {
- if len(iter.insns) == 0 {
- return false
- }
-
- if iter.Ins != nil {
- iter.Index++
- iter.Offset += RawInstructionOffset(iter.Ins.OpCode.rawInstructions())
- }
- iter.Ins = &iter.insns[0]
- iter.insns = iter.insns[1:]
- return true
-}
-
-type bpfRegisters uint8
-
-func newBPFRegisters(dst, src Register, bo binary.ByteOrder) (bpfRegisters, error) {
- switch bo {
- case binary.LittleEndian:
- return bpfRegisters((src << 4) | (dst & 0xF)), nil
- case binary.BigEndian:
- return bpfRegisters((dst << 4) | (src & 0xF)), nil
- default:
- return 0, fmt.Errorf("unrecognized ByteOrder %T", bo)
- }
-}
-
-// IsUnreferencedSymbol returns true if err was caused by
-// an unreferenced symbol.
-//
-// Deprecated: use errors.Is(err, asm.ErrUnreferencedSymbol).
-func IsUnreferencedSymbol(err error) bool {
- return errors.Is(err, ErrUnreferencedSymbol)
-}