xref: /aosp_15_r20/external/google-breakpad/src/processor/dump_context.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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 
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       (GetContextCPU() != MD_CONTEXT_MIPS64)) {
139     BPLOG(ERROR) << "DumpContext cannot get MIPS context";
140     return NULL;
141   }
142 
143   return context_.ctx_mips;
144 }
145 
GetContextRISCV() const146 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 
GetContextRISCV64() const155 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 
GetInstructionPointer(uint64_t * ip) const164 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 
GetStackPointer(uint64_t * sp) const214 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 
SetContextFlags(uint32_t context_flags)264 void DumpContext::SetContextFlags(uint32_t context_flags) {
265   context_flags_ = context_flags;
266 }
267 
SetContextX86(MDRawContextX86 * x86)268 void DumpContext::SetContextX86(MDRawContextX86* x86) {
269   context_.x86 = x86;
270 }
271 
SetContextPPC(MDRawContextPPC * ppc)272 void DumpContext::SetContextPPC(MDRawContextPPC* ppc) {
273   context_.ppc = ppc;
274 }
275 
SetContextPPC64(MDRawContextPPC64 * ppc64)276 void DumpContext::SetContextPPC64(MDRawContextPPC64* ppc64) {
277   context_.ppc64 = ppc64;
278 }
279 
SetContextAMD64(MDRawContextAMD64 * amd64)280 void DumpContext::SetContextAMD64(MDRawContextAMD64* amd64) {
281   context_.amd64 = amd64;
282 }
283 
SetContextSPARC(MDRawContextSPARC * ctx_sparc)284 void DumpContext::SetContextSPARC(MDRawContextSPARC* ctx_sparc) {
285   context_.ctx_sparc = ctx_sparc;
286 }
287 
SetContextARM(MDRawContextARM * arm)288 void DumpContext::SetContextARM(MDRawContextARM* arm) {
289   context_.arm = arm;
290 }
291 
SetContextARM64(MDRawContextARM64 * arm64)292 void DumpContext::SetContextARM64(MDRawContextARM64* arm64) {
293   context_.arm64 = arm64;
294 }
295 
SetContextMIPS(MDRawContextMIPS * ctx_mips)296 void DumpContext::SetContextMIPS(MDRawContextMIPS* ctx_mips) {
297   context_.ctx_mips = ctx_mips;
298 }
299 
SetContextRISCV(MDRawContextRISCV * riscv)300 void DumpContext::SetContextRISCV(MDRawContextRISCV* riscv) {
301   context_.riscv = riscv;
302 }
303 
SetContextRISCV64(MDRawContextRISCV64 * riscv64)304 void DumpContext::SetContextRISCV64(MDRawContextRISCV64* riscv64) {
305   context_.riscv64 = riscv64;
306 }
307 
FreeContext()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 
Print()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
882