diff --git a/asm/instruction.go b/asm/instruction.go index 67cd39d6f..46d1bec1c 100644 --- a/asm/instruction.go +++ b/asm/instruction.go @@ -935,14 +935,19 @@ func (iter *InstructionIterator) Next() bool { type bpfRegisters uint8 func newBPFRegisters(dst, src Register, bo binary.ByteOrder) (bpfRegisters, error) { + buf := make([]byte, 2) + val := uint16(dst&0x0F)<<8 | uint16(src&0x0F) switch bo { case binary.LittleEndian: - return bpfRegisters((src << 4) | (dst & 0xF)), nil + binary.LittleEndian.PutUint16(buf, val) case binary.BigEndian: - return bpfRegisters((dst << 4) | (src & 0xF)), nil + binary.BigEndian.PutUint16(buf, val) + case binary.NativeEndian: + binary.NativeEndian.PutUint16(buf, val) default: return 0, fmt.Errorf("unrecognized ByteOrder %T", bo) } + return bpfRegisters(buf[0]<<4 | buf[1]), nil } // IsUnreferencedSymbol returns true if err was caused by diff --git a/asm/instruction_test.go b/asm/instruction_test.go index e8d3495b2..9c999ca54 100644 --- a/asm/instruction_test.go +++ b/asm/instruction_test.go @@ -431,3 +431,34 @@ func TestLongJumpPatching(t *testing.T) { t.Errorf("Expected offset to be 3, got %d", insns[1].Constant) } } + +func TestNewBPFRegisters(t *testing.T) { + for _, test := range []struct { + src, dst Register + order binary.ByteOrder + result bpfRegisters + }{ + { + R1, R2, + binary.LittleEndian, + 0x12, + }, + { + RFP, R2, + binary.BigEndian, + 0x2a, + }, + } { + t.Run(fmt.Sprintf("%s %s:%s", test.order, test.src, test.dst), func(t *testing.T) { + have, err := newBPFRegisters(test.dst, test.src, test.order) + qt.Assert(t, qt.IsNil(err)) + qt.Assert(t, qt.Equals(have, test.result)) + }) + } + + allocs := testing.AllocsPerRun(1, func() { + newBPFRegisters(R1, RFP, binary.NativeEndian) + }) + + qt.Assert(t, qt.Equals(allocs, 0)) +} diff --git a/btf/btf.go b/btf/btf.go index 3d924672c..d125f0cc7 100644 --- a/btf/btf.go +++ b/btf/btf.go @@ -679,7 +679,7 @@ func (s *Spec) TypeByName(name string, typ interface{}) error { // Types from base are used to resolve references in the split BTF. // The returned Spec only contains types from the split BTF, not from the base. func LoadSplitSpecFromReader(r io.ReaderAt, base *Spec) (*Spec, error) { - return loadRawSpec(r, internal.NativeEndian, base) + return loadRawSpec(r, binary.NativeEndian, base) } // TypesIterator iterates over types of a given spec. diff --git a/btf/core.go b/btf/core.go index a3d311a06..f86f8c64b 100644 --- a/btf/core.go +++ b/btf/core.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/cilium/ebpf/asm" + "github.com/cilium/ebpf/internal" ) // Code in this file is derived from libbpf, which is available under a BSD @@ -211,7 +212,7 @@ func CORERelocate(relos []*CORERelocation, targets []*Spec, bo binary.ByteOrder, } for _, target := range targets { - if bo != target.imm.byteOrder { + if !internal.ByteOrderEqual(bo, target.imm.byteOrder) { return nil, fmt.Errorf("can't relocate %s against %s", bo, target.imm.byteOrder) } } diff --git a/btf/core_reloc_test.go b/btf/core_reloc_test.go index 798676007..c854ae9b0 100644 --- a/btf/core_reloc_test.go +++ b/btf/core_reloc_test.go @@ -26,7 +26,7 @@ func TestCORERelocationLoad(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -76,7 +76,7 @@ func TestCORERelocationRead(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -126,7 +126,7 @@ func TestLD64IMMReloc(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } diff --git a/btf/core_test.go b/btf/core_test.go index f56d3d481..e80001506 100644 --- a/btf/core_test.go +++ b/btf/core_test.go @@ -1,6 +1,7 @@ package btf import ( + "encoding/binary" "errors" "fmt" "os" @@ -10,7 +11,6 @@ import ( "github.com/google/go-cmp/cmp" - "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/testutils" "github.com/go-quicktest/qt" @@ -637,7 +637,7 @@ func TestCOREReloFieldSigned(t *testing.T) { relo := &CORERelocation{ typ, coreAccessor{0}, reloFieldSigned, 0, } - fixup, err := coreCalculateFixup(relo, &Void{}, 0, internal.NativeEndian) + fixup, err := coreCalculateFixup(relo, &Void{}, 0, binary.NativeEndian) qt.Assert(t, qt.IsTrue(fixup.poison)) qt.Assert(t, qt.IsNil(err)) }) @@ -647,7 +647,7 @@ func TestCOREReloFieldSigned(t *testing.T) { relo := &CORERelocation{ &Array{}, coreAccessor{0}, reloFieldSigned, 0, } - _, err := coreCalculateFixup(relo, &Array{}, 0, internal.NativeEndian) + _, err := coreCalculateFixup(relo, &Array{}, 0, binary.NativeEndian) qt.Assert(t, qt.ErrorIs(err, errNoSignedness)) }) } @@ -664,7 +664,7 @@ func TestCOREReloFieldShiftU64(t *testing.T) { {typ, coreAccessor{0, 0}, reloFieldLShiftU64, 1}, } { t.Run(relo.kind.String(), func(t *testing.T) { - _, err := coreCalculateFixup(relo, typ, 1, internal.NativeEndian) + _, err := coreCalculateFixup(relo, typ, 1, binary.NativeEndian) qt.Assert(t, qt.ErrorIs(err, errUnsizedType)) }) } diff --git a/btf/ext_info.go b/btf/ext_info.go index d5652bad5..f75bff005 100644 --- a/btf/ext_info.go +++ b/btf/ext_info.go @@ -408,8 +408,8 @@ func (fi *funcInfo) marshal(w *bytes.Buffer, b *Builder) error { TypeID: id, } buf := make([]byte, FuncInfoSize) - internal.NativeEndian.PutUint32(buf, bfi.InsnOff) - internal.NativeEndian.PutUint32(buf[4:], uint32(bfi.TypeID)) + binary.NativeEndian.PutUint32(buf, bfi.InsnOff) + binary.NativeEndian.PutUint32(buf[4:], uint32(bfi.TypeID)) _, err = w.Write(buf) return err } @@ -617,10 +617,10 @@ func (li *lineInfo) marshal(w *bytes.Buffer, b *Builder) error { } buf := make([]byte, LineInfoSize) - internal.NativeEndian.PutUint32(buf, bli.InsnOff) - internal.NativeEndian.PutUint32(buf[4:], bli.FileNameOff) - internal.NativeEndian.PutUint32(buf[8:], bli.LineOff) - internal.NativeEndian.PutUint32(buf[12:], bli.LineCol) + binary.NativeEndian.PutUint32(buf, bli.InsnOff) + binary.NativeEndian.PutUint32(buf[4:], bli.FileNameOff) + binary.NativeEndian.PutUint32(buf[8:], bli.LineOff) + binary.NativeEndian.PutUint32(buf[12:], bli.LineCol) _, err = w.Write(buf) return err } diff --git a/btf/ext_info_test.go b/btf/ext_info_test.go index f70266716..edcf8fb26 100644 --- a/btf/ext_info_test.go +++ b/btf/ext_info_test.go @@ -2,10 +2,9 @@ package btf import ( "bytes" + "encoding/binary" "strings" "testing" - - "github.com/cilium/ebpf/internal" ) func TestParseExtInfoBigRecordSize(t *testing.T) { @@ -15,11 +14,11 @@ func TestParseExtInfoBigRecordSize(t *testing.T) { t.Fatal(err) } - if _, err := parseFuncInfos(rd, internal.NativeEndian, table); err == nil { + if _, err := parseFuncInfos(rd, binary.NativeEndian, table); err == nil { t.Error("Parsing func info with large record size doesn't return an error") } - if _, err := parseLineInfos(rd, internal.NativeEndian, table); err == nil { + if _, err := parseLineInfos(rd, binary.NativeEndian, table); err == nil { t.Error("Parsing line info with large record size doesn't return an error") } } diff --git a/btf/fuzz_test.go b/btf/fuzz_test.go index 64ebe1098..d38edd2a0 100644 --- a/btf/fuzz_test.go +++ b/btf/fuzz_test.go @@ -6,13 +6,11 @@ import ( "fmt" "io" "testing" - - "github.com/cilium/ebpf/internal" ) func FuzzSpec(f *testing.F) { var buf bytes.Buffer - err := binary.Write(&buf, internal.NativeEndian, &btfHeader{ + err := binary.Write(&buf, binary.NativeEndian, &btfHeader{ Magic: btfMagic, Version: 1, HdrLen: uint32(binary.Size(btfHeader{})), @@ -26,7 +24,7 @@ func FuzzSpec(f *testing.F) { t.Skip("data is too short") } - spec, err := loadRawSpec(bytes.NewReader(data), internal.NativeEndian, nil) + spec, err := loadRawSpec(bytes.NewReader(data), binary.NativeEndian, nil) if err != nil { if spec != nil { t.Fatal("spec is not nil") @@ -47,7 +45,7 @@ func FuzzSpec(f *testing.F) { func FuzzExtInfo(f *testing.F) { var buf bytes.Buffer - err := binary.Write(&buf, internal.NativeEndian, &btfExtHeader{ + err := binary.Write(&buf, binary.NativeEndian, &btfExtHeader{ Magic: btfMagic, Version: 1, HdrLen: uint32(binary.Size(btfExtHeader{})), @@ -70,7 +68,7 @@ func FuzzExtInfo(f *testing.F) { emptySpec := specFromTypes(t, nil) emptySpec.strings = table - info, err := loadExtInfos(bytes.NewReader(data), internal.NativeEndian, emptySpec) + info, err := loadExtInfos(bytes.NewReader(data), binary.NativeEndian, emptySpec) if err != nil { if info != nil { t.Fatal("info is not nil") diff --git a/btf/handle.go b/btf/handle.go index b6b3e87f5..c4db34a8c 100644 --- a/btf/handle.go +++ b/btf/handle.go @@ -2,6 +2,7 @@ package btf import ( "bytes" + "encoding/binary" "errors" "fmt" "math" @@ -113,7 +114,7 @@ func (h *Handle) Spec(base *Spec) (*Spec, error) { return nil, fmt.Errorf("missing base types") } - return loadRawSpec(bytes.NewReader(btfBuffer), internal.NativeEndian, base) + return loadRawSpec(bytes.NewReader(btfBuffer), binary.NativeEndian, base) } // Close destroys the handle. diff --git a/btf/kernel.go b/btf/kernel.go index 7421a72be..d52a3dbe1 100644 --- a/btf/kernel.go +++ b/btf/kernel.go @@ -1,6 +1,7 @@ package btf import ( + "encoding/binary" "errors" "fmt" "os" @@ -98,7 +99,7 @@ func loadKernelSpec() (_ *Spec, fallback bool, _ error) { if err == nil { defer fh.Close() - spec, err := loadRawSpec(fh, internal.NativeEndian, nil) + spec, err := loadRawSpec(fh, binary.NativeEndian, nil) return spec, false, err } @@ -124,7 +125,7 @@ func loadKernelModuleSpec(module string, base *Spec) (*Spec, error) { } defer fh.Close() - return loadRawSpec(fh, internal.NativeEndian, base) + return loadRawSpec(fh, binary.NativeEndian, base) } // findVMLinux scans multiple well-known paths for vmlinux kernel images. diff --git a/btf/marshal.go b/btf/marshal.go index 744c84c4c..dd2e64d96 100644 --- a/btf/marshal.go +++ b/btf/marshal.go @@ -24,7 +24,7 @@ type MarshalOptions struct { // KernelMarshalOptions will generate BTF suitable for the current kernel. func KernelMarshalOptions() *MarshalOptions { return &MarshalOptions{ - Order: internal.NativeEndian, + Order: binary.NativeEndian, StripFuncLinkage: haveFuncLinkage() != nil, ReplaceEnum64: haveEnum64() != nil, } @@ -149,7 +149,7 @@ func (b *Builder) Marshal(buf []byte, opts *MarshalOptions) ([]byte, error) { } if opts == nil { - opts = &MarshalOptions{Order: internal.NativeEndian} + opts = &MarshalOptions{Order: binary.NativeEndian} } // Reserve space for the BTF header. diff --git a/btf/marshal_test.go b/btf/marshal_test.go index 9cbfc0b5e..ae662cc56 100644 --- a/btf/marshal_test.go +++ b/btf/marshal_test.go @@ -9,7 +9,6 @@ import ( "github.com/go-quicktest/qt" "github.com/google/go-cmp/cmp" - "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/testutils" ) @@ -31,11 +30,11 @@ func TestBuilderMarshal(t *testing.T) { qt.Assert(t, qt.IsNil(err)) cpy := *b - buf, err := b.Marshal(nil, &MarshalOptions{Order: internal.NativeEndian}) + buf, err := b.Marshal(nil, &MarshalOptions{Order: binary.NativeEndian}) qt.Assert(t, qt.IsNil(err)) qt.Assert(t, qt.CmpEquals(b, &cpy, cmp.AllowUnexported(*b)), qt.Commentf("Marshaling should not change Builder state")) - have, err := loadRawSpec(bytes.NewReader(buf), internal.NativeEndian, nil) + have, err := loadRawSpec(bytes.NewReader(buf), binary.NativeEndian, nil) qt.Assert(t, qt.IsNil(err), qt.Commentf("Couldn't parse BTF")) qt.Assert(t, qt.DeepEquals(have.imm.types, want)) } @@ -129,12 +128,12 @@ func TestMarshalEnum64(t *testing.T) { b, err := NewBuilder([]Type{enum}) qt.Assert(t, qt.IsNil(err)) buf, err := b.Marshal(nil, &MarshalOptions{ - Order: internal.NativeEndian, + Order: binary.NativeEndian, ReplaceEnum64: true, }) qt.Assert(t, qt.IsNil(err)) - spec, err := loadRawSpec(bytes.NewReader(buf), internal.NativeEndian, nil) + spec, err := loadRawSpec(bytes.NewReader(buf), binary.NativeEndian, nil) qt.Assert(t, qt.IsNil(err)) var have *Union @@ -196,7 +195,7 @@ func specFromTypes(tb testing.TB, types []Type) *Spec { tb.Helper() btf := marshalNativeEndian(tb, types) - spec, err := loadRawSpec(bytes.NewReader(btf), internal.NativeEndian, nil) + spec, err := loadRawSpec(bytes.NewReader(btf), binary.NativeEndian, nil) qt.Assert(tb, qt.IsNil(err)) return spec diff --git a/collection.go b/collection.go index a5532220f..292d30813 100644 --- a/collection.go +++ b/collection.go @@ -623,7 +623,7 @@ func resolveKconfig(m *MapSpec) error { if err != nil { return fmt.Errorf("getting kernel version: %w", err) } - internal.NativeEndian.PutUint32(data[vsi.Offset:], kv.Kernel()) + binary.NativeEndian.PutUint32(data[vsi.Offset:], kv.Kernel()) case "LINUX_HAS_SYSCALL_WRAPPER": integer, ok := v.Type.(*btf.Int) diff --git a/elf_reader_test.go b/elf_reader_test.go index c1058adfa..ad41593e0 100644 --- a/elf_reader_test.go +++ b/elf_reader_test.go @@ -188,7 +188,7 @@ func TestLoadCollectionSpec(t *testing.T) { t.Errorf("MapSpec mismatch (-want +got):\n%s", diff) } - if have.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(have.ByteOrder) { return } @@ -381,7 +381,7 @@ func TestLoadInitializedBTFMap(t *testing.T) { } t.Run("NewCollection", func(t *testing.T) { - if coll.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(coll.ByteOrder) { t.Skipf("Skipping %s collection", coll.ByteOrder) } @@ -537,7 +537,7 @@ func TestLoadRawTracepoint(t *testing.T) { t.Fatal("Can't parse ELF:", err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -562,7 +562,7 @@ func TestTailCall(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -599,7 +599,7 @@ func TestKconfigKernelVersion(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -640,7 +640,7 @@ func TestKconfigSyscallWrapper(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -681,7 +681,7 @@ func TestKconfigConfig(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -723,7 +723,7 @@ func TestKfunc(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -758,7 +758,7 @@ func TestWeakKfunc(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -810,7 +810,7 @@ func TestKfuncKmod(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -846,7 +846,7 @@ func TestSubprogRelocation(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -882,7 +882,7 @@ func TestUnassignedProgArray(t *testing.T) { t.Fatal(err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -911,7 +911,7 @@ func TestIPRoute2Compat(t *testing.T) { t.Fatal("Can't parse ELF:", err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } diff --git a/examples/tcprtt/main.go b/examples/tcprtt/main.go index 3c55cc625..7a2296923 100644 --- a/examples/tcprtt/main.go +++ b/examples/tcprtt/main.go @@ -24,7 +24,6 @@ import ( "os/signal" "syscall" - "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/link" "github.com/cilium/ebpf/ringbuf" "github.com/cilium/ebpf/rlimit" @@ -90,7 +89,7 @@ func readLoop(rd *ringbuf.Reader) { } // Parse the ringbuf event entry into a bpfEvent structure. - if err := binary.Read(bytes.NewBuffer(record.RawSample), internal.NativeEndian, &event); err != nil { + if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.NativeEndian, &event); err != nil { log.Printf("parsing ringbuf event: %s", err) continue } @@ -108,6 +107,6 @@ func readLoop(rd *ringbuf.Reader) { // intToIP converts IPv4 number to net.IP func intToIP(ipNum uint32) net.IP { ip := make(net.IP, 4) - internal.NativeEndian.PutUint32(ip, ipNum) + binary.NativeEndian.PutUint32(ip, ipNum) return ip } diff --git a/examples/tcprtt_sockops/main.go b/examples/tcprtt_sockops/main.go index 7360d9b28..15a224d5d 100644 --- a/examples/tcprtt_sockops/main.go +++ b/examples/tcprtt_sockops/main.go @@ -32,7 +32,6 @@ import ( "syscall" "github.com/cilium/ebpf" - "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/link" "github.com/cilium/ebpf/ringbuf" "github.com/cilium/ebpf/rlimit" @@ -126,7 +125,7 @@ func readLoop(rd *ringbuf.Reader) { } // Parse the ringbuf event entry into a bpfRttEvent structure. - if err := binary.Read(bytes.NewBuffer(record.RawSample), internal.NativeEndian, &event); err != nil { + if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.NativeEndian, &event); err != nil { log.Printf("parsing ringbuf event: %s", err) continue } diff --git a/info.go b/info.go index 79b11c951..77e68e552 100644 --- a/info.go +++ b/info.go @@ -3,6 +3,7 @@ package ebpf import ( "bufio" "bytes" + "encoding/binary" "encoding/hex" "errors" "fmt" @@ -288,7 +289,7 @@ func (pi *ProgramInfo) Instructions() (asm.Instructions, error) { r := bytes.NewReader(pi.insns) var insns asm.Instructions - if err := insns.Unmarshal(r, internal.NativeEndian); err != nil { + if err := insns.Unmarshal(r, binary.NativeEndian); err != nil { return nil, fmt.Errorf("unmarshaling instructions: %w", err) } @@ -313,7 +314,7 @@ func (pi *ProgramInfo) Instructions() (asm.Instructions, error) { lineInfos, err := btf.LoadLineInfos( bytes.NewReader(pi.lineInfos), - internal.NativeEndian, + binary.NativeEndian, pi.numLineInfos, spec, ) @@ -323,7 +324,7 @@ func (pi *ProgramInfo) Instructions() (asm.Instructions, error) { funcInfos, err := btf.LoadFuncInfos( bytes.NewReader(pi.funcInfos), - internal.NativeEndian, + binary.NativeEndian, pi.numFuncInfos, spec, ) diff --git a/internal/auxv_test.go b/internal/auxv_test.go index ac9d0430a..7e54d7e91 100644 --- a/internal/auxv_test.go +++ b/internal/auxv_test.go @@ -66,7 +66,7 @@ func newAuxFileReader(path string, order binary.ByteOrder, uintptrIs32bits bool) func newDefaultAuxvFileReader() (auxvPairReader, error) { const uintptrIs32bits = unsafe.Sizeof((uintptr)(0)) == 4 - return newAuxFileReader("/proc/self/auxv", NativeEndian, uintptrIs32bits) + return newAuxFileReader("/proc/self/auxv", binary.NativeEndian, uintptrIs32bits) } func TestAuxvBothSourcesEqual(t *testing.T) { diff --git a/internal/endian.go b/internal/endian.go new file mode 100644 index 000000000..d245e1c28 --- /dev/null +++ b/internal/endian.go @@ -0,0 +1,42 @@ +package internal + +import ( + "encoding/binary" + + "golang.org/x/sys/cpu" +) + +// IsNativeEndian returns true if order matches the native endianness of the host. +func IsNativeEndian(order binary.ByteOrder) bool { + if order == binary.NativeEndian { + return true + } + + if !cpu.IsBigEndian { + return order == binary.LittleEndian + } + + return order == binary.BigEndian +} + +// ByteOrderEqual returns true if the two byte orders are semantically identical. +// +// For example, on a little endian system NativeEndian and LittleEndian are +// considered identical. +func ByteOrderEqual(a, b binary.ByteOrder) bool { + a = normaliseByteOrder(a) + b = normaliseByteOrder(b) + return a == b +} + +func normaliseByteOrder(order binary.ByteOrder) binary.ByteOrder { + if order != binary.NativeEndian { + return order + } + + if !cpu.IsBigEndian { + return binary.LittleEndian + } + + return binary.BigEndian +} diff --git a/internal/endian_be.go b/internal/endian_be.go index 39f49ba3a..2fc89d44f 100644 --- a/internal/endian_be.go +++ b/internal/endian_be.go @@ -2,11 +2,5 @@ package internal -import "encoding/binary" - -// NativeEndian is set to either binary.BigEndian or binary.LittleEndian, -// depending on the host's endianness. -var NativeEndian = binary.BigEndian - // ClangEndian is set to either "el" or "eb" depending on the host's endianness. const ClangEndian = "eb" diff --git a/internal/endian_le.go b/internal/endian_le.go index 9488e301b..79fc69649 100644 --- a/internal/endian_le.go +++ b/internal/endian_le.go @@ -2,11 +2,5 @@ package internal -import "encoding/binary" - -// NativeEndian is set to either binary.BigEndian or binary.LittleEndian, -// depending on the host's endianness. -var NativeEndian = binary.LittleEndian - // ClangEndian is set to either "el" or "eb" depending on the host's endianness. const ClangEndian = "el" diff --git a/internal/epoll/poller.go b/internal/epoll/poller.go index ee86a2e75..d2ccaaea2 100644 --- a/internal/epoll/poller.go +++ b/internal/epoll/poller.go @@ -1,6 +1,7 @@ package epoll import ( + "encoding/binary" "fmt" "math" "os" @@ -8,7 +9,6 @@ import ( "sync" "time" - "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/unix" ) @@ -213,7 +213,7 @@ func (efd *eventFd) close() error { func (efd *eventFd) add(n uint64) error { var buf [8]byte - internal.NativeEndian.PutUint64(buf[:], 1) + binary.NativeEndian.PutUint64(buf[:], 1) _, err := efd.file.Write(buf[:]) return err } @@ -221,5 +221,5 @@ func (efd *eventFd) add(n uint64) error { func (efd *eventFd) read() (uint64, error) { var buf [8]byte _, err := efd.file.Read(buf[:]) - return internal.NativeEndian.Uint64(buf[:]), err + return binary.NativeEndian.Uint64(buf[:]), err } diff --git a/internal/kconfig/kconfig.go b/internal/kconfig/kconfig.go index 1921e4f15..8286be43a 100644 --- a/internal/kconfig/kconfig.go +++ b/internal/kconfig/kconfig.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "compress/gzip" + "encoding/binary" "fmt" "io" "math" @@ -181,7 +182,7 @@ func putValueTri(data []byte, typ btf.Type, value string) error { return fmt.Errorf("value %q is not support for libbpf_tristate", value) } - internal.NativeEndian.PutUint64(data, uint64(tri)) + binary.NativeEndian.PutUint64(data, uint64(tri)) default: return fmt.Errorf("cannot add number value, expected btf.Int or btf.Enum, got: %T", v) } @@ -277,14 +278,14 @@ func PutInteger(data []byte, integer *btf.Int, n uint64) error { if integer.Encoding == btf.Signed && (int64(n) > math.MaxInt16 || int64(n) < math.MinInt16) { return fmt.Errorf("can't represent %d as a signed integer of size %d", int64(n), integer.Size) } - internal.NativeEndian.PutUint16(data, uint16(n)) + binary.NativeEndian.PutUint16(data, uint16(n)) case 4: if integer.Encoding == btf.Signed && (int64(n) > math.MaxInt32 || int64(n) < math.MinInt32) { return fmt.Errorf("can't represent %d as a signed integer of size %d", int64(n), integer.Size) } - internal.NativeEndian.PutUint32(data, uint32(n)) + binary.NativeEndian.PutUint32(data, uint32(n)) case 8: - internal.NativeEndian.PutUint64(data, uint64(n)) + binary.NativeEndian.PutUint64(data, uint64(n)) default: return fmt.Errorf("size (%d) is not valid, expected: 1, 2, 4 or 8", integer.Size) } diff --git a/internal/kconfig/kconfig_test.go b/internal/kconfig/kconfig_test.go index 19f42f745..20b9ae65f 100644 --- a/internal/kconfig/kconfig_test.go +++ b/internal/kconfig/kconfig_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/cilium/ebpf/btf" - "github.com/cilium/ebpf/internal" "github.com/go-quicktest/qt" ) @@ -402,7 +401,7 @@ func TestPutValue(t *testing.T) { } var buf bytes.Buffer - err := binary.Write(&buf, internal.NativeEndian, c.expected) + err := binary.Write(&buf, binary.NativeEndian, c.expected) if err != nil { t.Fatal(err) } diff --git a/internal/sysenc/marshal.go b/internal/sysenc/marshal.go index 0026af8f2..e1fe75dff 100644 --- a/internal/sysenc/marshal.go +++ b/internal/sysenc/marshal.go @@ -37,17 +37,17 @@ func Marshal(data any, size int) (Buffer, error) { case []byte: buf = value case int16: - buf = internal.NativeEndian.AppendUint16(make([]byte, 0, 2), uint16(value)) + buf = binary.NativeEndian.AppendUint16(make([]byte, 0, 2), uint16(value)) case uint16: - buf = internal.NativeEndian.AppendUint16(make([]byte, 0, 2), value) + buf = binary.NativeEndian.AppendUint16(make([]byte, 0, 2), value) case int32: - buf = internal.NativeEndian.AppendUint32(make([]byte, 0, 4), uint32(value)) + buf = binary.NativeEndian.AppendUint32(make([]byte, 0, 4), uint32(value)) case uint32: - buf = internal.NativeEndian.AppendUint32(make([]byte, 0, 4), value) + buf = binary.NativeEndian.AppendUint32(make([]byte, 0, 4), value) case int64: - buf = internal.NativeEndian.AppendUint64(make([]byte, 0, 8), uint64(value)) + buf = binary.NativeEndian.AppendUint64(make([]byte, 0, 8), uint64(value)) case uint64: - buf = internal.NativeEndian.AppendUint64(make([]byte, 0, 8), value) + buf = binary.NativeEndian.AppendUint64(make([]byte, 0, 8), value) default: if buf := unsafeBackingMemory(data); len(buf) == size { return newBuffer(buf), nil @@ -56,7 +56,7 @@ func Marshal(data any, size int) (Buffer, error) { wr := internal.NewBuffer(make([]byte, 0, size)) defer internal.PutBuffer(wr) - err = binary.Write(wr, internal.NativeEndian, value) + err = binary.Write(wr, binary.NativeEndian, value) buf = wr.Bytes() } if err != nil { @@ -105,7 +105,7 @@ func Unmarshal(data interface{}, buf []byte) error { rd.Reset(buf) - if err := binary.Read(rd, internal.NativeEndian, value); err != nil { + if err := binary.Read(rd, binary.NativeEndian, value); err != nil { return err } diff --git a/internal/sysenc/marshal_test.go b/internal/sysenc/marshal_test.go index 96b8a988d..3eff95f32 100644 --- a/internal/sysenc/marshal_test.go +++ b/internal/sysenc/marshal_test.go @@ -10,8 +10,6 @@ import ( "github.com/go-quicktest/qt" "github.com/google/go-cmp/cmp/cmpopts" - - "github.com/cilium/ebpf/internal" ) type testcase struct { @@ -61,7 +59,7 @@ func TestMarshal(t *testing.T) { value := test.new() t.Run(fmt.Sprintf("%T", value), func(t *testing.T) { var want bytes.Buffer - if err := binary.Write(&want, internal.NativeEndian, value); err != nil { + if err := binary.Write(&want, binary.NativeEndian, value); err != nil { t.Fatal(err) } @@ -148,7 +146,7 @@ func TestUnsafeBackingMemory(t *testing.T) { t.Helper() var buf bytes.Buffer - qt.Assert(t, qt.IsNil(binary.Write(&buf, internal.NativeEndian, data))) + qt.Assert(t, qt.IsNil(binary.Write(&buf, binary.NativeEndian, data))) return buf.Bytes() } @@ -295,7 +293,7 @@ func randomiseValue(tb testing.TB, value any) []byte { buf[i] = byte(i) } - err := binary.Read(bytes.NewReader(buf), internal.NativeEndian, value) + err := binary.Read(bytes.NewReader(buf), binary.NativeEndian, value) qt.Assert(tb, qt.IsNil(err)) return buf diff --git a/link/tracing_test.go b/link/tracing_test.go index 5761b4c7d..fe324ed6c 100644 --- a/link/tracing_test.go +++ b/link/tracing_test.go @@ -18,7 +18,7 @@ func TestFreplace(t *testing.T) { t.Fatal("Can't parse ELF:", err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } diff --git a/linker.go b/linker.go index 538fd4e9e..cbef3a13d 100644 --- a/linker.go +++ b/linker.go @@ -11,7 +11,6 @@ import ( "github.com/cilium/ebpf/asm" "github.com/cilium/ebpf/btf" - "github.com/cilium/ebpf/internal" ) // handles stores handle objects to avoid gc cleanup @@ -136,7 +135,7 @@ func applyRelocations(insns asm.Instructions, targets []*btf.Spec, kmodName stri } if bo == nil { - bo = internal.NativeEndian + bo = binary.NativeEndian } if len(targets) == 0 { diff --git a/linker_test.go b/linker_test.go index e75c50c8b..dbdb8b078 100644 --- a/linker_test.go +++ b/linker_test.go @@ -65,7 +65,7 @@ func TestForwardFunctionDeclaration(t *testing.T) { t.Fatal(err) } - if coll.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(coll.ByteOrder) { return } diff --git a/map.go b/map.go index 1eeee1776..1725b9080 100644 --- a/map.go +++ b/map.go @@ -2,6 +2,7 @@ package ebpf import ( "bytes" + "encoding/binary" "errors" "fmt" "io" @@ -1482,7 +1483,7 @@ func marshalMap(m *Map, length int) ([]byte, error) { } buf := make([]byte, 4) - internal.NativeEndian.PutUint32(buf, m.fd.Uint()) + binary.NativeEndian.PutUint32(buf, m.fd.Uint()) return buf, nil } diff --git a/map_test.go b/map_test.go index be36721a8..811b3b798 100644 --- a/map_test.go +++ b/map_test.go @@ -1,6 +1,7 @@ package ebpf import ( + "encoding/binary" "errors" "fmt" "math" @@ -80,7 +81,7 @@ func TestMap(t *testing.T) { var slice []byte qt.Assert(t, qt.IsNil(m.Lookup(uint32(0), &slice))) - qt.Assert(t, qt.DeepEquals(slice, internal.NativeEndian.AppendUint32(nil, 42))) + qt.Assert(t, qt.DeepEquals(slice, binary.NativeEndian.AppendUint32(nil, 42))) var k uint32 if err := m.NextKey(uint32(0), &k); err != nil { @@ -326,7 +327,7 @@ func TestBatchMapWithLock(t *testing.T) { if err != nil { t.Fatal("Can't parse ELF:", err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -387,7 +388,7 @@ func TestMapWithLock(t *testing.T) { if err != nil { t.Fatal("Can't parse ELF:", err) } - if spec.ByteOrder != internal.NativeEndian { + if !internal.IsNativeEndian(spec.ByteOrder) { return } @@ -1835,21 +1836,21 @@ type benchValue struct { type customBenchValue benchValue func (cbv *customBenchValue) UnmarshalBinary(buf []byte) error { - cbv.ID = internal.NativeEndian.Uint32(buf) - cbv.Val16 = internal.NativeEndian.Uint16(buf[4:]) - cbv.Val16_2 = internal.NativeEndian.Uint16(buf[6:]) + cbv.ID = binary.NativeEndian.Uint32(buf) + cbv.Val16 = binary.NativeEndian.Uint16(buf[4:]) + cbv.Val16_2 = binary.NativeEndian.Uint16(buf[6:]) copy(cbv.Name[:], buf[8:]) - cbv.LID = internal.NativeEndian.Uint64(buf[16:]) + cbv.LID = binary.NativeEndian.Uint64(buf[16:]) return nil } func (cbv *customBenchValue) MarshalBinary() ([]byte, error) { buf := make([]byte, 24) - internal.NativeEndian.PutUint32(buf, cbv.ID) - internal.NativeEndian.PutUint16(buf[4:], cbv.Val16) - internal.NativeEndian.PutUint16(buf[6:], cbv.Val16_2) + binary.NativeEndian.PutUint32(buf, cbv.ID) + binary.NativeEndian.PutUint16(buf[4:], cbv.Val16) + binary.NativeEndian.PutUint16(buf[6:], cbv.Val16_2) copy(buf[8:], cbv.Name[:]) - internal.NativeEndian.PutUint64(buf[16:], cbv.LID) + binary.NativeEndian.PutUint64(buf[16:], cbv.LID) return buf, nil } @@ -1859,7 +1860,7 @@ type benchKey struct { func (bk *benchKey) MarshalBinary() ([]byte, error) { buf := make([]byte, 8) - internal.NativeEndian.PutUint64(buf, bk.id) + binary.NativeEndian.PutUint64(buf, bk.id) return buf, nil } diff --git a/marshalers_test.go b/marshalers_test.go index 1351e7a9c..93eca060c 100644 --- a/marshalers_test.go +++ b/marshalers_test.go @@ -1,6 +1,7 @@ package ebpf import ( + "encoding/binary" "testing" "github.com/cilium/ebpf/internal" @@ -39,7 +40,7 @@ func TestMarshalBatchPerCPUValue(t *testing.T) { expected := make([]byte, sliceLen*internal.Align(elemLength, 8)) b := expected for _, elem := range slice { - internal.NativeEndian.PutUint32(b, elem) + binary.NativeEndian.PutUint32(b, elem) b = b[8:] } buf, err := marshalBatchPerCPUValue(slice, batchLen, elemLength) @@ -70,7 +71,7 @@ func TestUnmarshalBatchPerCPUValue(t *testing.T) { buf := make([]byte, batchLen*possibleCPU*internal.Align(elemLength, 8)) b := buf for _, elem := range expected { - internal.NativeEndian.PutUint32(b, elem) + binary.NativeEndian.PutUint32(b, elem) b = b[8:] } err := unmarshalBatchPerCPUValue(output, batchLen, elemLength, buf) @@ -106,7 +107,7 @@ func TestUnmarshalPerCPUValue(t *testing.T) { buf := make([]byte, possibleCPUs*internal.Align(elemLength, 8)) b := buf for _, elem := range expected { - internal.NativeEndian.PutUint32(b, elem) + binary.NativeEndian.PutUint32(b, elem) b = b[8:] } slice := make([]uint32, possibleCPUs) diff --git a/perf/reader.go b/perf/reader.go index 3c820708c..343f8152e 100644 --- a/perf/reader.go +++ b/perf/reader.go @@ -11,7 +11,6 @@ import ( "time" "github.com/cilium/ebpf" - "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/epoll" "github.com/cilium/ebpf/internal/unix" ) @@ -68,9 +67,9 @@ func readRecord(rd io.Reader, rec *Record, buf []byte, overwritable bool) error } header := perfEventHeader{ - internal.NativeEndian.Uint32(buf[0:4]), - internal.NativeEndian.Uint16(buf[4:6]), - internal.NativeEndian.Uint16(buf[6:8]), + binary.NativeEndian.Uint32(buf[0:4]), + binary.NativeEndian.Uint16(buf[4:6]), + binary.NativeEndian.Uint16(buf[6:8]), } switch header.Type { @@ -97,7 +96,7 @@ func readLostRecords(rd io.Reader) (uint64, error) { Lost uint64 } - err := binary.Read(rd, internal.NativeEndian, &lostHeader) + err := binary.Read(rd, binary.NativeEndian, &lostHeader) if err != nil { return 0, fmt.Errorf("can't read lost records header: %v", err) } @@ -119,7 +118,7 @@ func readRawSample(rd io.Reader, buf, sampleBuf []byte) ([]byte, error) { } sample := perfEventSample{ - internal.NativeEndian.Uint32(buf), + binary.NativeEndian.Uint32(buf), } var data []byte diff --git a/perf/reader_test.go b/perf/reader_test.go index 27316ad65..e3df3be84 100644 --- a/perf/reader_test.go +++ b/perf/reader_test.go @@ -392,7 +392,7 @@ func TestCreatePerfEvent(t *testing.T) { func TestReadRecord(t *testing.T) { var buf bytes.Buffer - err := binary.Write(&buf, internal.NativeEndian, &perfEventHeader{}) + err := binary.Write(&buf, binary.NativeEndian, &perfEventHeader{}) if err != nil { t.Fatal(err) } diff --git a/prog.go b/prog.go index d479a3881..e2df41410 100644 --- a/prog.go +++ b/prog.go @@ -154,7 +154,7 @@ func (ps *ProgramSpec) Copy() *ProgramSpec { // // Use asm.Instructions.Tag if you need to calculate for non-native endianness. func (ps *ProgramSpec) Tag() (string, error) { - return ps.Instructions.Tag(internal.NativeEndian) + return ps.Instructions.Tag(binary.NativeEndian) } // KernelModule returns the kernel module, if any, the AttachTo function is contained in. @@ -237,8 +237,8 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er return nil, errors.New("can't load program of unspecified type") } - if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian { - return nil, fmt.Errorf("can't load %s program on %s", spec.ByteOrder, internal.NativeEndian) + if spec.ByteOrder != nil && !internal.IsNativeEndian(spec.ByteOrder) { + return nil, fmt.Errorf("wrong byte order: %s", spec.ByteOrder) } if opts.LogSize < 0 { @@ -350,7 +350,7 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er } buf := bytes.NewBuffer(make([]byte, 0, insns.Size())) - err = insns.Marshal(buf, internal.NativeEndian) + err = insns.Marshal(buf, binary.NativeEndian) if err != nil { return nil, err } @@ -741,7 +741,7 @@ func (p *Program) run(opts *RunOptions) (uint32, time.Duration, error) { var ctxBytes []byte if opts.Context != nil { ctx := new(bytes.Buffer) - if err := binary.Write(ctx, internal.NativeEndian, opts.Context); err != nil { + if err := binary.Write(ctx, binary.NativeEndian, opts.Context); err != nil { return 0, 0, fmt.Errorf("cannot serialize context: %v", err) } ctxBytes = ctx.Bytes() @@ -815,7 +815,7 @@ retry: if len(ctxOut) != 0 { b := bytes.NewReader(ctxOut) - if err := binary.Read(b, internal.NativeEndian, opts.ContextOut); err != nil { + if err := binary.Read(b, binary.NativeEndian, opts.ContextOut); err != nil { return 0, 0, fmt.Errorf("failed to decode ContextOut: %v", err) } } @@ -841,7 +841,7 @@ func marshalProgram(p *Program, length int) ([]byte, error) { } buf := make([]byte, 4) - internal.NativeEndian.PutUint32(buf, p.fd.Uint()) + binary.NativeEndian.PutUint32(buf, p.fd.Uint()) return buf, nil } diff --git a/prog_test.go b/prog_test.go index 0cb58e0d4..7c3c7ed0f 100644 --- a/prog_test.go +++ b/prog_test.go @@ -725,7 +725,7 @@ func TestProgramRejectIncorrectByteOrder(t *testing.T) { spec := socketFilterSpec.Copy() spec.ByteOrder = binary.BigEndian - if spec.ByteOrder == internal.NativeEndian { + if spec.ByteOrder == binary.NativeEndian { spec.ByteOrder = binary.LittleEndian } @@ -942,7 +942,7 @@ func TestProgramInstructions(t *testing.T) { t.Fatal(err) } - tagXlated, err := insns.Tag(internal.NativeEndian) + tagXlated, err := insns.Tag(binary.NativeEndian) if err != nil { t.Fatal(err) } diff --git a/syscalls.go b/syscalls.go index 4aef7faeb..9cebe2489 100644 --- a/syscalls.go +++ b/syscalls.go @@ -2,6 +2,7 @@ package ebpf import ( "bytes" + "encoding/binary" "errors" "fmt" "math" @@ -47,7 +48,7 @@ func invalidBPFObjNameChar(char rune) bool { func progLoad(insns asm.Instructions, typ ProgramType, license string) (*sys.FD, error) { buf := bytes.NewBuffer(make([]byte, 0, insns.Size())) - if err := insns.Marshal(buf, internal.NativeEndian); err != nil { + if err := insns.Marshal(buf, binary.NativeEndian); err != nil { return nil, err } bytecode := buf.Bytes() @@ -311,7 +312,7 @@ var haveProgramExtInfos = internal.NewFeatureTest("program ext_infos", "5.0", fu } buf := bytes.NewBuffer(make([]byte, 0, insns.Size())) - if err := insns.Marshal(buf, internal.NativeEndian); err != nil { + if err := insns.Marshal(buf, binary.NativeEndian); err != nil { return err } bytecode := buf.Bytes()