github.com/undoio/delve@v1.9.0/pkg/proc/arch.go (about) 1 package proc 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/undoio/delve/pkg/dwarf/frame" 8 "github.com/undoio/delve/pkg/dwarf/op" 9 ) 10 11 // Arch represents a CPU architecture. 12 type Arch struct { 13 Name string // architecture name 14 15 ptrSize int 16 maxInstructionLength int 17 prologues []opcodeSeq 18 breakpointInstruction []byte 19 altBreakpointInstruction []byte 20 breakInstrMovesPC bool 21 derefTLS bool 22 usesLR bool // architecture uses a link register, also called RA on some architectures 23 PCRegNum uint64 24 SPRegNum uint64 25 BPRegNum uint64 26 ContextRegNum uint64 // register used to pass a closure context when calling a function pointer 27 LRRegNum uint64 28 29 // asmDecode decodes the assembly instruction starting at mem[0:] into asmInst. 30 // It assumes that the Loc and AtPC fields of asmInst have already been filled. 31 asmDecode func(asmInst *AsmInstruction, mem []byte, regs *op.DwarfRegisters, memrw MemoryReadWriter, bi *BinaryInfo) error 32 // fixFrameUnwindContext applies architecture specific rules for unwinding a stack frame 33 // on the given arch. 34 fixFrameUnwindContext func(*frame.FrameContext, uint64, *BinaryInfo) *frame.FrameContext 35 // switchStack will use the current frame to determine if it's time to 36 // switch between the system stack and the goroutine stack or vice versa. 37 switchStack func(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool 38 // regSize returns the size (in bytes) of register regnum. 39 regSize func(uint64) int 40 // RegistersToDwarfRegisters maps hardware registers to DWARF registers. 41 RegistersToDwarfRegisters func(uint64, Registers) *op.DwarfRegisters 42 // addrAndStackRegsToDwarfRegisters returns DWARF registers from the passed in 43 // PC, SP, and BP registers in the format used by the DWARF expression interpreter. 44 addrAndStackRegsToDwarfRegisters func(uint64, uint64, uint64, uint64, uint64) op.DwarfRegisters 45 // DwarfRegisterToString returns the name and value representation of the 46 // given register, the register value can be nil in which case only the 47 // register name will be returned. 48 DwarfRegisterToString func(int, *op.DwarfRegister) (string, bool, string) 49 // inhibitStepInto returns whether StepBreakpoint can be set at pc. 50 inhibitStepInto func(bi *BinaryInfo, pc uint64) bool 51 RegisterNameToDwarf func(s string) (int, bool) 52 // debugCallMinStackSize is the minimum stack size for call injection on this architecture. 53 debugCallMinStackSize uint64 54 // maxRegArgBytes is extra padding for ABI1 call injections, equivalent to 55 // the maximum space occupied by register arguments. 56 maxRegArgBytes int 57 58 // asmRegisters maps assembly register numbers to dwarf registers. 59 asmRegisters map[int]asmRegister 60 61 // crosscall2fn is the DIE of crosscall2, a function used by the go runtime 62 // to call C functions. This function in go 1.9 (and previous versions) had 63 // a bad frame descriptor which needs to be fixed to generate good stack 64 // traces. 65 crosscall2fn *Function 66 67 // sigreturnfn is the DIE of runtime.sigreturn, the return trampoline for 68 // the signal handler. See comment in FixFrameUnwindContext for a 69 // description of why this is needed. 70 sigreturnfn *Function 71 } 72 73 type asmRegister struct { 74 dwarfNum uint64 75 offset uint 76 mask uint64 77 } 78 79 const ( 80 mask8 = 0x000000ff 81 mask16 = 0x0000ffff 82 mask32 = 0xffffffff 83 ) 84 85 // PtrSize returns the size of a pointer for the architecture. 86 func (a *Arch) PtrSize() int { 87 return a.ptrSize 88 } 89 90 // MaxInstructionLength is the maximum size in bytes of an instruction. 91 func (a *Arch) MaxInstructionLength() int { 92 return a.maxInstructionLength 93 } 94 95 // BreakpointInstruction is the instruction that will trigger a breakpoint trap for 96 // the given architecture. 97 func (a *Arch) BreakpointInstruction() []byte { 98 return a.breakpointInstruction 99 } 100 101 // AltBreakpointInstruction returns an alternate encoding for the breakpoint instruction. 102 func (a *Arch) AltBreakpointInstruction() []byte { 103 return a.altBreakpointInstruction 104 } 105 106 // BreakInstrMovesPC is true if hitting the breakpoint instruction advances the 107 // instruction counter by the size of the breakpoint instruction. 108 func (a *Arch) BreakInstrMovesPC() bool { 109 return a.breakInstrMovesPC 110 } 111 112 // BreakpointSize is the size of the breakpoint instruction for the given architecture. 113 func (a *Arch) BreakpointSize() int { 114 return len(a.breakpointInstruction) 115 } 116 117 // DerefTLS is true if the G struct stored in the TLS section is a pointer 118 // and the address must be dereferenced to find to actual G struct. 119 func (a *Arch) DerefTLS() bool { 120 return a.derefTLS 121 } 122 123 // getAsmRegister returns the value of the asm register asmreg using the asmRegisters table of arch. 124 // The interpretation of asmreg is architecture specific and defined by the disassembler. 125 // A mask value of 0 inside asmRegisters is equivalent to ^uint64(0). 126 func (arch *Arch) getAsmRegister(regs *op.DwarfRegisters, asmreg int) (uint64, error) { 127 hwreg, ok := arch.asmRegisters[asmreg] 128 if !ok { 129 return 0, ErrUnknownRegister 130 } 131 reg := regs.Reg(hwreg.dwarfNum) 132 if reg == nil { 133 return 0, fmt.Errorf("register %#x not found", asmreg) 134 } 135 n := (reg.Uint64Val >> hwreg.offset) 136 if hwreg.mask != 0 { 137 n = n & hwreg.mask 138 } 139 return n, nil 140 } 141 142 func nameToDwarfFunc(n2d map[string]int) func(string) (int, bool) { 143 return func(name string) (int, bool) { 144 r, ok := n2d[strings.ToLower(name)] 145 return r, ok 146 } 147 } 148 149 // crosscall2 is defined in $GOROOT/src/runtime/cgo/asm_amd64.s. 150 const ( 151 crosscall2SPOffsetBad = 0x8 152 crosscall2SPOffsetWindows = 0x118 153 crosscall2SPOffsetNonWindows = 0x58 154 )