github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/binary_info/arch_arm64.go (about) 1 // The MIT License (MIT) 2 3 // Copyright (c) 2014 Derek Parker 4 5 // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 // this software and associated documentation files (the "Software"), to deal in 7 // the Software without restriction, including without limitation the rights to 8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 // the Software, and to permit persons to whom the Software is furnished to do so, 10 // subject to the following conditions: 11 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 //go:build arm64 23 // +build arm64 24 25 package binary_info 26 27 import ( 28 "bytes" 29 "encoding/binary" 30 "fmt" 31 "strings" 32 33 "github.com/Rookout/GoSDK/pkg/services/collection/registers" 34 "github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/frame" 35 "github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/op" 36 ) 37 38 var arm64BreakInstruction = []byte{0x0, 0x0, 0x20, 0xd4} 39 40 const ( 41 DwarfPCRegNum uint64 = 32 42 DwarfSPRegNum uint64 = 31 43 DwarfLRRegNum uint64 = 30 44 DwarfBPRegNum uint64 = 29 45 DwarfV0RegNum uint64 = 64 46 _ARM64_MaxRegNum = DwarfV0RegNum + 31 47 crosscall2SPOffsetNonWindows = 0x58 48 ) 49 50 func FixFrameUnwindContext(fctxt *frame.FrameContext, pc uint64, bi *BinaryInfo) *frame.FrameContext { 51 if fctxt == nil || (bi.sigreturnfn != nil && pc >= bi.sigreturnfn.Entry && pc < bi.sigreturnfn.End) { 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 return &frame.FrameContext{ 71 RetAddrReg: DwarfPCRegNum, 72 Regs: map[uint64]frame.DWRule{ 73 DwarfPCRegNum: frame.DWRule{ 74 Rule: frame.RuleOffset, 75 Offset: int64(-bi.PointerSize), 76 }, 77 DwarfBPRegNum: frame.DWRule{ 78 Rule: frame.RuleOffset, 79 Offset: int64(-2 * bi.PointerSize), 80 }, 81 DwarfSPRegNum: frame.DWRule{ 82 Rule: frame.RuleValOffset, 83 Offset: 0, 84 }, 85 }, 86 CFA: frame.DWRule{ 87 Rule: frame.RuleCFA, 88 Reg: DwarfBPRegNum, 89 Offset: int64(2 * bi.PointerSize), 90 }, 91 } 92 } 93 94 if bi.crosscall2fn != nil && pc >= bi.crosscall2fn.Entry && pc < bi.crosscall2fn.End { 95 rule := fctxt.CFA 96 if rule.Offset == crosscall2SPOffsetBad { 97 rule.Offset += crosscall2SPOffsetNonWindows 98 } 99 fctxt.CFA = rule 100 } 101 102 103 104 105 106 if fctxt.Regs[DwarfBPRegNum].Rule == frame.RuleUndefined { 107 fctxt.Regs[DwarfBPRegNum] = frame.DWRule{ 108 Rule: frame.RuleFramePointer, 109 Reg: DwarfBPRegNum, 110 Offset: 0, 111 } 112 } 113 if fctxt.Regs[DwarfLRRegNum].Rule == frame.RuleUndefined { 114 fctxt.Regs[DwarfLRRegNum] = frame.DWRule{ 115 Rule: frame.RuleFramePointer, 116 Reg: DwarfLRRegNum, 117 Offset: 0, 118 } 119 } 120 121 return fctxt 122 } 123 124 const arm64cgocallSPOffsetSaveSlot = 0x8 125 const prevG0schedSPOffsetSaveSlot = 0x10 126 127 func RegSize(regnum uint64) int { 128 129 if regnum >= 64 && regnum <= 95 { 130 return 16 131 } 132 133 return 8 134 } 135 136 func ARM64ToName(num uint64) string { 137 switch { 138 case num <= 30: 139 return fmt.Sprintf("X%d", num) 140 case num == DwarfSPRegNum: 141 return "SP" 142 case num == DwarfPCRegNum: 143 return "PC" 144 case num >= DwarfV0RegNum && num <= 95: 145 return fmt.Sprintf("V%d", num-64) 146 default: 147 return fmt.Sprintf("unknown%d", num) 148 } 149 } 150 151 var NameToDwarf = func() map[string]int { 152 r := make(map[string]int) 153 for i := 0; i <= 32; i++ { 154 r[fmt.Sprintf("x%d", i)] = i 155 } 156 r["fp"] = 29 157 r["lr"] = int(DwarfLRRegNum) 158 r["sp"] = 31 159 r["pc"] = int(DwarfPCRegNum) 160 for i := 0; i <= 31; i++ { 161 r[fmt.Sprintf("v%d", i)] = i + 64 162 } 163 return r 164 }() 165 166 func RegistersToDwarfRegisters(staticBase uint64, regs registers.Registers) op.DwarfRegisters { 167 dregs := initDwarfRegistersFromSlice(int(_ARM64_MaxRegNum), regs, NameToDwarf) 168 dr := op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, DwarfPCRegNum, DwarfSPRegNum, DwarfBPRegNum, DwarfLRRegNum) 169 dr.SetLoadMoreCallback(loadMoreDwarfRegistersFromSliceFunc(dr, regs, NameToDwarf)) 170 return *dr 171 } 172 173 func loadMoreDwarfRegistersFromSliceFunc(dr *op.DwarfRegisters, regs registers.Registers, nameToDwarf map[string]int) func() { 174 return func() { 175 regslice, err := regs.Slice(true) 176 dr.FloatLoadError = err 177 for _, reg := range regslice { 178 name := strings.ToLower(reg.Name) 179 if dwarfReg, ok := nameToDwarf[name]; ok { 180 dr.AddReg(uint64(dwarfReg), reg.Reg) 181 } else if reg.Reg.Bytes != nil && (strings.HasPrefix(name, "ymm") || strings.HasPrefix(name, "zmm")) { 182 xmmIdx, ok := nameToDwarf["x"+name[1:]] 183 if !ok { 184 continue 185 } 186 xmmReg := dr.Reg(uint64(xmmIdx)) 187 if xmmReg == nil || xmmReg.Bytes == nil { 188 continue 189 } 190 nb := make([]byte, 0, len(xmmReg.Bytes)+len(reg.Reg.Bytes)) 191 nb = append(nb, xmmReg.Bytes...) 192 nb = append(nb, reg.Reg.Bytes...) 193 xmmReg.Bytes = nb 194 } 195 } 196 } 197 } 198 199 func arm64AddrAndStackRegsToDwarfRegisters(staticBase, pc, sp, bp, lr uint64) op.DwarfRegisters { 200 dregs := make([]*op.DwarfRegister, DwarfPCRegNum+1) 201 dregs[DwarfPCRegNum] = op.DwarfRegisterFromUint64(pc) 202 dregs[DwarfSPRegNum] = op.DwarfRegisterFromUint64(sp) 203 dregs[DwarfBPRegNum] = op.DwarfRegisterFromUint64(bp) 204 dregs[DwarfLRRegNum] = op.DwarfRegisterFromUint64(lr) 205 206 return *op.NewDwarfRegisters(staticBase, dregs, binary.LittleEndian, DwarfPCRegNum, DwarfSPRegNum, DwarfBPRegNum, DwarfLRRegNum) 207 } 208 209 func initDwarfRegistersFromSlice(maxRegs int, regs registers.Registers, nameToDwarf map[string]int) []*op.DwarfRegister { 210 dregs := make([]*op.DwarfRegister, maxRegs+1) 211 regslice, _ := regs.Slice(false) 212 for _, reg := range regslice { 213 if dwarfReg, ok := nameToDwarf[strings.ToLower(reg.Name)]; ok { 214 dregs[dwarfReg] = reg.Reg 215 } 216 } 217 return dregs 218 } 219 220 func arm64DwarfRegisterToString(i int, reg *op.DwarfRegister) (name string, floatingPoint bool, repr string) { 221 name = ARM64ToName(uint64(i)) 222 223 if reg == nil { 224 return name, false, "" 225 } 226 227 if reg.Bytes != nil && name[0] == 'V' { 228 buf := bytes.NewReader(reg.Bytes) 229 230 var out bytes.Buffer 231 var vi [16]uint8 232 for i := range vi { 233 _ = binary.Read(buf, binary.LittleEndian, &vi[i]) 234 } 235 236 fmt.Fprintf(&out, " {\n\tD = {u = {0x%02x%02x%02x%02x%02x%02x%02x%02x,", vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0]) 237 fmt.Fprintf(&out, " 0x%02x%02x%02x%02x%02x%02x%02x%02x},", vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8]) 238 fmt.Fprintf(&out, " s = {0x%02x%02x%02x%02x%02x%02x%02x%02x,", vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0]) 239 fmt.Fprintf(&out, " 0x%02x%02x%02x%02x%02x%02x%02x%02x}},", vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8]) 240 241 242 fmt.Fprintf(&out, " \n\tS = {u = {0x%02x%02x%02x%02x,0x%02x%02x%02x%02x,", vi[3], vi[2], vi[1], vi[0], vi[7], vi[6], vi[5], vi[4]) 243 fmt.Fprintf(&out, " 0x%02x%02x%02x%02x,0x%02x%02x%02x%02x},", vi[11], vi[10], vi[9], vi[8], vi[15], vi[14], vi[13], vi[12]) 244 fmt.Fprintf(&out, " s = {0x%02x%02x%02x%02x,0x%02x%02x%02x%02x,", vi[3], vi[2], vi[1], vi[0], vi[7], vi[6], vi[5], vi[4]) 245 fmt.Fprintf(&out, " 0x%02x%02x%02x%02x,0x%02x%02x%02x%02x}},", vi[11], vi[10], vi[9], vi[8], vi[15], vi[14], vi[13], vi[12]) 246 247 248 fmt.Fprintf(&out, " \n\tH = {u = {0x%02x%02x,0x%02x%02x,0x%02x%02x,0x%02x%02x,", vi[1], vi[0], vi[3], vi[2], vi[5], vi[4], vi[7], vi[6]) 249 fmt.Fprintf(&out, " 0x%02x%02x,0x%02x%02x,0x%02x%02x,0x%02x%02x},", vi[9], vi[8], vi[11], vi[10], vi[13], vi[12], vi[15], vi[14]) 250 fmt.Fprintf(&out, " s = {0x%02x%02x,0x%02x%02x,0x%02x%02x,0x%02x%02x,", vi[1], vi[0], vi[3], vi[2], vi[5], vi[4], vi[7], vi[6]) 251 fmt.Fprintf(&out, " 0x%02x%02x,0x%02x%02x,0x%02x%02x,0x%02x%02x}},", vi[9], vi[8], vi[11], vi[10], vi[13], vi[12], vi[15], vi[14]) 252 253 254 fmt.Fprintf(&out, " \n\tB = {u = {0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,", vi[0], vi[1], vi[2], vi[3], vi[4], vi[5], vi[6], vi[7]) 255 fmt.Fprintf(&out, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x},", vi[8], vi[9], vi[10], vi[11], vi[12], vi[13], vi[14], vi[15]) 256 fmt.Fprintf(&out, " s = {0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,", vi[0], vi[1], vi[2], vi[3], vi[4], vi[5], vi[6], vi[7]) 257 fmt.Fprintf(&out, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}}", vi[8], vi[9], vi[10], vi[11], vi[12], vi[13], vi[14], vi[15]) 258 259 260 fmt.Fprintf(&out, " \n\tQ = {u = {0x%02x%02x%02x%02x%02x%02x%02x%02x", vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8]) 261 fmt.Fprintf(&out, "%02x%02x%02x%02x%02x%02x%02x%02x},", vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0]) 262 fmt.Fprintf(&out, " s = {0x%02x%02x%02x%02x%02x%02x%02x%02x", vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8]) 263 fmt.Fprintf(&out, "%02x%02x%02x%02x%02x%02x%02x%02x}}\n\t}", vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0]) 264 return name, true, out.String() 265 } else if reg.Bytes == nil || (reg.Bytes != nil && len(reg.Bytes) < 16) { 266 return name, false, fmt.Sprintf("%#016x", reg.Uint64Val) 267 } 268 return name, false, fmt.Sprintf("%#x", reg.Bytes) 269 }