From 60b5f7c7e9a5c0856ce6f0e61af03fcb1fbb54bb Mon Sep 17 00:00:00 2001 From: "ivan.penkov@gmail.com" Date: Wed, 6 Mar 2013 19:32:13 +0000 Subject: Keeping track of modules without symbols during crash report processing. http://breakpad.appspot.com/534002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1126 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/google_breakpad/processor/process_state.h | 6 +++ src/google_breakpad/processor/stackwalker.h | 12 ++++- src/processor/minidump_processor.cc | 7 +-- src/processor/minidump_stackwalk.cc | 57 +++++++++++++++++---- src/processor/process_state.cc | 3 ++ src/processor/stackwalker.cc | 28 +++++++++- src/processor/stackwalker_amd64_unittest.cc | 35 ++++++++++--- src/processor/stackwalker_arm_unittest.cc | 53 +++++++++++++++---- src/processor/stackwalker_selftest.cc | 5 +- src/processor/stackwalker_x86_unittest.cc | 73 +++++++++++++++++++++------ 10 files changed, 230 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/google_breakpad/processor/process_state.h b/src/google_breakpad/processor/process_state.h index 780cb548..d234ebbf 100644 --- a/src/google_breakpad/processor/process_state.h +++ b/src/google_breakpad/processor/process_state.h @@ -106,6 +106,9 @@ class ProcessState { } const SystemInfo* system_info() const { return &system_info_; } const CodeModules* modules() const { return modules_; } + const vector* modules_without_symbols() const { + return &modules_without_symbols_; + } ExploitabilityRating exploitability() const { return exploitability_; } private: @@ -158,6 +161,9 @@ class ProcessState { // ProcessState. const CodeModules *modules_; + // The modules that didn't have symbols when the report was processed. + vector modules_without_symbols_; + // The exploitability rating as determined by the exploitability // engine. When the exploitability engine is not enabled this // defaults to EXPLOITABILITY_NONE. diff --git a/src/google_breakpad/processor/stackwalker.h b/src/google_breakpad/processor/stackwalker.h index 9e678e3c..f09291fe 100644 --- a/src/google_breakpad/processor/stackwalker.h +++ b/src/google_breakpad/processor/stackwalker.h @@ -43,6 +43,7 @@ #include #include +#include #include "common/using_std_string.h" #include "google_breakpad/common/breakpad_types.h" @@ -57,6 +58,7 @@ class MinidumpContext; class StackFrameSymbolizer; using std::set; +using std::vector; class Stackwalker { public: @@ -66,7 +68,15 @@ class Stackwalker { // GetCallerFrame. The frames are further processed to fill all available // data. Returns true if the stackwalk completed, or false if it was // interrupted by SymbolSupplier::GetSymbolFile(). - bool Walk(CallStack* stack); + // Upon return, modules_without_symbols will be populated with pointers to + // the code modules (CodeModule*) that DON'T have symbols. + // modules_without_symbols DOES NOT take ownership of the code modules. + // The lifetime of these code modules is the same as the lifetime of the + // CodeModules passed to the StackWalker constructor (which currently + // happens to be the lifetime of the Breakpad's ProcessingState object). + // There is a check for duplicate modules so no duplicates are expected. + bool Walk(CallStack* stack, + vector* modules_without_symbols); // Returns a new concrete subclass suitable for the CPU that a stack was // generated on, according to the CPU type indicated by the context diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc index 059d8849..08682780 100644 --- a/src/processor/minidump_processor.cc +++ b/src/processor/minidump_processor.cc @@ -227,9 +227,10 @@ ProcessResult MinidumpProcessor::Process( scoped_ptr stack(new CallStack()); if (stackwalker.get()) { - if (!stackwalker->Walk(stack.get())) { - BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at " << - thread_string; + if (!stackwalker->Walk(stack.get(), + &process_state->modules_without_symbols_)) { + BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at " + << thread_string; interrupted = true; } } else { diff --git a/src/processor/minidump_stackwalk.cc b/src/processor/minidump_stackwalk.cc index 7b930e46..6bf78ac1 100644 --- a/src/processor/minidump_stackwalk.cc +++ b/src/processor/minidump_stackwalk.cc @@ -333,7 +333,51 @@ static void PrintStackMachineReadable(int thread_num, const CallStack *stack) { } } -static void PrintModules(const CodeModules *modules) { +// ContainsModule checks whether a given |module| is in the vector +// |modules_without_symbols|. +static bool ContainsModule( + const vector *modules, + const CodeModule *module) { + assert(modules); + assert(module); + vector::const_iterator iter; + for (iter = modules->begin(); iter != modules->end(); ++iter) { + if (module->debug_file().compare((*iter)->debug_file()) == 0 && + module->debug_identifier().compare((*iter)->debug_identifier()) == 0) { + return true; + } + } + return false; +} + +// PrintModule prints a single |module| to stdout. +// |modules_without_symbols| should contain the list of modules that were +// confirmed to be missing their symbols during the stack walk. +static void PrintModule( + const CodeModule *module, + const vector *modules_without_symbols, + uint64_t main_address) { + string missing_symbols; + if (ContainsModule(modules_without_symbols, module)) { + missing_symbols = " (WARNING: No symbols, " + + PathnameStripper::File(module->debug_file()) + ", " + + module->debug_identifier() + ")"; + } + uint64_t base_address = module->base_address(); + printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s%s\n", + base_address, base_address + module->size() - 1, + PathnameStripper::File(module->code_file()).c_str(), + module->version().empty() ? "???" : module->version().c_str(), + main_address != 0 && base_address == main_address ? " (main)" : "", + missing_symbols.c_str()); +} + +// PrintModules prints the list of all loaded |modules| to stdout. +// |modules_without_symbols| should contain the list of modules that were +// confirmed to be missing their symbols during the stack walk. +static void PrintModules( + const CodeModules *modules, + const vector *modules_without_symbols) { if (!modules) return; @@ -351,13 +395,7 @@ static void PrintModules(const CodeModules *modules) { module_sequence < module_count; ++module_sequence) { const CodeModule *module = modules->GetModuleAtSequence(module_sequence); - uint64_t base_address = module->base_address(); - printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s\n", - base_address, base_address + module->size() - 1, - PathnameStripper::File(module->code_file()).c_str(), - module->version().empty() ? "???" : module->version().c_str(), - main_module != NULL && base_address == main_address ? - " (main)" : ""); + PrintModule(module, modules_without_symbols, main_address); } } @@ -449,7 +487,8 @@ static void PrintProcessState(const ProcessState& process_state) { } } - PrintModules(process_state.modules()); + PrintModules(process_state.modules(), + process_state.modules_without_symbols()); } static void PrintProcessStateMachineReadable(const ProcessState& process_state) diff --git a/src/processor/process_state.cc b/src/processor/process_state.cc index 1d970bad..6c3a6567 100644 --- a/src/processor/process_state.cc +++ b/src/processor/process_state.cc @@ -57,6 +57,9 @@ void ProcessState::Clear() { } threads_.clear(); system_info_.Clear(); + // modules_without_symbols_ DOES NOT owns the underlying CodeModule pointers. + // Just clear the vector. + modules_without_symbols_.clear(); delete modules_; modules_ = NULL; } diff --git a/src/processor/stackwalker.cc b/src/processor/stackwalker.cc index c1b290e6..a92d71b8 100644 --- a/src/processor/stackwalker.cc +++ b/src/processor/stackwalker.cc @@ -70,11 +70,16 @@ Stackwalker::Stackwalker(const SystemInfo* system_info, } -bool Stackwalker::Walk(CallStack* stack) { +bool Stackwalker::Walk(CallStack* stack, + vector* modules_without_symbols) { BPLOG_IF(ERROR, !stack) << "Stackwalker::Walk requires |stack|"; assert(stack); stack->Clear(); + BPLOG_IF(ERROR, !modules_without_symbols) << "Stackwalker::Walk requires " + << "|modules_without_symbols|"; + assert(modules_without_symbols); + // Begin with the context frame, and keep getting callers until there are // no more. @@ -95,6 +100,27 @@ bool Stackwalker::Walk(CallStack* stack) { return false; } + // Keep track of modules that have no symbols. + if (symbolizer_result == StackFrameSymbolizer::kError && + frame->module != NULL) { + bool found = false; + vector::iterator iter; + for (iter = modules_without_symbols->begin(); + iter != modules_without_symbols->end(); + ++iter) { + if (*iter == frame->module) { + found = true; + break; + } + } + if (!found) { + BPLOG(INFO) << "Couldn't load symbols for: " + << frame->module->debug_file() << "|" + << frame->module->debug_identifier(); + modules_without_symbols->push_back(frame->module); + } + } + // Add the frame to the call stack. Relinquish the ownership claim // over the frame, because the stack now owns it. stack->frames_.push_back(frame.release()); diff --git a/src/processor/stackwalker_amd64_unittest.cc b/src/processor/stackwalker_amd64_unittest.cc index a726e8ac..8faf09ab 100644 --- a/src/processor/stackwalker_amd64_unittest.cc +++ b/src/processor/stackwalker_amd64_unittest.cc @@ -41,6 +41,7 @@ #include "google_breakpad/common/minidump_format.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/code_module.h" #include "google_breakpad/processor/source_line_resolver_interface.h" #include "google_breakpad/processor/stack_frame_cpu.h" #include "processor/stackwalker_unittest_utils.h" @@ -48,6 +49,7 @@ using google_breakpad::BasicSourceLineResolver; using google_breakpad::CallStack; +using google_breakpad::CodeModule; using google_breakpad::StackFrameSymbolizer; using google_breakpad::StackFrame; using google_breakpad::StackFrameAMD64; @@ -143,7 +145,10 @@ TEST_F(SanityCheck, NoResolver) { StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); // This should succeed even without a resolver or supplier. - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(1U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); frames = call_stack.frames(); ASSERT_GE(1U, frames->size()); StackFrameAMD64 *frame = static_cast(frames->at(0)); @@ -163,7 +168,10 @@ TEST_F(GetContextFrame, Simple) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(1U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); frames = call_stack.frames(); ASSERT_GE(1U, frames->size()); StackFrameAMD64 *frame = static_cast(frames->at(0)); @@ -181,7 +189,10 @@ TEST_F(GetContextFrame, NoStackMemory) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerAMD64 walker(&system_info, &raw_context, NULL, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(1U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); frames = call_stack.frames(); ASSERT_GE(1U, frames->size()); StackFrameAMD64 *frame = static_cast(frames->at(0)); @@ -236,7 +247,11 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(2U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); + ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); frames = call_stack.frames(); ASSERT_EQ(3U, frames->size()); @@ -304,7 +319,9 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -369,7 +386,9 @@ TEST_F(GetCallerFrame, CallerPushedRBP) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -445,7 +464,9 @@ struct CFIFixture: public StackwalkerAMD64Fixture { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); diff --git a/src/processor/stackwalker_arm_unittest.cc b/src/processor/stackwalker_arm_unittest.cc index f1d18bb7..588b5c5f 100644 --- a/src/processor/stackwalker_arm_unittest.cc +++ b/src/processor/stackwalker_arm_unittest.cc @@ -41,6 +41,7 @@ #include "google_breakpad/common/minidump_format.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/code_module.h" #include "google_breakpad/processor/source_line_resolver_interface.h" #include "google_breakpad/processor/stack_frame_cpu.h" #include "processor/stackwalker_unittest_utils.h" @@ -49,6 +50,7 @@ using google_breakpad::BasicSourceLineResolver; using google_breakpad::CallStack; +using google_breakpad::CodeModule; using google_breakpad::StackFrameSymbolizer; using google_breakpad::StackFrame; using google_breakpad::StackFrameARM; @@ -139,7 +141,9 @@ TEST_F(SanityCheck, NoResolver) { StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, &frame_symbolizer); // This should succeed even without a resolver or supplier. - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(1U, frames->size()); StackFrameARM *frame = static_cast(frames->at(0)); @@ -157,7 +161,9 @@ TEST_F(GetContextFrame, Simple) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(1U, frames->size()); StackFrameARM *frame = static_cast(frames->at(0)); @@ -172,7 +178,9 @@ TEST_F(GetContextFrame, NoStackMemory) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, NULL, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(1U, frames->size()); StackFrameARM *frame = static_cast(frames->at(0)); @@ -220,7 +228,11 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(2U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); + ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); frames = call_stack.frames(); ASSERT_EQ(3U, frames->size()); @@ -284,7 +296,9 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -345,7 +359,11 @@ TEST_F(GetCallerFrame, ScanFirstFrame) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(2U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); + ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -453,7 +471,9 @@ struct CFIFixture: public StackwalkerARMFixture { StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, &frame_symbolizer); walker.SetContextFrameValidity(context_frame_validity); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -645,7 +665,9 @@ TEST_F(CFI, RejectBackwards) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(1U, frames->size()); } @@ -657,7 +679,9 @@ TEST_F(CFI, RejectBadExpressions) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(1U, frames->size()); } @@ -715,7 +739,11 @@ TEST_F(GetFramesByFramePointer, OnlyFramePointer) { StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(2U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); + ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); frames = call_stack.frames(); ASSERT_EQ(3U, frames->size()); @@ -805,7 +833,10 @@ TEST_F(GetFramesByFramePointer, FramePointerAndCFI) { StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(1U, modules_without_symbols.size()); + ASSERT_EQ("module2", modules_without_symbols[0]->debug_file()); frames = call_stack.frames(); ASSERT_EQ(3U, frames->size()); diff --git a/src/processor/stackwalker_selftest.cc b/src/processor/stackwalker_selftest.cc index 99644d7a..75d47582 100644 --- a/src/processor/stackwalker_selftest.cc +++ b/src/processor/stackwalker_selftest.cc @@ -69,12 +69,14 @@ #include "google_breakpad/common/minidump_format.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/code_module.h" #include "google_breakpad/processor/memory_region.h" #include "google_breakpad/processor/stack_frame.h" #include "google_breakpad/processor/stack_frame_cpu.h" using google_breakpad::BasicSourceLineResolver; using google_breakpad::CallStack; +using google_breakpad::CodeModule; using google_breakpad::MemoryRegion; using google_breakpad::scoped_ptr; using google_breakpad::StackFrame; @@ -337,7 +339,8 @@ static unsigned int CountCallerFrames() { #endif // __i386__ || __ppc__ || __sparc__ CallStack stack; - stackwalker.Walk(&stack); + vector modules_without_symbols; + stackwalker.Walk(&stack, &modules_without_symbols); #ifdef PRINT_STACKS printf("\n"); diff --git a/src/processor/stackwalker_x86_unittest.cc b/src/processor/stackwalker_x86_unittest.cc index 841ad0d8..caf899e6 100644 --- a/src/processor/stackwalker_x86_unittest.cc +++ b/src/processor/stackwalker_x86_unittest.cc @@ -40,6 +40,7 @@ #include "google_breakpad/common/minidump_format.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/code_module.h" #include "google_breakpad/processor/source_line_resolver_interface.h" #include "google_breakpad/processor/stack_frame_cpu.h" #include "processor/stackwalker_unittest_utils.h" @@ -48,6 +49,7 @@ using google_breakpad::BasicSourceLineResolver; using google_breakpad::CallStack; +using google_breakpad::CodeModule; using google_breakpad::StackFrameSymbolizer; using google_breakpad::StackFrame; using google_breakpad::StackFrameX86; @@ -153,7 +155,10 @@ TEST_F(SanityCheck, NoResolver) { StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); // This should succeed, even without a resolver or supplier. - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(1U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); frames = call_stack.frames(); StackFrameX86 *frame = static_cast(frames->at(0)); // Check that the values from the original raw context made it @@ -173,7 +178,10 @@ TEST_F(GetContextFrame, Simple) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(1U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); frames = call_stack.frames(); StackFrameX86 *frame = static_cast(frames->at(0)); // Check that the values from the original raw context made it @@ -190,7 +198,10 @@ TEST_F(GetContextFrame, NoStackMemory) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, NULL, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(1U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); frames = call_stack.frames(); StackFrameX86 *frame = static_cast(frames->at(0)); // Check that the values from the original raw context made it @@ -223,7 +234,10 @@ TEST_F(GetCallerFrame, Traditional) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(1U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -279,7 +293,10 @@ TEST_F(GetCallerFrame, TraditionalScan) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(1U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -341,7 +358,10 @@ TEST_F(GetCallerFrame, TraditionalScanLongWay) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(1U, modules_without_symbols.size()); + ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -413,7 +433,9 @@ TEST_F(GetCallerFrame, WindowsFrameData) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -485,7 +507,10 @@ TEST_F(GetCallerFrame, WindowsFrameDataAligned) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(1U, modules_without_symbols.size()); + ASSERT_EQ("module2", modules_without_symbols[0]->debug_file()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -568,7 +593,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(3U, frames->size()); @@ -663,7 +690,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataScan) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -747,7 +776,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -815,7 +846,9 @@ TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -892,7 +925,9 @@ TEST_F(GetCallerFrame, WindowsFPOUsedEBP) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); @@ -1030,7 +1065,9 @@ TEST_F(GetCallerFrame, WindowsFPOSystemCall) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(4U, frames->size()); @@ -1238,7 +1275,9 @@ TEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &local_modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(3U, frames->size()); @@ -1365,7 +1404,9 @@ struct CFIFixture: public StackwalkerX86Fixture { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); - ASSERT_TRUE(walker.Walk(&call_stack)); + vector modules_without_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols)); + ASSERT_EQ(0U, modules_without_symbols.size()); frames = call_stack.frames(); ASSERT_EQ(2U, frames->size()); -- cgit v1.2.1