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 "lldb/Utility/RegisterValue.h" 13 #include "lldb/Utility/DataExtractor.h" 14 #include "lldb/Utility/LLDBAssert.h" 15 #include "lldb/lldb-enumerations.h" 16 17 // C includes 18 #include <assert.h> 19 20 // C++ includes 21 22 using namespace lldb; 23 using namespace lldb_private; 24 using namespace minidump; 25 26 #define INV LLDB_INVALID_REGNUM 27 #define OFFSET(r) (offsetof(RegisterContextMinidump_ARM::Context, r)) 28 29 #define DEF_R(i) \ 30 { \ 31 "r" #i, nullptr, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \ 32 {dwarf_r##i, dwarf_r##i, INV, INV, reg_r##i}, \ 33 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 {dwarf_r##i, 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, {dwarf_d##i, 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 {dwarf_s##i, dwarf_s##i, INV, INV, reg_s##i}, \ 54 nullptr, nullptr, nullptr, 0 \ 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, nullptr, 0 \ 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 {INV, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7}, 177 nullptr, 178 nullptr, 179 nullptr, 180 0}; 181 182 static RegisterInfo g_reg_info_fp = { 183 "fp", 184 "r11", 185 4, 186 OFFSET(r) + 11 * 4, 187 eEncodingUint, 188 eFormatHex, 189 {INV, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11}, 190 nullptr, 191 nullptr, 192 nullptr, 193 0}; 194 195 // Register info definitions for this register context 196 static RegisterInfo g_reg_infos[] = { 197 DEF_R_ARG(0, 1), 198 DEF_R_ARG(1, 2), 199 DEF_R_ARG(2, 3), 200 DEF_R_ARG(3, 4), 201 DEF_R(4), 202 DEF_R(5), 203 DEF_R(6), 204 DEF_R(7), 205 DEF_R(8), 206 DEF_R(9), 207 DEF_R(10), 208 DEF_R(11), 209 DEF_R(12), 210 {"sp", 211 "r13", 212 4, 213 OFFSET(r) + 13 * 4, 214 eEncodingUint, 215 eFormatHex, 216 {INV, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp}, 217 nullptr, 218 nullptr, 219 nullptr, 220 0}, 221 {"lr", 222 "r14", 223 4, 224 OFFSET(r) + 14 * 4, 225 eEncodingUint, 226 eFormatHex, 227 {INV, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr}, 228 nullptr, 229 nullptr, 230 nullptr, 231 0}, 232 {"pc", 233 "r15", 234 4, 235 OFFSET(r) + 15 * 4, 236 eEncodingUint, 237 eFormatHex, 238 {INV, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc}, 239 nullptr, 240 nullptr, 241 nullptr, 242 0}, 243 {"cpsr", 244 "psr", 245 4, 246 OFFSET(cpsr), 247 eEncodingUint, 248 eFormatHex, 249 {INV, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr}, 250 nullptr, 251 nullptr, 252 nullptr, 253 0}, 254 {"fpscr", 255 nullptr, 256 8, 257 OFFSET(fpscr), 258 eEncodingUint, 259 eFormatHex, 260 {INV, INV, INV, INV, reg_fpscr}, 261 nullptr, 262 nullptr, 263 nullptr, 264 0}, 265 DEF_D(0), 266 DEF_D(1), 267 DEF_D(2), 268 DEF_D(3), 269 DEF_D(4), 270 DEF_D(5), 271 DEF_D(6), 272 DEF_D(7), 273 DEF_D(8), 274 DEF_D(9), 275 DEF_D(10), 276 DEF_D(11), 277 DEF_D(12), 278 DEF_D(13), 279 DEF_D(14), 280 DEF_D(15), 281 DEF_D(16), 282 DEF_D(17), 283 DEF_D(18), 284 DEF_D(19), 285 DEF_D(20), 286 DEF_D(21), 287 DEF_D(22), 288 DEF_D(23), 289 DEF_D(24), 290 DEF_D(25), 291 DEF_D(26), 292 DEF_D(27), 293 DEF_D(28), 294 DEF_D(29), 295 DEF_D(30), 296 DEF_D(31), 297 DEF_S(0), 298 DEF_S(1), 299 DEF_S(2), 300 DEF_S(3), 301 DEF_S(4), 302 DEF_S(5), 303 DEF_S(6), 304 DEF_S(7), 305 DEF_S(8), 306 DEF_S(9), 307 DEF_S(10), 308 DEF_S(11), 309 DEF_S(12), 310 DEF_S(13), 311 DEF_S(14), 312 DEF_S(15), 313 DEF_S(16), 314 DEF_S(17), 315 DEF_S(18), 316 DEF_S(19), 317 DEF_S(20), 318 DEF_S(21), 319 DEF_S(22), 320 DEF_S(23), 321 DEF_S(24), 322 DEF_S(25), 323 DEF_S(26), 324 DEF_S(27), 325 DEF_S(28), 326 DEF_S(29), 327 DEF_S(30), 328 DEF_S(31), 329 DEF_Q(0), 330 DEF_Q(1), 331 DEF_Q(2), 332 DEF_Q(3), 333 DEF_Q(4), 334 DEF_Q(5), 335 DEF_Q(6), 336 DEF_Q(7), 337 DEF_Q(8), 338 DEF_Q(9), 339 DEF_Q(10), 340 DEF_Q(11), 341 DEF_Q(12), 342 DEF_Q(13), 343 DEF_Q(14), 344 DEF_Q(15)}; 345 346 constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos); 347 348 // ARM general purpose registers. 349 const uint32_t g_gpr_regnums[] = { 350 reg_r0, 351 reg_r1, 352 reg_r2, 353 reg_r3, 354 reg_r4, 355 reg_r5, 356 reg_r6, 357 reg_r7, 358 reg_r8, 359 reg_r9, 360 reg_r10, 361 reg_r11, 362 reg_r12, 363 reg_sp, 364 reg_lr, 365 reg_pc, 366 reg_cpsr, 367 LLDB_INVALID_REGNUM // register sets need to end with this flag 368 }; 369 const uint32_t g_fpu_regnums[] = { 370 reg_fpscr, 371 reg_d0, 372 reg_d1, 373 reg_d2, 374 reg_d3, 375 reg_d4, 376 reg_d5, 377 reg_d6, 378 reg_d7, 379 reg_d8, 380 reg_d9, 381 reg_d10, 382 reg_d11, 383 reg_d12, 384 reg_d13, 385 reg_d14, 386 reg_d15, 387 reg_d16, 388 reg_d17, 389 reg_d18, 390 reg_d19, 391 reg_d20, 392 reg_d21, 393 reg_d22, 394 reg_d23, 395 reg_d24, 396 reg_d25, 397 reg_d26, 398 reg_d27, 399 reg_d28, 400 reg_d29, 401 reg_d30, 402 reg_d31, 403 reg_s0, 404 reg_s1, 405 reg_s2, 406 reg_s3, 407 reg_s4, 408 reg_s5, 409 reg_s6, 410 reg_s7, 411 reg_s8, 412 reg_s9, 413 reg_s10, 414 reg_s11, 415 reg_s12, 416 reg_s13, 417 reg_s14, 418 reg_s15, 419 reg_s16, 420 reg_s17, 421 reg_s18, 422 reg_s19, 423 reg_s20, 424 reg_s21, 425 reg_s22, 426 reg_s23, 427 reg_s24, 428 reg_s25, 429 reg_s26, 430 reg_s27, 431 reg_s28, 432 reg_s29, 433 reg_s30, 434 reg_s31, 435 reg_q0, 436 reg_q1, 437 reg_q2, 438 reg_q3, 439 reg_q4, 440 reg_q5, 441 reg_q6, 442 reg_q7, 443 reg_q8, 444 reg_q9, 445 reg_q10, 446 reg_q11, 447 reg_q12, 448 reg_q13, 449 reg_q14, 450 reg_q15, 451 LLDB_INVALID_REGNUM // register sets need to end with this flag 452 }; 453 454 // Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1 455 constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1; 456 constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1; 457 458 static RegisterSet g_reg_sets[] = { 459 {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums}, 460 {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums}, 461 }; 462 463 constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets); 464 465 RegisterContextMinidump_ARM::RegisterContextMinidump_ARM( 466 lldb_private::Thread &thread, const DataExtractor &data, bool apple) 467 : RegisterContext(thread, 0), m_apple(apple) { 468 lldb::offset_t offset = 0; 469 m_regs.context_flags = data.GetU32(&offset); 470 for (unsigned i = 0; i < llvm::array_lengthof(m_regs.r); ++i) 471 m_regs.r[i] = data.GetU32(&offset); 472 m_regs.cpsr = data.GetU32(&offset); 473 m_regs.fpscr = data.GetU64(&offset); 474 for (unsigned i = 0; i < llvm::array_lengthof(m_regs.d); ++i) 475 m_regs.d[i] = data.GetU64(&offset); 476 lldbassert(k_num_regs == k_num_reg_infos); 477 } 478 479 size_t RegisterContextMinidump_ARM::GetRegisterCount() { return k_num_regs; } 480 481 const RegisterInfo * 482 RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) { 483 if (reg < k_num_reg_infos) { 484 if (m_apple) { 485 if (reg == reg_r7) 486 return &g_reg_info_apple_fp; 487 } else { 488 if (reg == reg_r11) 489 return &g_reg_info_fp; 490 } 491 return &g_reg_infos[reg]; 492 } 493 return nullptr; 494 } 495 496 size_t RegisterContextMinidump_ARM::GetRegisterSetCount() { 497 return k_num_reg_sets; 498 } 499 500 const RegisterSet *RegisterContextMinidump_ARM::GetRegisterSet(size_t set) { 501 if (set < k_num_reg_sets) 502 return &g_reg_sets[set]; 503 return nullptr; 504 } 505 506 const char *RegisterContextMinidump_ARM::GetRegisterName(unsigned reg) { 507 if (reg < k_num_reg_infos) 508 return g_reg_infos[reg].name; 509 return nullptr; 510 } 511 512 bool RegisterContextMinidump_ARM::ReadRegister(const RegisterInfo *reg_info, 513 RegisterValue ®_value) { 514 Status error; 515 reg_value.SetFromMemoryData( 516 reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset, 517 reg_info->byte_size, lldb::eByteOrderLittle, error); 518 return error.Success(); 519 } 520 521 bool RegisterContextMinidump_ARM::WriteRegister(const RegisterInfo *, 522 const RegisterValue &) { 523 return false; 524 } 525 526 uint32_t RegisterContextMinidump_ARM::ConvertRegisterKindToRegisterNumber( 527 lldb::RegisterKind kind, uint32_t num) { 528 for (size_t i = 0; i < k_num_regs; ++i) { 529 if (g_reg_infos[i].kinds[kind] == num) 530 return i; 531 } 532 return LLDB_INVALID_REGNUM; 533 } 534