From 7bfde557067284eaccac0d2a3c9a82445867a01a Mon Sep 17 00:00:00 2001 From: Dylan Reimerink Date: Tue, 22 Feb 2022 18:20:08 +0100 Subject: [PATCH] asm: moved Instruction.Symbol and Instruction.Reference into metadata This commit adds per-instruction metadata, which is sparse in nature, meaning that most instructions don't have metadata but some do. Metadata is linked to an instruction via a pointer which is nil by default, thus if an instruction has no metadata, at most one pointer worth of space is unused which is desirable since we expect the size of the metadata struct to grow in future commits. The metadata struct is copy-on-write, so multiple instructions can share the same metadata object after being copied, but as soon as a modification on one of the instruction's metadata is performed, the metadata object is copied so writes to a copied instruction doesn't effect the original instruction. This commit also deprecates `Instruction.Sym` in favor of `Instruction.WithSymbol`. This follows the convention of prefixing func names with `With...` if they have value receivers to make it clear to callers that this doesn't modify the instruction it is being called on. --- asm/dsl_test.go | 18 ++-- asm/instruction.go | 136 +++++++++++++++++++++++------- asm/instruction_test.go | 4 +- asm/jump.go | 66 +++++++++------ collection.go | 8 +- collection_test.go | 6 +- elf_reader.go | 12 ++- elf_reader_test.go | 2 +- example_sock_extract_dist_test.go | 8 +- features/misc.go | 6 +- info.go | 2 +- linker.go | 2 +- linker_test.go | 6 +- prog.go | 4 +- prog_test.go | 14 ++- ringbuf/reader_test.go | 2 +- 16 files changed, 200 insertions(+), 96 deletions(-) diff --git a/asm/dsl_test.go b/asm/dsl_test.go index ddbf8172a..b529678d6 100644 --- a/asm/dsl_test.go +++ b/asm/dsl_test.go @@ -25,21 +25,29 @@ func TestDSL(t *testing.T) { OpCode: 0x04, Dst: R1, Constant: 22, }}, {"JSGT.Imm", JSGT.Imm(R1, 4, "foo"), Instruction{ - OpCode: 0x65, Dst: R1, Constant: 4, Offset: -1, Reference: "foo", + OpCode: 0x65, Dst: R1, Constant: 4, Offset: -1, metadata: &metadata{ + reference: "foo", + }, }}, {"JSGT.Imm32", JSGT.Imm32(R1, -2, "foo"), Instruction{ - OpCode: 0x66, Dst: R1, Constant: -2, Offset: -1, Reference: "foo", + OpCode: 0x66, Dst: R1, Constant: -2, Offset: -1, metadata: &metadata{ + reference: "foo", + }, }}, {"JSLT.Reg", JSLT.Reg(R1, R2, "foo"), Instruction{ - OpCode: 0xcd, Dst: R1, Src: R2, Offset: -1, Reference: "foo", + OpCode: 0xcd, Dst: R1, Src: R2, Offset: -1, metadata: &metadata{ + reference: "foo", + }, }}, {"JSLT.Reg32", JSLT.Reg32(R1, R3, "foo"), Instruction{ - OpCode: 0xce, Dst: R1, Src: R3, Offset: -1, Reference: "foo", + OpCode: 0xce, Dst: R1, Src: R3, Offset: -1, metadata: &metadata{ + reference: "foo", + }, }}, } for _, tc := range testcases { - if tc.have != tc.want { + if !tc.have.equal(tc.want) { t.Errorf("%s: have %v, want %v", tc.name, tc.have, tc.want) } } diff --git a/asm/instruction.go b/asm/instruction.go index bc3b883f4..32f72dd83 100644 --- a/asm/instruction.go +++ b/asm/instruction.go @@ -35,17 +35,36 @@ type Instruction struct { Offset int16 Constant int64 - // Reference denotes a reference (e.g. a jump) to another symbol. - Reference string + // Metadata contains optional metadata about this instruction + metadata *metadata +} + +// WithSymbol adds symbol metadata to the instruction, which other instructions can use as Reference. +func (ins Instruction) WithSymbol(name string) Instruction { + if (ins.metadata != nil && ins.metadata.symbol == name) || + (ins.metadata == nil && name == "") { + return ins + } - // Symbol denotes an instruction at the start of a function body. - Symbol string + ins.metadata = ins.metadata.copy() + ins.metadata.symbol = name + return ins } // Sym creates a symbol. +// +// Deprecated: use WithSymbol instread func (ins Instruction) Sym(name string) Instruction { - ins.Symbol = name - return ins + return ins.WithSymbol(name) +} + +// Symbol returns the name of the function that starts at ins. +func (ins Instruction) Symbol() string { + if ins.metadata == nil { + return "" + } + + return ins.metadata.symbol } // Unmarshal decodes a BPF instruction. @@ -299,16 +318,75 @@ func (ins Instruction) Format(f fmt.State, c rune) { } ref: - if ins.Reference != "" { - fmt.Fprintf(f, " <%s>", ins.Reference) + 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()) } +// SetReference makes ins reference another Instruction by name within the same +func (ins *Instruction) SetReference(ref string) { + if (ins.metadata != nil && ins.metadata.reference == ref) || + (ins.metadata == nil && ref == "") { + return + } + + ins.metadata = ins.metadata.copy() + ins.metadata.reference = ref +} + +// Reference returns a reference (e.g. a jump) to another symbol. +func (ins Instruction) Reference() string { + if ins.metadata == nil { + return "" + } + + return ins.metadata.reference +} + +// FDer isn't actually used as a meaningful interface, rater it is used because we can't directly use types from the +// ebpf package since this would cause in import loop. +type FDer interface { + FD() int +} + +// metadata holds metadata about an Instruction. +type metadata struct { + // reference denotes a reference (e.g. a jump) to another symbol. + reference string + // symbol denotes an instruction at the start of a function body. + symbol string +} + +// copy returns a copy of metadata. +// Always returns a valid pointer, even when called on a nil metadata. +func (m *metadata) copy() *metadata { + var copy metadata + if m != nil { + copy = *m + } + return © +} + +// SimpleContext can be used to set a string as context of an Instruction. +type SimpleContext string + +func (sc SimpleContext) String() string { + return string(sc) +} + // Instructions is an eBPF program. type Instructions []Instruction @@ -342,7 +420,7 @@ func (insns Instructions) Name() string { if len(insns) == 0 { return "" } - return insns[0].Symbol + return insns[0].Symbol() } func (insns Instructions) String() string { @@ -369,7 +447,7 @@ func (insns Instructions) RewriteMapPtr(symbol string, fd int) error { found := false for i := range insns { ins := &insns[i] - if ins.Reference != symbol { + if ins.Reference() != symbol { continue } @@ -393,15 +471,15 @@ func (insns Instructions) SymbolOffsets() (map[string]int, error) { offsets := make(map[string]int) for i, ins := range insns { - if ins.Symbol == "" { + if ins.Symbol() == "" { continue } - if _, ok := offsets[ins.Symbol]; ok { - return nil, fmt.Errorf("duplicate symbol %s", ins.Symbol) + if _, ok := offsets[ins.Symbol()]; ok { + return nil, fmt.Errorf("duplicate symbol %s", ins.Symbol()) } - offsets[ins.Symbol] = i + offsets[ins.Symbol()] = i } return offsets, nil @@ -418,7 +496,7 @@ func (insns Instructions) FunctionReferences() map[string]bool { continue } - if ins.Reference == "" { + if ins.Reference() == "" { continue } @@ -426,7 +504,7 @@ func (insns Instructions) FunctionReferences() map[string]bool { continue } - calls[ins.Reference] = true + calls[ins.Reference()] = true } return calls @@ -438,11 +516,11 @@ func (insns Instructions) ReferenceOffsets() map[string][]int { offsets := make(map[string][]int) for i, ins := range insns { - if ins.Reference == "" { + if ins.Reference() == "" { continue } - offsets[ins.Reference] = append(offsets[ins.Reference], i) + offsets[ins.Reference()] = append(offsets[ins.Reference()], i) } return offsets @@ -493,8 +571,8 @@ func (insns Instructions) Format(f fmt.State, c rune) { iter := insns.Iterate() for iter.Next() { - if iter.Ins.Symbol != "" { - fmt.Fprintf(f, "%s%s:\n", symIndent, iter.Ins.Symbol) + if iter.Ins.Symbol() != "" { + fmt.Fprintf(f, "%s%s:\n", symIndent, iter.Ins.Symbol()) } fmt.Fprintf(f, "%s%*d: %v\n", indent, offsetWidth, iter.Offset, iter.Ins) } @@ -552,15 +630,15 @@ func (insns Instructions) resolveFunctionReferences() error { for iter.Next() { ins := iter.Ins - if ins.Symbol == "" { + if ins.Symbol() == "" { continue } - if _, ok := symbolOffsets[ins.Symbol]; ok { - return fmt.Errorf("duplicate symbol %s", ins.Symbol) + if _, ok := symbolOffsets[ins.Symbol()]; ok { + return fmt.Errorf("duplicate symbol %s", ins.Symbol()) } - symbolOffsets[ins.Symbol] = iter.Offset + symbolOffsets[ins.Symbol()] = iter.Offset } // Find all instructions tagged as references to other symbols. @@ -572,23 +650,23 @@ func (insns Instructions) resolveFunctionReferences() error { offset := iter.Offset ins := iter.Ins - if ins.Reference == "" { + if ins.Reference() == "" { continue } switch { case ins.IsFunctionReference() && ins.Constant == -1: - symOffset, ok := symbolOffsets[ins.Reference] + symOffset, ok := symbolOffsets[ins.Reference()] if !ok { - return fmt.Errorf("%s at insn %d: symbol %q: %w", ins.OpCode, i, ins.Reference, ErrUnsatisfiedProgramReference) + 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] + symOffset, ok := symbolOffsets[ins.Reference()] if !ok { - return fmt.Errorf("%s at insn %d: symbol %q: %w", ins.OpCode, i, ins.Reference, ErrUnsatisfiedProgramReference) + return fmt.Errorf("%s at insn %d: symbol %q: %w", ins.OpCode, i, ins.Reference(), ErrUnsatisfiedProgramReference) } ins.Offset = int16(symOffset - offset - 1) diff --git a/asm/instruction_test.go b/asm/instruction_test.go index b18c0f3a0..d41646411 100644 --- a/asm/instruction_test.go +++ b/asm/instruction_test.go @@ -154,7 +154,7 @@ func TestInstructionsRewriteMapPtr(t *testing.T) { LoadMapPtr(R1, 0), Return(), } - insns[0].Reference = "good" + insns[0].SetReference("good") if err := insns.RewriteMapPtr("good", 1); err != nil { t.Fatal(err) @@ -181,7 +181,7 @@ func TestInstructionsRewriteMapPtr(t *testing.T) { // program is stringified. func ExampleInstructions_Format() { insns := Instructions{ - FnMapLookupElem.Call().Sym("my_func"), + FnMapLookupElem.Call().WithSymbol("my_func"), LoadImm(R0, 42, DWord), Return(), } diff --git a/asm/jump.go b/asm/jump.go index 199c06940..0dc4bf494 100644 --- a/asm/jump.go +++ b/asm/jump.go @@ -63,11 +63,13 @@ func (op JumpOp) Op(source Source) OpCode { // Imm compares 64 bit dst to 64 bit value (sign extended), and adjusts PC by offset if the condition is fulfilled. func (op JumpOp) Imm(dst Register, value int32, label string) Instruction { return Instruction{ - OpCode: op.opCode(JumpClass, ImmSource), - Dst: dst, - Offset: -1, - Constant: int64(value), - Reference: label, + OpCode: op.opCode(JumpClass, ImmSource), + Dst: dst, + Offset: -1, + Constant: int64(value), + metadata: &metadata{ + reference: label, + }, } } @@ -75,22 +77,26 @@ func (op JumpOp) Imm(dst Register, value int32, label string) Instruction { // Requires kernel 5.1. func (op JumpOp) Imm32(dst Register, value int32, label string) Instruction { return Instruction{ - OpCode: op.opCode(Jump32Class, ImmSource), - Dst: dst, - Offset: -1, - Constant: int64(value), - Reference: label, + OpCode: op.opCode(Jump32Class, ImmSource), + Dst: dst, + Offset: -1, + Constant: int64(value), + metadata: &metadata{ + reference: label, + }, } } // Reg compares 64 bit dst to 64 bit src, and adjusts PC by offset if the condition is fulfilled. func (op JumpOp) Reg(dst, src Register, label string) Instruction { return Instruction{ - OpCode: op.opCode(JumpClass, RegSource), - Dst: dst, - Src: src, - Offset: -1, - Reference: label, + OpCode: op.opCode(JumpClass, RegSource), + Dst: dst, + Src: src, + Offset: -1, + metadata: &metadata{ + reference: label, + }, } } @@ -98,11 +104,13 @@ func (op JumpOp) Reg(dst, src Register, label string) Instruction { // Requires kernel 5.1. func (op JumpOp) Reg32(dst, src Register, label string) Instruction { return Instruction{ - OpCode: op.opCode(Jump32Class, RegSource), - Dst: dst, - Src: src, - Offset: -1, - Reference: label, + OpCode: op.opCode(Jump32Class, RegSource), + Dst: dst, + Src: src, + Offset: -1, + metadata: &metadata{ + reference: label, + }, } } @@ -118,16 +126,20 @@ func (op JumpOp) opCode(class Class, source Source) OpCode { func (op JumpOp) Label(label string) Instruction { if op == Call { return Instruction{ - OpCode: OpCode(JumpClass).SetJumpOp(Call), - Src: PseudoCall, - Constant: -1, - Reference: label, + OpCode: OpCode(JumpClass).SetJumpOp(Call), + Src: PseudoCall, + Constant: -1, + metadata: &metadata{ + reference: label, + }, } } return Instruction{ - OpCode: OpCode(JumpClass).SetJumpOp(op), - Offset: -1, - Reference: label, + OpCode: OpCode(JumpClass).SetJumpOp(op), + Offset: -1, + metadata: &metadata{ + reference: label, + }, } } diff --git a/collection.go b/collection.go index 0e0dc5322..c435ac5b0 100644 --- a/collection.go +++ b/collection.go @@ -452,7 +452,7 @@ func (cl *collectionLoader) loadProgram(progName string) (*Program, error) { for i := range progSpec.Instructions { ins := &progSpec.Instructions[i] - if !ins.IsLoadFromMap() || ins.Reference == "" { + if !ins.IsLoadFromMap() || ins.Reference() == "" { continue } @@ -462,17 +462,17 @@ func (cl *collectionLoader) loadProgram(progName string) (*Program, error) { continue } - m, err := cl.loadMap(ins.Reference) + m, err := cl.loadMap(ins.Reference()) if err != nil { return nil, fmt.Errorf("program %s: %w", progName, err) } fd := m.FD() if fd < 0 { - return nil, fmt.Errorf("map %s: %w", ins.Reference, sys.ErrClosedFd) + return nil, fmt.Errorf("map %s: %w", ins.Reference(), sys.ErrClosedFd) } if err := ins.RewriteMapPtr(m.FD()); err != nil { - return nil, fmt.Errorf("program %s: map %s: %w", progName, ins.Reference, err) + return nil, fmt.Errorf("program %s: map %s: %w", progName, ins.Reference(), err) } } diff --git a/collection_test.go b/collection_test.go index 13ac84dbf..d731ffcee 100644 --- a/collection_test.go +++ b/collection_test.go @@ -32,7 +32,7 @@ func TestCollectionSpecNotModified(t *testing.T) { }, } - cs.Programs["test"].Instructions[0].Reference = "my-map" + cs.Programs["test"].Instructions[0].SetReference("my-map") coll, err := NewCollection(&cs) if err != nil { @@ -94,9 +94,9 @@ func TestCollectionSpecRewriteMaps(t *testing.T) { asm.FnMapLookupElem.Call(), asm.JEq.Imm(asm.R0, 0, "ret"), asm.LoadMem(asm.R0, asm.R0, 0, asm.Word), - asm.Return().Sym("ret"), + asm.Return().WithSymbol("ret"), } - insns[0].Reference = "test-map" + insns[0].SetReference("test-map") cs := &CollectionSpec{ Maps: map[string]*MapSpec{ diff --git a/elf_reader.go b/elf_reader.go index 774956c90..0fc7d16ed 100644 --- a/elf_reader.go +++ b/elf_reader.go @@ -349,10 +349,8 @@ func (ec *elfCode) loadFunctions(section *elfSection) (map[string]asm.Instructio insns asm.Instructions ) for { - ins := asm.Instruction{ - // Symbols denote the first instruction of a function body. - Symbol: section.symbols[offset].Name, - } + // Symbols denote the first instruction of a function body. + ins := asm.Instruction{}.WithSymbol(section.symbols[offset].Name) // Pull one instruction from the instruction stream. n, err := ins.Unmarshal(r, ec.ByteOrder) @@ -374,7 +372,7 @@ func (ec *elfCode) loadFunctions(section *elfSection) (map[string]asm.Instructio // Decoded the first instruction of a function body but insns already // holds a valid instruction stream. Store the result and flush insns. - if ins.Symbol != "" && insns.Name() != "" { + if ins.Symbol() != "" && insns.Name() != "" { funcs[insns.Name()] = insns insns = nil } @@ -399,7 +397,7 @@ func (ec *elfCode) loadFunctions(section *elfSection) (map[string]asm.Instructio return nil, fmt.Errorf("offset %d: no jump target found at offset %d", offset, tgt) } - ins.Reference = sym + ins.SetReference(sym) ins.Constant = -1 } } @@ -579,7 +577,7 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err return fmt.Errorf("relocation to %q: %w", target.Name, ErrNotSupported) } - ins.Reference = name + ins.SetReference(name) return nil } diff --git a/elf_reader_test.go b/elf_reader_test.go index 01a35df14..ccf7e4d4a 100644 --- a/elf_reader_test.go +++ b/elf_reader_test.go @@ -260,7 +260,7 @@ func TestInlineASMConstant(t *testing.T) { } spec := coll.Programs["asm_relocation"] - if spec.Instructions[0].Reference != "MY_CONST" { + if spec.Instructions[0].Reference() != "MY_CONST" { t.Fatal("First instruction is not a reference to MY_CONST") } diff --git a/example_sock_extract_dist_test.go b/example_sock_extract_dist_test.go index 25dccf65c..cbd1254fd 100644 --- a/example_sock_extract_dist_test.go +++ b/example_sock_extract_dist_test.go @@ -107,11 +107,11 @@ func newDistanceFilter() (*ebpf.Program, *ebpf.Map, error) { // 7th byte in IPv6 is Hop count // LDABS requires ctx in R6 - asm.Mov.Reg(asm.R6, asm.R1).Sym("ipv6"), + asm.Mov.Reg(asm.R6, asm.R1).WithSymbol("ipv6"), asm.LoadAbs(-0x100000+7, asm.Byte), // stash the load result into FP[-4] - asm.StoreMem(asm.RFP, -4, asm.R0, asm.Word).Sym("store-ttl"), + asm.StoreMem(asm.RFP, -4, asm.R0, asm.Word).WithSymbol("store-ttl"), // stash the &FP[-4] into r2 asm.Mov.Reg(asm.R2, asm.RFP), asm.Add.Imm(asm.R2, -4), @@ -128,7 +128,7 @@ func newDistanceFilter() (*ebpf.Program, *ebpf.Map, error) { // MapUpdate // r1 has map ptr - asm.LoadMapPtr(asm.R1, ttls.FD()).Sym("update-map"), + asm.LoadMapPtr(asm.R1, ttls.FD()).WithSymbol("update-map"), // r2 has key -> &FP[-4] asm.Mov.Reg(asm.R2, asm.RFP), asm.Add.Imm(asm.R2, -4), @@ -141,7 +141,7 @@ func newDistanceFilter() (*ebpf.Program, *ebpf.Map, error) { asm.FnMapUpdateElem.Call(), // set exit code to -1, don't trunc packet - asm.Mov.Imm(asm.R0, -1).Sym("exit"), + asm.Mov.Imm(asm.R0, -1).WithSymbol("exit"), asm.Return(), } diff --git a/features/misc.go b/features/misc.go index 1c2802dd9..8a81f001a 100644 --- a/features/misc.go +++ b/features/misc.go @@ -129,7 +129,7 @@ func createMiscProbeAttr(mt miscType) (*sys.ProgLoadAttr, error) { case boundedLoops: insns = asm.Instructions{ asm.Mov.Imm(asm.R0, 10), - asm.Sub.Imm(asm.R0, 1).Sym("loop"), + asm.Sub.Imm(asm.R0, 1).WithSymbol("loop"), asm.JNE.Imm(asm.R0, 0, "loop"), asm.Return(), } @@ -138,14 +138,14 @@ func createMiscProbeAttr(mt miscType) (*sys.ProgLoadAttr, error) { asm.Mov.Imm(asm.R0, 0), asm.JLT.Imm(asm.R0, 0, "exit"), asm.Mov.Imm(asm.R0, 1), - asm.Return().Sym("exit"), + asm.Return().WithSymbol("exit"), } case v3ISA: insns = asm.Instructions{ asm.Mov.Imm(asm.R0, 0), asm.JLT.Imm32(asm.R0, 0, "exit"), asm.Mov.Imm(asm.R0, 1), - asm.Return().Sym("exit"), + asm.Return().WithSymbol("exit"), } default: return nil, fmt.Errorf("misc probe %d not implemented", mt) diff --git a/info.go b/info.go index cf692c762..c1ad3fa5a 100644 --- a/info.go +++ b/info.go @@ -233,7 +233,7 @@ func (pi *ProgramInfo) Instructions() (asm.Instructions, error) { } // Tag the first instruction with the name of the program, if available. - insns[0] = insns[0].Sym(pi.Name) + insns[0] = insns[0].WithSymbol(pi.Name) return insns, nil } diff --git a/linker.go b/linker.go index f9cf84cd2..594073e71 100644 --- a/linker.go +++ b/linker.go @@ -123,7 +123,7 @@ func fixupAndValidate(insns asm.Instructions) error { ins := iter.Ins if ins.IsLoadFromMap() && ins.MapPtr() == -1 { - return fmt.Errorf("instruction %d: map %s: %w", iter.Index, ins.Reference, asm.ErrUnsatisfiedMapReference) + return fmt.Errorf("instruction %d: map %s: %w", iter.Index, ins.Reference(), asm.ErrUnsatisfiedMapReference) } fixupProbeReadKernel(ins) diff --git a/linker_test.go b/linker_test.go index 34e028de9..38327aa11 100644 --- a/linker_test.go +++ b/linker_test.go @@ -24,13 +24,13 @@ func TestFindReferences(t *testing.T) { }, "my_other_func": { Instructions: asm.Instructions{ - asm.LoadImm(asm.R0, 1337, asm.DWord).Sym("my_other_func"), + asm.LoadImm(asm.R0, 1337, asm.DWord).WithSymbol("my_other_func"), asm.Return(), }, }, "my_func": { Instructions: asm.Instructions{ - asm.Call.Label("my_other_func").Sym("my_func"), + asm.Call.Label("my_other_func").WithSymbol("my_func"), asm.Return(), }, }, @@ -80,7 +80,7 @@ func TestForwardFunctionDeclaration(t *testing.T) { // Append the implementation of fwd(). spec.Instructions = append(spec.Instructions, - asm.Mov.Imm32(asm.R0, 23).Sym("fwd"), + asm.Mov.Imm32(asm.R0, 23).WithSymbol("fwd"), asm.Return(), ) diff --git a/prog.go b/prog.go index 7490b384b..32f7681d3 100644 --- a/prog.go +++ b/prog.go @@ -180,7 +180,7 @@ func (spec *ProgramSpec) layout() ([]reference, error) { // Skip non-symbols and symbols that describe the ProgramSpec itself, // which is usually the first instruction in Instructions. // ProgramSpec itself is already included and not present in references. - if ins.Symbol == "" || ins.Symbol == name { + if ins.Symbol() == "" || ins.Symbol() == name { continue } @@ -188,7 +188,7 @@ func (spec *ProgramSpec) layout() ([]reference, error) { // with valid progs that contain multiple symbols and don't have references // populated. Assume ProgramSpec is used similarly in the wild, so don't // alter this behaviour. - ref := spec.references[ins.Symbol] + ref := spec.references[ins.Symbol()] if ref != nil { out = append(out, reference{iter.Offset.Bytes(), ref}) } diff --git a/prog_test.go b/prog_test.go index 2f846ca75..b312b8d8d 100644 --- a/prog_test.go +++ b/prog_test.go @@ -49,7 +49,7 @@ func TestProgramRun(t *testing.T) { } ins = append(ins, // return 42 - asm.LoadImm(asm.R0, 42, asm.DWord).Sym("out"), + asm.LoadImm(asm.R0, 42, asm.DWord).WithSymbol("out"), asm.Return(), ) @@ -692,7 +692,7 @@ func TestProgramInstructions(t *testing.T) { Type: SocketFilter, Name: name, Instructions: asm.Instructions{ - asm.LoadImm(asm.R0, -1, asm.DWord).Sym(name), + asm.LoadImm(asm.R0, -1, asm.DWord).WithSymbol(name), asm.Mov.Imm32(asm.R0, 0), asm.Return(), }, @@ -716,7 +716,15 @@ func TestProgramInstructions(t *testing.T) { t.Fatal(err) } - if diff := cmp.Diff(insns, spec.Instructions); diff != "" { + instructionComparer := func(a, b asm.Instruction) bool { + return a.OpCode == b.OpCode && + a.Constant == b.Constant && + a.Dst == b.Dst && + a.Src == b.Src && + a.Offset == b.Offset + } + + if diff := cmp.Diff(insns, spec.Instructions, cmp.Comparer(instructionComparer)); diff != "" { t.Fatal(diff) } } diff --git a/ringbuf/reader_test.go b/ringbuf/reader_test.go index 9da5622c3..71278fbb6 100644 --- a/ringbuf/reader_test.go +++ b/ringbuf/reader_test.go @@ -134,7 +134,7 @@ func outputSamplesProg(flags int32, sampleSizes ...int) (*ebpf.Program, *ebpf.Ma } insns = append(insns, - asm.Mov.Imm(asm.R0, int32(0)).Sym("exit"), + asm.Mov.Imm(asm.R0, int32(0)).WithSymbol("exit"), asm.Return(), )