github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/export_debug_amd64_test.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build amd64 && linux 6 7 package runtime 8 9 import ( 10 "internal/abi" 11 "internal/goarch" 12 "unsafe" 13 ) 14 15 type sigContext struct { 16 savedRegs sigcontext 17 // sigcontext.fpstate is a pointer, so we need to save 18 // the its value with a fpstate1 structure. 19 savedFP fpstate1 20 } 21 22 func sigctxtSetContextRegister(ctxt *sigctxt, x uint64) { 23 ctxt.regs().rdx = x 24 } 25 26 func sigctxtAtTrapInstruction(ctxt *sigctxt) bool { 27 return *(*byte)(unsafe.Pointer(uintptr(ctxt.rip() - 1))) == 0xcc // INT 3 28 } 29 30 func sigctxtStatus(ctxt *sigctxt) uint64 { 31 return ctxt.r12() 32 } 33 34 func (h *debugCallHandler) saveSigContext(ctxt *sigctxt) { 35 // Push current PC on the stack. 36 rsp := ctxt.rsp() - goarch.PtrSize 37 *(*uint64)(unsafe.Pointer(uintptr(rsp))) = ctxt.rip() 38 ctxt.set_rsp(rsp) 39 // Write the argument frame size. 40 *(*uintptr)(unsafe.Pointer(uintptr(rsp - 16))) = h.argSize 41 // Save current registers. 42 h.sigCtxt.savedRegs = *ctxt.regs() 43 h.sigCtxt.savedFP = *h.sigCtxt.savedRegs.fpstate 44 h.sigCtxt.savedRegs.fpstate = nil 45 } 46 47 // case 0 48 func (h *debugCallHandler) debugCallRun(ctxt *sigctxt) { 49 rsp := ctxt.rsp() 50 memmove(unsafe.Pointer(uintptr(rsp)), h.argp, h.argSize) 51 if h.regArgs != nil { 52 storeRegArgs(ctxt.regs(), h.regArgs) 53 } 54 // Push return PC. 55 rsp -= goarch.PtrSize 56 ctxt.set_rsp(rsp) 57 // The signal PC is the next PC of the trap instruction. 58 *(*uint64)(unsafe.Pointer(uintptr(rsp))) = ctxt.rip() 59 // Set PC to call and context register. 60 ctxt.set_rip(uint64(h.fv.fn)) 61 sigctxtSetContextRegister(ctxt, uint64(uintptr(unsafe.Pointer(h.fv)))) 62 } 63 64 // case 1 65 func (h *debugCallHandler) debugCallReturn(ctxt *sigctxt) { 66 rsp := ctxt.rsp() 67 memmove(h.argp, unsafe.Pointer(uintptr(rsp)), h.argSize) 68 if h.regArgs != nil { 69 loadRegArgs(h.regArgs, ctxt.regs()) 70 } 71 } 72 73 // case 2 74 func (h *debugCallHandler) debugCallPanicOut(ctxt *sigctxt) { 75 rsp := ctxt.rsp() 76 memmove(unsafe.Pointer(&h.panic), unsafe.Pointer(uintptr(rsp)), 2*goarch.PtrSize) 77 } 78 79 // case 8 80 func (h *debugCallHandler) debugCallUnsafe(ctxt *sigctxt) { 81 rsp := ctxt.rsp() 82 reason := *(*string)(unsafe.Pointer(uintptr(rsp))) 83 h.err = plainError(reason) 84 } 85 86 // case 16 87 func (h *debugCallHandler) restoreSigContext(ctxt *sigctxt) { 88 // Restore all registers except RIP and RSP. 89 rip, rsp := ctxt.rip(), ctxt.rsp() 90 fp := ctxt.regs().fpstate 91 *ctxt.regs() = h.sigCtxt.savedRegs 92 ctxt.regs().fpstate = fp 93 *fp = h.sigCtxt.savedFP 94 ctxt.set_rip(rip) 95 ctxt.set_rsp(rsp) 96 } 97 98 // storeRegArgs sets up argument registers in the signal 99 // context state from an abi.RegArgs. 100 // 101 // Both src and dst must be non-nil. 102 func storeRegArgs(dst *sigcontext, src *abi.RegArgs) { 103 dst.rax = uint64(src.Ints[0]) 104 dst.rbx = uint64(src.Ints[1]) 105 dst.rcx = uint64(src.Ints[2]) 106 dst.rdi = uint64(src.Ints[3]) 107 dst.rsi = uint64(src.Ints[4]) 108 dst.r8 = uint64(src.Ints[5]) 109 dst.r9 = uint64(src.Ints[6]) 110 dst.r10 = uint64(src.Ints[7]) 111 dst.r11 = uint64(src.Ints[8]) 112 for i := range src.Floats { 113 dst.fpstate._xmm[i].element[0] = uint32(src.Floats[i] >> 0) 114 dst.fpstate._xmm[i].element[1] = uint32(src.Floats[i] >> 32) 115 } 116 } 117 118 func loadRegArgs(dst *abi.RegArgs, src *sigcontext) { 119 dst.Ints[0] = uintptr(src.rax) 120 dst.Ints[1] = uintptr(src.rbx) 121 dst.Ints[2] = uintptr(src.rcx) 122 dst.Ints[3] = uintptr(src.rdi) 123 dst.Ints[4] = uintptr(src.rsi) 124 dst.Ints[5] = uintptr(src.r8) 125 dst.Ints[6] = uintptr(src.r9) 126 dst.Ints[7] = uintptr(src.r10) 127 dst.Ints[8] = uintptr(src.r11) 128 for i := range dst.Floats { 129 dst.Floats[i] = uint64(src.fpstate._xmm[i].element[0]) << 0 130 dst.Floats[i] |= uint64(src.fpstate._xmm[i].element[1]) << 32 131 } 132 }