proc: support reading deferred calls' arguments on linux/arm64 (#2210)

This commit is contained in:
Alessandro Arzilli
2020-10-22 17:26:19 +02:00
committed by GitHub
parent 1a782d321d
commit 775c923ec4
5 changed files with 20 additions and 10 deletions

View File

@ -3,10 +3,9 @@ Tests skipped by each supported backend:
* 386 skipped = 2.1% (3/145) * 386 skipped = 2.1% (3/145)
* 1 broken * 1 broken
* 2 broken - cgo stacktraces * 2 broken - cgo stacktraces
* arm64 skipped = 2.8% (4/145) * arm64 skipped = 2.1% (3/145)
* 2 broken * 2 broken
* 1 broken - global variable symbolication * 1 broken - global variable symbolication
* 1 broken - reading defers
* darwin/lldb skipped = 0.69% (1/145) * darwin/lldb skipped = 0.69% (1/145)
* 1 upstream issue * 1 upstream issue
* freebsd skipped = 7.6% (11/145) * freebsd skipped = 7.6% (11/145)

View File

@ -15,6 +15,7 @@ type Arch struct {
breakpointInstruction []byte breakpointInstruction []byte
breakInstrMovesPC bool breakInstrMovesPC bool
derefTLS bool derefTLS bool
usesLR bool // architecture uses a link register, also called RA on some architectures
// asmDecode decodes the assembly instruction starting at mem[0:] into asmInst. // asmDecode decodes the assembly instruction starting at mem[0:] into asmInst.
// It assumes that the Loc and AtPC fields of asmInst have already been filled. // It assumes that the Loc and AtPC fields of asmInst have already been filled.

View File

@ -40,6 +40,7 @@ func ARM64Arch(goos string) *Arch {
DwarfRegisterToString: arm64DwarfRegisterToString, DwarfRegisterToString: arm64DwarfRegisterToString,
inhibitStepInto: func(*BinaryInfo, uint64) bool { return false }, inhibitStepInto: func(*BinaryInfo, uint64) bool { return false },
asmDecode: arm64AsmDecode, asmDecode: arm64AsmDecode,
usesLR: true,
} }
} }

View File

@ -4160,7 +4160,6 @@ func TestNextUnknownInstr(t *testing.T) {
} }
func TestReadDeferArgs(t *testing.T) { func TestReadDeferArgs(t *testing.T) {
skipOn(t, "broken - reading defers", "arm64")
var tests = []struct { var tests = []struct {
frame, deferCall int frame, deferCall int
a, b int64 a, b int64

View File

@ -660,13 +660,23 @@ func (d *Defer) EvalScope(thread Thread) (*EvalScope, error) {
} }
// The arguments are stored immediately after the defer header struct, i.e. // The arguments are stored immediately after the defer header struct, i.e.
// addr+sizeof(_defer). Since CFA in go is always the address of the first // addr+sizeof(_defer).
// argument, that's what we use for the value of CFA.
// For SP we use CFA minus the size of one pointer because that would be if !bi.Arch.usesLR {
// the space occupied by pushing the return address on the stack during the // On architectures that don't have a link register CFA is always the address of the first
// CALL. // argument, that's what we use for the value of CFA.
scope.Regs.CFA = (int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize) // For SP we use CFA minus the size of one pointer because that would be
scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(scope.Regs.CFA - int64(bi.Arch.PtrSize())) // the space occupied by pushing the return address on the stack during the
// CALL.
scope.Regs.CFA = (int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize)
scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(scope.Regs.CFA - int64(bi.Arch.PtrSize()))
} else {
// On architectures that have a link register CFA and SP have the same
// value but the address of the first argument is at CFA+ptrSize so we set
// CFA to the start of the argument frame minus one pointer size.
scope.Regs.CFA = int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize - int64(bi.Arch.PtrSize())
scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(scope.Regs.CFA)
}
rdr := scope.Fn.cu.image.dwarfReader rdr := scope.Fn.cu.image.dwarfReader
rdr.Seek(scope.Fn.offset) rdr.Seek(scope.Fn.offset)