• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
DumpContext()52  DumpContext::DumpContext() : context_(),
53                               context_flags_(0) { }
54  
~DumpContext()55  DumpContext::~DumpContext() {
56    FreeContext();
57  }
58  
GetContextCPU() const59  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  
GetContextFlags() const69  uint32_t DumpContext::GetContextFlags() const {
70    return context_flags_;
71  }
72  
GetContextX86() const73  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  
GetContextPPC() const82  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  
GetContextPPC64() const91  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  
GetContextAMD64() const100  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  
GetContextSPARC() const109  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  
GetContextARM() const118  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  
GetContextARM64() const127  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  
GetContextMIPS() const136  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  
GetInstructionPointer(uint64_t * ip) const145  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  
SetContextFlags(uint32_t context_flags)188  void DumpContext::SetContextFlags(uint32_t context_flags) {
189    context_flags_ = context_flags;
190  }
191  
SetContextX86(MDRawContextX86 * x86)192  void DumpContext::SetContextX86(MDRawContextX86* x86) {
193    context_.x86 = x86;
194  }
195  
SetContextPPC(MDRawContextPPC * ppc)196  void DumpContext::SetContextPPC(MDRawContextPPC* ppc) {
197    context_.ppc = ppc;
198  }
199  
SetContextPPC64(MDRawContextPPC64 * ppc64)200  void DumpContext::SetContextPPC64(MDRawContextPPC64* ppc64) {
201    context_.ppc64 = ppc64;
202  }
203  
SetContextAMD64(MDRawContextAMD64 * amd64)204  void DumpContext::SetContextAMD64(MDRawContextAMD64* amd64) {
205    context_.amd64 = amd64;
206  }
207  
SetContextSPARC(MDRawContextSPARC * ctx_sparc)208  void DumpContext::SetContextSPARC(MDRawContextSPARC* ctx_sparc) {
209    context_.ctx_sparc = ctx_sparc;
210  }
211  
SetContextARM(MDRawContextARM * arm)212  void DumpContext::SetContextARM(MDRawContextARM* arm) {
213    context_.arm = arm;
214  }
215  
SetContextARM64(MDRawContextARM64 * arm64)216  void DumpContext::SetContextARM64(MDRawContextARM64* arm64) {
217    context_.arm64 = arm64;
218  }
219  
SetContextMIPS(MDRawContextMIPS * ctx_mips)220  void DumpContext::SetContextMIPS(MDRawContextMIPS* ctx_mips) {
221    context_.ctx_mips = ctx_mips;
222  }
223  
FreeContext()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  
Print()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