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