github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/pkg/proc/winutil/regs_arm64_arch.go (about) 1 package winutil 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "unsafe" 8 9 "github.com/go-delve/delve/pkg/dwarf/op" 10 "github.com/go-delve/delve/pkg/dwarf/regnum" 11 "github.com/go-delve/delve/pkg/proc" 12 ) 13 14 const ( 15 ARM64_MAX_BREAKPOINTS = 8 16 ARM64_MAX_WATCHPOINTS = 2 17 ) 18 19 // neon128 tracks the neon128 windows struct. 20 type neon128 struct { 21 Low uint64 22 High int64 23 } 24 25 // ARM64Registers represents CPU registers on an ARM64 processor. 26 type ARM64Registers struct { 27 iscgo bool 28 Regs [31]uint64 29 Sp uint64 30 Pc uint64 31 FloatRegisters [32]neon128 32 Fpcr uint32 33 Fpsr uint32 34 Bcr [ARM64_MAX_BREAKPOINTS]uint32 35 Bvr [ARM64_MAX_BREAKPOINTS]uint64 36 Wcr [ARM64_MAX_WATCHPOINTS]uint32 37 Wvr [ARM64_MAX_WATCHPOINTS]uint64 38 Context *ARM64CONTEXT 39 } 40 41 // NewARM64Registers creates a new ARM64Registers struct from a CONTEXT. 42 func NewARM64Registers(context *ARM64CONTEXT, iscgo bool) *ARM64Registers { 43 regs := &ARM64Registers{ 44 iscgo: iscgo, 45 Regs: context.Regs, 46 Sp: context.Sp, 47 Pc: context.Pc, 48 FloatRegisters: context.FloatRegisters, 49 Fpcr: context.Fpcr, 50 Fpsr: context.Fpsr, 51 Bcr: context.Bcr, 52 Bvr: context.Bvr, 53 Wcr: context.Wcr, 54 Wvr: context.Wvr, 55 Context: context, 56 } 57 58 return regs 59 } 60 61 // Slice returns the registers as a list of (name, value) pairs. 62 func (r *ARM64Registers) Slice(floatingPoint bool) ([]proc.Register, error) { 63 out := make([]proc.Register, 0, len(r.Regs)+len(r.FloatRegisters)+2) 64 for i, v := range r.Regs { 65 out = proc.AppendUint64Register(out, fmt.Sprintf("X%d", i), v) 66 } 67 out = proc.AppendUint64Register(out, "SP", r.Sp) 68 out = proc.AppendUint64Register(out, "PC", r.Pc) 69 if floatingPoint { 70 for i := range r.FloatRegisters { 71 var buf bytes.Buffer 72 binary.Write(&buf, binary.LittleEndian, r.FloatRegisters[i].Low) 73 binary.Write(&buf, binary.LittleEndian, r.FloatRegisters[i].High) 74 out = proc.AppendBytesRegister(out, fmt.Sprintf("V%d", i), buf.Bytes()) 75 } 76 out = proc.AppendUint64Register(out, "Fpcr", uint64(r.Fpcr)) 77 out = proc.AppendUint64Register(out, "Fpsr", uint64(r.Fpsr)) 78 } 79 return out, nil 80 } 81 82 // PC returns the value of RIP register. 83 func (r *ARM64Registers) PC() uint64 { 84 return r.Pc 85 } 86 87 // SP returns the value of RSP register. 88 func (r *ARM64Registers) SP() uint64 { 89 return r.Sp 90 } 91 92 func (r *ARM64Registers) BP() uint64 { 93 return r.Regs[29] 94 } 95 96 // TLS returns the address of the thread local storage memory segment. 97 func (r *ARM64Registers) TLS() uint64 { 98 if !r.iscgo { 99 return 0 100 } 101 return r.Regs[18] 102 } 103 104 // GAddr returns the address of the G variable if it is known, 0 and false 105 // otherwise. 106 func (r *ARM64Registers) GAddr() (uint64, bool) { 107 return r.Regs[28], !r.iscgo 108 } 109 110 // LR returns the link register. 111 func (r *ARM64Registers) LR() uint64 { 112 return r.Regs[30] 113 } 114 115 // Copy returns a copy of these registers that is guaranteed not to change. 116 func (r *ARM64Registers) Copy() (proc.Registers, error) { 117 rr := *r 118 rr.Context = NewARM64CONTEXT() 119 *(rr.Context) = *(r.Context) 120 return &rr, nil 121 } 122 123 // ARM64CONTEXT tracks the _ARM64_NT_CONTEXT of windows. 124 type ARM64CONTEXT struct { 125 ContextFlags uint32 126 Cpsr uint32 127 Regs [31]uint64 128 Sp uint64 129 Pc uint64 130 FloatRegisters [32]neon128 131 Fpcr uint32 132 Fpsr uint32 133 Bcr [ARM64_MAX_BREAKPOINTS]uint32 134 Bvr [ARM64_MAX_BREAKPOINTS]uint64 135 Wcr [ARM64_MAX_WATCHPOINTS]uint32 136 Wvr [ARM64_MAX_WATCHPOINTS]uint64 137 } 138 139 // NewARM64CONTEXT allocates Windows CONTEXT structure aligned to 16 bytes. 140 func NewARM64CONTEXT() *ARM64CONTEXT { 141 var c *ARM64CONTEXT 142 buf := make([]byte, unsafe.Sizeof(*c)+15) 143 return (*ARM64CONTEXT)(unsafe.Pointer((uintptr(unsafe.Pointer(&buf[15]))) &^ 15)) 144 } 145 146 func (ctx *ARM64CONTEXT) SetFlags(flags uint32) { 147 ctx.ContextFlags = flags 148 } 149 150 func (ctx *ARM64CONTEXT) SetPC(pc uint64) { 151 ctx.Pc = pc 152 } 153 154 func (ctx *ARM64CONTEXT) SetTrap(trap bool) { 155 const v = 0x200000 156 if trap { 157 ctx.Cpsr |= v 158 } else { 159 ctx.Cpsr &= ^uint32(v) 160 } 161 } 162 163 func (ctx *ARM64CONTEXT) SetReg(regNum uint64, reg *op.DwarfRegister) error { 164 switch regNum { 165 case regnum.ARM64_PC: 166 ctx.Pc = reg.Uint64Val 167 return nil 168 case regnum.ARM64_SP: 169 ctx.Sp = reg.Uint64Val 170 return nil 171 default: 172 switch { 173 case regNum >= regnum.ARM64_X0 && regNum <= regnum.ARM64_X0+30: 174 ctx.Regs[regNum-regnum.ARM64_X0] = reg.Uint64Val 175 return nil 176 177 case regNum >= regnum.ARM64_V0 && regNum <= regnum.ARM64_V0+30: 178 i := regNum - regnum.ARM64_V0 179 ctx.FloatRegisters[i].Low = reg.Uint64Val 180 ctx.FloatRegisters[i].High = 0 181 return nil 182 default: 183 return fmt.Errorf("changing register %d not implemented", regNum) 184 } 185 } 186 }