From 97d392dc4b60f0099cd7ad8c8a5f06581a532392 Mon Sep 17 00:00:00 2001 From: mmentovai Date: Wed, 10 Jan 2007 22:47:56 +0000 Subject: Communicate OS and CPU to SymbolSupplier (#107). r=bryner Interface change: moved a few fields around in ProcessState; added new arguments to Stackwalker and SymbolSupplier. http://groups.google.com/group/airbag-dev/browse_thread/thread/17e4a48ec3ede932 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@101 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/processor/minidump.cc | 46 ++++++++++++ src/processor/minidump_processor.cc | 102 +++++++++++++-------------- src/processor/minidump_processor_unittest.cc | 43 +++++++++-- src/processor/minidump_stackwalk.cc | 9 +-- src/processor/process_state.cc | 5 +- src/processor/simple_symbol_supplier.cc | 4 +- src/processor/simple_symbol_supplier.h | 4 +- src/processor/stackwalker.cc | 16 +++-- src/processor/stackwalker_ppc.cc | 5 +- src/processor/stackwalker_ppc.h | 3 +- src/processor/stackwalker_selftest.cc | 8 +-- src/processor/stackwalker_x86.cc | 5 +- src/processor/stackwalker_x86.h | 3 +- 13 files changed, 171 insertions(+), 82 deletions(-) (limited to 'src/processor') diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc index 34796d19..d27e14b3 100644 --- a/src/processor/minidump.cc +++ b/src/processor/minidump.cc @@ -2047,6 +2047,52 @@ bool MinidumpSystemInfo::Read(u_int32_t expected_size) { } +string MinidumpSystemInfo::GetOS() { + if (!valid_) + return NULL; + + string os; + + switch (system_info_.platform_id) { + case MD_OS_WIN32_NT: + case MD_OS_WIN32_WINDOWS: + os = "windows"; + break; + + case MD_OS_MAC_OS_X: + os = "mac"; + break; + + case MD_OS_LINUX: + os = "linux"; + break; + } + + return os; +} + + +string MinidumpSystemInfo::GetCPU() { + if (!valid_) + return ""; + + string cpu; + + switch (system_info_.processor_architecture) { + case MD_CPU_ARCHITECTURE_X86: + case MD_CPU_ARCHITECTURE_X86_WIN64: + cpu = "x86"; + break; + + case MD_CPU_ARCHITECTURE_PPC: + cpu = "ppc"; + break; + } + + return cpu; +} + + const string* MinidumpSystemInfo::GetCSDVersion() { if (!valid_) return NULL; diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc index dd4c7156..e1dd5e1c 100644 --- a/src/processor/minidump_processor.cc +++ b/src/processor/minidump_processor.cc @@ -59,8 +59,8 @@ MinidumpProcessor::ProcessResult MinidumpProcessor::Process( assert(header); process_state->time_date_stamp_ = header->time_date_stamp; - process_state->cpu_ = GetCPUInfo(&dump, &process_state->cpu_info_); - process_state->os_ = GetOSInfo(&dump, &process_state->os_version_); + GetCPUInfo(&dump, &process_state->system_info_); + GetOSInfo(&dump, &process_state->system_info_); u_int32_t dump_thread_id = 0; bool has_dump_thread = false; @@ -162,7 +162,8 @@ MinidumpProcessor::ProcessResult MinidumpProcessor::Process( // (just like the StackFrame objects), and is much more suitable for this // task. scoped_ptr stackwalker( - Stackwalker::StackwalkerForCPU(context, + Stackwalker::StackwalkerForCPU(process_state->system_info(), + context, thread_memory, process_state->modules_, supplier_, @@ -202,38 +203,38 @@ static const MDRawSystemInfo* GetSystemInfo(Minidump *dump, } // static -string MinidumpProcessor::GetCPUInfo(Minidump *dump, string *cpu_info) { - if (cpu_info) - cpu_info->clear(); +void MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) { + assert(dump); + assert(info); + + info->cpu.clear(); + info->cpu_info.clear(); MinidumpSystemInfo *system_info; const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); if (!raw_system_info) - return ""; + return; - string cpu; switch (raw_system_info->processor_architecture) { case MD_CPU_ARCHITECTURE_X86: { - cpu = "x86"; - if (cpu_info) { - const string *cpu_vendor = system_info->GetCPUVendor(); - if (cpu_vendor) { - cpu_info->assign(*cpu_vendor); - cpu_info->append(" "); - } - - char x86_info[36]; - snprintf(x86_info, sizeof(x86_info), "family %u model %u stepping %u", - raw_system_info->processor_level, - raw_system_info->processor_revision >> 8, - raw_system_info->processor_revision & 0xff); - cpu_info->append(x86_info); + info->cpu = "x86"; + const string *cpu_vendor = system_info->GetCPUVendor(); + if (cpu_vendor) { + info->cpu_info = *cpu_vendor; + info->cpu_info.append(" "); } + + char x86_info[36]; + snprintf(x86_info, sizeof(x86_info), "family %u model %u stepping %u", + raw_system_info->processor_level, + raw_system_info->processor_revision >> 8, + raw_system_info->processor_revision & 0xff); + info->cpu_info.append(x86_info); break; } case MD_CPU_ARCHITECTURE_PPC: { - cpu = "ppc"; + info->cpu = "ppc"; break; } @@ -242,43 +243,46 @@ string MinidumpProcessor::GetCPUInfo(Minidump *dump, string *cpu_info) { char cpu_string[7]; snprintf(cpu_string, sizeof(cpu_string), "0x%04x", raw_system_info->processor_architecture); - cpu = cpu_string; + info->cpu = cpu_string; break; } } - - return cpu; } // static -string MinidumpProcessor::GetOSInfo(Minidump *dump, string *os_version) { - if (os_version) - os_version->clear(); +void MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) { + assert(dump); + assert(info); + + info->os.clear(); + info->os_short.clear(); + info->os_version.clear(); MinidumpSystemInfo *system_info; const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); if (!raw_system_info) - return ""; + return; + + info->os_short = system_info->GetOS(); - string os; switch (raw_system_info->platform_id) { case MD_OS_WIN32_NT: { - os = "Windows NT"; + info->os = "Windows NT"; break; } case MD_OS_WIN32_WINDOWS: { - os = "Windows"; + info->os = "Windows"; break; } case MD_OS_MAC_OS_X: { - os = "Mac OS X"; + info->os = "Mac OS X"; break; } case MD_OS_LINUX: { - os = "Linux"; + info->os = "Linux"; break; } @@ -287,27 +291,23 @@ string MinidumpProcessor::GetOSInfo(Minidump *dump, string *os_version) { char os_string[11]; snprintf(os_string, sizeof(os_string), "0x%08x", raw_system_info->platform_id); - os = os_string; + info->os = os_string; break; } } - if (os_version) { - char os_version_string[33]; - snprintf(os_version_string, sizeof(os_version_string), "%u.%u.%u", - raw_system_info->major_version, - raw_system_info->minor_version, - raw_system_info->build_number); - os_version->assign(os_version_string); - - const string *csd_version = system_info->GetCSDVersion(); - if (csd_version) { - os_version->append(" "); - os_version->append(*csd_version); - } + char os_version_string[33]; + snprintf(os_version_string, sizeof(os_version_string), "%u.%u.%u", + raw_system_info->major_version, + raw_system_info->minor_version, + raw_system_info->build_number); + info->os_version = os_version_string; + + const string *csd_version = system_info->GetCSDVersion(); + if (csd_version) { + info->os_version.append(" "); + info->os_version.append(*csd_version); } - - return os; } // static diff --git a/src/processor/minidump_processor_unittest.cc b/src/processor/minidump_processor_unittest.cc index 69a29965..d7381ae1 100644 --- a/src/processor/minidump_processor_unittest.cc +++ b/src/processor/minidump_processor_unittest.cc @@ -30,6 +30,7 @@ // Unit test for MinidumpProcessor. Uses a pre-generated minidump and // corresponding symbol file, and checks the stack frames for correctness. +#include #include #include "google_airbag/processor/basic_source_line_resolver.h" #include "google_airbag/processor/call_stack.h" @@ -51,6 +52,14 @@ using google_airbag::MinidumpProcessor; using google_airbag::ProcessState; using google_airbag::scoped_ptr; using google_airbag::SymbolSupplier; +using google_airbag::SystemInfo; + +static const char *kSystemInfoOS = "Windows NT"; +static const char *kSystemInfoOSShort = "windows"; +static const char *kSystemInfoOSVersion = "5.1.2600 Service Pack 2"; +static const char *kSystemInfoCPU = "x86"; +static const char *kSystemInfoCPUInfo = + "GenuineIntel family 6 model 13 stepping 8"; #define ASSERT_TRUE(cond) \ if (!(cond)) { \ @@ -62,11 +71,21 @@ using google_airbag::SymbolSupplier; #define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2)) +// Use ASSERT_*_ABORT in functions that can't return a boolean. +#define ASSERT_TRUE_ABORT(cond) \ + if (!(cond)) { \ + fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \ + abort(); \ + } + +#define ASSERT_EQ_ABORT(e1, e2) ASSERT_TRUE_ABORT((e1) == (e2)) + class TestSymbolSupplier : public SymbolSupplier { public: TestSymbolSupplier() : interrupt_(false) {} virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, string *symbol_file); // When set to true, causes the SymbolSupplier to return INTERRUPT @@ -77,7 +96,17 @@ class TestSymbolSupplier : public SymbolSupplier { }; SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile( - const CodeModule *module, string *symbol_file) { + const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file) { + ASSERT_TRUE_ABORT(module); + ASSERT_TRUE_ABORT(system_info); + ASSERT_EQ_ABORT(system_info->cpu, kSystemInfoCPU); + ASSERT_EQ_ABORT(system_info->cpu_info, kSystemInfoCPUInfo); + ASSERT_EQ_ABORT(system_info->os, kSystemInfoOS); + ASSERT_EQ_ABORT(system_info->os_short, kSystemInfoOSShort); + ASSERT_EQ_ABORT(system_info->os_version, kSystemInfoOSVersion); + if (interrupt_) { return INTERRUPT; } @@ -104,10 +133,11 @@ static bool RunTests() { ProcessState state; ASSERT_EQ(processor.Process(minidump_file, &state), MinidumpProcessor::PROCESS_OK); - ASSERT_EQ(state.cpu(), "x86"); - ASSERT_EQ(state.cpu_info(), "GenuineIntel family 6 model 13 stepping 8"); - ASSERT_EQ(state.os(), "Windows NT"); - ASSERT_EQ(state.os_version(), "5.1.2600 Service Pack 2"); + ASSERT_EQ(state.system_info()->os, kSystemInfoOS); + ASSERT_EQ(state.system_info()->os_short, kSystemInfoOSShort); + ASSERT_EQ(state.system_info()->os_version, kSystemInfoOSVersion); + ASSERT_EQ(state.system_info()->cpu, kSystemInfoCPU); + ASSERT_EQ(state.system_info()->cpu_info, kSystemInfoCPUInfo); ASSERT_TRUE(state.crashed()); ASSERT_EQ(state.crash_reason(), "EXCEPTION_ACCESS_VIOLATION"); ASSERT_EQ(state.crash_address(), 0x45); @@ -121,7 +151,8 @@ static bool RunTests() { ASSERT_TRUE(stack->frames()->at(0)->module); ASSERT_EQ(stack->frames()->at(0)->module->base_address(), 0x400000); ASSERT_EQ(stack->frames()->at(0)->module->code_file(), "C:\\test_app.exe"); - ASSERT_EQ(stack->frames()->at(0)->function_name, "`anonymous namespace'::CrashFunction"); + ASSERT_EQ(stack->frames()->at(0)->function_name, + "`anonymous namespace'::CrashFunction"); ASSERT_EQ(stack->frames()->at(0)->source_file_name, "c:\\test_app.cc"); ASSERT_EQ(stack->frames()->at(0)->source_line, 56); diff --git a/src/processor/minidump_stackwalk.cc b/src/processor/minidump_stackwalk.cc index 2bd32d7a..e86fbdf6 100644 --- a/src/processor/minidump_stackwalk.cc +++ b/src/processor/minidump_stackwalk.cc @@ -206,10 +206,11 @@ static bool PrintMinidumpProcess(const string &minidump_file, } // Print OS and CPU information. - string cpu = process_state.cpu(); - string cpu_info = process_state.cpu_info(); - printf("Operating system: %s\n", process_state.os().c_str()); - printf(" %s\n", process_state.os_version().c_str()); + string cpu = process_state.system_info()->cpu; + string cpu_info = process_state.system_info()->cpu_info; + printf("Operating system: %s\n", process_state.system_info()->os.c_str()); + printf(" %s\n", + process_state.system_info()->os_version.c_str()); printf("CPU: %s\n", cpu.c_str()); if (!cpu_info.empty()) { // This field is optional. diff --git a/src/processor/process_state.cc b/src/processor/process_state.cc index d1e21cb8..3e90a79b 100644 --- a/src/processor/process_state.cc +++ b/src/processor/process_state.cc @@ -55,10 +55,7 @@ void ProcessState::Clear() { delete *iterator; } threads_.clear(); - os_.clear(); - os_version_.clear(); - cpu_.clear(); - cpu_info_.clear(); + system_info_.Clear(); delete modules_; modules_ = NULL; } diff --git a/src/processor/simple_symbol_supplier.cc b/src/processor/simple_symbol_supplier.cc index e2bd9184..fb16818d 100644 --- a/src/processor/simple_symbol_supplier.cc +++ b/src/processor/simple_symbol_supplier.cc @@ -37,12 +37,14 @@ #include "processor/simple_symbol_supplier.h" #include "google_airbag/processor/code_module.h" +#include "google_airbag/processor/system_info.h" #include "processor/pathname_stripper.h" namespace google_airbag { SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFileAtPath( - const CodeModule *module, const string &root_path, string *symbol_file) { + const CodeModule *module, const SystemInfo *system_info, + const string &root_path, string *symbol_file) { assert(symbol_file); if (!module) return NOT_FOUND; diff --git a/src/processor/simple_symbol_supplier.h b/src/processor/simple_symbol_supplier.h index 9995161e..6359da2a 100644 --- a/src/processor/simple_symbol_supplier.h +++ b/src/processor/simple_symbol_supplier.h @@ -94,12 +94,14 @@ class SimpleSymbolSupplier : public SymbolSupplier { // Returns the path to the symbol file for the given module. See the // description above. virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, string *symbol_file) { - return GetSymbolFileAtPath(module, path_, symbol_file); + return GetSymbolFileAtPath(module, system_info, path_, symbol_file); } protected: SymbolResult GetSymbolFileAtPath(const CodeModule *module, + const SystemInfo *system_info, const string &root_path, string *symbol_file); diff --git a/src/processor/stackwalker.cc b/src/processor/stackwalker.cc index e6a26bb9..d9ca045b 100644 --- a/src/processor/stackwalker.cc +++ b/src/processor/stackwalker.cc @@ -53,10 +53,13 @@ namespace google_airbag { -Stackwalker::Stackwalker(MemoryRegion *memory, const CodeModules *modules, +Stackwalker::Stackwalker(const SystemInfo *system_info, + MemoryRegion *memory, + const CodeModules *modules, SymbolSupplier *supplier, SourceLineResolverInterface *resolver) - : memory_(memory), + : system_info_(system_info), + memory_(memory), modules_(modules), supplier_(supplier), resolver_(resolver) { @@ -96,7 +99,7 @@ bool Stackwalker::Walk(CallStack *stack) { supplier_) { string symbol_file; SymbolSupplier::SymbolResult symbol_result = - supplier_->GetSymbolFile(module, &symbol_file); + supplier_->GetSymbolFile(module, system_info_, &symbol_file); switch (symbol_result) { case SymbolSupplier::FOUND: @@ -130,6 +133,7 @@ bool Stackwalker::Walk(CallStack *stack) { // static Stackwalker* Stackwalker::StackwalkerForCPU( + const SystemInfo *system_info, MinidumpContext *context, MemoryRegion *memory, const CodeModules *modules, @@ -140,13 +144,15 @@ Stackwalker* Stackwalker::StackwalkerForCPU( u_int32_t cpu = context->GetContextCPU(); switch (cpu) { case MD_CONTEXT_X86: - cpu_stackwalker = new StackwalkerX86(context->GetContextX86(), + cpu_stackwalker = new StackwalkerX86(system_info, + context->GetContextX86(), memory, modules, supplier, resolver); break; case MD_CONTEXT_PPC: - cpu_stackwalker = new StackwalkerPPC(context->GetContextPPC(), + cpu_stackwalker = new StackwalkerPPC(system_info, + context->GetContextPPC(), memory, modules, supplier, resolver); break; diff --git a/src/processor/stackwalker_ppc.cc b/src/processor/stackwalker_ppc.cc index ff5243c6..5a8e6002 100644 --- a/src/processor/stackwalker_ppc.cc +++ b/src/processor/stackwalker_ppc.cc @@ -42,12 +42,13 @@ namespace google_airbag { -StackwalkerPPC::StackwalkerPPC(const MDRawContextPPC *context, +StackwalkerPPC::StackwalkerPPC(const SystemInfo *system_info, + const MDRawContextPPC *context, MemoryRegion *memory, const CodeModules *modules, SymbolSupplier *supplier, SourceLineResolverInterface *resolver) - : Stackwalker(memory, modules, supplier, resolver), + : Stackwalker(system_info, memory, modules, supplier, resolver), context_(context) { if (memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) { // This implementation only covers 32-bit ppc CPUs. The limits of the diff --git a/src/processor/stackwalker_ppc.h b/src/processor/stackwalker_ppc.h index 9901f673..68b57f10 100644 --- a/src/processor/stackwalker_ppc.h +++ b/src/processor/stackwalker_ppc.h @@ -53,7 +53,8 @@ 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 MDRawContextPPC *context, + StackwalkerPPC(const SystemInfo *system_info, + const MDRawContextPPC *context, MemoryRegion *memory, const CodeModules *modules, SymbolSupplier *supplier, diff --git a/src/processor/stackwalker_selftest.cc b/src/processor/stackwalker_selftest.cc index af76a8e8..d3b88a6b 100644 --- a/src/processor/stackwalker_selftest.cc +++ b/src/processor/stackwalker_selftest.cc @@ -227,15 +227,15 @@ static unsigned int CountCallerFrames() { context.ebp = GetEBP(); context.esp = GetESP(); - StackwalkerX86 stackwalker = StackwalkerX86(&context, &memory, NULL, NULL, - &resolver); + StackwalkerX86 stackwalker = StackwalkerX86(NULL, &context, &memory, NULL, + NULL, &resolver); #elif defined(__ppc__) MDRawContextPPC context = MDRawContextPPC(); context.srr0 = GetPC(); context.gpr[1] = GetSP(); - StackwalkerPPC stackwalker = StackwalkerPPC(&context, &memory, NULL, NULL, - &resolver); + StackwalkerPPC stackwalker = StackwalkerPPC(NULL, &context, &memory, NULL, + NULL, &resolver); #endif // __i386__ || __ppc__ CallStack stack; diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc index 0ee2fbd2..444746cd 100644 --- a/src/processor/stackwalker_x86.cc +++ b/src/processor/stackwalker_x86.cc @@ -46,12 +46,13 @@ namespace google_airbag { -StackwalkerX86::StackwalkerX86(const MDRawContextX86 *context, +StackwalkerX86::StackwalkerX86(const SystemInfo *system_info, + const MDRawContextX86 *context, MemoryRegion *memory, const CodeModules *modules, SymbolSupplier *supplier, SourceLineResolverInterface *resolver) - : Stackwalker(memory, modules, supplier, resolver), + : Stackwalker(system_info, memory, modules, supplier, resolver), context_(context) { if (memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) { // The x86 is a 32-bit CPU, the limits of the supplied stack are invalid. diff --git a/src/processor/stackwalker_x86.h b/src/processor/stackwalker_x86.h index f53fc5f7..7f034c01 100644 --- a/src/processor/stackwalker_x86.h +++ b/src/processor/stackwalker_x86.h @@ -54,7 +54,8 @@ 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 MDRawContextX86 *context, + StackwalkerX86(const SystemInfo *system_info, + const MDRawContextX86 *context, MemoryRegion *memory, const CodeModules *modules, SymbolSupplier *supplier, -- cgit v1.2.1