Source file src/runtime/export_debug_amd64_test.go

     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  }
   133  

View as plain text