aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/export_debug_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/export_debug_test.go')
-rw-r--r--src/runtime/export_debug_test.go68
1 files changed, 17 insertions, 51 deletions
diff --git a/src/runtime/export_debug_test.go b/src/runtime/export_debug_test.go
index 19a9ec135f..09e9779696 100644
--- a/src/runtime/export_debug_test.go
+++ b/src/runtime/export_debug_test.go
@@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build amd64 && linux
+//go:build (amd64 || arm64) && linux
package runtime
import (
"internal/abi"
- "internal/goarch"
"unsafe"
)
@@ -100,10 +99,9 @@ type debugCallHandler struct {
handleF func(info *siginfo, ctxt *sigctxt, gp2 *g) bool
- err plainError
- done note
- savedRegs sigcontext
- savedFP fpstate1
+ err plainError
+ done note
+ sigCtxt sigContext
}
func (h *debugCallHandler) inject(info *siginfo, ctxt *sigctxt, gp2 *g) bool {
@@ -117,18 +115,10 @@ func (h *debugCallHandler) inject(info *siginfo, ctxt *sigctxt, gp2 *g) bool {
println("trap on wrong M", getg().m, h.mp)
return false
}
- // Push current PC on the stack.
- rsp := ctxt.rsp() - goarch.PtrSize
- *(*uint64)(unsafe.Pointer(uintptr(rsp))) = ctxt.rip()
- ctxt.set_rsp(rsp)
- // Write the argument frame size.
- *(*uintptr)(unsafe.Pointer(uintptr(rsp - 16))) = h.argSize
- // Save current registers.
- h.savedRegs = *ctxt.regs()
- h.savedFP = *h.savedRegs.fpstate
- h.savedRegs.fpstate = nil
+ // Save the signal context
+ h.saveSigContext(ctxt)
// Set PC to debugCallV2.
- ctxt.set_rip(uint64(abi.FuncPCABIInternal(debugCallV2)))
+ ctxt.setsigpc(uint64(abi.FuncPCABIInternal(debugCallV2)))
// Call injected. Switch to the debugCall protocol.
testSigtrap = h.handleF
case _Grunnable:
@@ -154,57 +144,33 @@ func (h *debugCallHandler) handle(info *siginfo, ctxt *sigctxt, gp2 *g) bool {
println("trap on wrong M", getg().m, h.mp)
return false
}
- f := findfunc(uintptr(ctxt.rip()))
+ f := findfunc(ctxt.sigpc())
if !(hasPrefix(funcname(f), "runtime.debugCall") || hasPrefix(funcname(f), "debugCall")) {
println("trap in unknown function", funcname(f))
return false
}
- if *(*byte)(unsafe.Pointer(uintptr(ctxt.rip() - 1))) != 0xcc {
- println("trap at non-INT3 instruction pc =", hex(ctxt.rip()))
+ if !sigctxtAtTrapInstruction(ctxt) {
+ println("trap at non-INT3 instruction pc =", hex(ctxt.sigpc()))
return false
}
- switch status := ctxt.r12(); status {
+ switch status := sigctxtStatus(ctxt); status {
case 0:
// Frame is ready. Copy the arguments to the frame and to registers.
- sp := ctxt.rsp()
- memmove(unsafe.Pointer(uintptr(sp)), h.argp, h.argSize)
- if h.regArgs != nil {
- storeRegArgs(ctxt.regs(), h.regArgs)
- }
- // Push return PC.
- sp -= goarch.PtrSize
- ctxt.set_rsp(sp)
- *(*uint64)(unsafe.Pointer(uintptr(sp))) = ctxt.rip()
- // Set PC to call and context register.
- ctxt.set_rip(uint64(h.fv.fn))
- ctxt.regs().rdx = uint64(uintptr(unsafe.Pointer(h.fv)))
+ // Call the debug function.
+ h.debugCallRun(ctxt)
case 1:
// Function returned. Copy frame and result registers back out.
- sp := ctxt.rsp()
- memmove(h.argp, unsafe.Pointer(uintptr(sp)), h.argSize)
- if h.regArgs != nil {
- loadRegArgs(h.regArgs, ctxt.regs())
- }
+ h.debugCallReturn(ctxt)
case 2:
// Function panicked. Copy panic out.
- sp := ctxt.rsp()
- memmove(unsafe.Pointer(&h.panic), unsafe.Pointer(uintptr(sp)), 2*goarch.PtrSize)
+ h.debugCallPanicOut(ctxt)
case 8:
// Call isn't safe. Get the reason.
- sp := ctxt.rsp()
- reason := *(*string)(unsafe.Pointer(uintptr(sp)))
- h.err = plainError(reason)
+ h.debugCallUnsafe(ctxt)
// Don't wake h.done. We need to transition to status 16 first.
case 16:
- // Restore all registers except RIP and RSP.
- rip, rsp := ctxt.rip(), ctxt.rsp()
- fp := ctxt.regs().fpstate
- *ctxt.regs() = h.savedRegs
- ctxt.regs().fpstate = fp
- *fp = h.savedFP
- ctxt.set_rip(rip)
- ctxt.set_rsp(rsp)
+ h.restoreSigContext(ctxt)
// Done
notewakeup(&h.done)
default: