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