From 54c2560a82ec0a1c48c087c78b802e72a5459c53 Mon Sep 17 00:00:00 2001 From: "mmandlis@chromium.org" Date: Mon, 8 Sep 2014 19:10:42 +0000 Subject: Refactoring in preparation for microdump processing git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1370 4c0a9323-5329-0410-9bdc-e9ce6186880e --- .../basic_source_line_resolver_unittest.cc | 4 + src/processor/cfi_frame_info_unittest.cc | 1 + src/processor/dump_context.cc | 605 +++++++++++++++++++++ src/processor/dump_object.cc | 39 ++ .../fast_source_line_resolver_unittest.cc | 4 + src/processor/minidump.cc | 570 +------------------ src/processor/minidump_processor_unittest.cc | 4 +- src/processor/postfix_evaluator_unittest.cc | 4 + src/processor/stackwalker.cc | 4 +- src/processor/stackwalker_selftest.cc | 17 +- src/processor/stackwalker_unittest_utils.h | 4 + 11 files changed, 699 insertions(+), 557 deletions(-) create mode 100644 src/processor/dump_context.cc create mode 100644 src/processor/dump_object.cc (limited to 'src/processor') diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processor/basic_source_line_resolver_unittest.cc index fcf3fa48..7d4cd5c5 100644 --- a/src/processor/basic_source_line_resolver_unittest.cc +++ b/src/processor/basic_source_line_resolver_unittest.cc @@ -27,6 +27,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include #include #include @@ -102,6 +103,9 @@ class MockMemoryRegion: public MemoryRegion { *value = address; return true; } + void Print() const { + assert(false); + } }; // Verify that, for every association in ACTUAL, EXPECTED has the same diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_info_unittest.cc index eabce113..542b2849 100644 --- a/src/processor/cfi_frame_info_unittest.cc +++ b/src/processor/cfi_frame_info_unittest.cc @@ -60,6 +60,7 @@ class MockMemoryRegion: public MemoryRegion { MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint16_t *)); MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint32_t *)); MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint64_t *)); + MOCK_CONST_METHOD0(Print, void()); }; // Handy definitions for all tests. diff --git a/src/processor/dump_context.cc b/src/processor/dump_context.cc new file mode 100644 index 00000000..54bf231e --- /dev/null +++ b/src/processor/dump_context.cc @@ -0,0 +1,605 @@ +// Copyright (c) 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// dump_context.cc: A (mini/micro)dump context. +// +// See dump_context.h for documentation. + +#include "google_breakpad/processor/dump_context.h" + +#include +#include + +#include "processor/logging.h" + +namespace google_breakpad { + +DumpContext::DumpContext() : context_(), + context_flags_(0) { } + +DumpContext::~DumpContext() { + FreeContext(); +} + +uint32_t DumpContext::GetContextCPU() const { + if (!valid_) { + // Don't log a message, GetContextCPU can be legitimately called with + // valid_ false by FreeContext, which is called by Read. + return 0; + } + + return context_flags_ & MD_CONTEXT_CPU_MASK; +} + +uint32_t DumpContext::GetContextFlags() const { + return context_flags_; +} + +const MDRawContextX86* DumpContext::GetContextX86() const { + if (GetContextCPU() != MD_CONTEXT_X86) { + BPLOG(ERROR) << "DumpContext cannot get x86 context"; + return NULL; + } + + return context_.x86; +} + +const MDRawContextPPC* DumpContext::GetContextPPC() const { + if (GetContextCPU() != MD_CONTEXT_PPC) { + BPLOG(ERROR) << "DumpContext cannot get ppc context"; + return NULL; + } + + return context_.ppc; +} + +const MDRawContextPPC64* DumpContext::GetContextPPC64() const { + if (GetContextCPU() != MD_CONTEXT_PPC64) { + BPLOG(ERROR) << "DumpContext cannot get ppc64 context"; + return NULL; + } + + return context_.ppc64; +} + +const MDRawContextAMD64* DumpContext::GetContextAMD64() const { + if (GetContextCPU() != MD_CONTEXT_AMD64) { + BPLOG(ERROR) << "DumpContext cannot get amd64 context"; + return NULL; + } + + return context_.amd64; +} + +const MDRawContextSPARC* DumpContext::GetContextSPARC() const { + if (GetContextCPU() != MD_CONTEXT_SPARC) { + BPLOG(ERROR) << "DumpContext cannot get sparc context"; + return NULL; + } + + return context_.ctx_sparc; +} + +const MDRawContextARM* DumpContext::GetContextARM() const { + if (GetContextCPU() != MD_CONTEXT_ARM) { + BPLOG(ERROR) << "DumpContext cannot get arm context"; + return NULL; + } + + return context_.arm; +} + +const MDRawContextARM64* DumpContext::GetContextARM64() const { + if (GetContextCPU() != MD_CONTEXT_ARM64) { + BPLOG(ERROR) << "DumpContext cannot get arm64 context"; + return NULL; + } + + return context_.arm64; +} + +const MDRawContextMIPS* DumpContext::GetContextMIPS() const { + if (GetContextCPU() != MD_CONTEXT_MIPS) { + BPLOG(ERROR) << "DumpContext cannot get MIPS context"; + return NULL; + } + + return context_.ctx_mips; +} + +bool DumpContext::GetInstructionPointer(uint64_t* ip) const { + BPLOG_IF(ERROR, !ip) << "DumpContext::GetInstructionPointer requires |ip|"; + assert(ip); + *ip = 0; + + if (!valid_) { + BPLOG(ERROR) << "Invalid DumpContext for GetInstructionPointer"; + return false; + } + + switch (GetContextCPU()) { + case MD_CONTEXT_AMD64: + *ip = GetContextAMD64()->rip; + break; + case MD_CONTEXT_ARM: + *ip = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_PC]; + break; + case MD_CONTEXT_ARM64: + *ip = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_PC]; + break; + case MD_CONTEXT_PPC: + *ip = GetContextPPC()->srr0; + break; + case MD_CONTEXT_PPC64: + *ip = GetContextPPC64()->srr0; + break; + case MD_CONTEXT_SPARC: + *ip = GetContextSPARC()->pc; + break; + case MD_CONTEXT_X86: + *ip = GetContextX86()->eip; + break; + case MD_CONTEXT_MIPS: + *ip = GetContextMIPS()->epc; + break; + default: + // This should never happen. + BPLOG(ERROR) << "Unknown CPU architecture in GetInstructionPointer"; + return false; + } + return true; +} + +void DumpContext::SetContextFlags(uint32_t context_flags) { + context_flags_ = context_flags; +} + +void DumpContext::SetContextX86(MDRawContextX86* x86) { + context_.x86 = x86; +} + +void DumpContext::SetContextPPC(MDRawContextPPC* ppc) { + context_.ppc = ppc; +} + +void DumpContext::SetContextPPC64(MDRawContextPPC64* ppc64) { + context_.ppc64 = ppc64; +} + +void DumpContext::SetContextAMD64(MDRawContextAMD64* amd64) { + context_.amd64 = amd64; +} + +void DumpContext::SetContextSPARC(MDRawContextSPARC* ctx_sparc) { + context_.ctx_sparc = ctx_sparc; +} + +void DumpContext::SetContextARM(MDRawContextARM* arm) { + context_.arm = arm; +} + +void DumpContext::SetContextARM64(MDRawContextARM64* arm64) { + context_.arm64 = arm64; +} + +void DumpContext::SetContextMIPS(MDRawContextMIPS* ctx_mips) { + context_.ctx_mips = ctx_mips; +} + +void DumpContext::FreeContext() { + switch (GetContextCPU()) { + case MD_CONTEXT_X86: + delete context_.x86; + break; + + case MD_CONTEXT_PPC: + delete context_.ppc; + break; + + case MD_CONTEXT_PPC64: + delete context_.ppc64; + break; + + case MD_CONTEXT_AMD64: + delete context_.amd64; + break; + + case MD_CONTEXT_SPARC: + delete context_.ctx_sparc; + break; + + case MD_CONTEXT_ARM: + delete context_.arm; + break; + + case MD_CONTEXT_ARM64: + delete context_.arm64; + break; + + case MD_CONTEXT_MIPS: + delete context_.ctx_mips; + break; + + default: + // There is no context record (valid_ is false) or there's a + // context record for an unknown CPU (shouldn't happen, only known + // records are stored by Read). + break; + } + + context_flags_ = 0; + context_.base = NULL; +} + +void DumpContext::Print() { + if (!valid_) { + BPLOG(ERROR) << "DumpContext cannot print invalid data"; + return; + } + + switch (GetContextCPU()) { + case MD_CONTEXT_X86: { + const MDRawContextX86* context_x86 = GetContextX86(); + printf("MDRawContextX86\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", + context_x86->float_save.control_word); + printf(" float_save.status_word = 0x%x\n", + context_x86->float_save.status_word); + printf(" float_save.tag_word = 0x%x\n", + context_x86->float_save.tag_word); + printf(" float_save.error_offset = 0x%x\n", + context_x86->float_save.error_offset); + printf(" float_save.error_selector = 0x%x\n", + context_x86->float_save.error_selector); + printf(" float_save.data_offset = 0x%x\n", + context_x86->float_save.data_offset); + 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]); + } + printf("\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"); + + break; + } + + case MD_CONTEXT_PPC: { + const MDRawContextPPC* context_ppc = GetContextPPC(); + printf("MDRawContextPPC\n"); + printf(" context_flags = 0x%x\n", + context_ppc->context_flags); + printf(" srr0 = 0x%x\n", context_ppc->srr0); + printf(" srr1 = 0x%x\n", context_ppc->srr1); + for (unsigned int gpr_index = 0; + gpr_index < MD_CONTEXT_PPC_GPR_COUNT; + ++gpr_index) { + printf(" gpr[%2d] = 0x%x\n", + gpr_index, context_ppc->gpr[gpr_index]); + } + printf(" cr = 0x%x\n", context_ppc->cr); + printf(" xer = 0x%x\n", context_ppc->xer); + printf(" lr = 0x%x\n", context_ppc->lr); + printf(" ctr = 0x%x\n", context_ppc->ctr); + printf(" mq = 0x%x\n", context_ppc->mq); + printf(" vrsave = 0x%x\n", context_ppc->vrsave); + for (unsigned int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; + ++fpr_index) { + printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", + fpr_index, context_ppc->float_save.fpregs[fpr_index]); + } + printf(" float_save.fpscr = 0x%x\n", + context_ppc->float_save.fpscr); + // TODO(mmentovai): print the 128-bit quantities in + // context_ppc->vector_save. This isn't done yet because printf + // doesn't support 128-bit quantities, and printing them using + // PRIx64 as two 64-bit quantities requires knowledge of the CPU's + // byte ordering. + printf(" vector_save.save_vrvalid = 0x%x\n", + context_ppc->vector_save.save_vrvalid); + printf("\n"); + + break; + } + + case MD_CONTEXT_PPC64: { + const MDRawContextPPC64* context_ppc64 = GetContextPPC64(); + printf("MDRawContextPPC64\n"); + printf(" context_flags = 0x%" PRIx64 "\n", + context_ppc64->context_flags); + printf(" srr0 = 0x%" PRIx64 "\n", + context_ppc64->srr0); + printf(" srr1 = 0x%" PRIx64 "\n", + context_ppc64->srr1); + for (unsigned int gpr_index = 0; + gpr_index < MD_CONTEXT_PPC64_GPR_COUNT; + ++gpr_index) { + printf(" gpr[%2d] = 0x%" PRIx64 "\n", + gpr_index, context_ppc64->gpr[gpr_index]); + } + printf(" cr = 0x%" PRIx64 "\n", context_ppc64->cr); + printf(" xer = 0x%" PRIx64 "\n", + context_ppc64->xer); + printf(" lr = 0x%" PRIx64 "\n", context_ppc64->lr); + printf(" ctr = 0x%" PRIx64 "\n", + context_ppc64->ctr); + printf(" vrsave = 0x%" PRIx64 "\n", + context_ppc64->vrsave); + for (unsigned int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; + ++fpr_index) { + printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", + fpr_index, context_ppc64->float_save.fpregs[fpr_index]); + } + printf(" float_save.fpscr = 0x%x\n", + context_ppc64->float_save.fpscr); + // TODO(mmentovai): print the 128-bit quantities in + // context_ppc64->vector_save. This isn't done yet because printf + // doesn't support 128-bit quantities, and printing them using + // PRIx64 as two 64-bit quantities requires knowledge of the CPU's + // byte ordering. + printf(" vector_save.save_vrvalid = 0x%x\n", + context_ppc64->vector_save.save_vrvalid); + printf("\n"); + + break; + } + + case MD_CONTEXT_AMD64: { + const MDRawContextAMD64* context_amd64 = GetContextAMD64(); + printf("MDRawContextAMD64\n"); + printf(" p1_home = 0x%" PRIx64 "\n", + context_amd64->p1_home); + printf(" p2_home = 0x%" PRIx64 "\n", + context_amd64->p2_home); + printf(" p3_home = 0x%" PRIx64 "\n", + context_amd64->p3_home); + printf(" p4_home = 0x%" PRIx64 "\n", + context_amd64->p4_home); + printf(" p5_home = 0x%" PRIx64 "\n", + context_amd64->p5_home); + printf(" p6_home = 0x%" PRIx64 "\n", + context_amd64->p6_home); + printf(" context_flags = 0x%x\n", + context_amd64->context_flags); + printf(" mx_csr = 0x%x\n", + context_amd64->mx_csr); + printf(" cs = 0x%x\n", context_amd64->cs); + printf(" ds = 0x%x\n", context_amd64->ds); + printf(" es = 0x%x\n", context_amd64->es); + printf(" fs = 0x%x\n", context_amd64->fs); + printf(" gs = 0x%x\n", context_amd64->gs); + printf(" ss = 0x%x\n", context_amd64->ss); + printf(" eflags = 0x%x\n", context_amd64->eflags); + printf(" dr0 = 0x%" PRIx64 "\n", context_amd64->dr0); + printf(" dr1 = 0x%" PRIx64 "\n", context_amd64->dr1); + printf(" dr2 = 0x%" PRIx64 "\n", context_amd64->dr2); + printf(" dr3 = 0x%" PRIx64 "\n", context_amd64->dr3); + printf(" dr6 = 0x%" PRIx64 "\n", context_amd64->dr6); + printf(" dr7 = 0x%" PRIx64 "\n", context_amd64->dr7); + printf(" rax = 0x%" PRIx64 "\n", context_amd64->rax); + printf(" rcx = 0x%" PRIx64 "\n", context_amd64->rcx); + printf(" rdx = 0x%" PRIx64 "\n", context_amd64->rdx); + printf(" rbx = 0x%" PRIx64 "\n", context_amd64->rbx); + printf(" rsp = 0x%" PRIx64 "\n", context_amd64->rsp); + printf(" rbp = 0x%" PRIx64 "\n", context_amd64->rbp); + printf(" rsi = 0x%" PRIx64 "\n", context_amd64->rsi); + printf(" rdi = 0x%" PRIx64 "\n", context_amd64->rdi); + printf(" r8 = 0x%" PRIx64 "\n", context_amd64->r8); + printf(" r9 = 0x%" PRIx64 "\n", context_amd64->r9); + printf(" r10 = 0x%" PRIx64 "\n", context_amd64->r10); + printf(" r11 = 0x%" PRIx64 "\n", context_amd64->r11); + printf(" r12 = 0x%" PRIx64 "\n", context_amd64->r12); + printf(" r13 = 0x%" PRIx64 "\n", context_amd64->r13); + 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 + printf("\n"); + break; + } + + case MD_CONTEXT_SPARC: { + const MDRawContextSPARC* context_sparc = GetContextSPARC(); + printf("MDRawContextSPARC\n"); + printf(" context_flags = 0x%x\n", + context_sparc->context_flags); + for (unsigned int g_r_index = 0; + g_r_index < MD_CONTEXT_SPARC_GPR_COUNT; + ++g_r_index) { + printf(" g_r[%2d] = 0x%" PRIx64 "\n", + g_r_index, context_sparc->g_r[g_r_index]); + } + printf(" ccr = 0x%" PRIx64 "\n", context_sparc->ccr); + printf(" pc = 0x%" PRIx64 "\n", context_sparc->pc); + printf(" npc = 0x%" PRIx64 "\n", context_sparc->npc); + printf(" y = 0x%" PRIx64 "\n", context_sparc->y); + printf(" asi = 0x%" PRIx64 "\n", context_sparc->asi); + printf(" fprs = 0x%" PRIx64 "\n", context_sparc->fprs); + + for (unsigned int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; + ++fpr_index) { + printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", + fpr_index, context_sparc->float_save.regs[fpr_index]); + } + printf(" float_save.filler = 0x%" PRIx64 "\n", + context_sparc->float_save.filler); + printf(" float_save.fsr = 0x%" PRIx64 "\n", + context_sparc->float_save.fsr); + break; + } + + case MD_CONTEXT_ARM: { + const MDRawContextARM* context_arm = GetContextARM(); + printf("MDRawContextARM\n"); + printf(" context_flags = 0x%x\n", + context_arm->context_flags); + for (unsigned int ireg_index = 0; + ireg_index < MD_CONTEXT_ARM_GPR_COUNT; + ++ireg_index) { + printf(" iregs[%2d] = 0x%x\n", + ireg_index, context_arm->iregs[ireg_index]); + } + printf(" cpsr = 0x%x\n", context_arm->cpsr); + printf(" float_save.fpscr = 0x%" PRIx64 "\n", + context_arm->float_save.fpscr); + for (unsigned int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; + ++fpr_index) { + printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", + fpr_index, context_arm->float_save.regs[fpr_index]); + } + for (unsigned int fpe_index = 0; + fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; + ++fpe_index) { + printf(" float_save.extra[%2d] = 0x%" PRIx32 "\n", + fpe_index, context_arm->float_save.extra[fpe_index]); + } + + break; + } + + case MD_CONTEXT_ARM64: { + const MDRawContextARM64* context_arm64 = GetContextARM64(); + printf("MDRawContextARM64\n"); + printf(" context_flags = 0x%" PRIx64 "\n", + context_arm64->context_flags); + for (unsigned int ireg_index = 0; + ireg_index < MD_CONTEXT_ARM64_GPR_COUNT; + ++ireg_index) { + printf(" iregs[%2d] = 0x%" PRIx64 "\n", + ireg_index, context_arm64->iregs[ireg_index]); + } + printf(" cpsr = 0x%x\n", context_arm64->cpsr); + printf(" float_save.fpsr = 0x%x\n", context_arm64->float_save.fpsr); + printf(" float_save.fpcr = 0x%x\n", context_arm64->float_save.fpcr); + + for (unsigned int freg_index = 0; + freg_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT; + ++freg_index) { + uint128_struct fp_value = context_arm64->float_save.regs[freg_index]; + printf(" float_save.regs[%2d] = 0x%" PRIx64 "%" PRIx64 "\n", + freg_index, fp_value.high, fp_value.low); + } + break; + } + + case MD_CONTEXT_MIPS: { + const MDRawContextMIPS* context_mips = GetContextMIPS(); + printf("MDRawContextMIPS\n"); + printf(" context_flags = 0x%x\n", + context_mips->context_flags); + for (int ireg_index = 0; + ireg_index < MD_CONTEXT_MIPS_GPR_COUNT; + ++ireg_index) { + printf(" iregs[%2d] = 0x%" PRIx64 "\n", + ireg_index, context_mips->iregs[ireg_index]); + } + printf(" mdhi = 0x%" PRIx64 "\n", + context_mips->mdhi); + printf(" mdlo = 0x%" PRIx64 "\n", + context_mips->mdhi); + for (int dsp_index = 0; + dsp_index < MD_CONTEXT_MIPS_DSP_COUNT; + ++dsp_index) { + printf(" hi[%1d] = 0x%" PRIx32 "\n", + dsp_index, context_mips->hi[dsp_index]); + printf(" lo[%1d] = 0x%" PRIx32 "\n", + dsp_index, context_mips->lo[dsp_index]); + } + printf(" dsp_control = 0x%" PRIx32 "\n", + context_mips->dsp_control); + printf(" epc = 0x%" PRIx64 "\n", + context_mips->epc); + printf(" badvaddr = 0x%" PRIx64 "\n", + context_mips->badvaddr); + printf(" status = 0x%" PRIx32 "\n", + context_mips->status); + printf(" cause = 0x%" PRIx32 "\n", + context_mips->cause); + + for (int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; + ++fpr_index) { + printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", + fpr_index, context_mips->float_save.regs[fpr_index]); + } + printf(" float_save.fpcsr = 0x%" PRIx32 "\n", + context_mips->float_save.fpcsr); + printf(" float_save.fir = 0x%" PRIx32 "\n", + context_mips->float_save.fir); + break; + } + + default: { + break; + } + } +} + +} // namespace google_breakpad diff --git a/src/processor/dump_object.cc b/src/processor/dump_object.cc new file mode 100644 index 00000000..2c82b200 --- /dev/null +++ b/src/processor/dump_object.cc @@ -0,0 +1,39 @@ +// Copyright (c) 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// dump_object.cc: A base class for all mini/micro dump object. + +#include "google_breakpad/processor/dump_object.h" + +namespace google_breakpad { + +DumpObject::DumpObject() : valid_(false) { +} + +} // namespace google_breakpad diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor/fast_source_line_resolver_unittest.cc index 7998fef1..72632f84 100644 --- a/src/processor/fast_source_line_resolver_unittest.cc +++ b/src/processor/fast_source_line_resolver_unittest.cc @@ -37,6 +37,7 @@ // // Author: Siyang Xie (lambxsy@google.com) +#include #include #include @@ -113,6 +114,9 @@ class MockMemoryRegion: public MemoryRegion { *value = address; return true; } + void Print() const { + assert(false); + } }; // Verify that, for every association in ACTUAL, EXPECTED has the same diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc index ee936719..8ae260d5 100644 --- a/src/processor/minidump.cc +++ b/src/processor/minidump.cc @@ -61,6 +61,7 @@ #include "processor/range_map-inl.h" #include "common/scoped_ptr.h" +#include "google_breakpad/processor/dump_context.h" #include "processor/basic_code_module.h" #include "processor/basic_code_modules.h" #include "processor/logging.h" @@ -391,8 +392,8 @@ string TimeTToUTCString(time_t tt) { MinidumpObject::MinidumpObject(Minidump* minidump) - : minidump_(minidump), - valid_(false) { + : DumpObject(), + minidump_(minidump) { } @@ -412,17 +413,13 @@ MinidumpStream::MinidumpStream(Minidump* minidump) MinidumpContext::MinidumpContext(Minidump* minidump) - : MinidumpStream(minidump), - context_(), - context_flags_(0) { + : DumpContext(), + minidump_(minidump) { } - MinidumpContext::~MinidumpContext() { - FreeContext(); } - bool MinidumpContext::Read(uint32_t expected_size) { valid_ = false; @@ -547,9 +544,9 @@ bool MinidumpContext::Read(uint32_t expected_size) { Swap(&context_amd64->last_exception_from_rip); } - context_flags_ = context_amd64->context_flags; + SetContextFlags(context_amd64->context_flags); - context_.amd64 = context_amd64.release(); + SetContextAMD64(context_amd64.release()); } else if (expected_size == sizeof(MDRawContextPPC64)) { // |context_flags| of MDRawContextPPC64 is 64 bits, but other MDRawContext // in the else case have 32 bits |context_flags|, so special case it here. @@ -633,17 +630,17 @@ bool MinidumpContext::Read(uint32_t expected_size) { Swap(&context_ppc64->vector_save.save_vrvalid); } - context_flags_ = static_cast(context_ppc64->context_flags); + SetContextFlags(static_cast(context_ppc64->context_flags)); // Check for data loss when converting context flags from uint64_t into // uint32_t - if (static_cast(context_flags_) != + if (static_cast(GetContextFlags()) != context_ppc64->context_flags) { BPLOG(ERROR) << "Data loss detected when converting PPC64 context_flags"; return false; } - context_.ppc64 = context_ppc64.release(); + SetContextPPC64(context_ppc64.release()); } else if (expected_size == sizeof(MDRawContextARM64)) { // |context_flags| of MDRawContextARM64 is 64 bits, but other MDRawContext // in the else case have 32 bits |context_flags|, so special case it here. @@ -718,17 +715,17 @@ bool MinidumpContext::Read(uint32_t expected_size) { Swap(&context_arm64->float_save.regs[fpr_index]); } } - context_flags_ = static_cast(context_arm64->context_flags); + SetContextFlags(static_cast(context_arm64->context_flags)); // Check for data loss when converting context flags from uint64_t into // uint32_t - if (static_cast(context_flags_) != + if (static_cast(GetContextFlags()) != context_arm64->context_flags) { BPLOG(ERROR) << "Data loss detected when converting ARM64 context_flags"; return false; } - context_.arm64 = context_arm64.release(); + SetContextARM64(context_arm64.release()); } else { uint32_t context_flags; if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { @@ -833,7 +830,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { // does not need to be swapped. } - context_.x86 = context_x86.release(); + SetContextX86(context_x86.release()); break; } @@ -909,7 +906,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { Swap(&context_ppc->vector_save.save_vrvalid); } - context_.ppc = context_ppc.release(); + SetContextPPC(context_ppc.release()); break; } @@ -965,7 +962,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { Swap(&context_sparc->float_save.filler); Swap(&context_sparc->float_save.fsr); } - context_.ctx_sparc = context_sparc.release(); + SetContextSPARC(context_sparc.release()); break; } @@ -1020,16 +1017,16 @@ bool MinidumpContext::Read(uint32_t expected_size) { Swap(&context_arm->float_save.extra[fpe_index]); } } - context_.arm = context_arm.release(); + SetContextARM(context_arm.release()); break; } case MD_CONTEXT_MIPS: { if (expected_size != sizeof(MDRawContextMIPS)) { - BPLOG(ERROR) << "MinidumpContext MIPS size mismatch, " - << expected_size - << " != " + BPLOG(ERROR) << "MinidumpContext MIPS size mismatch, " + << expected_size + << " != " << sizeof(MDRawContextMIPS); return false; } @@ -1085,7 +1082,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { Swap(&context_mips->float_save.fpcsr); Swap(&context_mips->float_save.fir); } - context_.ctx_mips = context_mips.release(); + SetContextMIPS(context_mips.release()); break; } @@ -1099,188 +1096,13 @@ bool MinidumpContext::Read(uint32_t expected_size) { break; } } - context_flags_ = context_flags; + SetContextFlags(context_flags); } valid_ = true; return true; } - -uint32_t MinidumpContext::GetContextCPU() const { - if (!valid_) { - // Don't log a message, GetContextCPU can be legitimately called with - // valid_ false by FreeContext, which is called by Read. - return 0; - } - - return context_flags_ & MD_CONTEXT_CPU_MASK; -} - -bool MinidumpContext::GetInstructionPointer(uint64_t* ip) const { - BPLOG_IF(ERROR, !ip) << "MinidumpContext::GetInstructionPointer " - "requires |ip|"; - assert(ip); - *ip = 0; - - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpContext for GetInstructionPointer"; - return false; - } - - switch (context_flags_ & MD_CONTEXT_CPU_MASK) { - case MD_CONTEXT_AMD64: - *ip = context_.amd64->rip; - break; - case MD_CONTEXT_ARM: - *ip = context_.arm->iregs[MD_CONTEXT_ARM_REG_PC]; - break; - case MD_CONTEXT_ARM64: - *ip = context_.arm64->iregs[MD_CONTEXT_ARM64_REG_PC]; - break; - case MD_CONTEXT_PPC: - *ip = context_.ppc->srr0; - break; - case MD_CONTEXT_PPC64: - *ip = context_.ppc64->srr0; - break; - case MD_CONTEXT_SPARC: - *ip = context_.ctx_sparc->pc; - break; - case MD_CONTEXT_X86: - *ip = context_.x86->eip; - break; - case MD_CONTEXT_MIPS: - *ip = context_.ctx_mips->epc; - break; - default: - // This should never happen. - BPLOG(ERROR) << "Unknown CPU architecture in GetInstructionPointer"; - return false; - } - return true; -} - - -const MDRawContextX86* MinidumpContext::GetContextX86() const { - if (GetContextCPU() != MD_CONTEXT_X86) { - BPLOG(ERROR) << "MinidumpContext cannot get x86 context"; - return NULL; - } - - return context_.x86; -} - - -const MDRawContextPPC* MinidumpContext::GetContextPPC() const { - if (GetContextCPU() != MD_CONTEXT_PPC) { - BPLOG(ERROR) << "MinidumpContext cannot get ppc context"; - return NULL; - } - - return context_.ppc; -} - -const MDRawContextPPC64* MinidumpContext::GetContextPPC64() const { - if (GetContextCPU() != MD_CONTEXT_PPC64) { - BPLOG(ERROR) << "MinidumpContext cannot get ppc64 context"; - return NULL; - } - - return context_.ppc64; -} - -const MDRawContextAMD64* MinidumpContext::GetContextAMD64() const { - if (GetContextCPU() != MD_CONTEXT_AMD64) { - BPLOG(ERROR) << "MinidumpContext cannot get amd64 context"; - return NULL; - } - - return context_.amd64; -} - -const MDRawContextSPARC* MinidumpContext::GetContextSPARC() const { - if (GetContextCPU() != MD_CONTEXT_SPARC) { - BPLOG(ERROR) << "MinidumpContext cannot get sparc context"; - return NULL; - } - - return context_.ctx_sparc; -} - -const MDRawContextARM* MinidumpContext::GetContextARM() const { - if (GetContextCPU() != MD_CONTEXT_ARM) { - BPLOG(ERROR) << "MinidumpContext cannot get arm context"; - return NULL; - } - - return context_.arm; -} - -const MDRawContextARM64* MinidumpContext::GetContextARM64() const { - if (GetContextCPU() != MD_CONTEXT_ARM64) { - BPLOG(ERROR) << "MinidumpContext cannot get arm64 context"; - return NULL; - } - - return context_.arm64; -} - -const MDRawContextMIPS* MinidumpContext::GetContextMIPS() const { - if (GetContextCPU() != MD_CONTEXT_MIPS) { - BPLOG(ERROR) << "MinidumpContext cannot get MIPS context"; - return NULL; - } - - return context_.ctx_mips; -} - -void MinidumpContext::FreeContext() { - switch (GetContextCPU()) { - case MD_CONTEXT_X86: - delete context_.x86; - break; - - case MD_CONTEXT_PPC: - delete context_.ppc; - break; - - case MD_CONTEXT_PPC64: - delete context_.ppc64; - break; - - case MD_CONTEXT_AMD64: - delete context_.amd64; - break; - - case MD_CONTEXT_SPARC: - delete context_.ctx_sparc; - break; - - case MD_CONTEXT_ARM: - delete context_.arm; - break; - - case MD_CONTEXT_ARM64: - delete context_.arm64; - break; - - case MD_CONTEXT_MIPS: - delete context_.ctx_mips; - break; - - default: - // There is no context record (valid_ is false) or there's a - // context record for an unknown CPU (shouldn't happen, only known - // records are stored by Read). - break; - } - - context_flags_ = 0; - context_.base = NULL; -} - - bool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) { // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM, // as this function just implements a sanity check. @@ -1359,352 +1181,6 @@ bool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) { } -void MinidumpContext::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpContext cannot print invalid data"; - return; - } - - switch (GetContextCPU()) { - case MD_CONTEXT_X86: { - const MDRawContextX86* context_x86 = GetContextX86(); - printf("MDRawContextX86\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", - context_x86->float_save.control_word); - printf(" float_save.status_word = 0x%x\n", - context_x86->float_save.status_word); - printf(" float_save.tag_word = 0x%x\n", - context_x86->float_save.tag_word); - printf(" float_save.error_offset = 0x%x\n", - context_x86->float_save.error_offset); - printf(" float_save.error_selector = 0x%x\n", - context_x86->float_save.error_selector); - printf(" float_save.data_offset = 0x%x\n", - context_x86->float_save.data_offset); - 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]); - } - printf("\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"); - - break; - } - - case MD_CONTEXT_PPC: { - const MDRawContextPPC* context_ppc = GetContextPPC(); - printf("MDRawContextPPC\n"); - printf(" context_flags = 0x%x\n", - context_ppc->context_flags); - printf(" srr0 = 0x%x\n", context_ppc->srr0); - printf(" srr1 = 0x%x\n", context_ppc->srr1); - for (unsigned int gpr_index = 0; - gpr_index < MD_CONTEXT_PPC_GPR_COUNT; - ++gpr_index) { - printf(" gpr[%2d] = 0x%x\n", - gpr_index, context_ppc->gpr[gpr_index]); - } - printf(" cr = 0x%x\n", context_ppc->cr); - printf(" xer = 0x%x\n", context_ppc->xer); - printf(" lr = 0x%x\n", context_ppc->lr); - printf(" ctr = 0x%x\n", context_ppc->ctr); - printf(" mq = 0x%x\n", context_ppc->mq); - printf(" vrsave = 0x%x\n", context_ppc->vrsave); - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; - ++fpr_index) { - printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", - fpr_index, context_ppc->float_save.fpregs[fpr_index]); - } - printf(" float_save.fpscr = 0x%x\n", - context_ppc->float_save.fpscr); - // TODO(mmentovai): print the 128-bit quantities in - // context_ppc->vector_save. This isn't done yet because printf - // doesn't support 128-bit quantities, and printing them using - // PRIx64 as two 64-bit quantities requires knowledge of the CPU's - // byte ordering. - printf(" vector_save.save_vrvalid = 0x%x\n", - context_ppc->vector_save.save_vrvalid); - printf("\n"); - - break; - } - - case MD_CONTEXT_PPC64: { - const MDRawContextPPC64* context_ppc64 = GetContextPPC64(); - printf("MDRawContextPPC64\n"); - printf(" context_flags = 0x%" PRIx64 "\n", - context_ppc64->context_flags); - printf(" srr0 = 0x%" PRIx64 "\n", - context_ppc64->srr0); - printf(" srr1 = 0x%" PRIx64 "\n", - context_ppc64->srr1); - for (unsigned int gpr_index = 0; - gpr_index < MD_CONTEXT_PPC64_GPR_COUNT; - ++gpr_index) { - printf(" gpr[%2d] = 0x%" PRIx64 "\n", - gpr_index, context_ppc64->gpr[gpr_index]); - } - printf(" cr = 0x%" PRIx64 "\n", context_ppc64->cr); - printf(" xer = 0x%" PRIx64 "\n", - context_ppc64->xer); - printf(" lr = 0x%" PRIx64 "\n", context_ppc64->lr); - printf(" ctr = 0x%" PRIx64 "\n", - context_ppc64->ctr); - printf(" vrsave = 0x%" PRIx64 "\n", - context_ppc64->vrsave); - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; - ++fpr_index) { - printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", - fpr_index, context_ppc64->float_save.fpregs[fpr_index]); - } - printf(" float_save.fpscr = 0x%x\n", - context_ppc64->float_save.fpscr); - // TODO(mmentovai): print the 128-bit quantities in - // context_ppc64->vector_save. This isn't done yet because printf - // doesn't support 128-bit quantities, and printing them using - // PRIx64 as two 64-bit quantities requires knowledge of the CPU's - // byte ordering. - printf(" vector_save.save_vrvalid = 0x%x\n", - context_ppc64->vector_save.save_vrvalid); - printf("\n"); - - break; - } - - case MD_CONTEXT_AMD64: { - const MDRawContextAMD64* context_amd64 = GetContextAMD64(); - printf("MDRawContextAMD64\n"); - printf(" p1_home = 0x%" PRIx64 "\n", - context_amd64->p1_home); - printf(" p2_home = 0x%" PRIx64 "\n", - context_amd64->p2_home); - printf(" p3_home = 0x%" PRIx64 "\n", - context_amd64->p3_home); - printf(" p4_home = 0x%" PRIx64 "\n", - context_amd64->p4_home); - printf(" p5_home = 0x%" PRIx64 "\n", - context_amd64->p5_home); - printf(" p6_home = 0x%" PRIx64 "\n", - context_amd64->p6_home); - printf(" context_flags = 0x%x\n", - context_amd64->context_flags); - printf(" mx_csr = 0x%x\n", - context_amd64->mx_csr); - printf(" cs = 0x%x\n", context_amd64->cs); - printf(" ds = 0x%x\n", context_amd64->ds); - printf(" es = 0x%x\n", context_amd64->es); - printf(" fs = 0x%x\n", context_amd64->fs); - printf(" gs = 0x%x\n", context_amd64->gs); - printf(" ss = 0x%x\n", context_amd64->ss); - printf(" eflags = 0x%x\n", context_amd64->eflags); - printf(" dr0 = 0x%" PRIx64 "\n", context_amd64->dr0); - printf(" dr1 = 0x%" PRIx64 "\n", context_amd64->dr1); - printf(" dr2 = 0x%" PRIx64 "\n", context_amd64->dr2); - printf(" dr3 = 0x%" PRIx64 "\n", context_amd64->dr3); - printf(" dr6 = 0x%" PRIx64 "\n", context_amd64->dr6); - printf(" dr7 = 0x%" PRIx64 "\n", context_amd64->dr7); - printf(" rax = 0x%" PRIx64 "\n", context_amd64->rax); - printf(" rcx = 0x%" PRIx64 "\n", context_amd64->rcx); - printf(" rdx = 0x%" PRIx64 "\n", context_amd64->rdx); - printf(" rbx = 0x%" PRIx64 "\n", context_amd64->rbx); - printf(" rsp = 0x%" PRIx64 "\n", context_amd64->rsp); - printf(" rbp = 0x%" PRIx64 "\n", context_amd64->rbp); - printf(" rsi = 0x%" PRIx64 "\n", context_amd64->rsi); - printf(" rdi = 0x%" PRIx64 "\n", context_amd64->rdi); - printf(" r8 = 0x%" PRIx64 "\n", context_amd64->r8); - printf(" r9 = 0x%" PRIx64 "\n", context_amd64->r9); - printf(" r10 = 0x%" PRIx64 "\n", context_amd64->r10); - printf(" r11 = 0x%" PRIx64 "\n", context_amd64->r11); - printf(" r12 = 0x%" PRIx64 "\n", context_amd64->r12); - printf(" r13 = 0x%" PRIx64 "\n", context_amd64->r13); - 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 - printf("\n"); - break; - } - - case MD_CONTEXT_SPARC: { - const MDRawContextSPARC* context_sparc = GetContextSPARC(); - printf("MDRawContextSPARC\n"); - printf(" context_flags = 0x%x\n", - context_sparc->context_flags); - for (unsigned int g_r_index = 0; - g_r_index < MD_CONTEXT_SPARC_GPR_COUNT; - ++g_r_index) { - printf(" g_r[%2d] = 0x%" PRIx64 "\n", - g_r_index, context_sparc->g_r[g_r_index]); - } - printf(" ccr = 0x%" PRIx64 "\n", context_sparc->ccr); - printf(" pc = 0x%" PRIx64 "\n", context_sparc->pc); - printf(" npc = 0x%" PRIx64 "\n", context_sparc->npc); - printf(" y = 0x%" PRIx64 "\n", context_sparc->y); - printf(" asi = 0x%" PRIx64 "\n", context_sparc->asi); - printf(" fprs = 0x%" PRIx64 "\n", context_sparc->fprs); - - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; - ++fpr_index) { - printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", - fpr_index, context_sparc->float_save.regs[fpr_index]); - } - printf(" float_save.filler = 0x%" PRIx64 "\n", - context_sparc->float_save.filler); - printf(" float_save.fsr = 0x%" PRIx64 "\n", - context_sparc->float_save.fsr); - break; - } - - case MD_CONTEXT_ARM: { - const MDRawContextARM* context_arm = GetContextARM(); - printf("MDRawContextARM\n"); - printf(" context_flags = 0x%x\n", - context_arm->context_flags); - for (unsigned int ireg_index = 0; - ireg_index < MD_CONTEXT_ARM_GPR_COUNT; - ++ireg_index) { - printf(" iregs[%2d] = 0x%x\n", - ireg_index, context_arm->iregs[ireg_index]); - } - printf(" cpsr = 0x%x\n", context_arm->cpsr); - printf(" float_save.fpscr = 0x%" PRIx64 "\n", - context_arm->float_save.fpscr); - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; - ++fpr_index) { - printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", - fpr_index, context_arm->float_save.regs[fpr_index]); - } - for (unsigned int fpe_index = 0; - fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; - ++fpe_index) { - printf(" float_save.extra[%2d] = 0x%" PRIx32 "\n", - fpe_index, context_arm->float_save.extra[fpe_index]); - } - - break; - } - - case MD_CONTEXT_ARM64: { - const MDRawContextARM64* context_arm64 = GetContextARM64(); - printf("MDRawContextARM64\n"); - printf(" context_flags = 0x%" PRIx64 "\n", - context_arm64->context_flags); - for (unsigned int ireg_index = 0; - ireg_index < MD_CONTEXT_ARM64_GPR_COUNT; - ++ireg_index) { - printf(" iregs[%2d] = 0x%" PRIx64 "\n", - ireg_index, context_arm64->iregs[ireg_index]); - } - printf(" cpsr = 0x%x\n", context_arm64->cpsr); - printf(" float_save.fpsr = 0x%x\n", context_arm64->float_save.fpsr); - printf(" float_save.fpcr = 0x%x\n", context_arm64->float_save.fpcr); - - for (unsigned int freg_index = 0; - freg_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT; - ++freg_index) { - uint128_struct fp_value = context_arm64->float_save.regs[freg_index]; - printf(" float_save.regs[%2d] = 0x%" PRIx64 "%" PRIx64 "\n", - freg_index, fp_value.high, fp_value.low); - } - break; - } - - case MD_CONTEXT_MIPS: { - const MDRawContextMIPS* context_mips = GetContextMIPS(); - printf("MDRawContextMIPS\n"); - printf(" context_flags = 0x%x\n", - context_mips->context_flags); - for (int ireg_index = 0; - ireg_index < MD_CONTEXT_MIPS_GPR_COUNT; - ++ireg_index) { - printf(" iregs[%2d] = 0x%" PRIx64 "\n", - ireg_index, context_mips->iregs[ireg_index]); - } - printf(" mdhi = 0x%" PRIx64 "\n", - context_mips->mdhi); - printf(" mdlo = 0x%" PRIx64 "\n", - context_mips->mdhi); - for (int dsp_index = 0; - dsp_index < MD_CONTEXT_MIPS_DSP_COUNT; - ++dsp_index) { - printf(" hi[%1d] = 0x%" PRIx32 "\n", - dsp_index, context_mips->hi[dsp_index]); - printf(" lo[%1d] = 0x%" PRIx32 "\n", - dsp_index, context_mips->lo[dsp_index]); - } - printf(" dsp_control = 0x%" PRIx32 "\n", - context_mips->dsp_control); - printf(" epc = 0x%" PRIx64 "\n", - context_mips->epc); - printf(" badvaddr = 0x%" PRIx64 "\n", - context_mips->badvaddr); - printf(" status = 0x%" PRIx32 "\n", - context_mips->status); - printf(" cause = 0x%" PRIx32 "\n", - context_mips->cause); - - for (int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; - ++fpr_index) { - printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", - fpr_index, context_mips->float_save.regs[fpr_index]); - } - printf(" float_save.fpcsr = 0x%" PRIx32 "\n", - context_mips->float_save.fpcsr); - printf(" float_save.fir = 0x%" PRIx32 "\n", - context_mips->float_save.fir); - break; - } - - default: { - break; - } - } -} - - // // MinidumpMemoryRegion // @@ -1867,7 +1343,7 @@ bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, } -void MinidumpMemoryRegion::Print() { +void MinidumpMemoryRegion::Print() const { if (!valid_) { BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data"; return; diff --git a/src/processor/minidump_processor_unittest.cc b/src/processor/minidump_processor_unittest.cc index 9395cc2d..abf28376 100644 --- a/src/processor/minidump_processor_unittest.cc +++ b/src/processor/minidump_processor_unittest.cc @@ -299,8 +299,8 @@ class TestMinidumpContext : public MinidumpContext { explicit TestMinidumpContext(const MDRawContextX86& context) : MinidumpContext(NULL) { valid_ = true; - context_.x86 = new MDRawContextX86(context); - context_flags_ = MD_CONTEXT_X86; + SetContextX86(new MDRawContextX86(context)); + SetContextFlags(MD_CONTEXT_X86); } }; diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix_evaluator_unittest.cc index 516be518..f1189828 100644 --- a/src/processor/postfix_evaluator_unittest.cc +++ b/src/processor/postfix_evaluator_unittest.cc @@ -31,6 +31,7 @@ // // Author: Mark Mentovai +#include #include #include @@ -75,6 +76,9 @@ class FakeMemoryRegion : public MemoryRegion { *value = address + 1; return true; } + virtual void Print() const { + assert(false); + } }; diff --git a/src/processor/stackwalker.cc b/src/processor/stackwalker.cc index 2ca8f166..424cf4c4 100644 --- a/src/processor/stackwalker.cc +++ b/src/processor/stackwalker.cc @@ -41,7 +41,7 @@ #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/code_module.h" #include "google_breakpad/processor/code_modules.h" -#include "google_breakpad/processor/minidump.h" +#include "google_breakpad/processor/dump_context.h" #include "google_breakpad/processor/stack_frame.h" #include "google_breakpad/processor/stack_frame_symbolizer.h" #include "google_breakpad/processor/system_info.h" @@ -190,7 +190,7 @@ bool Stackwalker::Walk( // static Stackwalker* Stackwalker::StackwalkerForCPU( const SystemInfo* system_info, - MinidumpContext* context, + DumpContext* context, MemoryRegion* memory, const CodeModules* modules, StackFrameSymbolizer* frame_symbolizer) { diff --git a/src/processor/stackwalker_selftest.cc b/src/processor/stackwalker_selftest.cc index 75d47582..f692d4c4 100644 --- a/src/processor/stackwalker_selftest.cc +++ b/src/processor/stackwalker_selftest.cc @@ -49,6 +49,8 @@ // // Author: Mark Mentovai +#include + #include "processor/logging.h" #if defined(__i386) && !defined(__i386__) @@ -102,17 +104,20 @@ using google_breakpad::StackwalkerSPARC; // process' memory space by pointer. class SelfMemoryRegion : public MemoryRegion { public: - virtual uint64_t GetBase() { return 0; } - virtual uint32_t GetSize() { return 0xffffffff; } + virtual uint64_t GetBase() const { return 0; } + virtual uint32_t GetSize() const { return 0xffffffff; } - bool GetMemoryAtAddress(uint64_t address, uint8_t* value) { + bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const { return GetMemoryAtAddressInternal(address, value); } - bool GetMemoryAtAddress(uint64_t address, uint16_t* value) { + bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const { return GetMemoryAtAddressInternal(address, value); } - bool GetMemoryAtAddress(uint64_t address, uint32_t* value) { + bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const { return GetMemoryAtAddressInternal(address, value); } - bool GetMemoryAtAddress(uint64_t address, uint64_t* value) { + bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const { return GetMemoryAtAddressInternal(address, value); } + void Print() const { + assert(false); + } private: template bool GetMemoryAtAddressInternal(uint64_t address, diff --git a/src/processor/stackwalker_unittest_utils.h b/src/processor/stackwalker_unittest_utils.h index a72b8e0d..73ceb199 100644 --- a/src/processor/stackwalker_unittest_utils.h +++ b/src/processor/stackwalker_unittest_utils.h @@ -36,6 +36,7 @@ #ifndef PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_ #define PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_ +#include #include #include #include @@ -75,6 +76,9 @@ class MockMemoryRegion: public google_breakpad::MemoryRegion { bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const { return GetMemoryLittleEndian(address, value); } + void Print() const { + assert(false); + } private: // Fetch a little-endian value from ADDRESS in contents_ whose size -- cgit v1.2.1