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