diff options
Diffstat (limited to 'src/runtime/export_debug_test.go')
-rw-r--r-- | src/runtime/export_debug_test.go | 68 |
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: |