1 // Copyright (c) 2010 Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 // dump_context.cc: A (mini/micro)dump context. 31 // 32 // See dump_context.h for documentation. 33 34 #include "google_breakpad/processor/dump_context.h" 35 36 #include <assert.h> 37 38 #ifdef _WIN32 39 #include <io.h> 40 #else // _WIN32 41 #include <unistd.h> 42 #endif // _WIN32 43 44 #include "common/stdio_wrapper.h" 45 #include "processor/logging.h" 46 47 namespace google_breakpad { 48 49 DumpContext::DumpContext() : context_(), 50 context_flags_(0) { } 51 52 DumpContext::~DumpContext() { 53 FreeContext(); 54 } 55 56 uint32_t DumpContext::GetContextCPU() const { 57 if (!valid_) { 58 // Don't log a message, GetContextCPU can be legitimately called with 59 // valid_ false by FreeContext, which is called by Read. 60 return 0; 61 } 62 63 return context_flags_ & MD_CONTEXT_CPU_MASK; 64 } 65 66 uint32_t DumpContext::GetContextFlags() const { 67 return context_flags_; 68 } 69 70 const MDRawContextX86* DumpContext::GetContextX86() const { 71 if (GetContextCPU() != MD_CONTEXT_X86) { 72 BPLOG(ERROR) << "DumpContext cannot get x86 context"; 73 return NULL; 74 } 75 76 return context_.x86; 77 } 78 79 const MDRawContextPPC* DumpContext::GetContextPPC() const { 80 if (GetContextCPU() != MD_CONTEXT_PPC) { 81 BPLOG(ERROR) << "DumpContext cannot get ppc context"; 82 return NULL; 83 } 84 85 return context_.ppc; 86 } 87 88 const MDRawContextPPC64* DumpContext::GetContextPPC64() const { 89 if (GetContextCPU() != MD_CONTEXT_PPC64) { 90 BPLOG(ERROR) << "DumpContext cannot get ppc64 context"; 91 return NULL; 92 } 93 94 return context_.ppc64; 95 } 96 97 const MDRawContextAMD64* DumpContext::GetContextAMD64() const { 98 if (GetContextCPU() != MD_CONTEXT_AMD64) { 99 BPLOG(ERROR) << "DumpContext cannot get amd64 context"; 100 return NULL; 101 } 102 103 return context_.amd64; 104 } 105 106 const MDRawContextSPARC* DumpContext::GetContextSPARC() const { 107 if (GetContextCPU() != MD_CONTEXT_SPARC) { 108 BPLOG(ERROR) << "DumpContext cannot get sparc context"; 109 return NULL; 110 } 111 112 return context_.ctx_sparc; 113 } 114 115 const MDRawContextARM* DumpContext::GetContextARM() const { 116 if (GetContextCPU() != MD_CONTEXT_ARM) { 117 BPLOG(ERROR) << "DumpContext cannot get arm context"; 118 return NULL; 119 } 120 121 return context_.arm; 122 } 123 124 const MDRawContextARM64* DumpContext::GetContextARM64() const { 125 if (GetContextCPU() != MD_CONTEXT_ARM64) { 126 BPLOG(ERROR) << "DumpContext cannot get arm64 context"; 127 return NULL; 128 } 129 130 return context_.arm64; 131 } 132 133 const MDRawContextMIPS* DumpContext::GetContextMIPS() const { 134 if ((GetContextCPU() != MD_CONTEXT_MIPS) && 135 (GetContextCPU() != MD_CONTEXT_MIPS64)) { 136 BPLOG(ERROR) << "DumpContext cannot get MIPS context"; 137 return NULL; 138 } 139 140 return context_.ctx_mips; 141 } 142 143 bool DumpContext::GetInstructionPointer(uint64_t* ip) const { 144 BPLOG_IF(ERROR, !ip) << "DumpContext::GetInstructionPointer requires |ip|"; 145 assert(ip); 146 *ip = 0; 147 148 if (!valid_) { 149 BPLOG(ERROR) << "Invalid DumpContext for GetInstructionPointer"; 150 return false; 151 } 152 153 switch (GetContextCPU()) { 154 case MD_CONTEXT_AMD64: 155 *ip = GetContextAMD64()->rip; 156 break; 157 case MD_CONTEXT_ARM: 158 *ip = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_PC]; 159 break; 160 case MD_CONTEXT_ARM64: 161 *ip = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_PC]; 162 break; 163 case MD_CONTEXT_PPC: 164 *ip = GetContextPPC()->srr0; 165 break; 166 case MD_CONTEXT_PPC64: 167 *ip = GetContextPPC64()->srr0; 168 break; 169 case MD_CONTEXT_SPARC: 170 *ip = GetContextSPARC()->pc; 171 break; 172 case MD_CONTEXT_X86: 173 *ip = GetContextX86()->eip; 174 break; 175 case MD_CONTEXT_MIPS: 176 case MD_CONTEXT_MIPS64: 177 *ip = GetContextMIPS()->epc; 178 break; 179 default: 180 // This should never happen. 181 BPLOG(ERROR) << "Unknown CPU architecture in GetInstructionPointer"; 182 return false; 183 } 184 return true; 185 } 186 187 bool DumpContext::GetStackPointer(uint64_t* sp) const { 188 BPLOG_IF(ERROR, !sp) << "DumpContext::GetStackPointer requires |sp|"; 189 assert(sp); 190 *sp = 0; 191 192 if (!valid_) { 193 BPLOG(ERROR) << "Invalid DumpContext for GetStackPointer"; 194 return false; 195 } 196 197 switch (GetContextCPU()) { 198 case MD_CONTEXT_AMD64: 199 *sp = GetContextAMD64()->rsp; 200 break; 201 case MD_CONTEXT_ARM: 202 *sp = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_SP]; 203 break; 204 case MD_CONTEXT_ARM64: 205 *sp = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_SP]; 206 break; 207 case MD_CONTEXT_PPC: 208 *sp = GetContextPPC()->gpr[MD_CONTEXT_PPC_REG_SP]; 209 break; 210 case MD_CONTEXT_PPC64: 211 *sp = GetContextPPC64()->gpr[MD_CONTEXT_PPC64_REG_SP]; 212 break; 213 case MD_CONTEXT_SPARC: 214 *sp = GetContextSPARC()->g_r[MD_CONTEXT_SPARC_REG_SP]; 215 break; 216 case MD_CONTEXT_X86: 217 *sp = GetContextX86()->esp; 218 break; 219 case MD_CONTEXT_MIPS: 220 case MD_CONTEXT_MIPS64: 221 *sp = GetContextMIPS()->iregs[MD_CONTEXT_MIPS_REG_SP]; 222 break; 223 default: 224 // This should never happen. 225 BPLOG(ERROR) << "Unknown CPU architecture in GetStackPointer"; 226 return false; 227 } 228 return true; 229 } 230 231 void DumpContext::SetContextFlags(uint32_t context_flags) { 232 context_flags_ = context_flags; 233 } 234 235 void DumpContext::SetContextX86(MDRawContextX86* x86) { 236 context_.x86 = x86; 237 } 238 239 void DumpContext::SetContextPPC(MDRawContextPPC* ppc) { 240 context_.ppc = ppc; 241 } 242 243 void DumpContext::SetContextPPC64(MDRawContextPPC64* ppc64) { 244 context_.ppc64 = ppc64; 245 } 246 247 void DumpContext::SetContextAMD64(MDRawContextAMD64* amd64) { 248 context_.amd64 = amd64; 249 } 250 251 void DumpContext::SetContextSPARC(MDRawContextSPARC* ctx_sparc) { 252 context_.ctx_sparc = ctx_sparc; 253 } 254 255 void DumpContext::SetContextARM(MDRawContextARM* arm) { 256 context_.arm = arm; 257 } 258 259 void DumpContext::SetContextARM64(MDRawContextARM64* arm64) { 260 context_.arm64 = arm64; 261 } 262 263 void DumpContext::SetContextMIPS(MDRawContextMIPS* ctx_mips) { 264 context_.ctx_mips = ctx_mips; 265 } 266 267 void DumpContext::FreeContext() { 268 switch (GetContextCPU()) { 269 case MD_CONTEXT_X86: 270 delete context_.x86; 271 break; 272 273 case MD_CONTEXT_PPC: 274 delete context_.ppc; 275 break; 276 277 case MD_CONTEXT_PPC64: 278 delete context_.ppc64; 279 break; 280 281 case MD_CONTEXT_AMD64: 282 delete context_.amd64; 283 break; 284 285 case MD_CONTEXT_SPARC: 286 delete context_.ctx_sparc; 287 break; 288 289 case MD_CONTEXT_ARM: 290 delete context_.arm; 291 break; 292 293 case MD_CONTEXT_ARM64: 294 delete context_.arm64; 295 break; 296 297 case MD_CONTEXT_MIPS: 298 case MD_CONTEXT_MIPS64: 299 delete context_.ctx_mips; 300 break; 301 302 default: 303 // There is no context record (valid_ is false) or there's a 304 // context record for an unknown CPU (shouldn't happen, only known 305 // records are stored by Read). 306 break; 307 } 308 309 context_flags_ = 0; 310 context_.base = NULL; 311 } 312 313 void DumpContext::Print() { 314 if (!valid_) { 315 BPLOG(ERROR) << "DumpContext cannot print invalid data"; 316 return; 317 } 318 319 switch (GetContextCPU()) { 320 case MD_CONTEXT_X86: { 321 const MDRawContextX86* context_x86 = GetContextX86(); 322 printf("MDRawContextX86\n"); 323 printf(" context_flags = 0x%x\n", 324 context_x86->context_flags); 325 printf(" dr0 = 0x%x\n", context_x86->dr0); 326 printf(" dr1 = 0x%x\n", context_x86->dr1); 327 printf(" dr2 = 0x%x\n", context_x86->dr2); 328 printf(" dr3 = 0x%x\n", context_x86->dr3); 329 printf(" dr6 = 0x%x\n", context_x86->dr6); 330 printf(" dr7 = 0x%x\n", context_x86->dr7); 331 printf(" float_save.control_word = 0x%x\n", 332 context_x86->float_save.control_word); 333 printf(" float_save.status_word = 0x%x\n", 334 context_x86->float_save.status_word); 335 printf(" float_save.tag_word = 0x%x\n", 336 context_x86->float_save.tag_word); 337 printf(" float_save.error_offset = 0x%x\n", 338 context_x86->float_save.error_offset); 339 printf(" float_save.error_selector = 0x%x\n", 340 context_x86->float_save.error_selector); 341 printf(" float_save.data_offset = 0x%x\n", 342 context_x86->float_save.data_offset); 343 printf(" float_save.data_selector = 0x%x\n", 344 context_x86->float_save.data_selector); 345 printf(" float_save.register_area[%2d] = 0x", 346 MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE); 347 for (unsigned int register_index = 0; 348 register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE; 349 ++register_index) { 350 printf("%02x", context_x86->float_save.register_area[register_index]); 351 } 352 printf("\n"); 353 printf(" float_save.cr0_npx_state = 0x%x\n", 354 context_x86->float_save.cr0_npx_state); 355 printf(" gs = 0x%x\n", context_x86->gs); 356 printf(" fs = 0x%x\n", context_x86->fs); 357 printf(" es = 0x%x\n", context_x86->es); 358 printf(" ds = 0x%x\n", context_x86->ds); 359 printf(" edi = 0x%x\n", context_x86->edi); 360 printf(" esi = 0x%x\n", context_x86->esi); 361 printf(" ebx = 0x%x\n", context_x86->ebx); 362 printf(" edx = 0x%x\n", context_x86->edx); 363 printf(" ecx = 0x%x\n", context_x86->ecx); 364 printf(" eax = 0x%x\n", context_x86->eax); 365 printf(" ebp = 0x%x\n", context_x86->ebp); 366 printf(" eip = 0x%x\n", context_x86->eip); 367 printf(" cs = 0x%x\n", context_x86->cs); 368 printf(" eflags = 0x%x\n", context_x86->eflags); 369 printf(" esp = 0x%x\n", context_x86->esp); 370 printf(" ss = 0x%x\n", context_x86->ss); 371 printf(" extended_registers[%3d] = 0x", 372 MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE); 373 for (unsigned int register_index = 0; 374 register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE; 375 ++register_index) { 376 printf("%02x", context_x86->extended_registers[register_index]); 377 } 378 printf("\n\n"); 379 380 break; 381 } 382 383 case MD_CONTEXT_PPC: { 384 const MDRawContextPPC* context_ppc = GetContextPPC(); 385 printf("MDRawContextPPC\n"); 386 printf(" context_flags = 0x%x\n", 387 context_ppc->context_flags); 388 printf(" srr0 = 0x%x\n", context_ppc->srr0); 389 printf(" srr1 = 0x%x\n", context_ppc->srr1); 390 for (unsigned int gpr_index = 0; dissect_evs_cmr(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * evs_tree,int offset,guint8 cmr_oct)391 gpr_index < MD_CONTEXT_PPC_GPR_COUNT; 392 ++gpr_index) { 393 printf(" gpr[%2d] = 0x%x\n", 394 gpr_index, context_ppc->gpr[gpr_index]); 395 } 396 printf(" cr = 0x%x\n", context_ppc->cr); 397 printf(" xer = 0x%x\n", context_ppc->xer); 398 printf(" lr = 0x%x\n", context_ppc->lr); 399 printf(" ctr = 0x%x\n", context_ppc->ctr); 400 printf(" mq = 0x%x\n", context_ppc->mq); 401 printf(" vrsave = 0x%x\n", context_ppc->vrsave); 402 for (unsigned int fpr_index = 0; 403 fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; 404 ++fpr_index) { 405 printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", 406 fpr_index, context_ppc->float_save.fpregs[fpr_index]); 407 } 408 printf(" float_save.fpscr = 0x%x\n", 409 context_ppc->float_save.fpscr); 410 // TODO(mmentovai): print the 128-bit quantities in 411 // context_ppc->vector_save. This isn't done yet because printf 412 // doesn't support 128-bit quantities, and printing them using 413 // PRIx64 as two 64-bit quantities requires knowledge of the CPU's 414 // byte ordering. 415 printf(" vector_save.save_vrvalid = 0x%x\n", 416 context_ppc->vector_save.save_vrvalid); 417 printf("\n"); 418 419 break; 420 } 421 422 case MD_CONTEXT_PPC64: { 423 const MDRawContextPPC64* context_ppc64 = GetContextPPC64(); 424 printf("MDRawContextPPC64\n"); 425 printf(" context_flags = 0x%" PRIx64 "\n", 426 context_ppc64->context_flags); 427 printf(" srr0 = 0x%" PRIx64 "\n", 428 context_ppc64->srr0); 429 printf(" srr1 = 0x%" PRIx64 "\n", 430 context_ppc64->srr1); 431 for (unsigned int gpr_index = 0; 432 gpr_index < MD_CONTEXT_PPC64_GPR_COUNT; 433 ++gpr_index) { 434 printf(" gpr[%2d] = 0x%" PRIx64 "\n", 435 gpr_index, context_ppc64->gpr[gpr_index]); 436 } 437 printf(" cr = 0x%" PRIx64 "\n", context_ppc64->cr); 438 printf(" xer = 0x%" PRIx64 "\n", 439 context_ppc64->xer); 440 printf(" lr = 0x%" PRIx64 "\n", context_ppc64->lr); 441 printf(" ctr = 0x%" PRIx64 "\n", 442 context_ppc64->ctr); 443 printf(" vrsave = 0x%" PRIx64 "\n", 444 context_ppc64->vrsave); 445 for (unsigned int fpr_index = 0; 446 fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; 447 ++fpr_index) { 448 printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", 449 fpr_index, context_ppc64->float_save.fpregs[fpr_index]); 450 } 451 printf(" float_save.fpscr = 0x%x\n", 452 context_ppc64->float_save.fpscr); 453 // TODO(mmentovai): print the 128-bit quantities in 454 // context_ppc64->vector_save. This isn't done yet because printf 455 // doesn't support 128-bit quantities, and printing them using 456 // PRIx64 as two 64-bit quantities requires knowledge of the CPU's 457 // byte ordering. 458 printf(" vector_save.save_vrvalid = 0x%x\n", 459 context_ppc64->vector_save.save_vrvalid); 460 printf("\n"); 461 462 break; 463 } 464 465 case MD_CONTEXT_AMD64: { 466 const MDRawContextAMD64* context_amd64 = GetContextAMD64(); 467 printf("MDRawContextAMD64\n"); 468 printf(" p1_home = 0x%" PRIx64 "\n", 469 context_amd64->p1_home); 470 printf(" p2_home = 0x%" PRIx64 "\n", 471 context_amd64->p2_home); 472 printf(" p3_home = 0x%" PRIx64 "\n", 473 context_amd64->p3_home); 474 printf(" p4_home = 0x%" PRIx64 "\n", 475 context_amd64->p4_home); 476 printf(" p5_home = 0x%" PRIx64 "\n", 477 context_amd64->p5_home); 478 printf(" p6_home = 0x%" PRIx64 "\n", 479 context_amd64->p6_home); 480 printf(" context_flags = 0x%x\n", 481 context_amd64->context_flags); 482 printf(" mx_csr = 0x%x\n", 483 context_amd64->mx_csr); 484 printf(" cs = 0x%x\n", context_amd64->cs); 485 printf(" ds = 0x%x\n", context_amd64->ds); 486 printf(" es = 0x%x\n", context_amd64->es); 487 printf(" fs = 0x%x\n", context_amd64->fs); 488 printf(" gs = 0x%x\n", context_amd64->gs); 489 printf(" ss = 0x%x\n", context_amd64->ss); 490 printf(" eflags = 0x%x\n", context_amd64->eflags); 491 printf(" dr0 = 0x%" PRIx64 "\n", context_amd64->dr0); 492 printf(" dr1 = 0x%" PRIx64 "\n", context_amd64->dr1); 493 printf(" dr2 = 0x%" PRIx64 "\n", context_amd64->dr2); 494 printf(" dr3 = 0x%" PRIx64 "\n", context_amd64->dr3); 495 printf(" dr6 = 0x%" PRIx64 "\n", context_amd64->dr6); 496 printf(" dr7 = 0x%" PRIx64 "\n", context_amd64->dr7); 497 printf(" rax = 0x%" PRIx64 "\n", context_amd64->rax); 498 printf(" rcx = 0x%" PRIx64 "\n", context_amd64->rcx); 499 printf(" rdx = 0x%" PRIx64 "\n", context_amd64->rdx); 500 printf(" rbx = 0x%" PRIx64 "\n", context_amd64->rbx); 501 printf(" rsp = 0x%" PRIx64 "\n", context_amd64->rsp); 502 printf(" rbp = 0x%" PRIx64 "\n", context_amd64->rbp); 503 printf(" rsi = 0x%" PRIx64 "\n", context_amd64->rsi); 504 printf(" rdi = 0x%" PRIx64 "\n", context_amd64->rdi); 505 printf(" r8 = 0x%" PRIx64 "\n", context_amd64->r8); 506 printf(" r9 = 0x%" PRIx64 "\n", context_amd64->r9); 507 printf(" r10 = 0x%" PRIx64 "\n", context_amd64->r10); 508 printf(" r11 = 0x%" PRIx64 "\n", context_amd64->r11); 509 printf(" r12 = 0x%" PRIx64 "\n", context_amd64->r12); 510 printf(" r13 = 0x%" PRIx64 "\n", context_amd64->r13); 511 printf(" r14 = 0x%" PRIx64 "\n", context_amd64->r14); 512 printf(" r15 = 0x%" PRIx64 "\n", context_amd64->r15); 513 printf(" rip = 0x%" PRIx64 "\n", context_amd64->rip); 514 // TODO: print xmm, vector, debug registers 515 printf("\n"); 516 break; 517 } 518 519 case MD_CONTEXT_SPARC: { 520 const MDRawContextSPARC* context_sparc = GetContextSPARC(); 521 printf("MDRawContextSPARC\n"); 522 printf(" context_flags = 0x%x\n", 523 context_sparc->context_flags); 524 for (unsigned int g_r_index = 0; dissect_evs(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)525 g_r_index < MD_CONTEXT_SPARC_GPR_COUNT; 526 ++g_r_index) { 527 printf(" g_r[%2d] = 0x%" PRIx64 "\n", 528 g_r_index, context_sparc->g_r[g_r_index]); 529 } 530 printf(" ccr = 0x%" PRIx64 "\n", context_sparc->ccr); 531 printf(" pc = 0x%" PRIx64 "\n", context_sparc->pc); 532 printf(" npc = 0x%" PRIx64 "\n", context_sparc->npc); 533 printf(" y = 0x%" PRIx64 "\n", context_sparc->y); 534 printf(" asi = 0x%" PRIx64 "\n", context_sparc->asi); 535 printf(" fprs = 0x%" PRIx64 "\n", context_sparc->fprs); 536 537 for (unsigned int fpr_index = 0; 538 fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; 539 ++fpr_index) { 540 printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", 541 fpr_index, context_sparc->float_save.regs[fpr_index]); 542 } 543 printf(" float_save.filler = 0x%" PRIx64 "\n", 544 context_sparc->float_save.filler); 545 printf(" float_save.fsr = 0x%" PRIx64 "\n", 546 context_sparc->float_save.fsr); 547 break; 548 } 549 550 case MD_CONTEXT_ARM: { 551 const MDRawContextARM* context_arm = GetContextARM(); 552 printf("MDRawContextARM\n"); 553 printf(" context_flags = 0x%x\n", 554 context_arm->context_flags); 555 for (unsigned int ireg_index = 0; 556 ireg_index < MD_CONTEXT_ARM_GPR_COUNT; 557 ++ireg_index) { 558 printf(" iregs[%2d] = 0x%x\n", 559 ireg_index, context_arm->iregs[ireg_index]); 560 } 561 printf(" cpsr = 0x%x\n", context_arm->cpsr); 562 printf(" float_save.fpscr = 0x%" PRIx64 "\n", 563 context_arm->float_save.fpscr); 564 for (unsigned int fpr_index = 0; 565 fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; 566 ++fpr_index) { 567 printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", 568 fpr_index, context_arm->float_save.regs[fpr_index]); 569 } 570 for (unsigned int fpe_index = 0; 571 fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; 572 ++fpe_index) { 573 printf(" float_save.extra[%2d] = 0x%" PRIx32 "\n", 574 fpe_index, context_arm->float_save.extra[fpe_index]); 575 } 576 577 break; 578 } 579 580 case MD_CONTEXT_ARM64: { 581 const MDRawContextARM64* context_arm64 = GetContextARM64(); 582 printf("MDRawContextARM64\n"); 583 printf(" context_flags = 0x%" PRIx64 "\n", 584 context_arm64->context_flags); 585 for (unsigned int ireg_index = 0; 586 ireg_index < MD_CONTEXT_ARM64_GPR_COUNT; 587 ++ireg_index) { 588 printf(" iregs[%2d] = 0x%" PRIx64 "\n", 589 ireg_index, context_arm64->iregs[ireg_index]); 590 } 591 printf(" cpsr = 0x%x\n", context_arm64->cpsr); 592 printf(" float_save.fpsr = 0x%x\n", context_arm64->float_save.fpsr); 593 printf(" float_save.fpcr = 0x%x\n", context_arm64->float_save.fpcr); 594 595 for (unsigned int freg_index = 0; 596 freg_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT; 597 ++freg_index) { 598 uint128_struct fp_value = context_arm64->float_save.regs[freg_index]; 599 printf(" float_save.regs[%2d] = 0x%" PRIx64 "%" PRIx64 "\n", 600 freg_index, fp_value.high, fp_value.low); 601 } 602 break; 603 } 604 605 case MD_CONTEXT_MIPS: 606 case MD_CONTEXT_MIPS64: { 607 const MDRawContextMIPS* context_mips = GetContextMIPS(); 608 printf("MDRawContextMIPS\n"); 609 printf(" context_flags = 0x%x\n", 610 context_mips->context_flags); 611 for (int ireg_index = 0; 612 ireg_index < MD_CONTEXT_MIPS_GPR_COUNT; 613 ++ireg_index) { 614 printf(" iregs[%2d] = 0x%" PRIx64 "\n", 615 ireg_index, context_mips->iregs[ireg_index]); 616 } 617 printf(" mdhi = 0x%" PRIx64 "\n", 618 context_mips->mdhi); 619 printf(" mdlo = 0x%" PRIx64 "\n", 620 context_mips->mdhi); 621 for (int dsp_index = 0; 622 dsp_index < MD_CONTEXT_MIPS_DSP_COUNT; 623 ++dsp_index) { 624 printf(" hi[%1d] = 0x%" PRIx32 "\n", 625 dsp_index, context_mips->hi[dsp_index]); 626 printf(" lo[%1d] = 0x%" PRIx32 "\n", 627 dsp_index, context_mips->lo[dsp_index]); 628 } 629 printf(" dsp_control = 0x%" PRIx32 "\n", 630 context_mips->dsp_control); 631 printf(" epc = 0x%" PRIx64 "\n", 632 context_mips->epc); 633 printf(" badvaddr = 0x%" PRIx64 "\n", 634 context_mips->badvaddr); 635 printf(" status = 0x%" PRIx32 "\n", 636 context_mips->status); 637 printf(" cause = 0x%" PRIx32 "\n", 638 context_mips->cause); 639 640 for (int fpr_index = 0; 641 fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; 642 ++fpr_index) { 643 printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", 644 fpr_index, context_mips->float_save.regs[fpr_index]); 645 } 646 printf(" float_save.fpcsr = 0x%" PRIx32 "\n", 647 context_mips->float_save.fpcsr); 648 printf(" float_save.fir = 0x%" PRIx32 "\n", 649 context_mips->float_save.fir); 650 break; 651 } 652 653 default: { 654 break; 655 } 656 } 657 } 658 659 } // namespace google_breakpad 660