dump_context.cc
1 // Copyright 2010 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 // dump_context.cc: A (mini/micro)dump context. 30 // 31 // See dump_context.h for documentation. 32 33 #ifdef HAVE_CONFIG_H 34 #include <config.h> // Must come first 35 #endif 36 37 #include "google_breakpad/processor/dump_context.h" 38 39 #include <assert.h> 40 41 #ifdef _WIN32 42 #include <io.h> 43 #else // _WIN32 44 #include <unistd.h> 45 #endif // _WIN32 46 47 #include "common/stdio_wrapper.h" 48 #include "processor/logging.h" 49 50 namespace google_breakpad { 51 52 DumpContext::DumpContext() : context_(), 53 context_flags_(0) { } 54 55 DumpContext::~DumpContext() { 56 FreeContext(); 57 } 58 59 uint32_t DumpContext::GetContextCPU() const { 60 if (!valid_) { 61 // Don't log a message, GetContextCPU can be legitimately called with 62 // valid_ false by FreeContext, which is called by Read. 63 return 0; 64 } 65 66 return context_flags_ & MD_CONTEXT_CPU_MASK; 67 } 68 69 uint32_t DumpContext::GetContextFlags() const { 70 return context_flags_; 71 } 72 73 const MDRawContextX86* DumpContext::GetContextX86() const { 74 if (GetContextCPU() != MD_CONTEXT_X86) { 75 BPLOG(ERROR) << "DumpContext cannot get x86 context"; 76 return NULL; 77 } 78 79 return context_.x86; 80 } 81 82 const MDRawContextPPC* DumpContext::GetContextPPC() const { 83 if (GetContextCPU() != MD_CONTEXT_PPC) { 84 BPLOG(ERROR) << "DumpContext cannot get ppc context"; 85 return NULL; 86 } 87 88 return context_.ppc; 89 } 90 91 const MDRawContextPPC64* DumpContext::GetContextPPC64() const { 92 if (GetContextCPU() != MD_CONTEXT_PPC64) { 93 BPLOG(ERROR) << "DumpContext cannot get ppc64 context"; 94 return NULL; 95 } 96 97 return context_.ppc64; 98 } 99 100 const MDRawContextAMD64* DumpContext::GetContextAMD64() const { 101 if (GetContextCPU() != MD_CONTEXT_AMD64) { 102 BPLOG(ERROR) << "DumpContext cannot get amd64 context"; 103 return NULL; 104 } 105 106 return context_.amd64; 107 } 108 109 const MDRawContextSPARC* DumpContext::GetContextSPARC() const { 110 if (GetContextCPU() != MD_CONTEXT_SPARC) { 111 BPLOG(ERROR) << "DumpContext cannot get sparc context"; 112 return NULL; 113 } 114 115 return context_.ctx_sparc; 116 } 117 118 const MDRawContextARM* DumpContext::GetContextARM() const { 119 if (GetContextCPU() != MD_CONTEXT_ARM) { 120 BPLOG(ERROR) << "DumpContext cannot get arm context"; 121 return NULL; 122 } 123 124 return context_.arm; 125 } 126 127 const MDRawContextARM64* DumpContext::GetContextARM64() const { 128 if (GetContextCPU() != MD_CONTEXT_ARM64) { 129 BPLOG(ERROR) << "DumpContext cannot get arm64 context"; 130 return NULL; 131 } 132 133 return context_.arm64; 134 } 135 136 const MDRawContextMIPS* DumpContext::GetContextMIPS() const { 137 if ((GetContextCPU() != MD_CONTEXT_MIPS) && 138 (GetContextCPU() != MD_CONTEXT_MIPS64)) { 139 BPLOG(ERROR) << "DumpContext cannot get MIPS context"; 140 return NULL; 141 } 142 143 return context_.ctx_mips; 144 } 145 146 const MDRawContextRISCV* DumpContext::GetContextRISCV() const { 147 if (GetContextCPU() != MD_CONTEXT_RISCV) { 148 BPLOG(ERROR) << "DumpContext cannot get RISCV context"; 149 return NULL; 150 } 151 152 return context_.riscv; 153 } 154 155 const MDRawContextRISCV64* DumpContext::GetContextRISCV64() const { 156 if (GetContextCPU() != MD_CONTEXT_RISCV64) { 157 BPLOG(ERROR) << "DumpContext cannot get RISCV64 context"; 158 return NULL; 159 } 160 161 return context_.riscv64; 162 } 163 164 bool DumpContext::GetInstructionPointer(uint64_t* ip) const { 165 BPLOG_IF(ERROR, !ip) << "DumpContext::GetInstructionPointer requires |ip|"; 166 assert(ip); 167 *ip = 0; 168 169 if (!valid_) { 170 BPLOG(ERROR) << "Invalid DumpContext for GetInstructionPointer"; 171 return false; 172 } 173 174 switch (GetContextCPU()) { 175 case MD_CONTEXT_AMD64: 176 *ip = GetContextAMD64()->rip; 177 break; 178 case MD_CONTEXT_ARM: 179 *ip = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_PC]; 180 break; 181 case MD_CONTEXT_ARM64: 182 *ip = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_PC]; 183 break; 184 case MD_CONTEXT_PPC: 185 *ip = GetContextPPC()->srr0; 186 break; 187 case MD_CONTEXT_PPC64: 188 *ip = GetContextPPC64()->srr0; 189 break; 190 case MD_CONTEXT_SPARC: 191 *ip = GetContextSPARC()->pc; 192 break; 193 case MD_CONTEXT_X86: 194 *ip = GetContextX86()->eip; 195 break; 196 case MD_CONTEXT_MIPS: 197 case MD_CONTEXT_MIPS64: 198 *ip = GetContextMIPS()->epc; 199 break; 200 case MD_CONTEXT_RISCV: 201 *ip = GetContextRISCV()->pc; 202 break; 203 case MD_CONTEXT_RISCV64: 204 *ip = GetContextRISCV64()->pc; 205 break; 206 default: 207 // This should never happen. 208 BPLOG(ERROR) << "Unknown CPU architecture in GetInstructionPointer"; 209 return false; 210 } 211 return true; 212 } 213 214 bool DumpContext::GetStackPointer(uint64_t* sp) const { 215 BPLOG_IF(ERROR, !sp) << "DumpContext::GetStackPointer requires |sp|"; 216 assert(sp); 217 *sp = 0; 218 219 if (!valid_) { 220 BPLOG(ERROR) << "Invalid DumpContext for GetStackPointer"; 221 return false; 222 } 223 224 switch (GetContextCPU()) { 225 case MD_CONTEXT_AMD64: 226 *sp = GetContextAMD64()->rsp; 227 break; 228 case MD_CONTEXT_ARM: 229 *sp = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_SP]; 230 break; 231 case MD_CONTEXT_ARM64: 232 *sp = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_SP]; 233 break; 234 case MD_CONTEXT_PPC: 235 *sp = GetContextPPC()->gpr[MD_CONTEXT_PPC_REG_SP]; 236 break; 237 case MD_CONTEXT_PPC64: 238 *sp = GetContextPPC64()->gpr[MD_CONTEXT_PPC64_REG_SP]; 239 break; 240 case MD_CONTEXT_SPARC: 241 *sp = GetContextSPARC()->g_r[MD_CONTEXT_SPARC_REG_SP]; 242 break; 243 case MD_CONTEXT_X86: 244 *sp = GetContextX86()->esp; 245 break; 246 case MD_CONTEXT_MIPS: 247 case MD_CONTEXT_MIPS64: 248 *sp = GetContextMIPS()->iregs[MD_CONTEXT_MIPS_REG_SP]; 249 break; 250 case MD_CONTEXT_RISCV: 251 *sp = GetContextRISCV()->sp; 252 break; 253 case MD_CONTEXT_RISCV64: 254 *sp = GetContextRISCV64()->sp; 255 break; 256 default: 257 // This should never happen. 258 BPLOG(ERROR) << "Unknown CPU architecture in GetStackPointer"; 259 return false; 260 } 261 return true; 262 } 263 264 void DumpContext::SetContextFlags(uint32_t context_flags) { 265 context_flags_ = context_flags; 266 } 267 268 void DumpContext::SetContextX86(MDRawContextX86* x86) { 269 context_.x86 = x86; 270 } 271 272 void DumpContext::SetContextPPC(MDRawContextPPC* ppc) { 273 context_.ppc = ppc; 274 } 275 276 void DumpContext::SetContextPPC64(MDRawContextPPC64* ppc64) { 277 context_.ppc64 = ppc64; 278 } 279 280 void DumpContext::SetContextAMD64(MDRawContextAMD64* amd64) { 281 context_.amd64 = amd64; 282 } 283 284 void DumpContext::SetContextSPARC(MDRawContextSPARC* ctx_sparc) { 285 context_.ctx_sparc = ctx_sparc; 286 } 287 288 void DumpContext::SetContextARM(MDRawContextARM* arm) { 289 context_.arm = arm; 290 } 291 292 void DumpContext::SetContextARM64(MDRawContextARM64* arm64) { 293 context_.arm64 = arm64; 294 } 295 296 void DumpContext::SetContextMIPS(MDRawContextMIPS* ctx_mips) { 297 context_.ctx_mips = ctx_mips; 298 } 299 300 void DumpContext::SetContextRISCV(MDRawContextRISCV* riscv) { 301 context_.riscv = riscv; 302 } 303 304 void DumpContext::SetContextRISCV64(MDRawContextRISCV64* riscv64) { 305 context_.riscv64 = riscv64; 306 } 307 308 void DumpContext::FreeContext() { 309 switch (GetContextCPU()) { 310 case MD_CONTEXT_X86: 311 delete context_.x86; 312 break; 313 314 case MD_CONTEXT_PPC: 315 delete context_.ppc; 316 break; 317 318 case MD_CONTEXT_PPC64: 319 delete context_.ppc64; 320 break; 321 322 case MD_CONTEXT_AMD64: 323 delete context_.amd64; 324 break; 325 326 case MD_CONTEXT_SPARC: 327 delete context_.ctx_sparc; 328 break; 329 330 case MD_CONTEXT_ARM: 331 delete context_.arm; 332 break; 333 334 case MD_CONTEXT_ARM64: 335 delete context_.arm64; 336 break; 337 338 case MD_CONTEXT_MIPS: 339 case MD_CONTEXT_MIPS64: 340 delete context_.ctx_mips; 341 break; 342 343 case MD_CONTEXT_RISCV: 344 delete context_.riscv; 345 break; 346 347 case MD_CONTEXT_RISCV64: 348 delete context_.riscv64; 349 break; 350 351 default: 352 // There is no context record (valid_ is false) or there's a 353 // context record for an unknown CPU (shouldn't happen, only known 354 // records are stored by Read). 355 break; 356 } 357 358 context_flags_ = 0; 359 context_.base = NULL; 360 } 361 362 void DumpContext::Print() { 363 if (!valid_) { 364 BPLOG(ERROR) << "DumpContext cannot print invalid data"; 365 return; 366 } 367 368 switch (GetContextCPU()) { 369 case MD_CONTEXT_X86: { 370 const MDRawContextX86* context_x86 = GetContextX86(); 371 printf("MDRawContextX86\n"); 372 printf(" context_flags = 0x%x\n", 373 context_x86->context_flags); 374 printf(" dr0 = 0x%x\n", context_x86->dr0); 375 printf(" dr1 = 0x%x\n", context_x86->dr1); 376 printf(" dr2 = 0x%x\n", context_x86->dr2); 377 printf(" dr3 = 0x%x\n", context_x86->dr3); 378 printf(" dr6 = 0x%x\n", context_x86->dr6); 379 printf(" dr7 = 0x%x\n", context_x86->dr7); 380 printf(" float_save.control_word = 0x%x\n", 381 context_x86->float_save.control_word); 382 printf(" float_save.status_word = 0x%x\n", 383 context_x86->float_save.status_word); 384 printf(" float_save.tag_word = 0x%x\n", 385 context_x86->float_save.tag_word); 386 printf(" float_save.error_offset = 0x%x\n", 387 context_x86->float_save.error_offset); 388 printf(" float_save.error_selector = 0x%x\n", 389 context_x86->float_save.error_selector); 390 printf(" float_save.data_offset = 0x%x\n", 391 context_x86->float_save.data_offset); 392 printf(" float_save.data_selector = 0x%x\n", 393 context_x86->float_save.data_selector); 394 printf(" float_save.register_area[%2d] = 0x", 395 MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE); 396 for (unsigned int register_index = 0; 397 register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE; 398 ++register_index) { 399 printf("%02x", context_x86->float_save.register_area[register_index]); 400 } 401 printf("\n"); 402 printf(" float_save.cr0_npx_state = 0x%x\n", 403 context_x86->float_save.cr0_npx_state); 404 printf(" gs = 0x%x\n", context_x86->gs); 405 printf(" fs = 0x%x\n", context_x86->fs); 406 printf(" es = 0x%x\n", context_x86->es); 407 printf(" ds = 0x%x\n", context_x86->ds); 408 printf(" edi = 0x%x\n", context_x86->edi); 409 printf(" esi = 0x%x\n", context_x86->esi); 410 printf(" ebx = 0x%x\n", context_x86->ebx); 411 printf(" edx = 0x%x\n", context_x86->edx); 412 printf(" ecx = 0x%x\n", context_x86->ecx); 413 printf(" eax = 0x%x\n", context_x86->eax); 414 printf(" ebp = 0x%x\n", context_x86->ebp); 415 printf(" eip = 0x%x\n", context_x86->eip); 416 printf(" cs = 0x%x\n", context_x86->cs); 417 printf(" eflags = 0x%x\n", context_x86->eflags); 418 printf(" esp = 0x%x\n", context_x86->esp); 419 printf(" ss = 0x%x\n", context_x86->ss); 420 printf(" extended_registers[%3d] = 0x", 421 MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE); 422 for (unsigned int register_index = 0; 423 register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE; 424 ++register_index) { 425 printf("%02x", context_x86->extended_registers[register_index]); 426 } 427 printf("\n\n"); 428 429 break; 430 } 431 432 case MD_CONTEXT_PPC: { 433 const MDRawContextPPC* context_ppc = GetContextPPC(); 434 printf("MDRawContextPPC\n"); 435 printf(" context_flags = 0x%x\n", 436 context_ppc->context_flags); 437 printf(" srr0 = 0x%x\n", context_ppc->srr0); 438 printf(" srr1 = 0x%x\n", context_ppc->srr1); 439 for (unsigned int gpr_index = 0; 440 gpr_index < MD_CONTEXT_PPC_GPR_COUNT; 441 ++gpr_index) { 442 printf(" gpr[%2d] = 0x%x\n", 443 gpr_index, context_ppc->gpr[gpr_index]); 444 } 445 printf(" cr = 0x%x\n", context_ppc->cr); 446 printf(" xer = 0x%x\n", context_ppc->xer); 447 printf(" lr = 0x%x\n", context_ppc->lr); 448 printf(" ctr = 0x%x\n", context_ppc->ctr); 449 printf(" mq = 0x%x\n", context_ppc->mq); 450 printf(" vrsave = 0x%x\n", context_ppc->vrsave); 451 for (unsigned int fpr_index = 0; 452 fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; 453 ++fpr_index) { 454 printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", 455 fpr_index, context_ppc->float_save.fpregs[fpr_index]); 456 } 457 printf(" float_save.fpscr = 0x%x\n", 458 context_ppc->float_save.fpscr); 459 // TODO(mmentovai): print the 128-bit quantities in 460 // context_ppc->vector_save. This isn't done yet because printf 461 // doesn't support 128-bit quantities, and printing them using 462 // PRIx64 as two 64-bit quantities requires knowledge of the CPU's 463 // byte ordering. 464 printf(" vector_save.save_vrvalid = 0x%x\n", 465 context_ppc->vector_save.save_vrvalid); 466 printf("\n"); 467 468 break; 469 } 470 471 case MD_CONTEXT_PPC64: { 472 const MDRawContextPPC64* context_ppc64 = GetContextPPC64(); 473 printf("MDRawContextPPC64\n"); 474 printf(" context_flags = 0x%" PRIx64 "\n", 475 context_ppc64->context_flags); 476 printf(" srr0 = 0x%" PRIx64 "\n", 477 context_ppc64->srr0); 478 printf(" srr1 = 0x%" PRIx64 "\n", 479 context_ppc64->srr1); 480 for (unsigned int gpr_index = 0; 481 gpr_index < MD_CONTEXT_PPC64_GPR_COUNT; 482 ++gpr_index) { 483 printf(" gpr[%2d] = 0x%" PRIx64 "\n", 484 gpr_index, context_ppc64->gpr[gpr_index]); 485 } 486 printf(" cr = 0x%" PRIx64 "\n", context_ppc64->cr); 487 printf(" xer = 0x%" PRIx64 "\n", 488 context_ppc64->xer); 489 printf(" lr = 0x%" PRIx64 "\n", context_ppc64->lr); 490 printf(" ctr = 0x%" PRIx64 "\n", 491 context_ppc64->ctr); 492 printf(" vrsave = 0x%" PRIx64 "\n", 493 context_ppc64->vrsave); 494 for (unsigned int fpr_index = 0; 495 fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; 496 ++fpr_index) { 497 printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", 498 fpr_index, context_ppc64->float_save.fpregs[fpr_index]); 499 } 500 printf(" float_save.fpscr = 0x%x\n", 501 context_ppc64->float_save.fpscr); 502 // TODO(mmentovai): print the 128-bit quantities in 503 // context_ppc64->vector_save. This isn't done yet because printf 504 // doesn't support 128-bit quantities, and printing them using 505 // PRIx64 as two 64-bit quantities requires knowledge of the CPU's 506 // byte ordering. 507 printf(" vector_save.save_vrvalid = 0x%x\n", 508 context_ppc64->vector_save.save_vrvalid); 509 printf("\n"); 510 511 break; 512 } 513 514 case MD_CONTEXT_AMD64: { 515 const MDRawContextAMD64* context_amd64 = GetContextAMD64(); 516 printf("MDRawContextAMD64\n"); 517 printf(" p1_home = 0x%" PRIx64 "\n", 518 context_amd64->p1_home); 519 printf(" p2_home = 0x%" PRIx64 "\n", 520 context_amd64->p2_home); 521 printf(" p3_home = 0x%" PRIx64 "\n", 522 context_amd64->p3_home); 523 printf(" p4_home = 0x%" PRIx64 "\n", 524 context_amd64->p4_home); 525 printf(" p5_home = 0x%" PRIx64 "\n", 526 context_amd64->p5_home); 527 printf(" p6_home = 0x%" PRIx64 "\n", 528 context_amd64->p6_home); 529 printf(" context_flags = 0x%x\n", 530 context_amd64->context_flags); 531 printf(" mx_csr = 0x%x\n", 532 context_amd64->mx_csr); 533 printf(" cs = 0x%x\n", context_amd64->cs); 534 printf(" ds = 0x%x\n", context_amd64->ds); 535 printf(" es = 0x%x\n", context_amd64->es); 536 printf(" fs = 0x%x\n", context_amd64->fs); 537 printf(" gs = 0x%x\n", context_amd64->gs); 538 printf(" ss = 0x%x\n", context_amd64->ss); 539 printf(" eflags = 0x%x\n", context_amd64->eflags); 540 printf(" dr0 = 0x%" PRIx64 "\n", context_amd64->dr0); 541 printf(" dr1 = 0x%" PRIx64 "\n", context_amd64->dr1); 542 printf(" dr2 = 0x%" PRIx64 "\n", context_amd64->dr2); 543 printf(" dr3 = 0x%" PRIx64 "\n", context_amd64->dr3); 544 printf(" dr6 = 0x%" PRIx64 "\n", context_amd64->dr6); 545 printf(" dr7 = 0x%" PRIx64 "\n", context_amd64->dr7); 546 printf(" rax = 0x%" PRIx64 "\n", context_amd64->rax); 547 printf(" rcx = 0x%" PRIx64 "\n", context_amd64->rcx); 548 printf(" rdx = 0x%" PRIx64 "\n", context_amd64->rdx); 549 printf(" rbx = 0x%" PRIx64 "\n", context_amd64->rbx); 550 printf(" rsp = 0x%" PRIx64 "\n", context_amd64->rsp); 551 printf(" rbp = 0x%" PRIx64 "\n", context_amd64->rbp); 552 printf(" rsi = 0x%" PRIx64 "\n", context_amd64->rsi); 553 printf(" rdi = 0x%" PRIx64 "\n", context_amd64->rdi); 554 printf(" r8 = 0x%" PRIx64 "\n", context_amd64->r8); 555 printf(" r9 = 0x%" PRIx64 "\n", context_amd64->r9); 556 printf(" r10 = 0x%" PRIx64 "\n", context_amd64->r10); 557 printf(" r11 = 0x%" PRIx64 "\n", context_amd64->r11); 558 printf(" r12 = 0x%" PRIx64 "\n", context_amd64->r12); 559 printf(" r13 = 0x%" PRIx64 "\n", context_amd64->r13); 560 printf(" r14 = 0x%" PRIx64 "\n", context_amd64->r14); 561 printf(" r15 = 0x%" PRIx64 "\n", context_amd64->r15); 562 printf(" rip = 0x%" PRIx64 "\n", context_amd64->rip); 563 // TODO: print xmm, vector, debug registers 564 printf("\n"); 565 break; 566 } 567 568 case MD_CONTEXT_SPARC: { 569 const MDRawContextSPARC* context_sparc = GetContextSPARC(); 570 printf("MDRawContextSPARC\n"); 571 printf(" context_flags = 0x%x\n", 572 context_sparc->context_flags); 573 for (unsigned int g_r_index = 0; 574 g_r_index < MD_CONTEXT_SPARC_GPR_COUNT; 575 ++g_r_index) { 576 printf(" g_r[%2d] = 0x%" PRIx64 "\n", 577 g_r_index, context_sparc->g_r[g_r_index]); 578 } 579 printf(" ccr = 0x%" PRIx64 "\n", context_sparc->ccr); 580 printf(" pc = 0x%" PRIx64 "\n", context_sparc->pc); 581 printf(" npc = 0x%" PRIx64 "\n", context_sparc->npc); 582 printf(" y = 0x%" PRIx64 "\n", context_sparc->y); 583 printf(" asi = 0x%" PRIx64 "\n", context_sparc->asi); 584 printf(" fprs = 0x%" PRIx64 "\n", context_sparc->fprs); 585 586 for (unsigned int fpr_index = 0; 587 fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; 588 ++fpr_index) { 589 printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", 590 fpr_index, context_sparc->float_save.regs[fpr_index]); 591 } 592 printf(" float_save.filler = 0x%" PRIx64 "\n", 593 context_sparc->float_save.filler); 594 printf(" float_save.fsr = 0x%" PRIx64 "\n", 595 context_sparc->float_save.fsr); 596 break; 597 } 598 599 case MD_CONTEXT_ARM: { 600 const MDRawContextARM* context_arm = GetContextARM(); 601 const char * const names[] = { 602 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 603 "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", 604 }; 605 printf("MDRawContextARM\n"); 606 printf(" context_flags = 0x%x\n", 607 context_arm->context_flags); 608 for (unsigned int ireg_index = 0; 609 ireg_index < MD_CONTEXT_ARM_GPR_COUNT; 610 ++ireg_index) { 611 printf(" %-3s = 0x%x\n", 612 names[ireg_index], context_arm->iregs[ireg_index]); 613 } 614 printf(" cpsr = 0x%x\n", context_arm->cpsr); 615 printf(" float_save.fpscr = 0x%" PRIx64 "\n", 616 context_arm->float_save.fpscr); 617 for (unsigned int fpr_index = 0; 618 fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; 619 ++fpr_index) { 620 printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", 621 fpr_index, context_arm->float_save.regs[fpr_index]); 622 } 623 for (unsigned int fpe_index = 0; 624 fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; 625 ++fpe_index) { 626 printf(" float_save.extra[%2d] = 0x%" PRIx32 "\n", 627 fpe_index, context_arm->float_save.extra[fpe_index]); 628 } 629 630 break; 631 } 632 633 case MD_CONTEXT_ARM64: { 634 const MDRawContextARM64* context_arm64 = GetContextARM64(); 635 printf("MDRawContextARM64\n"); 636 printf(" context_flags = 0x%x\n", 637 context_arm64->context_flags); 638 for (unsigned int ireg_index = 0; 639 ireg_index < MD_CONTEXT_ARM64_GPR_COUNT; 640 ++ireg_index) { 641 printf(" iregs[%2d] = 0x%" PRIx64 "\n", 642 ireg_index, context_arm64->iregs[ireg_index]); 643 } 644 printf(" cpsr = 0x%x\n", context_arm64->cpsr); 645 printf(" float_save.fpsr = 0x%x\n", context_arm64->float_save.fpsr); 646 printf(" float_save.fpcr = 0x%x\n", context_arm64->float_save.fpcr); 647 648 for (unsigned int freg_index = 0; 649 freg_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT; 650 ++freg_index) { 651 uint128_struct fp_value = context_arm64->float_save.regs[freg_index]; 652 printf(" float_save.regs[%2d] = 0x%" PRIx64 "%" PRIx64 "\n", 653 freg_index, fp_value.high, fp_value.low); 654 } 655 656 break; 657 } 658 659 case MD_CONTEXT_MIPS: 660 case MD_CONTEXT_MIPS64: { 661 const MDRawContextMIPS* context_mips = GetContextMIPS(); 662 printf("MDRawContextMIPS\n"); 663 printf(" context_flags = 0x%x\n", 664 context_mips->context_flags); 665 for (int ireg_index = 0; 666 ireg_index < MD_CONTEXT_MIPS_GPR_COUNT; 667 ++ireg_index) { 668 printf(" iregs[%2d] = 0x%" PRIx64 "\n", 669 ireg_index, context_mips->iregs[ireg_index]); 670 } 671 printf(" mdhi = 0x%" PRIx64 "\n", 672 context_mips->mdhi); 673 printf(" mdlo = 0x%" PRIx64 "\n", 674 context_mips->mdhi); 675 for (int dsp_index = 0; 676 dsp_index < MD_CONTEXT_MIPS_DSP_COUNT; 677 ++dsp_index) { 678 printf(" hi[%1d] = 0x%" PRIx32 "\n", 679 dsp_index, context_mips->hi[dsp_index]); 680 printf(" lo[%1d] = 0x%" PRIx32 "\n", 681 dsp_index, context_mips->lo[dsp_index]); 682 } 683 printf(" dsp_control = 0x%" PRIx32 "\n", 684 context_mips->dsp_control); 685 printf(" epc = 0x%" PRIx64 "\n", 686 context_mips->epc); 687 printf(" badvaddr = 0x%" PRIx64 "\n", 688 context_mips->badvaddr); 689 printf(" status = 0x%" PRIx32 "\n", 690 context_mips->status); 691 printf(" cause = 0x%" PRIx32 "\n", 692 context_mips->cause); 693 694 for (int fpr_index = 0; 695 fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; 696 ++fpr_index) { 697 printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", 698 fpr_index, context_mips->float_save.regs[fpr_index]); 699 } 700 printf(" float_save.fpcsr = 0x%" PRIx32 "\n", 701 context_mips->float_save.fpcsr); 702 printf(" float_save.fir = 0x%" PRIx32 "\n", 703 context_mips->float_save.fir); 704 break; 705 } 706 707 case MD_CONTEXT_RISCV: { 708 const MDRawContextRISCV* context_riscv = GetContextRISCV(); 709 printf("MDRawContextRISCV\n"); 710 printf(" context_flags = 0x%x\n", 711 context_riscv->context_flags); 712 713 printf(" pc = 0x%" PRIx32 "\n", 714 context_riscv->pc); 715 printf(" ra = 0x%" PRIx32 "\n", 716 context_riscv->ra); 717 printf(" sp = 0x%" PRIx32 "\n", 718 context_riscv->sp); 719 printf(" gp = 0x%" PRIx32 "\n", 720 context_riscv->gp); 721 printf(" tp = 0x%" PRIx32 "\n", 722 context_riscv->tp); 723 printf(" t0 = 0x%" PRIx32 "\n", 724 context_riscv->t0); 725 printf(" t1 = 0x%" PRIx32 "\n", 726 context_riscv->t1); 727 printf(" t2 = 0x%" PRIx32 "\n", 728 context_riscv->t2); 729 printf(" s0 = 0x%" PRIx32 "\n", 730 context_riscv->s0); 731 printf(" s1 = 0x%" PRIx32 "\n", 732 context_riscv->s1); 733 printf(" a0 = 0x%" PRIx32 "\n", 734 context_riscv->a0); 735 printf(" a1 = 0x%" PRIx32 "\n", 736 context_riscv->a1); 737 printf(" a2 = 0x%" PRIx32 "\n", 738 context_riscv->a2); 739 printf(" a3 = 0x%" PRIx32 "\n", 740 context_riscv->a3); 741 printf(" a4 = 0x%" PRIx32 "\n", 742 context_riscv->a4); 743 printf(" a5 = 0x%" PRIx32 "\n", 744 context_riscv->a5); 745 printf(" a6 = 0x%" PRIx32 "\n", 746 context_riscv->a6); 747 printf(" a7 = 0x%" PRIx32 "\n", 748 context_riscv->a7); 749 printf(" s2 = 0x%" PRIx32 "\n", 750 context_riscv->s2); 751 printf(" s3 = 0x%" PRIx32 "\n", 752 context_riscv->s3); 753 printf(" s4 = 0x%" PRIx32 "\n", 754 context_riscv->s4); 755 printf(" s5 = 0x%" PRIx32 "\n", 756 context_riscv->s5); 757 printf(" s6 = 0x%" PRIx32 "\n", 758 context_riscv->s6); 759 printf(" s7 = 0x%" PRIx32 "\n", 760 context_riscv->s7); 761 printf(" s8 = 0x%" PRIx32 "\n", 762 context_riscv->s8); 763 printf(" s9 = 0x%" PRIx32 "\n", 764 context_riscv->s9); 765 printf(" s10 = 0x%" PRIx32 "\n", 766 context_riscv->s10); 767 printf(" s11 = 0x%" PRIx32 "\n", 768 context_riscv->s11); 769 printf(" t3 = 0x%" PRIx32 "\n", 770 context_riscv->t3); 771 printf(" t4 = 0x%" PRIx32 "\n", 772 context_riscv->t4); 773 printf(" t5 = 0x%" PRIx32 "\n", 774 context_riscv->t5); 775 printf(" t6 = 0x%" PRIx32 "\n", 776 context_riscv->t6); 777 778 #if defined(__riscv) 779 for (unsigned int freg_index = 0; freg_index < MD_CONTEXT_RISCV_FPR_COUNT; 780 ++freg_index) { 781 // Breakpad only supports RISCV32 with 32 bit floating point. 782 uint32_t fp_value = context_riscv->fpregs[freg_index]; 783 printf(" fpregs[%2d] = 0x%" PRIx32 "\n", freg_index, 784 fp_value); 785 } 786 printf(" fcsr = 0x%" PRIx32 "\n", context_riscv->fcsr); 787 #endif 788 break; 789 } 790 791 case MD_CONTEXT_RISCV64: { 792 const MDRawContextRISCV64* context_riscv64 = GetContextRISCV64(); 793 printf("MDRawContextRISCV64\n"); 794 printf(" context_flags = 0x%x\n", 795 context_riscv64->context_flags); 796 797 printf(" pc = 0x%" PRIx64 "\n", 798 context_riscv64->pc); 799 printf(" ra = 0x%" PRIx64 "\n", 800 context_riscv64->ra); 801 printf(" sp = 0x%" PRIx64 "\n", 802 context_riscv64->sp); 803 printf(" gp = 0x%" PRIx64 "\n", 804 context_riscv64->gp); 805 printf(" tp = 0x%" PRIx64 "\n", 806 context_riscv64->tp); 807 printf(" t0 = 0x%" PRIx64 "\n", 808 context_riscv64->t0); 809 printf(" t1 = 0x%" PRIx64 "\n", 810 context_riscv64->t1); 811 printf(" t2 = 0x%" PRIx64 "\n", 812 context_riscv64->t2); 813 printf(" s0 = 0x%" PRIx64 "\n", 814 context_riscv64->s0); 815 printf(" s1 = 0x%" PRIx64 "\n", 816 context_riscv64->s1); 817 printf(" a0 = 0x%" PRIx64 "\n", 818 context_riscv64->a0); 819 printf(" a1 = 0x%" PRIx64 "\n", 820 context_riscv64->a1); 821 printf(" a2 = 0x%" PRIx64 "\n", 822 context_riscv64->a2); 823 printf(" a3 = 0x%" PRIx64 "\n", 824 context_riscv64->a3); 825 printf(" a4 = 0x%" PRIx64 "\n", 826 context_riscv64->a4); 827 printf(" a5 = 0x%" PRIx64 "\n", 828 context_riscv64->a5); 829 printf(" a6 = 0x%" PRIx64 "\n", 830 context_riscv64->a6); 831 printf(" a7 = 0x%" PRIx64 "\n", 832 context_riscv64->a7); 833 printf(" s2 = 0x%" PRIx64 "\n", 834 context_riscv64->s2); 835 printf(" s3 = 0x%" PRIx64 "\n", 836 context_riscv64->s3); 837 printf(" s4 = 0x%" PRIx64 "\n", 838 context_riscv64->s4); 839 printf(" s5 = 0x%" PRIx64 "\n", 840 context_riscv64->s5); 841 printf(" s6 = 0x%" PRIx64 "\n", 842 context_riscv64->s6); 843 printf(" s7 = 0x%" PRIx64 "\n", 844 context_riscv64->s7); 845 printf(" s8 = 0x%" PRIx64 "\n", 846 context_riscv64->s8); 847 printf(" s9 = 0x%" PRIx64 "\n", 848 context_riscv64->s9); 849 printf(" s10 = 0x%" PRIx64 "\n", 850 context_riscv64->s10); 851 printf(" s11 = 0x%" PRIx64 "\n", 852 context_riscv64->s11); 853 printf(" t3 = 0x%" PRIx64 "\n", 854 context_riscv64->t3); 855 printf(" t4 = 0x%" PRIx64 "\n", 856 context_riscv64->t4); 857 printf(" t5 = 0x%" PRIx64 "\n", 858 context_riscv64->t5); 859 printf(" t6 = 0x%" PRIx64 "\n", 860 context_riscv64->t6); 861 862 #if defined(__riscv) 863 for (unsigned int freg_index = 0; freg_index < MD_CONTEXT_RISCV_FPR_COUNT; 864 ++freg_index) { 865 // Breakpad only supports RISCV64 with 64 bit floating point. 866 uint64_t fp_value = context_riscv64->fpregs[freg_index]; 867 printf(" fpregs[%2d] = 0x%" PRIx64 "\n", freg_index, 868 fp_value); 869 } 870 printf(" fcsr = 0x%" PRIx32 "\n", context_riscv64->fcsr); 871 #endif 872 break; 873 } 874 875 default: { 876 break; 877 } 878 } 879 } 880 881 } // namespace google_breakpad