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