1 //===-- RegisterContextMinidump_ARM.cpp -------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "RegisterContextMinidump_ARM.h" 11 12 #include "Utility/ARM_DWARF_Registers.h" 13 #include "lldb/Utility/RegisterValue.h" 14 #include "lldb/Utility/DataExtractor.h" 15 #include "lldb/Utility/LLDBAssert.h" 16 #include "lldb/lldb-enumerations.h" 17 18 // C includes 19 #include <assert.h> 20 21 // C++ includes 22 23 using namespace lldb; 24 using namespace lldb_private; 25 using namespace minidump; 26 27 #define INV LLDB_INVALID_REGNUM 28 #define OFFSET(r) (offsetof(RegisterContextMinidump_ARM::Context, r)) 29 30 #define DEF_R(i) \ 31 { \ 32 "r" #i, nullptr, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \ 33 {INV, dwarf_r##i, INV, INV, reg_r##i}, nullptr, nullptr, nullptr, 0 \ 34 } 35 36 #define DEF_R_ARG(i, n) \ 37 { \ 38 "r" #i, "arg" #n, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \ 39 {INV, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, reg_r##i}, \ 40 nullptr, nullptr, nullptr, 0 \ 41 } 42 43 #define DEF_D(i) \ 44 { \ 45 "d" #i, nullptr, 8, OFFSET(d) + i * 8, eEncodingVector, \ 46 eFormatVectorOfUInt8, {INV, dwarf_d##i, INV, INV, reg_d##i}, \ 47 nullptr, nullptr, nullptr, 0 \ 48 } 49 50 #define DEF_S(i) \ 51 { \ 52 "s" #i, nullptr, 4, OFFSET(s) + i * 4, eEncodingIEEE754, eFormatFloat, \ 53 {INV, dwarf_s##i, INV, INV, reg_s##i}, nullptr, nullptr, nullptr, 0 \ 54 } 55 56 #define DEF_Q(i) \ 57 { \ 58 "q" #i, nullptr, 16, OFFSET(q) + i * 16, eEncodingVector, \ 59 eFormatVectorOfUInt8, {INV, dwarf_q##i, INV, INV, reg_q##i}, \ 60 nullptr, nullptr, nullptr, 0 \ 61 } 62 63 // Zero based LLDB register numbers for this register context 64 enum { 65 // General Purpose Registers 66 reg_r0, 67 reg_r1, 68 reg_r2, 69 reg_r3, 70 reg_r4, 71 reg_r5, 72 reg_r6, 73 reg_r7, 74 reg_r8, 75 reg_r9, 76 reg_r10, 77 reg_r11, 78 reg_r12, 79 reg_sp, 80 reg_lr, 81 reg_pc, 82 reg_cpsr, 83 // Floating Point Registers 84 reg_fpscr, 85 reg_d0, 86 reg_d1, 87 reg_d2, 88 reg_d3, 89 reg_d4, 90 reg_d5, 91 reg_d6, 92 reg_d7, 93 reg_d8, 94 reg_d9, 95 reg_d10, 96 reg_d11, 97 reg_d12, 98 reg_d13, 99 reg_d14, 100 reg_d15, 101 reg_d16, 102 reg_d17, 103 reg_d18, 104 reg_d19, 105 reg_d20, 106 reg_d21, 107 reg_d22, 108 reg_d23, 109 reg_d24, 110 reg_d25, 111 reg_d26, 112 reg_d27, 113 reg_d28, 114 reg_d29, 115 reg_d30, 116 reg_d31, 117 reg_s0, 118 reg_s1, 119 reg_s2, 120 reg_s3, 121 reg_s4, 122 reg_s5, 123 reg_s6, 124 reg_s7, 125 reg_s8, 126 reg_s9, 127 reg_s10, 128 reg_s11, 129 reg_s12, 130 reg_s13, 131 reg_s14, 132 reg_s15, 133 reg_s16, 134 reg_s17, 135 reg_s18, 136 reg_s19, 137 reg_s20, 138 reg_s21, 139 reg_s22, 140 reg_s23, 141 reg_s24, 142 reg_s25, 143 reg_s26, 144 reg_s27, 145 reg_s28, 146 reg_s29, 147 reg_s30, 148 reg_s31, 149 reg_q0, 150 reg_q1, 151 reg_q2, 152 reg_q3, 153 reg_q4, 154 reg_q5, 155 reg_q6, 156 reg_q7, 157 reg_q8, 158 reg_q9, 159 reg_q10, 160 reg_q11, 161 reg_q12, 162 reg_q13, 163 reg_q14, 164 reg_q15, 165 k_num_regs 166 }; 167 168 static RegisterInfo g_reg_info_apple_fp = { 169 "fp", 170 "r7", 171 4, 172 OFFSET(r) + 7 * 4, 173 eEncodingUint, 174 eFormatHex, 175 {INV, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7}, 176 nullptr, 177 nullptr, 178 nullptr, 179 0}; 180 181 static RegisterInfo g_reg_info_fp = { 182 "fp", 183 "r11", 184 4, 185 OFFSET(r) + 11 * 4, 186 eEncodingUint, 187 eFormatHex, 188 {INV, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11}, 189 nullptr, 190 nullptr, 191 nullptr, 192 0}; 193 194 // Register info definitions for this register context 195 static RegisterInfo g_reg_infos[] = { 196 DEF_R_ARG(0, 1), 197 DEF_R_ARG(1, 2), 198 DEF_R_ARG(2, 3), 199 DEF_R_ARG(3, 4), 200 DEF_R(4), 201 DEF_R(5), 202 DEF_R(6), 203 DEF_R(7), 204 DEF_R(8), 205 DEF_R(9), 206 DEF_R(10), 207 DEF_R(11), 208 DEF_R(12), 209 {"sp", 210 "r13", 211 4, 212 OFFSET(r) + 13 * 4, 213 eEncodingUint, 214 eFormatHex, 215 {INV, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp}, 216 nullptr, 217 nullptr, 218 nullptr, 219 0}, 220 {"lr", 221 "r14", 222 4, 223 OFFSET(r) + 14 * 4, 224 eEncodingUint, 225 eFormatHex, 226 {INV, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr}, 227 nullptr, 228 nullptr, 229 nullptr, 230 0}, 231 {"pc", 232 "r15", 233 4, 234 OFFSET(r) + 15 * 4, 235 eEncodingUint, 236 eFormatHex, 237 {INV, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc}, 238 nullptr, 239 nullptr, 240 nullptr, 241 0}, 242 {"cpsr", 243 "psr", 244 4, 245 OFFSET(cpsr), 246 eEncodingUint, 247 eFormatHex, 248 {INV, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr}, 249 nullptr, 250 nullptr, 251 nullptr, 252 0}, 253 {"fpscr", 254 nullptr, 255 8, 256 OFFSET(fpscr), 257 eEncodingUint, 258 eFormatHex, 259 {INV, INV, INV, INV, reg_fpscr}, 260 nullptr, 261 nullptr, 262 nullptr, 263 0}, 264 DEF_D(0), 265 DEF_D(1), 266 DEF_D(2), 267 DEF_D(3), 268 DEF_D(4), 269 DEF_D(5), 270 DEF_D(6), 271 DEF_D(7), 272 DEF_D(8), 273 DEF_D(9), 274 DEF_D(10), 275 DEF_D(11), 276 DEF_D(12), 277 DEF_D(13), 278 DEF_D(14), 279 DEF_D(15), 280 DEF_D(16), 281 DEF_D(17), 282 DEF_D(18), 283 DEF_D(19), 284 DEF_D(20), 285 DEF_D(21), 286 DEF_D(22), 287 DEF_D(23), 288 DEF_D(24), 289 DEF_D(25), 290 DEF_D(26), 291 DEF_D(27), 292 DEF_D(28), 293 DEF_D(29), 294 DEF_D(30), 295 DEF_D(31), 296 DEF_S(0), 297 DEF_S(1), 298 DEF_S(2), 299 DEF_S(3), 300 DEF_S(4), 301 DEF_S(5), 302 DEF_S(6), 303 DEF_S(7), 304 DEF_S(8), 305 DEF_S(9), 306 DEF_S(10), 307 DEF_S(11), 308 DEF_S(12), 309 DEF_S(13), 310 DEF_S(14), 311 DEF_S(15), 312 DEF_S(16), 313 DEF_S(17), 314 DEF_S(18), 315 DEF_S(19), 316 DEF_S(20), 317 DEF_S(21), 318 DEF_S(22), 319 DEF_S(23), 320 DEF_S(24), 321 DEF_S(25), 322 DEF_S(26), 323 DEF_S(27), 324 DEF_S(28), 325 DEF_S(29), 326 DEF_S(30), 327 DEF_S(31), 328 DEF_Q(0), 329 DEF_Q(1), 330 DEF_Q(2), 331 DEF_Q(3), 332 DEF_Q(4), 333 DEF_Q(5), 334 DEF_Q(6), 335 DEF_Q(7), 336 DEF_Q(8), 337 DEF_Q(9), 338 DEF_Q(10), 339 DEF_Q(11), 340 DEF_Q(12), 341 DEF_Q(13), 342 DEF_Q(14), 343 DEF_Q(15)}; 344 345 constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos); 346 347 // ARM general purpose registers. 348 const uint32_t g_gpr_regnums[] = { 349 reg_r0, 350 reg_r1, 351 reg_r2, 352 reg_r3, 353 reg_r4, 354 reg_r5, 355 reg_r6, 356 reg_r7, 357 reg_r8, 358 reg_r9, 359 reg_r10, 360 reg_r11, 361 reg_r12, 362 reg_sp, 363 reg_lr, 364 reg_pc, 365 reg_cpsr, 366 LLDB_INVALID_REGNUM // register sets need to end with this flag 367 }; 368 const uint32_t g_fpu_regnums[] = { 369 reg_fpscr, 370 reg_d0, 371 reg_d1, 372 reg_d2, 373 reg_d3, 374 reg_d4, 375 reg_d5, 376 reg_d6, 377 reg_d7, 378 reg_d8, 379 reg_d9, 380 reg_d10, 381 reg_d11, 382 reg_d12, 383 reg_d13, 384 reg_d14, 385 reg_d15, 386 reg_d16, 387 reg_d17, 388 reg_d18, 389 reg_d19, 390 reg_d20, 391 reg_d21, 392 reg_d22, 393 reg_d23, 394 reg_d24, 395 reg_d25, 396 reg_d26, 397 reg_d27, 398 reg_d28, 399 reg_d29, 400 reg_d30, 401 reg_d31, 402 reg_s0, 403 reg_s1, 404 reg_s2, 405 reg_s3, 406 reg_s4, 407 reg_s5, 408 reg_s6, 409 reg_s7, 410 reg_s8, 411 reg_s9, 412 reg_s10, 413 reg_s11, 414 reg_s12, 415 reg_s13, 416 reg_s14, 417 reg_s15, 418 reg_s16, 419 reg_s17, 420 reg_s18, 421 reg_s19, 422 reg_s20, 423 reg_s21, 424 reg_s22, 425 reg_s23, 426 reg_s24, 427 reg_s25, 428 reg_s26, 429 reg_s27, 430 reg_s28, 431 reg_s29, 432 reg_s30, 433 reg_s31, 434 reg_q0, 435 reg_q1, 436 reg_q2, 437 reg_q3, 438 reg_q4, 439 reg_q5, 440 reg_q6, 441 reg_q7, 442 reg_q8, 443 reg_q9, 444 reg_q10, 445 reg_q11, 446 reg_q12, 447 reg_q13, 448 reg_q14, 449 reg_q15, 450 LLDB_INVALID_REGNUM // register sets need to end with this flag 451 }; 452 453 // Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1 454 constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1; 455 constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1; 456 457 static RegisterSet g_reg_sets[] = { 458 {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums}, 459 {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums}, 460 }; 461 462 constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets); 463 464 RegisterContextMinidump_ARM::RegisterContextMinidump_ARM( 465 Thread &thread, const DataExtractor &data, bool apple) 466 : RegisterContext(thread, 0), m_apple(apple) { 467 lldb::offset_t offset = 0; 468 m_regs.context_flags = data.GetU32(&offset); 469 for (unsigned i = 0; i < llvm::array_lengthof(m_regs.r); ++i) 470 m_regs.r[i] = data.GetU32(&offset); 471 m_regs.cpsr = data.GetU32(&offset); 472 m_regs.fpscr = data.GetU64(&offset); 473 for (unsigned i = 0; i < llvm::array_lengthof(m_regs.d); ++i) 474 m_regs.d[i] = data.GetU64(&offset); 475 lldbassert(k_num_regs == k_num_reg_infos); 476 } 477 478 size_t RegisterContextMinidump_ARM::GetRegisterCount() { return k_num_regs; } 479 480 const RegisterInfo * 481 RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) { 482 if (reg < k_num_reg_infos) { 483 if (m_apple) { 484 if (reg == reg_r7) 485 return &g_reg_info_apple_fp; 486 } else { 487 if (reg == reg_r11) 488 return &g_reg_info_fp; 489 } 490 return &g_reg_infos[reg]; 491 } 492 return nullptr; 493 } 494 495 size_t RegisterContextMinidump_ARM::GetRegisterSetCount() { 496 return k_num_reg_sets; 497 } 498 499 const RegisterSet *RegisterContextMinidump_ARM::GetRegisterSet(size_t set) { 500 if (set < k_num_reg_sets) 501 return &g_reg_sets[set]; 502 return nullptr; 503 } 504 505 const char *RegisterContextMinidump_ARM::GetRegisterName(unsigned reg) { 506 if (reg < k_num_reg_infos) 507 return g_reg_infos[reg].name; 508 return nullptr; 509 } 510 511 bool RegisterContextMinidump_ARM::ReadRegister(const RegisterInfo *reg_info, 512 RegisterValue ®_value) { 513 Status error; 514 reg_value.SetFromMemoryData( 515 reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset, 516 reg_info->byte_size, lldb::eByteOrderLittle, error); 517 return error.Success(); 518 } 519 520 bool RegisterContextMinidump_ARM::WriteRegister(const RegisterInfo *, 521 const RegisterValue &) { 522 return false; 523 } 524 525 uint32_t RegisterContextMinidump_ARM::ConvertRegisterKindToRegisterNumber( 526 lldb::RegisterKind kind, uint32_t num) { 527 for (size_t i = 0; i < k_num_regs; ++i) { 528 if (g_reg_infos[i].kinds[kind] == num) 529 return i; 530 } 531 return LLDB_INVALID_REGNUM; 532 } 533