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