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