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