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 #include <stdio.h> 38 39 #ifdef _WIN32 40 #include <io.h> 41 #define PRIx64 "llx" 42 #define PRIx32 "lx" 43 #define snprintf _snprintf 44 #else // _WIN32 45 #include <unistd.h> 46 #endif // _WIN32 47 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 BPLOG(ERROR) << "DumpContext cannot get MIPS context"; 139 return NULL; 140 } 141 142 return context_.ctx_mips; 143 } 144 145 bool DumpContext::GetInstructionPointer(uint64_t* ip) const { 146 BPLOG_IF(ERROR, !ip) << "DumpContext::GetInstructionPointer requires |ip|"; 147 assert(ip); 148 *ip = 0; 149 150 if (!valid_) { 151 BPLOG(ERROR) << "Invalid DumpContext for GetInstructionPointer"; 152 return false; 153 } 154 155 switch (GetContextCPU()) { 156 case MD_CONTEXT_AMD64: 157 *ip = GetContextAMD64()->rip; 158 break; 159 case MD_CONTEXT_ARM: 160 *ip = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_PC]; 161 break; 162 case MD_CONTEXT_ARM64: 163 *ip = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_PC]; 164 break; 165 case MD_CONTEXT_PPC: 166 *ip = GetContextPPC()->srr0; 167 break; 168 case MD_CONTEXT_PPC64: 169 *ip = GetContextPPC64()->srr0; 170 break; 171 case MD_CONTEXT_SPARC: 172 *ip = GetContextSPARC()->pc; 173 break; 174 case MD_CONTEXT_X86: 175 *ip = GetContextX86()->eip; 176 break; 177 case MD_CONTEXT_MIPS: 178 *ip = GetContextMIPS()->epc; 179 break; 180 default: 181 // This should never happen. 182 BPLOG(ERROR) << "Unknown CPU architecture in GetInstructionPointer"; 183 return false; 184 } 185 return true; 186 } 187 188 void DumpContext::SetContextFlags(uint32_t context_flags) { 189 context_flags_ = context_flags; 190 } 191 192 void DumpContext::SetContextX86(MDRawContextX86* x86) { 193 context_.x86 = x86; 194 } 195 196 void DumpContext::SetContextPPC(MDRawContextPPC* ppc) { 197 context_.ppc = ppc; 198 } 199 200 void DumpContext::SetContextPPC64(MDRawContextPPC64* ppc64) { 201 context_.ppc64 = ppc64; 202 } 203 204 void DumpContext::SetContextAMD64(MDRawContextAMD64* amd64) { 205 context_.amd64 = amd64; 206 } 207 208 void DumpContext::SetContextSPARC(MDRawContextSPARC* ctx_sparc) { 209 context_.ctx_sparc = ctx_sparc; 210 } 211 212 void DumpContext::SetContextARM(MDRawContextARM* arm) { 213 context_.arm = arm; 214 } 215 216 void DumpContext::SetContextARM64(MDRawContextARM64* arm64) { 217 context_.arm64 = arm64; 218 } 219 220 void DumpContext::SetContextMIPS(MDRawContextMIPS* ctx_mips) { 221 context_.ctx_mips = ctx_mips; 222 } 223 224 void DumpContext::FreeContext() { 225 switch (GetContextCPU()) { 226 case MD_CONTEXT_X86: 227 delete context_.x86; 228 break; 229 230 case MD_CONTEXT_PPC: 231 delete context_.ppc; 232 break; 233 234 case MD_CONTEXT_PPC64: 235 delete context_.ppc64; 236 break; 237 238 case MD_CONTEXT_AMD64: 239 delete context_.amd64; 240 break; 241 242 case MD_CONTEXT_SPARC: 243 delete context_.ctx_sparc; 244 break; 245 246 case MD_CONTEXT_ARM: 247 delete context_.arm; 248 break; 249 250 case MD_CONTEXT_ARM64: 251 delete context_.arm64; 252 break; 253 254 case MD_CONTEXT_MIPS: 255 delete context_.ctx_mips; 256 break; 257 258 default: 259 // There is no context record (valid_ is false) or there's a 260 // context record for an unknown CPU (shouldn't happen, only known 261 // records are stored by Read). 262 break; 263 } 264 265 context_flags_ = 0; 266 context_.base = NULL; 267 } 268 269 void DumpContext::Print() { 270 if (!valid_) { 271 BPLOG(ERROR) << "DumpContext cannot print invalid data"; 272 return; 273 } 274 275 switch (GetContextCPU()) { 276 case MD_CONTEXT_X86: { 277 const MDRawContextX86* context_x86 = GetContextX86(); 278 printf("MDRawContextX86\n"); 279 printf(" context_flags = 0x%x\n", 280 context_x86->context_flags); 281 printf(" dr0 = 0x%x\n", context_x86->dr0); 282 printf(" dr1 = 0x%x\n", context_x86->dr1); 283 printf(" dr2 = 0x%x\n", context_x86->dr2); 284 printf(" dr3 = 0x%x\n", context_x86->dr3); 285 printf(" dr6 = 0x%x\n", context_x86->dr6); 286 printf(" dr7 = 0x%x\n", context_x86->dr7); 287 printf(" float_save.control_word = 0x%x\n", 288 context_x86->float_save.control_word); 289 printf(" float_save.status_word = 0x%x\n", 290 context_x86->float_save.status_word); 291 printf(" float_save.tag_word = 0x%x\n", 292 context_x86->float_save.tag_word); 293 printf(" float_save.error_offset = 0x%x\n", 294 context_x86->float_save.error_offset); 295 printf(" float_save.error_selector = 0x%x\n", 296 context_x86->float_save.error_selector); 297 printf(" float_save.data_offset = 0x%x\n", 298 context_x86->float_save.data_offset); 299 printf(" float_save.data_selector = 0x%x\n", 300 context_x86->float_save.data_selector); 301 printf(" float_save.register_area[%2d] = 0x", 302 MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE); 303 for (unsigned int register_index = 0; 304 register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE; 305 ++register_index) { 306 printf("%02x", context_x86->float_save.register_area[register_index]); 307 } 308 printf("\n"); 309 printf(" float_save.cr0_npx_state = 0x%x\n", 310 context_x86->float_save.cr0_npx_state); 311 printf(" gs = 0x%x\n", context_x86->gs); 312 printf(" fs = 0x%x\n", context_x86->fs); 313 printf(" es = 0x%x\n", context_x86->es); 314 printf(" ds = 0x%x\n", context_x86->ds); 315 printf(" edi = 0x%x\n", context_x86->edi); 316 printf(" esi = 0x%x\n", context_x86->esi); 317 printf(" ebx = 0x%x\n", context_x86->ebx); 318 printf(" edx = 0x%x\n", context_x86->edx); 319 printf(" ecx = 0x%x\n", context_x86->ecx); 320 printf(" eax = 0x%x\n", context_x86->eax); 321 printf(" ebp = 0x%x\n", context_x86->ebp); 322 printf(" eip = 0x%x\n", context_x86->eip); 323 printf(" cs = 0x%x\n", context_x86->cs); 324 printf(" eflags = 0x%x\n", context_x86->eflags); 325 printf(" esp = 0x%x\n", context_x86->esp); 326 printf(" ss = 0x%x\n", context_x86->ss); 327 printf(" extended_registers[%3d] = 0x", 328 MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE); 329 for (unsigned int register_index = 0; 330 register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE; 331 ++register_index) { 332 printf("%02x", context_x86->extended_registers[register_index]); 333 } 334 printf("\n\n"); 335 336 break; 337 } 338 339 case MD_CONTEXT_PPC: { 340 const MDRawContextPPC* context_ppc = GetContextPPC(); 341 printf("MDRawContextPPC\n"); 342 printf(" context_flags = 0x%x\n", 343 context_ppc->context_flags); 344 printf(" srr0 = 0x%x\n", context_ppc->srr0); 345 printf(" srr1 = 0x%x\n", context_ppc->srr1); 346 for (unsigned int gpr_index = 0; 347 gpr_index < MD_CONTEXT_PPC_GPR_COUNT; 348 ++gpr_index) { 349 printf(" gpr[%2d] = 0x%x\n", 350 gpr_index, context_ppc->gpr[gpr_index]); 351 } 352 printf(" cr = 0x%x\n", context_ppc->cr); 353 printf(" xer = 0x%x\n", context_ppc->xer); 354 printf(" lr = 0x%x\n", context_ppc->lr); 355 printf(" ctr = 0x%x\n", context_ppc->ctr); 356 printf(" mq = 0x%x\n", context_ppc->mq); 357 printf(" vrsave = 0x%x\n", context_ppc->vrsave); 358 for (unsigned int fpr_index = 0; 359 fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; 360 ++fpr_index) { 361 printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", 362 fpr_index, context_ppc->float_save.fpregs[fpr_index]); 363 } 364 printf(" float_save.fpscr = 0x%x\n", 365 context_ppc->float_save.fpscr); 366 // TODO(mmentovai): print the 128-bit quantities in 367 // context_ppc->vector_save. This isn't done yet because printf 368 // doesn't support 128-bit quantities, and printing them using 369 // PRIx64 as two 64-bit quantities requires knowledge of the CPU's 370 // byte ordering. 371 printf(" vector_save.save_vrvalid = 0x%x\n", 372 context_ppc->vector_save.save_vrvalid); 373 printf("\n"); 374 375 break; 376 } 377 378 case MD_CONTEXT_PPC64: { 379 const MDRawContextPPC64* context_ppc64 = GetContextPPC64(); 380 printf("MDRawContextPPC64\n"); 381 printf(" context_flags = 0x%" PRIx64 "\n", 382 context_ppc64->context_flags); 383 printf(" srr0 = 0x%" PRIx64 "\n", 384 context_ppc64->srr0); 385 printf(" srr1 = 0x%" PRIx64 "\n", 386 context_ppc64->srr1); 387 for (unsigned int gpr_index = 0; 388 gpr_index < MD_CONTEXT_PPC64_GPR_COUNT; 389 ++gpr_index) { 390 printf(" gpr[%2d] = 0x%" PRIx64 "\n", 391 gpr_index, context_ppc64->gpr[gpr_index]); 392 } 393 printf(" cr = 0x%" PRIx64 "\n", context_ppc64->cr); 394 printf(" xer = 0x%" PRIx64 "\n", 395 context_ppc64->xer); 396 printf(" lr = 0x%" PRIx64 "\n", context_ppc64->lr); 397 printf(" ctr = 0x%" PRIx64 "\n", 398 context_ppc64->ctr); 399 printf(" vrsave = 0x%" PRIx64 "\n", 400 context_ppc64->vrsave); 401 for (unsigned int fpr_index = 0; 402 fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; 403 ++fpr_index) { 404 printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", 405 fpr_index, context_ppc64->float_save.fpregs[fpr_index]); 406 } 407 printf(" float_save.fpscr = 0x%x\n", 408 context_ppc64->float_save.fpscr); 409 // TODO(mmentovai): print the 128-bit quantities in 410 // context_ppc64->vector_save. This isn't done yet because printf 411 // doesn't support 128-bit quantities, and printing them using 412 // PRIx64 as two 64-bit quantities requires knowledge of the CPU's 413 // byte ordering. 414 printf(" vector_save.save_vrvalid = 0x%x\n", 415 context_ppc64->vector_save.save_vrvalid); 416 printf("\n"); 417 418 break; 419 } 420 421 case MD_CONTEXT_AMD64: { 422 const MDRawContextAMD64* context_amd64 = GetContextAMD64(); 423 printf("MDRawContextAMD64\n"); 424 printf(" p1_home = 0x%" PRIx64 "\n", 425 context_amd64->p1_home); 426 printf(" p2_home = 0x%" PRIx64 "\n", 427 context_amd64->p2_home); 428 printf(" p3_home = 0x%" PRIx64 "\n", 429 context_amd64->p3_home); 430 printf(" p4_home = 0x%" PRIx64 "\n", 431 context_amd64->p4_home); 432 printf(" p5_home = 0x%" PRIx64 "\n", 433 context_amd64->p5_home); 434 printf(" p6_home = 0x%" PRIx64 "\n", 435 context_amd64->p6_home); 436 printf(" context_flags = 0x%x\n", 437 context_amd64->context_flags); 438 printf(" mx_csr = 0x%x\n", 439 context_amd64->mx_csr); 440 printf(" cs = 0x%x\n", context_amd64->cs); 441 printf(" ds = 0x%x\n", context_amd64->ds); 442 printf(" es = 0x%x\n", context_amd64->es); 443 printf(" fs = 0x%x\n", context_amd64->fs); 444 printf(" gs = 0x%x\n", context_amd64->gs); 445 printf(" ss = 0x%x\n", context_amd64->ss); 446 printf(" eflags = 0x%x\n", context_amd64->eflags); 447 printf(" dr0 = 0x%" PRIx64 "\n", context_amd64->dr0); 448 printf(" dr1 = 0x%" PRIx64 "\n", context_amd64->dr1); 449 printf(" dr2 = 0x%" PRIx64 "\n", context_amd64->dr2); 450 printf(" dr3 = 0x%" PRIx64 "\n", context_amd64->dr3); 451 printf(" dr6 = 0x%" PRIx64 "\n", context_amd64->dr6); 452 printf(" dr7 = 0x%" PRIx64 "\n", context_amd64->dr7); 453 printf(" rax = 0x%" PRIx64 "\n", context_amd64->rax); 454 printf(" rcx = 0x%" PRIx64 "\n", context_amd64->rcx); 455 printf(" rdx = 0x%" PRIx64 "\n", context_amd64->rdx); 456 printf(" rbx = 0x%" PRIx64 "\n", context_amd64->rbx); 457 printf(" rsp = 0x%" PRIx64 "\n", context_amd64->rsp); 458 printf(" rbp = 0x%" PRIx64 "\n", context_amd64->rbp); 459 printf(" rsi = 0x%" PRIx64 "\n", context_amd64->rsi); 460 printf(" rdi = 0x%" PRIx64 "\n", context_amd64->rdi); 461 printf(" r8 = 0x%" PRIx64 "\n", context_amd64->r8); 462 printf(" r9 = 0x%" PRIx64 "\n", context_amd64->r9); 463 printf(" r10 = 0x%" PRIx64 "\n", context_amd64->r10); 464 printf(" r11 = 0x%" PRIx64 "\n", context_amd64->r11); 465 printf(" r12 = 0x%" PRIx64 "\n", context_amd64->r12); 466 printf(" r13 = 0x%" PRIx64 "\n", context_amd64->r13); 467 printf(" r14 = 0x%" PRIx64 "\n", context_amd64->r14); 468 printf(" r15 = 0x%" PRIx64 "\n", context_amd64->r15); 469 printf(" rip = 0x%" PRIx64 "\n", context_amd64->rip); 470 // TODO: print xmm, vector, debug registers 471 printf("\n"); 472 break; 473 } 474 475 case MD_CONTEXT_SPARC: { 476 const MDRawContextSPARC* context_sparc = GetContextSPARC(); 477 printf("MDRawContextSPARC\n"); 478 printf(" context_flags = 0x%x\n", 479 context_sparc->context_flags); 480 for (unsigned int g_r_index = 0; 481 g_r_index < MD_CONTEXT_SPARC_GPR_COUNT; 482 ++g_r_index) { 483 printf(" g_r[%2d] = 0x%" PRIx64 "\n", 484 g_r_index, context_sparc->g_r[g_r_index]); 485 } 486 printf(" ccr = 0x%" PRIx64 "\n", context_sparc->ccr); 487 printf(" pc = 0x%" PRIx64 "\n", context_sparc->pc); 488 printf(" npc = 0x%" PRIx64 "\n", context_sparc->npc); 489 printf(" y = 0x%" PRIx64 "\n", context_sparc->y); 490 printf(" asi = 0x%" PRIx64 "\n", context_sparc->asi); 491 printf(" fprs = 0x%" PRIx64 "\n", context_sparc->fprs); 492 493 for (unsigned int fpr_index = 0; 494 fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; 495 ++fpr_index) { 496 printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", 497 fpr_index, context_sparc->float_save.regs[fpr_index]); 498 } 499 printf(" float_save.filler = 0x%" PRIx64 "\n", 500 context_sparc->float_save.filler); 501 printf(" float_save.fsr = 0x%" PRIx64 "\n", 502 context_sparc->float_save.fsr); 503 break; 504 } 505 506 case MD_CONTEXT_ARM: { 507 const MDRawContextARM* context_arm = GetContextARM(); 508 printf("MDRawContextARM\n"); 509 printf(" context_flags = 0x%x\n", 510 context_arm->context_flags); 511 for (unsigned int ireg_index = 0; 512 ireg_index < MD_CONTEXT_ARM_GPR_COUNT; 513 ++ireg_index) { 514 printf(" iregs[%2d] = 0x%x\n", 515 ireg_index, context_arm->iregs[ireg_index]); 516 } 517 printf(" cpsr = 0x%x\n", context_arm->cpsr); 518 printf(" float_save.fpscr = 0x%" PRIx64 "\n", 519 context_arm->float_save.fpscr); 520 for (unsigned int fpr_index = 0; 521 fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; 522 ++fpr_index) { 523 printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", 524 fpr_index, context_arm->float_save.regs[fpr_index]); 525 } 526 for (unsigned int fpe_index = 0; 527 fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; 528 ++fpe_index) { 529 printf(" float_save.extra[%2d] = 0x%" PRIx32 "\n", 530 fpe_index, context_arm->float_save.extra[fpe_index]); 531 } 532 533 break; 534 } 535 536 case MD_CONTEXT_ARM64: { 537 const MDRawContextARM64* context_arm64 = GetContextARM64(); 538 printf("MDRawContextARM64\n"); 539 printf(" context_flags = 0x%" PRIx64 "\n", 540 context_arm64->context_flags); 541 for (unsigned int ireg_index = 0; 542 ireg_index < MD_CONTEXT_ARM64_GPR_COUNT; 543 ++ireg_index) { 544 printf(" iregs[%2d] = 0x%" PRIx64 "\n", 545 ireg_index, context_arm64->iregs[ireg_index]); 546 } 547 printf(" cpsr = 0x%x\n", context_arm64->cpsr); 548 printf(" float_save.fpsr = 0x%x\n", context_arm64->float_save.fpsr); 549 printf(" float_save.fpcr = 0x%x\n", context_arm64->float_save.fpcr); 550 551 for (unsigned int freg_index = 0; 552 freg_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT; 553 ++freg_index) { 554 uint128_struct fp_value = context_arm64->float_save.regs[freg_index]; 555 printf(" float_save.regs[%2d] = 0x%" PRIx64 "%" PRIx64 "\n", 556 freg_index, fp_value.high, fp_value.low); 557 } 558 break; 559 } 560 561 case MD_CONTEXT_MIPS: { 562 const MDRawContextMIPS* context_mips = GetContextMIPS(); 563 printf("MDRawContextMIPS\n"); 564 printf(" context_flags = 0x%x\n", 565 context_mips->context_flags); 566 for (int ireg_index = 0; 567 ireg_index < MD_CONTEXT_MIPS_GPR_COUNT; 568 ++ireg_index) { 569 printf(" iregs[%2d] = 0x%" PRIx64 "\n", 570 ireg_index, context_mips->iregs[ireg_index]); 571 } 572 printf(" mdhi = 0x%" PRIx64 "\n", 573 context_mips->mdhi); 574 printf(" mdlo = 0x%" PRIx64 "\n", 575 context_mips->mdhi); 576 for (int dsp_index = 0; 577 dsp_index < MD_CONTEXT_MIPS_DSP_COUNT; 578 ++dsp_index) { 579 printf(" hi[%1d] = 0x%" PRIx32 "\n", 580 dsp_index, context_mips->hi[dsp_index]); 581 printf(" lo[%1d] = 0x%" PRIx32 "\n", 582 dsp_index, context_mips->lo[dsp_index]); 583 } 584 printf(" dsp_control = 0x%" PRIx32 "\n", 585 context_mips->dsp_control); 586 printf(" epc = 0x%" PRIx64 "\n", 587 context_mips->epc); 588 printf(" badvaddr = 0x%" PRIx64 "\n", 589 context_mips->badvaddr); 590 printf(" status = 0x%" PRIx32 "\n", 591 context_mips->status); 592 printf(" cause = 0x%" PRIx32 "\n", 593 context_mips->cause); 594 595 for (int fpr_index = 0; 596 fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; 597 ++fpr_index) { 598 printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", 599 fpr_index, context_mips->float_save.regs[fpr_index]); 600 } 601 printf(" float_save.fpcsr = 0x%" PRIx32 "\n", 602 context_mips->float_save.fpcsr); 603 printf(" float_save.fir = 0x%" PRIx32 "\n", 604 context_mips->float_save.fir); 605 break; 606 } 607 608 default: { 609 break; 610 } 611 } 612 } 613 614 } // namespace google_breakpad 615