Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Documentation/backend_test_health.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ Tests skipped by each supported backend:
* 1 broken
* linux/loong64 skipped = 1
* 1 not working on linux/loong64
* linux/ppc64le skipped = 3
* 1 broken - cgo stacktraces
* linux/ppc64le skipped = 2
* 2 not working on linux/ppc64le when -gcflags=-N -l is passed
* linux/ppc64le/native skipped = 1
* 1 broken in linux ppc64le
Expand Down
13 changes: 6 additions & 7 deletions pkg/proc/arm64_arch.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,18 @@ func arm64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool
return true

case "crosscall2":
// The offsets get from runtime/cgo/asm_arm64.s:10
// The offsets get from runtime/cgo/asm_arm64.s
bpoff := uint64(14)
lroff := uint64(15)
if producer := it.bi.Producer(); producer != "" && goversion.ProducerAfterOrEqual(producer, 1, 19) {
// In Go 1.19 (specifically eee6f9f82) the order registers are saved was changed.
bpoff = 22
lroff = 23
}
newsp, _ := readUintRaw(it.mem, it.regs.SP()+8*24, int64(it.bi.Arch.PtrSize()))
// crosscall2 does SUB $(8*24), RSP but does not spill SP. The caller's SP is
// therefore current SP + 8*24, not a value loaded from that address (which is
// the caller's stack contents).
newsp := it.regs.SP() + 8*24
newbp, _ := readUintRaw(it.mem, it.regs.SP()+8*bpoff, int64(it.bi.Arch.PtrSize()))
newlr, _ := readUintRaw(it.mem, it.regs.SP()+8*lroff, int64(it.bi.Arch.PtrSize()))
if it.regs.Reg(it.regs.BPRegNum) != nil {
Expand All @@ -256,11 +259,7 @@ func arm64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool
it.regs.AddReg(it.regs.BPRegNum, reg)
}
it.regs.Reg(it.regs.LRRegNum).Uint64Val = newlr
if linux {
it.regs.Reg(it.regs.SPRegNum).Uint64Val = newbp
} else {
it.regs.Reg(it.regs.SPRegNum).Uint64Val = newsp
}
it.regs.Reg(it.regs.SPRegNum).Uint64Val = newsp
it.pc = newlr
return true
case "runtime.mstart":
Expand Down
6 changes: 4 additions & 2 deletions pkg/proc/loong64_arch.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,10 @@ func loong64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) boo
return true

case "crosscall2":
// The offsets get from runtime/cgo/asm_loong64.s:25
newsp, _ := readUintRaw(it.mem, it.regs.SP()+8*23, int64(it.bi.Arch.PtrSize()))
// The offsets get from runtime/cgo/asm_loong64.s
// crosscall2 does ADDV $(-23*8), R3 but does not spill SP. The caller's SP is
// therefore current SP + 23*8, not a value loaded from that address.
newsp := it.regs.SP() + 8*23
newbp, _ := readUintRaw(it.mem, it.regs.SP()+8*4, int64(it.bi.Arch.PtrSize()))
newlr, _ := readUintRaw(it.mem, it.regs.SP()+8*22, int64(it.bi.Arch.PtrSize()))
if it.regs.Reg(it.regs.BPRegNum) != nil {
Expand Down
18 changes: 13 additions & 5 deletions pkg/proc/ppc64le_arch.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,22 @@ func ppc64leSwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) boo
it.atend = true
return true
case "crosscall2":
//The offsets get from runtime/cgo/asm_ppc64x.s:10
newsp, _ := readUintRaw(it.mem, it.regs.SP()+8*24, int64(it.bi.Arch.PtrSize()))
newbp, _ := readUintRaw(it.mem, it.regs.SP()+8*14, int64(it.bi.Arch.PtrSize()))
newlr, _ := readUintRaw(it.mem, it.regs.SP()+16, int64(it.bi.Arch.PtrSize()))
// Frame size from STACK_AND_SAVE_HOST_TO_GO_ABI(32) in
// runtime/cgo/abi_ppc64x.h: extra(32) + FIXED_FRAME(32) +
// SAVE_GPR(18*8) + SAVE_FPR(18*8) + SAVE_VR(12*16).
const frameSize = 32 + 32 + 18*8 + 18*8 + 12*16
newsp := it.regs.SP() + frameSize
// R31 (frame pointer) is the last GPR saved by SAVE_GPR at
// extra+FIXED_FRAME+8*17.
bpoff := uint64(32 + 32 + 8*17)
newbp, _ := readUintRaw(it.mem, it.regs.SP()+bpoff, int64(it.bi.Arch.PtrSize()))
// LR is saved into the caller's frame at 16(SP) before the stack
// allocation (host ELFv2 ABI).
newlr, _ := readUintRaw(it.mem, newsp+16, int64(it.bi.Arch.PtrSize()))
if it.regs.Reg(it.regs.BPRegNum) != nil {
it.regs.Reg(it.regs.BPRegNum).Uint64Val = newbp
} else {
reg, _ := it.readRegisterAt(it.regs.BPRegNum, it.regs.SP()+8*14)
reg, _ := it.readRegisterAt(it.regs.BPRegNum, it.regs.SP()+bpoff)
it.regs.AddReg(it.regs.BPRegNum, reg)
}
it.regs.Reg(it.regs.LRRegNum).Uint64Val = newlr
Expand Down
4 changes: 3 additions & 1 deletion pkg/proc/proc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3127,8 +3127,10 @@ func TestCgoStacktrace(t *testing.T) {
}
}
skipOn(t, "broken - cgo stacktraces", "386")
// C frames on windows/arm64 use PE .pdata/.xdata (clang), not DWARF
// .debug_frame; Delve does not unwind via .pdata yet. Unrelated to the
// arm64 crosscall2 SP restore.
skipOn(t, "broken - cgo stacktraces", "windows", "arm64")
skipOn(t, "broken - cgo stacktraces", "linux", "ppc64le")
protest.MustHaveCgo(t)

// Tests that:
Expand Down
4 changes: 3 additions & 1 deletion pkg/proc/riscv64_arch.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@ func riscv64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) boo

case "crosscall2":
// The offsets get from runtime/cgo/asm_riscv64.s
newsp, _ := readUintRaw(it.mem, it.regs.SP()+8*29, int64(it.bi.Arch.PtrSize()))
// crosscall2 does ADD $(-8*29), X2 but does not spill SP. The caller's SP is
// therefore current SP + 8*29, not a value loaded from that address.
newsp := it.regs.SP() + 8*29
newbp, _ := readUintRaw(it.mem, it.regs.SP()+8*4, int64(it.bi.Arch.PtrSize()))
newlr, _ := readUintRaw(it.mem, it.regs.SP()+8*16, int64(it.bi.Arch.PtrSize()))
if it.regs.Reg(it.regs.BPRegNum) != nil {
Expand Down