diff options
Diffstat (limited to 'src/processor')
-rw-r--r-- | src/processor/minidump_processor.cc | 28 | ||||
-rw-r--r-- | src/processor/stackwalker.cc | 125 | ||||
-rw-r--r-- | src/processor/stackwalker_amd64.cc | 39 | ||||
-rw-r--r-- | src/processor/stackwalker_amd64.h | 24 | ||||
-rw-r--r-- | src/processor/stackwalker_amd64_unittest.cc | 27 | ||||
-rw-r--r-- | src/processor/stackwalker_arm.cc | 55 | ||||
-rw-r--r-- | src/processor/stackwalker_arm.h | 23 | ||||
-rw-r--r-- | src/processor/stackwalker_arm_unittest.cc | 30 | ||||
-rw-r--r-- | src/processor/stackwalker_ppc.cc | 21 | ||||
-rw-r--r-- | src/processor/stackwalker_ppc.h | 15 | ||||
-rw-r--r-- | src/processor/stackwalker_sparc.cc | 29 | ||||
-rw-r--r-- | src/processor/stackwalker_sparc.h | 15 | ||||
-rw-r--r-- | src/processor/stackwalker_x86.cc | 71 | ||||
-rw-r--r-- | src/processor/stackwalker_x86.h | 30 | ||||
-rw-r--r-- | src/processor/stackwalker_x86_unittest.cc | 43 |
15 files changed, 285 insertions, 290 deletions
diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc index 814402be..a197cd10 100644 --- a/src/processor/minidump_processor.cc +++ b/src/processor/minidump_processor.cc @@ -36,6 +36,7 @@ #include "google_breakpad/processor/minidump.h" #include "google_breakpad/processor/process_state.h" #include "google_breakpad/processor/exploitability.h" +#include "google_breakpad/processor/stack_frame_symbolizer.h" #include "processor/logging.h" #include "processor/scoped_ptr.h" #include "processor/stackwalker_x86.h" @@ -44,18 +45,29 @@ namespace google_breakpad { MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, SourceLineResolverInterface *resolver) - : supplier_(supplier), resolver_(resolver), + : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), + own_frame_symbolizer_(true), enable_exploitability_(false) { } MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, SourceLineResolverInterface *resolver, bool enable_exploitability) - : supplier_(supplier), resolver_(resolver), + : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), + own_frame_symbolizer_(true), enable_exploitability_(enable_exploitability) { } +MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer *frame_symbolizer, + bool enable_exploitability) + : frame_symbolizer_(frame_symbolizer), + own_frame_symbolizer_(false), + enable_exploitability_(enable_exploitability) { + assert(frame_symbolizer_); +} + MinidumpProcessor::~MinidumpProcessor() { + if (own_frame_symbolizer_) delete frame_symbolizer_; } ProcessResult MinidumpProcessor::Process( @@ -126,6 +138,10 @@ ProcessResult MinidumpProcessor::Process( bool interrupted = false; bool found_requesting_thread = false; unsigned int thread_count = threads->thread_count(); + + // Reset frame_symbolizer_ at the beginning of stackwalk for each minidump. + frame_symbolizer_->Reset(); + for (unsigned int thread_index = 0; thread_index < thread_count; ++thread_index) { @@ -208,8 +224,7 @@ ProcessResult MinidumpProcessor::Process( context, thread_memory, process_state->modules_, - supplier_, - resolver_)); + frame_symbolizer_)); if (!stackwalker.get()) { BPLOG(ERROR) << "No stackwalker for " << thread_string; return PROCESS_ERROR_NO_STACKWALKER_FOR_THREAD; @@ -1160,7 +1175,8 @@ string MinidumpProcessor::GetAssertion(Minidump *dump) { break; default: { char assertion_type[32]; - sprintf(assertion_type, "0x%08x", raw_assertion->type); + snprintf(assertion_type, sizeof(assertion_type), + "0x%08x", raw_assertion->type); assertion_string = "Unknown assertion type "; assertion_string += assertion_type; break; @@ -1184,7 +1200,7 @@ string MinidumpProcessor::GetAssertion(Minidump *dump) { if (raw_assertion->line != 0) { char assertion_line[32]; - sprintf(assertion_line, "%u", raw_assertion->line); + snprintf(assertion_line, sizeof(assertion_line), "%u", raw_assertion->line); assertion_string.append(" at line "); assertion_string.append(assertion_line); } diff --git a/src/processor/stackwalker.cc b/src/processor/stackwalker.cc index 2bd333ac..762c47f5 100644 --- a/src/processor/stackwalker.cc +++ b/src/processor/stackwalker.cc @@ -41,9 +41,8 @@ #include "google_breakpad/processor/code_module.h" #include "google_breakpad/processor/code_modules.h" #include "google_breakpad/processor/minidump.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" #include "google_breakpad/processor/stack_frame.h" -#include "google_breakpad/processor/symbol_supplier.h" +#include "google_breakpad/processor/stack_frame_symbolizer.h" #include "google_breakpad/processor/system_info.h" #include "processor/linked_ptr.h" #include "processor/logging.h" @@ -58,20 +57,19 @@ namespace google_breakpad { u_int32_t Stackwalker::max_frames_ = 1024; -Stackwalker::Stackwalker(const SystemInfo *system_info, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver) +Stackwalker::Stackwalker(const SystemInfo* system_info, + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* frame_symbolizer) : system_info_(system_info), memory_(memory), modules_(modules), - resolver_(resolver), - supplier_(supplier) { + frame_symbolizer_(frame_symbolizer) { + assert(frame_symbolizer_); } -bool Stackwalker::Walk(CallStack *stack) { +bool Stackwalker::Walk(CallStack* stack) { BPLOG_IF(ERROR, !stack) << "Stackwalker::Walk requires |stack|"; assert(stack); stack->Clear(); @@ -88,42 +86,12 @@ bool Stackwalker::Walk(CallStack *stack) { // context frame (above) or a caller frame (below). // Resolve the module information, if a module map was provided. - if (modules_) { - const CodeModule *module = - modules_->GetModuleForAddress(frame->instruction); - if (module) { - frame->module = module; - if (resolver_ && - !resolver_->HasModule(frame->module) && - no_symbol_modules_.find( - module->code_file()) == no_symbol_modules_.end() && - supplier_) { - string symbol_file; - char *symbol_data = NULL; - SymbolSupplier::SymbolResult symbol_result = - supplier_->GetCStringSymbolData(module, - system_info_, - &symbol_file, - &symbol_data); - - switch (symbol_result) { - case SymbolSupplier::FOUND: - resolver_->LoadModuleUsingMemoryBuffer(frame->module, - symbol_data); - break; - case SymbolSupplier::NOT_FOUND: - no_symbol_modules_.insert(module->code_file()); - break; // nothing to do - case SymbolSupplier::INTERRUPT: - return false; - } - // Inform symbol supplier to free the unused data memory buffer. - if (resolver_->ShouldDeleteMemoryBufferAfterLoadModule()) - supplier_->FreeSymbolData(module); - } - if (resolver_) - resolver_->FillSourceLineInfo(frame.get()); - } + StackFrameSymbolizer::SymbolizerResult symbolizer_result = + frame_symbolizer_->FillSourceLineInfo(modules_, system_info_, + frame.get()); + if (symbolizer_result == StackFrameSymbolizer::INTERRUPT) { + BPLOG(INFO) << "Stack walk is interrupted."; + return false; } // Add the frame to the call stack. Relinquish the ownership claim @@ -144,47 +112,42 @@ bool Stackwalker::Walk(CallStack *stack) { // static Stackwalker* Stackwalker::StackwalkerForCPU( - const SystemInfo *system_info, - MinidumpContext *context, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver) { + const SystemInfo* system_info, + MinidumpContext* context, + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* frame_symbolizer) { if (!context) { BPLOG(ERROR) << "Can't choose a stackwalker implementation without context"; return NULL; } - Stackwalker *cpu_stackwalker = NULL; + Stackwalker* cpu_stackwalker = NULL; u_int32_t cpu = context->GetContextCPU(); switch (cpu) { case MD_CONTEXT_X86: cpu_stackwalker = new StackwalkerX86(system_info, context->GetContextX86(), - memory, modules, supplier, - resolver); + memory, modules, frame_symbolizer); break; case MD_CONTEXT_PPC: cpu_stackwalker = new StackwalkerPPC(system_info, context->GetContextPPC(), - memory, modules, supplier, - resolver); + memory, modules, frame_symbolizer); break; case MD_CONTEXT_AMD64: cpu_stackwalker = new StackwalkerAMD64(system_info, context->GetContextAMD64(), - memory, modules, supplier, - resolver); + memory, modules, frame_symbolizer); break; case MD_CONTEXT_SPARC: cpu_stackwalker = new StackwalkerSPARC(system_info, context->GetContextSPARC(), - memory, modules, supplier, - resolver); + memory, modules, frame_symbolizer); break; case MD_CONTEXT_ARM: @@ -193,8 +156,8 @@ Stackwalker* Stackwalker::StackwalkerForCPU( fp_register = MD_CONTEXT_ARM_REG_IOS_FP; cpu_stackwalker = new StackwalkerARM(system_info, context->GetContextARM(), - fp_register, memory, modules, - supplier, resolver); + fp_register, memory, modules, + frame_symbolizer); break; } @@ -205,38 +168,28 @@ Stackwalker* Stackwalker::StackwalkerForCPU( } bool Stackwalker::InstructionAddressSeemsValid(u_int64_t address) { - const CodeModule *module = modules_->GetModuleForAddress(address); - if (!module) { + StackFrame frame; + frame.instruction = address; + StackFrameSymbolizer::SymbolizerResult symbolizer_result = + frame_symbolizer_->FillSourceLineInfo(modules_, system_info_, &frame); + + if (!frame.module) { // not inside any loaded module return false; } - if (!resolver_ || !supplier_) { - // we don't have a resolver and or symbol supplier, - // but we're inside a known module + if (!frame_symbolizer_->HasImplementation()) { + // No valid implementation to symbolize stack frame, but the address is + // within a known module. return true; } - if (!resolver_->HasModule(module)) { - string symbol_file; - char *symbol_data = NULL; - SymbolSupplier::SymbolResult symbol_result = - supplier_->GetCStringSymbolData(module, system_info_, - &symbol_file, &symbol_data); - - if (symbol_result != SymbolSupplier::FOUND || - !resolver_->LoadModuleUsingMemoryBuffer(module, - symbol_data)) { - // we don't have symbols, but we're inside a loaded module - return true; - } + if (symbolizer_result != StackFrameSymbolizer::NO_ERROR) { + // Some error occurred during symbolization, but the address is within a + // known module + return true; } - StackFrame frame; - frame.module = module; - frame.instruction = address; - resolver_->FillSourceLineInfo(&frame); - // we have symbols, so return true if inside a function return !frame.function_name.empty(); } diff --git a/src/processor/stackwalker_amd64.cc b/src/processor/stackwalker_amd64.cc index 5a9ddb19..12aa6333 100644 --- a/src/processor/stackwalker_amd64.cc +++ b/src/processor/stackwalker_amd64.cc @@ -89,13 +89,12 @@ StackwalkerAMD64::cfi_register_map_[] = { StackFrameAMD64::CONTEXT_VALID_RIP, &MDRawContextAMD64::rip }, }; -StackwalkerAMD64::StackwalkerAMD64(const SystemInfo *system_info, - const MDRawContextAMD64 *context, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver) - : Stackwalker(system_info, memory, modules, supplier, resolver), +StackwalkerAMD64::StackwalkerAMD64(const SystemInfo* system_info, + const MDRawContextAMD64* context, + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* resolver_helper) + : Stackwalker(system_info, memory, modules, resolver_helper), context_(context), cfi_walker_(cfi_register_map_, (sizeof(cfi_register_map_) / sizeof(cfi_register_map_[0]))) { @@ -108,7 +107,7 @@ StackFrame* StackwalkerAMD64::GetContextFrame() { return NULL; } - StackFrameAMD64 *frame = new StackFrameAMD64(); + StackFrameAMD64* frame = new StackFrameAMD64(); // The instruction pointer is stored directly in a register, so pull it // straight out of the CPU context structure. @@ -120,10 +119,10 @@ StackFrame* StackwalkerAMD64::GetContextFrame() { return frame; } -StackFrameAMD64 *StackwalkerAMD64::GetCallerByCFIFrameInfo( - const vector<StackFrame *> &frames, - CFIFrameInfo *cfi_frame_info) { - StackFrameAMD64 *last_frame = static_cast<StackFrameAMD64*>(frames.back()); +StackFrameAMD64* StackwalkerAMD64::GetCallerByCFIFrameInfo( + const vector<StackFrame*> &frames, + CFIFrameInfo* cfi_frame_info) { + StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back()); scoped_ptr<StackFrameAMD64> frame(new StackFrameAMD64()); if (!cfi_walker_ @@ -142,9 +141,9 @@ StackFrameAMD64 *StackwalkerAMD64::GetCallerByCFIFrameInfo( return frame.release(); } -StackFrameAMD64 *StackwalkerAMD64::GetCallerByStackScan( - const vector<StackFrame *> &frames) { - StackFrameAMD64 *last_frame = static_cast<StackFrameAMD64 *>(frames.back()); +StackFrameAMD64* StackwalkerAMD64::GetCallerByStackScan( + const vector<StackFrame*> &frames) { + StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back()); u_int64_t last_rsp = last_frame->context.rsp; u_int64_t caller_rip_address, caller_rip; @@ -155,7 +154,7 @@ StackFrameAMD64 *StackwalkerAMD64::GetCallerByStackScan( // Create a new stack frame (ownership will be transferred to the caller) // and fill it in. - StackFrameAMD64 *frame = new StackFrameAMD64(); + StackFrameAMD64* frame = new StackFrameAMD64(); frame->trust = StackFrame::FRAME_TRUST_SCAN; frame->context = last_frame->context; @@ -191,19 +190,19 @@ StackFrameAMD64 *StackwalkerAMD64::GetCallerByStackScan( return frame; } -StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack *stack) { +StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack* stack) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; return NULL; } - const vector<StackFrame *> &frames = *stack->frames(); - StackFrameAMD64 *last_frame = static_cast<StackFrameAMD64 *>(frames.back()); + const vector<StackFrame*> &frames = *stack->frames(); + StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back()); scoped_ptr<StackFrameAMD64> new_frame; // If we have DWARF CFI information, use it. scoped_ptr<CFIFrameInfo> cfi_frame_info( - resolver_ ? resolver_->FindCFIFrameInfo(last_frame) : NULL); + frame_symbolizer_->FindCFIFrameInfo(last_frame)); if (cfi_frame_info.get()) new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); diff --git a/src/processor/stackwalker_amd64.h b/src/processor/stackwalker_amd64.h index cde95208..3e41c123 100644 --- a/src/processor/stackwalker_amd64.h +++ b/src/processor/stackwalker_amd64.h @@ -38,6 +38,7 @@ #ifndef PROCESSOR_STACKWALKER_AMD64_H__ #define PROCESSOR_STACKWALKER_AMD64_H__ +#include <vector> #include "google_breakpad/common/breakpad_types.h" #include "google_breakpad/common/minidump_format.h" @@ -55,12 +56,11 @@ class StackwalkerAMD64 : public Stackwalker { // register state corresponding to the innermost called frame to be // included in the stack. The other arguments are passed directly through // to the base Stackwalker constructor. - StackwalkerAMD64(const SystemInfo *system_info, - const MDRawContextAMD64 *context, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver); + StackwalkerAMD64(const SystemInfo* system_info, + const MDRawContextAMD64* context, + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* frame_symbolizer); private: // A STACK CFI-driven frame walker for the AMD64 @@ -69,21 +69,21 @@ class StackwalkerAMD64 : public Stackwalker { // Implementation of Stackwalker, using amd64 context (stack pointer in %rsp, // stack base in %rbp) and stack conventions (saved stack pointer at 0(%rbp)) virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack *stack); + virtual StackFrame* GetCallerFrame(const CallStack* stack); // Use cfi_frame_info (derived from STACK CFI records) to construct // the frame that called frames.back(). The caller takes ownership // of the returned frame. Return NULL on failure. - StackFrameAMD64 *GetCallerByCFIFrameInfo(const vector<StackFrame *> &frames, - CFIFrameInfo *cfi_frame_info); + StackFrameAMD64* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames, + CFIFrameInfo* cfi_frame_info); // Scan the stack for plausible return addresses. The caller takes ownership - // of the returned frame. Return NULL on failure. - StackFrameAMD64 *GetCallerByStackScan(const vector<StackFrame *> &frames); + // of the returned frame. Return NULL on failure. + StackFrameAMD64* GetCallerByStackScan(const vector<StackFrame*> &frames); // Stores the CPU context corresponding to the innermost stack frame to // be returned by GetContextFrame. - const MDRawContextAMD64 *context_; + const MDRawContextAMD64* context_; // Our register map, for cfi_walker_. static const CFIWalker::RegisterSet cfi_register_map_[]; diff --git a/src/processor/stackwalker_amd64_unittest.cc b/src/processor/stackwalker_amd64_unittest.cc index f3723c0c..1721b8cb 100644 --- a/src/processor/stackwalker_amd64_unittest.cc +++ b/src/processor/stackwalker_amd64_unittest.cc @@ -31,8 +31,8 @@ // stackwalker_amd64_unittest.cc: Unit tests for StackwalkerAMD64 class. -#include <string> #include <string.h> +#include <string> #include <vector> #include "breakpad_googletest_includes.h" @@ -48,6 +48,7 @@ using google_breakpad::BasicSourceLineResolver; using google_breakpad::CallStack; +using google_breakpad::StackFrameSymbolizer; using google_breakpad::StackFrame; using google_breakpad::StackFrameAMD64; using google_breakpad::StackwalkerAMD64; @@ -112,7 +113,7 @@ class StackwalkerAMD64Fixture { for (size_t i = 0; i < sizeof(*raw_context); i++) reinterpret_cast<u_int8_t *>(raw_context)[i] = (x += 17); } - + SystemInfo system_info; MDRawContextAMD64 raw_context; Section stack_section; @@ -138,8 +139,9 @@ TEST_F(SanityCheck, NoResolver) { raw_context.rip = 0x40000000c0000200ULL; raw_context.rbp = 0x8000000080000000ULL; + StackFrameSymbolizer frame_symbolizer(NULL, NULL); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - NULL, NULL); + &frame_symbolizer); // This should succeed even without a resolver or supplier. ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); @@ -158,8 +160,9 @@ TEST_F(GetContextFrame, Simple) { raw_context.rip = 0x40000000c0000200ULL; raw_context.rbp = 0x8000000080000000ULL; + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_GE(1U, frames->size()); @@ -207,13 +210,14 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) { .Append(32, 0); // end of stack RegionFromSection(); - + raw_context.rip = 0x40000000c0000200ULL; raw_context.rbp = frame1_rbp.Value(); raw_context.rsp = stack_section.start().Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(3U, frames->size()); @@ -267,7 +271,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { .Append(32, 0) // end of stack .Mark(&frame1_rbp); RegionFromSection(); - + raw_context.rip = 0x40000000c0000200ULL; raw_context.rbp = frame1_rbp.Value(); raw_context.rsp = stack_section.start().Value(); @@ -279,8 +283,9 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { // The calling frame's function. "FUNC 100 400 10 echidna\n"); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -343,8 +348,9 @@ TEST_F(GetCallerFrame, CallerPushedRBP) { // The calling frame's function. "FUNC 100 400 10 yeti\n"); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -418,8 +424,9 @@ struct CFIFixture: public StackwalkerAMD64Fixture { RegionFromSection(); raw_context.rsp = stack_section.start().Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc index 0a3c522d..3beaa449 100644 --- a/src/processor/stackwalker_arm.cc +++ b/src/processor/stackwalker_arm.cc @@ -33,6 +33,8 @@ // // Author: Mark Mentovai, Ted Mielczarek, Jim Blandy +#include <vector> + #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/memory_region.h" #include "google_breakpad/processor/source_line_resolver_interface.h" @@ -45,14 +47,13 @@ namespace google_breakpad { -StackwalkerARM::StackwalkerARM(const SystemInfo *system_info, - const MDRawContextARM *context, +StackwalkerARM::StackwalkerARM(const SystemInfo* system_info, + const MDRawContextARM* context, int fp_register, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver) - : Stackwalker(system_info, memory, modules, supplier, resolver), + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* resolver_helper) + : Stackwalker(system_info, memory, modules, resolver_helper), context_(context), fp_register_(fp_register), context_frame_validity_(StackFrameARM::CONTEXT_VALID_ALL) { } @@ -63,7 +64,7 @@ StackFrame* StackwalkerARM::GetContextFrame() { return NULL; } - StackFrameARM *frame = new StackFrameARM(); + StackFrameARM* frame = new StackFrameARM(); // The instruction pointer is stored directly in a register (r15), so pull it // straight out of the CPU context structure. @@ -75,12 +76,12 @@ StackFrame* StackwalkerARM::GetContextFrame() { return frame; } -StackFrameARM *StackwalkerARM::GetCallerByCFIFrameInfo( - const vector<StackFrame *> &frames, - CFIFrameInfo *cfi_frame_info) { - StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back()); +StackFrameARM* StackwalkerARM::GetCallerByCFIFrameInfo( + const vector<StackFrame*> &frames, + CFIFrameInfo* cfi_frame_info) { + StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back()); - static const char *register_names[] = { + static const char* register_names[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", @@ -121,7 +122,7 @@ StackFrameARM *StackwalkerARM::GetCallerByCFIFrameInfo( } } // If the CFI doesn't recover the PC explicitly, then use .ra. - if (! (frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) { + if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) { CFIFrameInfo::RegisterValueMap<u_int32_t>::iterator entry = caller_registers.find(".ra"); if (entry != caller_registers.end()) { @@ -140,7 +141,7 @@ StackFrameARM *StackwalkerARM::GetCallerByCFIFrameInfo( } } // If the CFI doesn't recover the SP explicitly, then use .cfa. - if (! (frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) { + if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) { CFIFrameInfo::RegisterValueMap<u_int32_t>::iterator entry = caller_registers.find(".cfa"); if (entry != caller_registers.end()) { @@ -159,9 +160,9 @@ StackFrameARM *StackwalkerARM::GetCallerByCFIFrameInfo( return frame.release(); } -StackFrameARM *StackwalkerARM::GetCallerByStackScan( - const vector<StackFrame *> &frames) { - StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back()); +StackFrameARM* StackwalkerARM::GetCallerByStackScan( + const vector<StackFrame*> &frames) { + StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back()); u_int32_t last_sp = last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP]; u_int32_t caller_sp, caller_pc; @@ -177,7 +178,7 @@ StackFrameARM *StackwalkerARM::GetCallerByStackScan( // Create a new stack frame (ownership will be transferred to the caller) // and fill it in. - StackFrameARM *frame = new StackFrameARM(); + StackFrameARM* frame = new StackFrameARM(); frame->trust = StackFrame::FRAME_TRUST_SCAN; frame->context = last_frame->context; @@ -189,9 +190,9 @@ StackFrameARM *StackwalkerARM::GetCallerByStackScan( return frame; } -StackFrameARM *StackwalkerARM::GetCallerByFramePointer( - const vector<StackFrame *> &frames) { - StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back()); +StackFrameARM* StackwalkerARM::GetCallerByFramePointer( + const vector<StackFrame*> &frames) { + StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back()); if (!(last_frame->context_validity & StackFrameARM::RegisterValidFlag(fp_register_))) { @@ -219,7 +220,7 @@ StackFrameARM *StackwalkerARM::GetCallerByFramePointer( // Create a new stack frame (ownership will be transferred to the caller) // and fill it in. - StackFrameARM *frame = new StackFrameARM(); + StackFrameARM* frame = new StackFrameARM(); frame->trust = StackFrame::FRAME_TRUST_FP; frame->context = last_frame->context; @@ -235,19 +236,19 @@ StackFrameARM *StackwalkerARM::GetCallerByFramePointer( return frame; } -StackFrame* StackwalkerARM::GetCallerFrame(const CallStack *stack) { +StackFrame* StackwalkerARM::GetCallerFrame(const CallStack* stack) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; return NULL; } - const vector<StackFrame *> &frames = *stack->frames(); - StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back()); + const vector<StackFrame*> &frames = *stack->frames(); + StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back()); scoped_ptr<StackFrameARM> frame; // See if there is DWARF call frame information covering this address. scoped_ptr<CFIFrameInfo> cfi_frame_info( - resolver_ ? resolver_->FindCFIFrameInfo(last_frame) : NULL); + frame_symbolizer_->FindCFIFrameInfo(last_frame)); if (cfi_frame_info.get()) frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); diff --git a/src/processor/stackwalker_arm.h b/src/processor/stackwalker_arm.h index 24fc60dd..eb480156 100644 --- a/src/processor/stackwalker_arm.h +++ b/src/processor/stackwalker_arm.h @@ -54,13 +54,12 @@ class StackwalkerARM : public Stackwalker { // register state corresponding to the innermost called frame to be // included in the stack. The other arguments are passed directly through // to the base Stackwalker constructor. - StackwalkerARM(const SystemInfo *system_info, - const MDRawContextARM *context, + StackwalkerARM(const SystemInfo* system_info, + const MDRawContextARM* context, int fp_register, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver); + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* frame_symbolizer); // Change the context validity mask of the frame returned by // GetContextFrame to VALID. This is only for use by unit tests; the @@ -70,25 +69,25 @@ class StackwalkerARM : public Stackwalker { private: // Implementation of Stackwalker, using arm context and stack conventions. virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack *stack); + virtual StackFrame* GetCallerFrame(const CallStack* stack); // Use cfi_frame_info (derived from STACK CFI records) to construct // the frame that called frames.back(). The caller takes ownership // of the returned frame. Return NULL on failure. - StackFrameARM *GetCallerByCFIFrameInfo(const vector<StackFrame *> &frames, - CFIFrameInfo *cfi_frame_info); + StackFrameARM* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames, + CFIFrameInfo* cfi_frame_info); // Use the frame pointer. The caller takes ownership of the returned frame. // Return NULL on failure. - StackFrameARM *GetCallerByFramePointer(const vector<StackFrame *> &frames); + StackFrameARM* GetCallerByFramePointer(const vector<StackFrame*> &frames); // Scan the stack for plausible return addresses. The caller takes ownership // of the returned frame. Return NULL on failure. - StackFrameARM *GetCallerByStackScan(const vector<StackFrame *> &frames); + StackFrameARM* GetCallerByStackScan(const vector<StackFrame*> &frames); // Stores the CPU context corresponding to the youngest stack frame, to // be returned by GetContextFrame. - const MDRawContextARM *context_; + const MDRawContextARM* context_; // The register to use a as frame pointer. The value is -1 if frame pointer // cannot be used. diff --git a/src/processor/stackwalker_arm_unittest.cc b/src/processor/stackwalker_arm_unittest.cc index 10772ba4..88517b77 100644 --- a/src/processor/stackwalker_arm_unittest.cc +++ b/src/processor/stackwalker_arm_unittest.cc @@ -31,8 +31,8 @@ // stackwalker_arm_unittest.cc: Unit tests for StackwalkerARM class. -#include <string> #include <string.h> +#include <string> #include <vector> #include "breakpad_googletest_includes.h" @@ -49,6 +49,7 @@ using google_breakpad::BasicSourceLineResolver; using google_breakpad::CallStack; +using google_breakpad::StackFrameSymbolizer; using google_breakpad::StackFrame; using google_breakpad::StackFrameARM; using google_breakpad::StackwalkerARM; @@ -134,8 +135,9 @@ TEST_F(SanityCheck, NoResolver) { // Since we have no call frame information, and all unwinding // requires call frame information, the stack walk will end after // the first frame. + StackFrameSymbolizer frame_symbolizer(NULL, NULL); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - NULL, NULL); + &frame_symbolizer); // This should succeed even without a resolver or supplier. ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); @@ -152,8 +154,9 @@ TEST_F(GetContextFrame, Simple) { // Since we have no call frame information, and all unwinding // requires call frame information, the stack walk will end after // the first frame. + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(1U, frames->size()); @@ -199,8 +202,9 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) { raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510; raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(3U, frames->size()); @@ -262,8 +266,9 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { // The calling frame's function. "FUNC 100 400 10 marsupial\n"); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -372,8 +377,9 @@ struct CFIFixture: public StackwalkerARMFixture { RegionFromSection(); raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, - &modules, &supplier, &resolver); + &modules, &frame_symbolizer); walker.SetContextFrameValidity(context_frame_validity); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); @@ -564,8 +570,9 @@ TEST_F(CFI, RejectBackwards) { raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40006000; raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000; raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = 0x40005510; + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(1U, frames->size()); @@ -575,8 +582,9 @@ TEST_F(CFI, RejectBackwards) { TEST_F(CFI, RejectBadExpressions) { raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40007000; raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000; + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(1U, frames->size()); @@ -631,8 +639,9 @@ TEST_F(GetFramesByFramePointer, OnlyFramePointer) { raw_context.iregs[MD_CONTEXT_ARM_REG_IOS_FP] = frame1_fp.Value(); raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP, - &stack_region, &modules, &supplier, &resolver); + &stack_region, &modules, &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); @@ -720,8 +729,9 @@ TEST_F(GetFramesByFramePointer, FramePointerAndCFI) { raw_context.iregs[MD_CONTEXT_ARM_REG_IOS_FP] = frame1_fp.Value(); raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP, - &stack_region, &modules, &supplier, &resolver); + &stack_region, &modules, &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); diff --git a/src/processor/stackwalker_ppc.cc b/src/processor/stackwalker_ppc.cc index 4d9a6282..6359e737 100644 --- a/src/processor/stackwalker_ppc.cc +++ b/src/processor/stackwalker_ppc.cc @@ -43,13 +43,12 @@ namespace google_breakpad { -StackwalkerPPC::StackwalkerPPC(const SystemInfo *system_info, - const MDRawContextPPC *context, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver) - : Stackwalker(system_info, memory, modules, supplier, resolver), +StackwalkerPPC::StackwalkerPPC(const SystemInfo* system_info, + const MDRawContextPPC* context, + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* resolver_helper) + : Stackwalker(system_info, memory, modules, resolver_helper), context_(context) { if (memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) { // This implementation only covers 32-bit ppc CPUs. The limits of the @@ -69,7 +68,7 @@ StackFrame* StackwalkerPPC::GetContextFrame() { return NULL; } - StackFramePPC *frame = new StackFramePPC(); + StackFramePPC* frame = new StackFramePPC(); // The instruction pointer is stored directly in a register, so pull it // straight out of the CPU context structure. @@ -82,7 +81,7 @@ StackFrame* StackwalkerPPC::GetContextFrame() { } -StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack *stack) { +StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack* stack) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; return NULL; @@ -97,7 +96,7 @@ StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack *stack) { // frame pointer, and what is typically thought of as the frame pointer on // an x86 is usually referred to as the stack pointer on a ppc. - StackFramePPC *last_frame = static_cast<StackFramePPC*>( + StackFramePPC* last_frame = static_cast<StackFramePPC*>( stack->frames()->back()); // A caller frame must reside higher in memory than its callee frames. @@ -121,7 +120,7 @@ StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack *stack) { return NULL; } - StackFramePPC *frame = new StackFramePPC(); + StackFramePPC* frame = new StackFramePPC(); frame->context = last_frame->context; frame->context.srr0 = instruction; diff --git a/src/processor/stackwalker_ppc.h b/src/processor/stackwalker_ppc.h index bfbb4f82..0c989578 100644 --- a/src/processor/stackwalker_ppc.h +++ b/src/processor/stackwalker_ppc.h @@ -53,23 +53,22 @@ class StackwalkerPPC : public Stackwalker { // register state corresponding to the innermost called frame to be // included in the stack. The other arguments are passed directly through // to the base Stackwalker constructor. - StackwalkerPPC(const SystemInfo *system_info, - const MDRawContextPPC *context, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver); + StackwalkerPPC(const SystemInfo* system_info, + const MDRawContextPPC* context, + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* frame_symbolizer); private: // Implementation of Stackwalker, using ppc context (stack pointer in %r1, // saved program counter in %srr0) and stack conventions (saved stack // pointer at 0(%r1), return address at 8(0(%r1)). virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack *stack); + virtual StackFrame* GetCallerFrame(const CallStack* stack); // Stores the CPU context corresponding to the innermost stack frame to // be returned by GetContextFrame. - const MDRawContextPPC *context_; + const MDRawContextPPC* context_; }; diff --git a/src/processor/stackwalker_sparc.cc b/src/processor/stackwalker_sparc.cc index 2e819a69..ac356baa 100644 --- a/src/processor/stackwalker_sparc.cc +++ b/src/processor/stackwalker_sparc.cc @@ -43,13 +43,12 @@ namespace google_breakpad { -StackwalkerSPARC::StackwalkerSPARC(const SystemInfo *system_info, - const MDRawContextSPARC *context, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver) - : Stackwalker(system_info, memory, modules, supplier, resolver), +StackwalkerSPARC::StackwalkerSPARC(const SystemInfo* system_info, + const MDRawContextSPARC* context, + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* resolver_helper) + : Stackwalker(system_info, memory, modules, resolver_helper), context_(context) { } @@ -60,7 +59,7 @@ StackFrame* StackwalkerSPARC::GetContextFrame() { return NULL; } - StackFrameSPARC *frame = new StackFrameSPARC(); + StackFrameSPARC* frame = new StackFrameSPARC(); // The instruction pointer is stored directly in a register, so pull it // straight out of the CPU context structure. @@ -73,13 +72,13 @@ StackFrame* StackwalkerSPARC::GetContextFrame() { } -StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack *stack) { +StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack* stack) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; return NULL; } - StackFrameSPARC *last_frame = static_cast<StackFrameSPARC*>( + StackFrameSPARC* last_frame = static_cast<StackFrameSPARC*>( stack->frames()->back()); // new: caller @@ -87,7 +86,7 @@ StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack *stack) { // %fp, %i6 and g_r[30] is the same, see minidump_format.h // %sp, %o6 and g_r[14] is the same, see minidump_format.h // %sp_new = %fp_old - // %fp_new = *(%fp_old + 32 + 32 - 8), where the callee's %i6 + // %fp_new = *(%fp_old + 32 + 32 - 8), where the callee's %i6 // %pc_new = *(%fp_old + 32 + 32 - 4) + 8 // which is callee's %i7 plus 8 @@ -111,14 +110,14 @@ StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack *stack) { return NULL; } - StackFrameSPARC *frame = new StackFrameSPARC(); + StackFrameSPARC* frame = new StackFrameSPARC(); frame->context = last_frame->context; frame->context.g_r[14] = stack_pointer; frame->context.g_r[30] = stack_base; - + // frame->context.pc is the return address, which is 2 instruction - // past the branch that caused us to arrive at the callee, which are + // past the branch that caused us to arrive at the callee, which are // a CALL instruction then a NOP instruction. // frame_ppc->instruction to 8 less than that. Since all sparc // instructions are 4 bytes wide, this is the address of the branch @@ -131,7 +130,7 @@ StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack *stack) { StackFrameSPARC::CONTEXT_VALID_SP | StackFrameSPARC::CONTEXT_VALID_FP; frame->trust = StackFrame::FRAME_TRUST_FP; - + return frame; } diff --git a/src/processor/stackwalker_sparc.h b/src/processor/stackwalker_sparc.h index ad41aeab..53fbc843 100644 --- a/src/processor/stackwalker_sparc.h +++ b/src/processor/stackwalker_sparc.h @@ -53,22 +53,21 @@ class StackwalkerSPARC : public Stackwalker { // register state corresponding to the innermost called frame to be // included in the stack. The other arguments are passed directly through // to the base Stackwalker constructor. - StackwalkerSPARC(const SystemInfo *system_info, - const MDRawContextSPARC *context, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver); + StackwalkerSPARC(const SystemInfo* system_info, + const MDRawContextSPARC* context, + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* frame_symbolizer); private: // Implementation of Stackwalker, using sparc context (%fp, %sp, %pc) and // stack conventions virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack *stack); + virtual StackFrame* GetCallerFrame(const CallStack* stack); // Stores the CPU context corresponding to the innermost stack frame to // be returned by GetContextFrame. - const MDRawContextSPARC *context_; + const MDRawContextSPARC* context_; }; diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc index ba3b8396..4ee5beed 100644 --- a/src/processor/stackwalker_x86.cc +++ b/src/processor/stackwalker_x86.cc @@ -33,8 +33,7 @@ // // Author: Mark Mentovai - -#include "processor/postfix_evaluator-inl.h" +#include <string> #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/code_modules.h" @@ -42,6 +41,7 @@ #include "google_breakpad/processor/source_line_resolver_interface.h" #include "google_breakpad/processor/stack_frame_cpu.h" #include "processor/logging.h" +#include "processor/postfix_evaluator-inl.h" #include "processor/scoped_ptr.h" #include "processor/stackwalker_x86.h" #include "processor/windows_frame_info.h" @@ -77,13 +77,12 @@ StackwalkerX86::cfi_register_map_[] = { StackFrameX86::CONTEXT_VALID_EDI, &MDRawContextX86::edi }, }; -StackwalkerX86::StackwalkerX86(const SystemInfo *system_info, - const MDRawContextX86 *context, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver) - : Stackwalker(system_info, memory, modules, supplier, resolver), +StackwalkerX86::StackwalkerX86(const SystemInfo* system_info, + const MDRawContextX86* context, + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* resolver_helper) + : Stackwalker(system_info, memory, modules, resolver_helper), context_(context), cfi_walker_(cfi_register_map_, (sizeof(cfi_register_map_) / sizeof(cfi_register_map_[0]))) { @@ -106,13 +105,13 @@ StackFrameX86::~StackFrameX86() { cfi_frame_info = NULL; } -StackFrame *StackwalkerX86::GetContextFrame() { +StackFrame* StackwalkerX86::GetContextFrame() { if (!context_ || !memory_) { BPLOG(ERROR) << "Can't get context frame without context or memory"; return NULL; } - StackFrameX86 *frame = new StackFrameX86(); + StackFrameX86* frame = new StackFrameX86(); // The instruction pointer is stored directly in a register, so pull it // straight out of the CPU context structure. @@ -124,12 +123,12 @@ StackFrame *StackwalkerX86::GetContextFrame() { return frame; } -StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo( - const vector<StackFrame *> &frames, - WindowsFrameInfo *last_frame_info) { +StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo( + const vector<StackFrame*> &frames, + WindowsFrameInfo* last_frame_info) { StackFrame::FrameTrust trust = StackFrame::FRAME_TRUST_NONE; - StackFrameX86 *last_frame = static_cast<StackFrameX86 *>(frames.back()); + StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); // Save the stack walking info we found, in case we need it later to // find the callee of the frame we're constructing now. @@ -176,9 +175,9 @@ StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo( u_int32_t last_frame_callee_parameter_size = 0; int frames_already_walked = frames.size(); if (frames_already_walked >= 2) { - const StackFrameX86 *last_frame_callee - = static_cast<StackFrameX86 *>(frames[frames_already_walked - 2]); - WindowsFrameInfo *last_frame_callee_info + const StackFrameX86* last_frame_callee + = static_cast<StackFrameX86*>(frames[frames_already_walked - 2]); + WindowsFrameInfo* last_frame_callee_info = last_frame_callee->windows_frame_info; if (last_frame_callee_info && (last_frame_callee_info->valid @@ -210,7 +209,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo( last_frame_info->saved_register_size; u_int32_t raSearchStartOld = raSearchStart; - u_int32_t found = 0; // dummy value + u_int32_t found = 0; // dummy value // Scan up to three words above the calculated search value, in case // the stack was aligned to a quadword boundary. if (ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3) && @@ -419,7 +418,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo( // Create a new stack frame (ownership will be transferred to the caller) // and fill it in. - StackFrameX86 *frame = new StackFrameX86(); + StackFrameX86* frame = new StackFrameX86(); frame->trust = trust; frame->context = last_frame->context; @@ -448,10 +447,10 @@ StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo( return frame; } -StackFrameX86 *StackwalkerX86::GetCallerByCFIFrameInfo( +StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo( const vector<StackFrame*> &frames, - CFIFrameInfo *cfi_frame_info) { - StackFrameX86 *last_frame = static_cast<StackFrameX86*>(frames.back()); + CFIFrameInfo* cfi_frame_info) { + StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); last_frame->cfi_frame_info = cfi_frame_info; scoped_ptr<StackFrameX86> frame(new StackFrameX86()); @@ -460,7 +459,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByCFIFrameInfo( last_frame->context, last_frame->context_validity, &frame->context, &frame->context_validity)) return NULL; - + // Make sure we recovered all the essentials. static const int essentials = (StackFrameX86::CONTEXT_VALID_EIP | StackFrameX86::CONTEXT_VALID_ESP @@ -473,10 +472,10 @@ StackFrameX86 *StackwalkerX86::GetCallerByCFIFrameInfo( return frame.release(); } -StackFrameX86 *StackwalkerX86::GetCallerByEBPAtBase( - const vector<StackFrame *> &frames) { +StackFrameX86* StackwalkerX86::GetCallerByEBPAtBase( + const vector<StackFrame*> &frames) { StackFrame::FrameTrust trust; - StackFrameX86 *last_frame = static_cast<StackFrameX86 *>(frames.back()); + StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); u_int32_t last_esp = last_frame->context.esp; u_int32_t last_ebp = last_frame->context.ebp; @@ -532,7 +531,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByEBPAtBase( // Create a new stack frame (ownership will be transferred to the caller) // and fill it in. - StackFrameX86 *frame = new StackFrameX86(); + StackFrameX86* frame = new StackFrameX86(); frame->trust = trust; frame->context = last_frame->context; @@ -546,26 +545,26 @@ StackFrameX86 *StackwalkerX86::GetCallerByEBPAtBase( return frame; } -StackFrame *StackwalkerX86::GetCallerFrame(const CallStack *stack) { +StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; return NULL; } - const vector<StackFrame *> &frames = *stack->frames(); - StackFrameX86 *last_frame = static_cast<StackFrameX86 *>(frames.back()); + const vector<StackFrame*> &frames = *stack->frames(); + StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); scoped_ptr<StackFrameX86> new_frame; // If the resolver has Windows stack walking information, use that. - WindowsFrameInfo *windows_frame_info - = resolver_ ? resolver_->FindWindowsFrameInfo(last_frame) : NULL; + WindowsFrameInfo* windows_frame_info + = frame_symbolizer_->FindWindowsFrameInfo(last_frame); if (windows_frame_info) new_frame.reset(GetCallerByWindowsFrameInfo(frames, windows_frame_info)); // If the resolver has DWARF CFI information, use that. if (!new_frame.get()) { - CFIFrameInfo *cfi_frame_info = - resolver_ ? resolver_->FindCFIFrameInfo(last_frame) : NULL; + CFIFrameInfo* cfi_frame_info = + frame_symbolizer_->FindCFIFrameInfo(last_frame); if (cfi_frame_info) new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info)); } @@ -577,7 +576,7 @@ StackFrame *StackwalkerX86::GetCallerFrame(const CallStack *stack) { // If nothing worked, tell the caller. if (!new_frame.get()) return NULL; - + // Treat an instruction address of 0 as end-of-stack. if (new_frame->context.eip == 0) return NULL; diff --git a/src/processor/stackwalker_x86.h b/src/processor/stackwalker_x86.h index 9c56ae80..410a473d 100644 --- a/src/processor/stackwalker_x86.h +++ b/src/processor/stackwalker_x86.h @@ -1,4 +1,4 @@ -// -*- mode: c++ -*- +// -*- mode: c++ -*- // Copyright (c) 2010 Google Inc. // All rights reserved. @@ -40,6 +40,7 @@ #ifndef PROCESSOR_STACKWALKER_X86_H__ #define PROCESSOR_STACKWALKER_X86_H__ +#include <vector> #include "google_breakpad/common/breakpad_types.h" #include "google_breakpad/common/minidump_format.h" @@ -58,12 +59,11 @@ class StackwalkerX86 : public Stackwalker { // register state corresponding to the innermost called frame to be // included in the stack. The other arguments are passed directly through // to the base Stackwalker constructor. - StackwalkerX86(const SystemInfo *system_info, - const MDRawContextX86 *context, - MemoryRegion *memory, - const CodeModules *modules, - SymbolSupplier *supplier, - SourceLineResolverInterface *resolver); + StackwalkerX86(const SystemInfo* system_info, + const MDRawContextX86* context, + MemoryRegion* memory, + const CodeModules* modules, + StackFrameSymbolizer* frame_symbolizer); private: // A STACK CFI-driven frame walker for the X86. @@ -73,32 +73,32 @@ class StackwalkerX86 : public Stackwalker { // stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp], or // alternate conventions as guided by any WindowsFrameInfo available for the // code in question.). - virtual StackFrame *GetContextFrame(); - virtual StackFrame *GetCallerFrame(const CallStack *stack); + virtual StackFrame* GetContextFrame(); + virtual StackFrame* GetCallerFrame(const CallStack* stack); // Use windows_frame_info (derived from STACK WIN and FUNC records) // to construct the frame that called frames.back(). The caller // takes ownership of the returned frame. Return NULL on failure. - StackFrameX86 *GetCallerByWindowsFrameInfo( + StackFrameX86* GetCallerByWindowsFrameInfo( const vector<StackFrame*> &frames, - WindowsFrameInfo *windows_frame_info); + WindowsFrameInfo* windows_frame_info); // Use cfi_frame_info (derived from STACK CFI records) to construct // the frame that called frames.back(). The caller takes ownership // of the returned frame. Return NULL on failure. - StackFrameX86 *GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames, - CFIFrameInfo *cfi_frame_info); + StackFrameX86* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames, + CFIFrameInfo* cfi_frame_info); // Assuming a traditional frame layout --- where the caller's %ebp // has been pushed just after the return address and the callee's // %ebp points to the saved %ebp --- construct the frame that called // frames.back(). The caller takes ownership of the returned frame. // Return NULL on failure. - StackFrameX86 *GetCallerByEBPAtBase(const vector<StackFrame*> &frames); + StackFrameX86* GetCallerByEBPAtBase(const vector<StackFrame*> &frames); // Stores the CPU context corresponding to the innermost stack frame to // be returned by GetContextFrame. - const MDRawContextX86 *context_; + const MDRawContextX86* context_; // Our register map, for cfi_walker_. static const CFIWalker::RegisterSet cfi_register_map_[]; diff --git a/src/processor/stackwalker_x86_unittest.cc b/src/processor/stackwalker_x86_unittest.cc index 08e2a6eb..23efe87d 100644 --- a/src/processor/stackwalker_x86_unittest.cc +++ b/src/processor/stackwalker_x86_unittest.cc @@ -48,6 +48,7 @@ using google_breakpad::BasicSourceLineResolver; using google_breakpad::CallStack; +using google_breakpad::StackFrameSymbolizer; using google_breakpad::StackFrame; using google_breakpad::StackFrameX86; using google_breakpad::StackwalkerX86; @@ -148,8 +149,9 @@ TEST_F(SanityCheck, NoResolver) { raw_context.eip = 0x40000200; raw_context.ebp = 0x80000000; + StackFrameSymbolizer frame_symbolizer(NULL, NULL); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - NULL, NULL); + &frame_symbolizer); // This should succeed, even without a resolver or supplier. ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); @@ -168,8 +170,9 @@ TEST_F(GetContextFrame, Simple) { raw_context.eip = 0x40000200; raw_context.ebp = 0x80000000; + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0)); @@ -200,8 +203,9 @@ TEST_F(GetCallerFrame, Traditional) { raw_context.esp = stack_section.start().Value(); raw_context.ebp = frame0_ebp.Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -255,8 +259,9 @@ TEST_F(GetCallerFrame, TraditionalScan) { // for something that looks like a return address. raw_context.ebp = 0xd43eed6e; + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -316,8 +321,9 @@ TEST_F(GetCallerFrame, TraditionalScanLongWay) { // for something that looks like a return address. raw_context.ebp = 0xd43eed6e; + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -387,8 +393,9 @@ TEST_F(GetCallerFrame, WindowsFrameData) { raw_context.esp = stack_section.start().Value(); raw_context.ebp = 0xf052c1de; // should not be needed to walk frame + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -458,8 +465,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataAligned) { raw_context.esp = stack_section.start().Value(); raw_context.ebp = 0xf052c1de; // should not be needed to walk frame + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -540,8 +548,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) { raw_context.esp = stack_section.start().Value(); raw_context.ebp = frame0_ebp.Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(3U, frames->size()); @@ -634,8 +643,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataScan) { raw_context.esp = stack_section.start().Value(); raw_context.ebp = 0x2ae314cd; // should not be needed to walk frame + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -717,8 +727,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) { raw_context.esp = stack_section.start().Value(); raw_context.ebp = frame0_ebp.Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -784,8 +795,9 @@ TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) { // Frame pointer unchanged from caller. raw_context.ebp = frame1_ebp.Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -860,8 +872,9 @@ TEST_F(GetCallerFrame, WindowsFPOUsedEBP) { // RaisedByTheAliens uses %ebp for its own mysterious purposes. raw_context.ebp = 0xecbdd1a5; + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -997,8 +1010,9 @@ TEST_F(GetCallerFrame, WindowsFPOSystemCall) { ASSERT_TRUE(raw_context.esp == frame0_esp.Value()); raw_context.ebp = frame1_ebp.Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); @@ -1097,8 +1111,9 @@ struct CFIFixture: public StackwalkerX86Fixture { RegionFromSection(); raw_context.esp = stack_section.start().Value(); + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &supplier, &resolver); + &frame_symbolizer); ASSERT_TRUE(walker.Walk(&call_stack)); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); |