Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(338)

Unified Diff: src/processor/dump_context.cc

Issue 4744002: Support the CrashpadInfo stream. Also: Decode x86 FPU state. Base URL: http://google-breakpad.googlecode.com/svn/trunk/
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/google_breakpad/processor/minidump.h ('k') | src/processor/minidump.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/processor/dump_context.cc
===================================================================
--- src/processor/dump_context.cc (revision 1435)
+++ src/processor/dump_context.cc (working copy)
@@ -35,6 +35,7 @@
#include <assert.h>
#include <stdio.h>
+#include <string.h>
#ifdef _WIN32
#include <io.h>
@@ -47,6 +48,163 @@
#include "processor/logging.h"
+static double X87DoubleExtendedToDouble(const uint8_t ldr[10]) {
+#if 1
+ bool sign = ldr[9] & 0x80;
+ uint16_t biased_exponent = ((ldr[9] & 0x7f) << 8) | ldr[8];
+// bool integer_bit = ldr[7] & 0x80;
+ uint64_t fraction =
+ ((static_cast<uint64_t>(ldr[7]) & 0x7f) << 56) |
+ (static_cast<uint64_t>(ldr[6]) << 48) |
+ (static_cast<uint64_t>(ldr[5]) << 40) |
+ (static_cast<uint64_t>(ldr[4]) << 32) |
+ (static_cast<uint32_t>(ldr[3]) << 24) |
+ (ldr[2] << 16) |
+ (ldr[1] << 8) |
+ ldr[0];
+
+// This isn't 100% right. It loses the lowest bits in the significant that
+// might distinguish between nan and infinity. It truncates but it probably
+// should round to nearest. And the handling of the integer bit for denormals
+// is probably wrong.
+ int unbiased_exponent = biased_exponent - 16383;
+ int d_exponent;
+ if (biased_exponent == 0) {
+ d_exponent = 0;
+ } else if (unbiased_exponent < -1022 || unbiased_exponent > 1023) {
+ d_exponent = 2047;
+ } else {
+ d_exponent = unbiased_exponent + 1023;
+ }
+
+ uint64_t as_double = ((sign ? 1ull : 0ull) << 63) |
+ (static_cast<uint64_t>(d_exponent & 0x7ff) << 52) |
+ (fraction >> 11);
+
+ double d;
+ memcpy(&d, &as_double, sizeof(d));
+#else
+// x86/x86_64 only! doesn't seem to get inf right!
+ uint8_t ldr2[16];
+ memcpy(&ldr2, ldr, 10);
+ memset(&ldr2[10], 0, 6);
+ long double ld;
+ memcpy(&ld, &ldr2, 16);
+ double d = ld;
+#endif
+
+ return d;
+}
+
+static std::string X87DoubleExtendedToString(const uint8_t ldr[10]) {
+// x86/x86_64 only!
+ uint8_t ldr2[16];
+ memcpy(&ldr2, ldr, 10);
+ long double ld;
+ memcpy(&ld, ldr, 10);
+ char result[256];
+ snprintf(result, sizeof(result), "%Le", ld);
+ return result;
+}
+
+struct FxsaveArea {
+ typedef uint8_t X87Register[10];
+
+ union X87OrMMXRegister {
+ struct {
+ X87Register st;
+ uint8_t st_reserved[6];
+ };
+ struct {
+ uint8_t mm_value[8];
+ uint8_t mm_reserved[8];
+ };
+ };
+
+ typedef uint8_t XMMRegister[16];
+
+ uint16_t fcw; // FPU control word
+ uint16_t fsw; // FPU status word
+ uint8_t ftw; // abridged FPU tag word
+ uint8_t reserved_1;
+ uint16_t fop; // FPU opcode
+ uint32_t fpu_ip; // FPU instruction pointer offset
+ uint16_t fpu_cs; // FPU instruction pointer segment selector
+ uint16_t reserved_2;
+ uint32_t fpu_dp; // FPU data pointer offset
+ uint16_t fpu_ds; // FPU data pointer segment selector
+ uint16_t reserved_3;
+ uint32_t mxcsr; // multimedia extensions status and control register
+ uint32_t mxcsr_mask; // valid bits in mxcsr
+ X87OrMMXRegister st_mm[8];
+ XMMRegister xmm[16];
+ uint8_t reserved_4[48];
+ uint8_t available[48];
+};
+
+void PrintFxsaveArea(const FxsaveArea* fxsave) {
+ printf(" fxsave.fcw = 0x%x\n", fxsave->fcw);
+ printf(" fxsave.fsw = 0x%x\n", fxsave->fsw);
+ printf(" fxsave.ftw = 0x%x\n", fxsave->ftw);
+ printf(" fxsave.reserved_1 = 0x%x\n", fxsave->reserved_1);
+ printf(" fxsave.fop = 0x%x\n", fxsave->fop);
+ printf(" fxsave.fpu_ip = 0x%x\n", fxsave->fpu_ip);
+ printf(" fxsave.fpu_cs = 0x%x\n", fxsave->fpu_cs);
+ printf(" fxsave.reserved_2 = 0x%x\n", fxsave->reserved_2);
+ printf(" fxsave.fpu_dp = 0x%x\n", fxsave->fpu_dp);
+ printf(" fxsave.fpu_ds = 0x%x\n", fxsave->fpu_ds);
+ printf(" fxsave.reserved_3 = 0x%x\n", fxsave->reserved_3);
+ printf(" fxsave.mxcsr = 0x%x\n", fxsave->mxcsr);
+ printf(" fxsave.mxcsr_mask = 0x%x\n", fxsave->mxcsr_mask);
+
+ int stack_top = (fxsave->fsw >> 11) & 0x7;
+ for (unsigned int st_index = 0; st_index < 8; ++st_index) {
+ printf(" fxsave.st_mm[%u] = 0x", st_index);
+ for (int i = 0; i < 10; ++i) {
+ printf("%02x", fxsave->st_mm[st_index].st[i]);
+ }
+ printf(" ");
+ for (int i = 0; i < 6; ++i) {
+ printf("%02x", fxsave->st_mm[st_index].st_reserved[i]);
+ }
+
+ std::string fs = X87DoubleExtendedToString(&fxsave->st_mm[st_index].st[0]);
+
+ unsigned int r_index = (st_index + stack_top) % 8;
+ unsigned int tag = (fxsave->ftw >> r_index) & 0x1;
+ const char* tag_name = tag ? "valid" : "empty";
+
+ printf(" (%s %s)\n", tag_name, fs.c_str());
+ }
+
+ for (unsigned int xmm_index = 0; xmm_index < 16; ++xmm_index) {
+ printf(" fxsave.xmm[%2d] = 0x", xmm_index);
+ for (int i = 0; i < 16; ++i) {
+ printf("%02x", fxsave->xmm[xmm_index][i]);
+ }
+
+// Nobody knows what's really in the register. If it's a double that was put
+// there by, for example, movsd, print it.
+double d;
+memcpy(&d, &fxsave->xmm[xmm_index], 8);
+printf( " (%e)", d);
+
+ printf("\n");
+ }
+
+ printf(" fxsave.reserved_4 = 0x");
+ for (int i = 0; i < 48; ++i) {
+ printf("%02x", fxsave->reserved_4[i]);
+ }
+ printf("\n");
+
+ printf(" fxsave.available = 0x");
+ for (int i = 0; i < 48; ++i) {
+ printf("%02x", fxsave->available[i]);
+ }
+ printf("\n");
+}
+
namespace google_breakpad {
DumpContext::DumpContext() : context_(),
@@ -266,6 +424,7 @@
context_.base = NULL;
}
+
void DumpContext::Print() {
if (!valid_) {
BPLOG(ERROR) << "DumpContext cannot print invalid data";
@@ -276,63 +435,88 @@
case MD_CONTEXT_X86: {
const MDRawContextX86* context_x86 = GetContextX86();
printf("MDRawContextX86\n");
- printf(" context_flags = 0x%x\n",
+ printf(" context_flags = 0x%x\n",
context_x86->context_flags);
- printf(" dr0 = 0x%x\n", context_x86->dr0);
- printf(" dr1 = 0x%x\n", context_x86->dr1);
- printf(" dr2 = 0x%x\n", context_x86->dr2);
- printf(" dr3 = 0x%x\n", context_x86->dr3);
- printf(" dr6 = 0x%x\n", context_x86->dr6);
- printf(" dr7 = 0x%x\n", context_x86->dr7);
- printf(" float_save.control_word = 0x%x\n",
+ printf(" dr0 = 0x%x\n", context_x86->dr0);
+ printf(" dr1 = 0x%x\n", context_x86->dr1);
+ printf(" dr2 = 0x%x\n", context_x86->dr2);
+ printf(" dr3 = 0x%x\n", context_x86->dr3);
+ printf(" dr6 = 0x%x\n", context_x86->dr6);
+ printf(" dr7 = 0x%x\n", context_x86->dr7);
+ printf(" float_save.control_word = 0x%x\n",
context_x86->float_save.control_word);
- printf(" float_save.status_word = 0x%x\n",
+ printf(" float_save.status_word = 0x%x\n",
context_x86->float_save.status_word);
- printf(" float_save.tag_word = 0x%x\n",
+ printf(" float_save.tag_word = 0x%x\n",
context_x86->float_save.tag_word);
- printf(" float_save.error_offset = 0x%x\n",
+ printf(" float_save.error_offset = 0x%x\n",
context_x86->float_save.error_offset);
- printf(" float_save.error_selector = 0x%x\n",
+ printf(" float_save.error_selector = 0x%x\n",
context_x86->float_save.error_selector);
- printf(" float_save.data_offset = 0x%x\n",
+ printf(" float_save.data_offset = 0x%x\n",
context_x86->float_save.data_offset);
- printf(" float_save.data_selector = 0x%x\n",
+ printf(" float_save.data_selector = 0x%x\n",
context_x86->float_save.data_selector);
- printf(" float_save.register_area[%2d] = 0x",
- MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE);
- for (unsigned int register_index = 0;
- register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE;
- ++register_index) {
- printf("%02x", context_x86->float_save.register_area[register_index]);
+
+ int stack_top = (context_x86->float_save.status_word >> 11) & 0x7;
+ for (unsigned int st_index = 0; st_index < 8; ++st_index) {
+ printf(" float_save_area.st[%d] = 0x", st_index);
+ const uint8_t* x87_register =
+ &context_x86->float_save.register_area[st_index * 10];
+ for (unsigned int byte_index = 0; byte_index < 10; ++byte_index) {
+ printf("%02x", x87_register[byte_index]);
+ }
+
+ std::string fs = X87DoubleExtendedToString(x87_register);
+
+ unsigned int r_index = (st_index + stack_top) % 8;
+ unsigned int tag =
+ (context_x86->float_save.tag_word >> (2 * r_index)) & 0x3;
+ const char* tag_name;
+ switch (tag) {
+ case 0:
+ tag_name = "valid";
+ break;
+ case 1:
+ tag_name = "zero ";
+ break;
+ case 2:
+ tag_name = "specl";
+ break;
+ case 3:
+ tag_name = "empty";
+ break;
+ default:
+ tag_name = "unkwn";
+ break;
+ }
+
+ printf(" (%s %s)\n", tag_name, fs.c_str());
}
- printf("\n");
- printf(" float_save.cr0_npx_state = 0x%x\n",
+ printf(" float_save.cr0_npx_state = 0x%x\n",
context_x86->float_save.cr0_npx_state);
- printf(" gs = 0x%x\n", context_x86->gs);
- printf(" fs = 0x%x\n", context_x86->fs);
- printf(" es = 0x%x\n", context_x86->es);
- printf(" ds = 0x%x\n", context_x86->ds);
- printf(" edi = 0x%x\n", context_x86->edi);
- printf(" esi = 0x%x\n", context_x86->esi);
- printf(" ebx = 0x%x\n", context_x86->ebx);
- printf(" edx = 0x%x\n", context_x86->edx);
- printf(" ecx = 0x%x\n", context_x86->ecx);
- printf(" eax = 0x%x\n", context_x86->eax);
- printf(" ebp = 0x%x\n", context_x86->ebp);
- printf(" eip = 0x%x\n", context_x86->eip);
- printf(" cs = 0x%x\n", context_x86->cs);
- printf(" eflags = 0x%x\n", context_x86->eflags);
- printf(" esp = 0x%x\n", context_x86->esp);
- printf(" ss = 0x%x\n", context_x86->ss);
- printf(" extended_registers[%3d] = 0x",
- MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE);
- for (unsigned int register_index = 0;
- register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE;
- ++register_index) {
- printf("%02x", context_x86->extended_registers[register_index]);
- }
- printf("\n\n");
+ printf(" gs = 0x%x\n", context_x86->gs);
+ printf(" fs = 0x%x\n", context_x86->fs);
+ printf(" es = 0x%x\n", context_x86->es);
+ printf(" ds = 0x%x\n", context_x86->ds);
+ printf(" edi = 0x%x\n", context_x86->edi);
+ printf(" esi = 0x%x\n", context_x86->esi);
+ printf(" ebx = 0x%x\n", context_x86->ebx);
+ printf(" edx = 0x%x\n", context_x86->edx);
+ printf(" ecx = 0x%x\n", context_x86->ecx);
+ printf(" eax = 0x%x\n", context_x86->eax);
+ printf(" ebp = 0x%x\n", context_x86->ebp);
+ printf(" eip = 0x%x\n", context_x86->eip);
+ printf(" cs = 0x%x\n", context_x86->cs);
+ printf(" eflags = 0x%x\n", context_x86->eflags);
+ printf(" esp = 0x%x\n", context_x86->esp);
+ printf(" ss = 0x%x\n", context_x86->ss);
+ PrintFxsaveArea(reinterpret_cast<const FxsaveArea*>(
+ &context_x86->extended_registers));
+
+ printf("\n");
+
break;
}
@@ -467,7 +651,12 @@
printf(" r14 = 0x%" PRIx64 "\n", context_amd64->r14);
printf(" r15 = 0x%" PRIx64 "\n", context_amd64->r15);
printf(" rip = 0x%" PRIx64 "\n", context_amd64->rip);
- // TODO: print xmm, vector, debug registers
+
+ PrintFxsaveArea(
+ reinterpret_cast<const FxsaveArea*>(&context_amd64->flt_save));
+
+ // TODO: print vector and debug registers
+
printf("\n");
break;
}
@@ -532,7 +721,7 @@
break;
}
-
+
case MD_CONTEXT_ARM64: {
const MDRawContextARM64* context_arm64 = GetContextARM64();
printf("MDRawContextARM64\n");
« no previous file with comments | « src/google_breakpad/processor/minidump.h ('k') | src/processor/minidump.cc » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld 1004:630ec63f810e-tainted