Home | History | Annotate | Download | only in processor
      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