From 1501ab99248363b73de4e26bb384846200b58e78 Mon Sep 17 00:00:00 2001 From: Florian Lehner Date: Fri, 30 Jan 2026 11:08:09 +0100 Subject: [PATCH] asm/arm: merge armhelpers https://github.com/open-telemetry/opentelemetry-ebpf-profiler/pull/1109 introduced a new asm/arm package. Move functionality of armhelpers into this new package for consistency. Signed-off-by: Florian Lehner --- .../arm_helpers.go => asm/arm/helpers.go | 3 +- asm/arm/tls.go | 13 ++++---- interpreter/golabels/tls_arm64.go | 4 +-- interpreter/hotspot/stubs.go | 6 ++-- interpreter/php/decode_aarch64.go | 16 +++++----- interpreter/python/arm64_decode.go | 10 +++--- libc/assembly_decode_aarch64.go | 12 +++---- libc/libc_aarch64.go | 32 +++++++++---------- maccess/maccess_arm64.go | 10 +++--- processmanager/execinfomanager/synthdeltas.go | 12 +++---- 10 files changed, 58 insertions(+), 60 deletions(-) rename armhelpers/arm_helpers.go => asm/arm/helpers.go (96%) diff --git a/armhelpers/arm_helpers.go b/asm/arm/helpers.go similarity index 96% rename from armhelpers/arm_helpers.go rename to asm/arm/helpers.go index 4887575f3..06d88f976 100644 --- a/armhelpers/arm_helpers.go +++ b/asm/arm/helpers.go @@ -1,8 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -// This package contains a series of helper functions that are useful for ARM disassembly. -package armhelpers // import "go.opentelemetry.io/ebpf-profiler/armhelpers" +package arm // import "go.opentelemetry.io/ebpf-profiler/asm/arm" import ( "fmt" diff --git a/asm/arm/tls.go b/asm/arm/tls.go index d75337863..572370708 100644 --- a/asm/arm/tls.go +++ b/asm/arm/tls.go @@ -6,7 +6,6 @@ package arm // import "go.opentelemetry.io/ebpf-profiler/asm/arm" import ( "fmt" - ah "go.opentelemetry.io/ebpf-profiler/armhelpers" "go.opentelemetry.io/ebpf-profiler/libpf" "go.opentelemetry.io/ebpf-profiler/libpf/pfelf" aa "golang.org/x/arch/arm64/arm64asm" @@ -70,7 +69,7 @@ func ExtractTLSOffset(code []byte, baseAddr uint64, ef *pfelf.File) (int32, erro // Check for MRS Xn, TPIDR_EL0 (system register S3_3_C13_C0_2) if inst.Op == aa.MRS && inst.Args[1].String() == "S3_3_C13_C0_2" { - reg, ok := ah.Xreg2num(inst.Args[0]) + reg, ok := Xreg2num(inst.Args[0]) if !ok { continue } @@ -86,9 +85,9 @@ func ExtractTLSOffset(code []byte, baseAddr uint64, ef *pfelf.File) (int32, erro // Check for ADD Xd, Xn, #imm if nextInst.Op == aa.ADD { - destReg, destOk := ah.Xreg2num(nextInst.Args[0]) - srcReg, srcOk := ah.Xreg2num(nextInst.Args[1]) - imm, immOk := ah.DecodeImmediate(nextInst.Args[2]) + destReg, destOk := Xreg2num(nextInst.Args[0]) + srcReg, srcOk := Xreg2num(nextInst.Args[1]) + imm, immOk := DecodeImmediate(nextInst.Args[2]) if destOk && srcOk && immOk && srcReg == tpReg { if imm > 0 && imm < 0x1000 { @@ -103,8 +102,8 @@ func ExtractTLSOffset(code []byte, baseAddr uint64, ef *pfelf.File) (int32, erro if nextInst.Op == aa.LDR { // Args[1] is MemImmediate if mem, ok := nextInst.Args[1].(aa.MemImmediate); ok { - baseReg, regOk := ah.Xreg2num(mem.Base) - imm, immOk := ah.DecodeImmediate(mem) + baseReg, regOk := Xreg2num(mem.Base) + imm, immOk := DecodeImmediate(mem) if regOk && immOk && baseReg == tpReg { if imm > 0 && imm < 0x1000 { diff --git a/interpreter/golabels/tls_arm64.go b/interpreter/golabels/tls_arm64.go index 40aad9fae..b8ac87e48 100644 --- a/interpreter/golabels/tls_arm64.go +++ b/interpreter/golabels/tls_arm64.go @@ -8,7 +8,7 @@ package golabels // import "go.opentelemetry.io/ebpf-profiler/interpreter/golabe import ( "fmt" - "go.opentelemetry.io/ebpf-profiler/armhelpers" + "go.opentelemetry.io/ebpf-profiler/asm/arm" "go.opentelemetry.io/ebpf-profiler/libpf" "go.opentelemetry.io/ebpf-profiler/libpf/pfelf" "go.opentelemetry.io/ebpf-profiler/nativeunwind/elfunwindinfo" @@ -82,7 +82,7 @@ func extractTLSGOffset(f *pfelf.File) (int32, error) { // movk x27, #0x10 // For now, we'll just decode the immediate value from the movk instruction since the one from the movz // instruction seems to always be 0. - imm, ok := armhelpers.DecodeImmediate(i.Args[1]) + imm, ok := arm.DecodeImmediate(i.Args[1]) if ok { return int32(imm), nil } diff --git a/interpreter/hotspot/stubs.go b/interpreter/hotspot/stubs.go index 655778cb9..188206c4a 100644 --- a/interpreter/hotspot/stubs.go +++ b/interpreter/hotspot/stubs.go @@ -10,7 +10,7 @@ import ( "slices" "strings" - "go.opentelemetry.io/ebpf-profiler/armhelpers" + "go.opentelemetry.io/ebpf-profiler/asm/arm" "go.opentelemetry.io/ebpf-profiler/libpf" "go.opentelemetry.io/ebpf-profiler/remotememory" "go.opentelemetry.io/ebpf-profiler/support" @@ -208,7 +208,7 @@ Outer: if arg.Mode != aa.AddrPostIndex && arg.Mode != aa.AddrPreIndex { continue } - imm, ok := armhelpers.DecodeImmediate(arg) + imm, ok := arm.DecodeImmediate(arg) if !ok { continue } @@ -221,7 +221,7 @@ Outer: continue Outer } } - imm, ok := armhelpers.DecodeImmediate(insn.Args[2]) + imm, ok := arm.DecodeImmediate(insn.Args[2]) if !ok { continue } diff --git a/interpreter/php/decode_aarch64.go b/interpreter/php/decode_aarch64.go index 6ec7dea25..b89309201 100644 --- a/interpreter/php/decode_aarch64.go +++ b/interpreter/php/decode_aarch64.go @@ -7,7 +7,7 @@ import ( "errors" "fmt" - ah "go.opentelemetry.io/ebpf-profiler/armhelpers" + "go.opentelemetry.io/ebpf-profiler/asm/arm" "go.opentelemetry.io/ebpf-profiler/libpf" aa "golang.org/x/arch/arm64/arm64asm" ) @@ -34,13 +34,13 @@ func retrieveZendVMKindARM(code []byte) (uint, error) { } // We only care about writes into w0 - dest, ok := ah.Xreg2num(inst.Args[0]) + dest, ok := arm.Xreg2num(inst.Args[0]) if dest != 0 || !ok { continue } if inst.Op == aa.MOV { - val, ok := ah.DecodeImmediate(inst.Args[1]) + val, ok := arm.DecodeImmediate(inst.Args[1]) if !ok { break } @@ -140,14 +140,14 @@ func retrieveJITBufferPtrARM(code []byte, addrBase libpf.SymbolValue) ( } // We only care about writes into xn/wn registers. - dest, ok := ah.Xreg2num(inst.Args[0]) + dest, ok := arm.Xreg2num(inst.Args[0]) if !ok { continue } switch inst.Op { case aa.ADD: - a2, ok := ah.DecodeImmediate(inst.Args[2]) + a2, ok := arm.DecodeImmediate(inst.Args[2]) if !ok { break } @@ -159,7 +159,7 @@ func retrieveJITBufferPtrARM(code []byte, addrBase libpf.SymbolValue) ( // Note that GDB lies to you here: it will give you // a different value in the ASM listing compared to the // disassembler - a2, ok := ah.DecodeImmediate(inst.Args[1]) + a2, ok := arm.DecodeImmediate(inst.Args[1]) if !ok { break } @@ -174,12 +174,12 @@ func retrieveJITBufferPtrARM(code []byte, addrBase libpf.SymbolValue) ( break } - val, ok := ah.DecodeImmediate(m) + val, ok := arm.DecodeImmediate(m) if !ok { break } - src, ok := ah.Xreg2num(m.Base) + src, ok := arm.Xreg2num(m.Base) if !ok { break } diff --git a/interpreter/python/arm64_decode.go b/interpreter/python/arm64_decode.go index f1577edcf..d3721453e 100644 --- a/interpreter/python/arm64_decode.go +++ b/interpreter/python/arm64_decode.go @@ -4,7 +4,7 @@ package python // import "go.opentelemetry.io/ebpf-profiler/interpreter/python" import ( - ah "go.opentelemetry.io/ebpf-profiler/armhelpers" + "go.opentelemetry.io/ebpf-profiler/asm/arm" "go.opentelemetry.io/ebpf-profiler/libpf" aa "golang.org/x/arch/arm64/arm64asm" ) @@ -60,7 +60,7 @@ func decodeStubArgumentARM64(code []byte, } // Interested only on commands modifying Xn - dest, ok := ah.Xreg2num(inst.Args[0]) + dest, ok := arm.Xreg2num(inst.Args[0]) if !ok { continue } @@ -69,7 +69,7 @@ func decodeStubArgumentARM64(code []byte, instRetval := libpf.SymbolValueInvalid switch inst.Op { case aa.ADD: - a2, ok := ah.DecodeImmediate(inst.Args[2]) + a2, ok := arm.DecodeImmediate(inst.Args[2]) if !ok { break } @@ -80,11 +80,11 @@ func decodeStubArgumentARM64(code []byte, if !ok { break } - src, ok := ah.Xreg2num(m.Base) + src, ok := arm.Xreg2num(m.Base) if !ok { break } - imm, ok := ah.DecodeImmediate(inst.Args[1]) + imm, ok := arm.DecodeImmediate(inst.Args[1]) if !ok { break } diff --git a/libc/assembly_decode_aarch64.go b/libc/assembly_decode_aarch64.go index 50bb706a6..c4c7e0f59 100644 --- a/libc/assembly_decode_aarch64.go +++ b/libc/assembly_decode_aarch64.go @@ -7,7 +7,7 @@ import ( "errors" "fmt" - ah "go.opentelemetry.io/ebpf-profiler/armhelpers" + "go.opentelemetry.io/ebpf-profiler/asm/arm" aa "golang.org/x/arch/arm64/arm64asm" ) @@ -49,11 +49,11 @@ func analyzeTLSSetARM(code []byte) (uint32, error) { switch inst.Op { case aa.MOV: // Track register moves - destReg, ok := ah.Xreg2num(inst.Args[0]) + destReg, ok := arm.Xreg2num(inst.Args[0]) if !ok { continue } - if srcReg, ok := ah.Xreg2num(inst.Args[1]); ok { + if srcReg, ok := arm.Xreg2num(inst.Args[1]); ok { arg[destReg] = arg[srcReg] } case aa.LDR: @@ -63,12 +63,12 @@ func analyzeTLSSetARM(code []byte) (uint32, error) { continue } var srcReg int - if srcReg, ok = ah.Xreg2num(m.Base); !ok || !arg[srcReg] { + if srcReg, ok = arm.Xreg2num(m.Base); !ok || !arg[srcReg] { continue } // FIXME: m.imm is not public, but should be. // https://github.com/golang/go/issues/51517 - imm, ok := ah.DecodeImmediate(m) + imm, ok := arm.DecodeImmediate(m) if !ok { return 0, err } @@ -80,7 +80,7 @@ func analyzeTLSSetARM(code []byte) (uint32, error) { return uint32(imm), nil default: // Reset register state if something unsupported happens on it - if destReg, ok := ah.Xreg2num(inst.Args[0]); ok { + if destReg, ok := arm.Xreg2num(inst.Args[0]); ok { arg[destReg] = false } } diff --git a/libc/libc_aarch64.go b/libc/libc_aarch64.go index fc5ceb76f..adf9ee67c 100644 --- a/libc/libc_aarch64.go +++ b/libc/libc_aarch64.go @@ -7,7 +7,7 @@ import ( "errors" "fmt" - ah "go.opentelemetry.io/ebpf-profiler/armhelpers" + "go.opentelemetry.io/ebpf-profiler/asm/arm" "go.opentelemetry.io/ebpf-profiler/stringutil" aa "golang.org/x/arch/arm64/arm64asm" ) @@ -57,7 +57,7 @@ func extractTSDInfoARM(code []byte) (TSDInfo, error) { break } - destReg, ok := ah.Xreg2num(inst.Args[0]) + destReg, ok := arm.Xreg2num(inst.Args[0]) if !ok { continue } @@ -80,7 +80,7 @@ func extractTSDInfoARM(code []byte) (TSDInfo, error) { } default: // Track register moves - srcReg, ok := ah.Xreg2num(inst.Args[1]) + srcReg, ok := arm.Xreg2num(inst.Args[1]) if !ok { continue } @@ -100,12 +100,12 @@ func extractTSDInfoARM(code []byte) (TSDInfo, error) { if !ok { continue } - srcReg, ok := ah.Xreg2num(m.Base) + srcReg, ok := arm.Xreg2num(m.Base) if !ok { continue } if regs[srcReg].status == TSDBase { - imm, ok := ah.DecodeImmediate(m) + imm, ok := arm.DecodeImmediate(m) if !ok { continue } @@ -122,11 +122,11 @@ func extractTSDInfoARM(code []byte) (TSDInfo, error) { switch m := inst.Args[1].(type) { case aa.MemExtend: // LDR X0, [X1,W0,UXTW #3] - srcReg, ok := ah.Xreg2num(m.Base) + srcReg, ok := arm.Xreg2num(m.Base) if !ok { continue } - srcIndex, ok := ah.Xreg2num(m.Index) + srcIndex, ok := arm.Xreg2num(m.Index) if !ok { continue } @@ -142,12 +142,12 @@ func extractTSDInfoARM(code []byte) (TSDInfo, error) { } case aa.MemImmediate: // ldr x0, [x2, #8] - srcReg, ok := ah.Xreg2num(m.Base) + srcReg, ok := arm.Xreg2num(m.Base) if !ok { continue } if regs[srcReg].status == TSDElementBase { - i, ok := ah.DecodeImmediate(m) + i, ok := arm.DecodeImmediate(m) if !ok { continue } @@ -163,7 +163,7 @@ func extractTSDInfoARM(code []byte) (TSDInfo, error) { } case aa.UBFIZ: // UBFIZ X0, X1, #4, #32 - srcReg, ok := ah.Xreg2num(inst.Args[1]) + srcReg, ok := arm.Xreg2num(inst.Args[1]) if !ok { continue } @@ -179,13 +179,13 @@ func extractTSDInfoARM(code []byte) (TSDInfo, error) { } } case aa.ADD: - srcReg, ok := ah.Xreg2num(inst.Args[1]) + srcReg, ok := arm.Xreg2num(inst.Args[1]) if !ok { continue } switch a2 := inst.Args[2].(type) { case aa.ImmShift: - i, ok := ah.DecodeImmediate(a2) + i, ok := arm.DecodeImmediate(a2) if !ok { continue } @@ -205,11 +205,11 @@ func extractTSDInfoARM(code []byte) (TSDInfo, error) { } } } - reg, ok := ah.DecodeRegister(regStr) + reg, ok := arm.DecodeRegister(regStr) if !ok { continue } - srcReg2, ok := ah.Xreg2num(reg) + srcReg2, ok := arm.Xreg2num(reg) if !ok { continue } @@ -231,12 +231,12 @@ func extractTSDInfoARM(code []byte) (TSDInfo, error) { } } case aa.SUB: - srcReg, ok := ah.Xreg2num(inst.Args[1]) + srcReg, ok := arm.Xreg2num(inst.Args[1]) if !ok { continue } if regs[srcReg].status != Unspec { - i, ok := ah.DecodeImmediate(inst.Args[2]) + i, ok := arm.DecodeImmediate(inst.Args[2]) if !ok { continue } diff --git a/maccess/maccess_arm64.go b/maccess/maccess_arm64.go index 7b68b984c..621caab26 100644 --- a/maccess/maccess_arm64.go +++ b/maccess/maccess_arm64.go @@ -8,7 +8,7 @@ package maccess // import "go.opentelemetry.io/ebpf-profiler/maccess" import ( "errors" - ah "go.opentelemetry.io/ebpf-profiler/armhelpers" + "go.opentelemetry.io/ebpf-profiler/asm/arm" aa "golang.org/x/arch/arm64/arm64asm" ) @@ -72,7 +72,7 @@ func CopyFromUserNoFaultIsPatched(codeblob []byte, _, _ uint64) (bool, error) { } if r, ok := inst.Args[0].(aa.Reg); ok { - if regN, ok := ah.Xreg2num(r); ok && + if regN, ok := arm.Xreg2num(r); ok && expectedInstructionTracker == stepNone { trackedReg = regN expectedInstructionTracker ^= stepMov @@ -84,14 +84,14 @@ func CopyFromUserNoFaultIsPatched(codeblob []byte, _, _ uint64) (bool, error) { trackedReg = -1 expectedInstructionTracker = stepNone case aa.CMP: - if regN, ok := ah.Xreg2num(inst.Args[0]); ok && + if regN, ok := arm.Xreg2num(inst.Args[0]); ok && expectedInstructionTracker&stepMov == stepMov { if trackedReg == regN { expectedInstructionTracker ^= stepCmp continue } } - if regN, ok := ah.Xreg2num(inst.Args[1]); ok { + if regN, ok := arm.Xreg2num(inst.Args[1]); ok { if trackedReg == regN { expectedInstructionTracker ^= stepCmp continue @@ -122,7 +122,7 @@ func CopyFromUserNoFaultIsPatched(codeblob []byte, _, _ uint64) (bool, error) { case aa.SUB: // If the minuend of the subtraction is trackedReg, copy_from_user_nofault seems // to be patched. - if regN, ok := ah.Xreg2num(inst.Args[1]); ok { + if regN, ok := arm.Xreg2num(inst.Args[1]); ok { if trackedReg == regN && expectedInstructionTracker == (stepMov|stepCmp|stepB) { return true, nil } diff --git a/processmanager/execinfomanager/synthdeltas.go b/processmanager/execinfomanager/synthdeltas.go index d22ab0388..29b384bbb 100644 --- a/processmanager/execinfomanager/synthdeltas.go +++ b/processmanager/execinfomanager/synthdeltas.go @@ -8,7 +8,7 @@ import ( aa "golang.org/x/arch/arm64/arm64asm" - ah "go.opentelemetry.io/ebpf-profiler/armhelpers" + "go.opentelemetry.io/ebpf-profiler/asm/arm" "go.opentelemetry.io/ebpf-profiler/libpf" "go.opentelemetry.io/ebpf-profiler/libpf/pfelf" sdtypes "go.opentelemetry.io/ebpf-profiler/nativeunwind/stackdeltatypes" @@ -70,13 +70,13 @@ func createVDSOSyntheticRecordArm64(ef *pfelf.File) sdtypes.IntervalData { case aa.RET: return true case aa.STP: - if reg, ok := ah.Xreg2num(inst.Args[0]); !ok || reg != regFP { + if reg, ok := arm.Xreg2num(inst.Args[0]); !ok || reg != regFP { continue } - if reg, ok := ah.Xreg2num(inst.Args[1]); !ok || reg != regLR { + if reg, ok := arm.Xreg2num(inst.Args[1]); !ok || reg != regLR { continue } - imm, ok := ah.DecodeImmediate(inst.Args[2]) + imm, ok := arm.DecodeImmediate(inst.Args[2]) if !ok { continue } @@ -86,10 +86,10 @@ func createVDSOSyntheticRecordArm64(ef *pfelf.File) sdtypes.IntervalData { frameSize = int(imm) } case aa.LDP: - if reg, ok := ah.Xreg2num(inst.Args[0]); !ok || reg != regFP { + if reg, ok := arm.Xreg2num(inst.Args[0]); !ok || reg != regFP { continue } - if reg, ok := ah.Xreg2num(inst.Args[1]); !ok || reg != regLR { + if reg, ok := arm.Xreg2num(inst.Args[1]); !ok || reg != regLR { continue } if frameStart == 0 {