aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/google_airbag/processor/minidump.h9
-rw-r--r--src/google_airbag/processor/minidump_processor.h21
-rw-r--r--src/google_airbag/processor/process_state.h32
-rw-r--r--src/google_airbag/processor/stackwalker.h12
-rw-r--r--src/google_airbag/processor/symbol_supplier.h7
-rw-r--r--src/google_airbag/processor/system_info.h89
-rw-r--r--src/processor/minidump.cc46
-rw-r--r--src/processor/minidump_processor.cc102
-rw-r--r--src/processor/minidump_processor_unittest.cc43
-rw-r--r--src/processor/minidump_stackwalk.cc9
-rw-r--r--src/processor/process_state.cc5
-rw-r--r--src/processor/simple_symbol_supplier.cc4
-rw-r--r--src/processor/simple_symbol_supplier.h4
-rw-r--r--src/processor/stackwalker.cc16
-rw-r--r--src/processor/stackwalker_ppc.cc5
-rw-r--r--src/processor/stackwalker_ppc.h3
-rw-r--r--src/processor/stackwalker_selftest.cc8
-rw-r--r--src/processor/stackwalker_x86.cc5
-rw-r--r--src/processor/stackwalker_x86.h3
19 files changed, 299 insertions, 124 deletions
diff --git a/src/google_airbag/processor/minidump.h b/src/google_airbag/processor/minidump.h
index d9392655..f2700119 100644
--- a/src/google_airbag/processor/minidump.h
+++ b/src/google_airbag/processor/minidump.h
@@ -569,6 +569,15 @@ class MinidumpSystemInfo : public MinidumpStream {
return valid_ ? &system_info_ : NULL;
}
+ // GetOS and GetCPU return textual representations of the operating system
+ // and CPU that produced the minidump. Unlike most other Minidump* methods,
+ // they return string objects, not weak pointers. Defined values for
+ // GetOS() are "mac", "windows", and "linux". Defined values for GetCPU
+ // are "x86" and "ppc". These methods return an empty string when their
+ // values are unknown.
+ string GetOS();
+ string GetCPU();
+
// I don't know what CSD stands for, but this field is documented as
// returning a textual representation of the OS service pack. On other
// platforms, this provides additional information about an OS version
diff --git a/src/google_airbag/processor/minidump_processor.h b/src/google_airbag/processor/minidump_processor.h
index a50d8a79..b1ee5392 100644
--- a/src/google_airbag/processor/minidump_processor.h
+++ b/src/google_airbag/processor/minidump_processor.h
@@ -40,6 +40,7 @@ class Minidump;
class ProcessState;
class SourceLineResolverInterface;
class SymbolSupplier;
+class SystemInfo;
class MinidumpProcessor {
public:
@@ -60,19 +61,15 @@ class MinidumpProcessor {
ProcessResult Process(const string &minidump_file,
ProcessState *process_state);
- // Returns a textual representation of the base CPU type that the minidump
- // in dump was produced on. Returns an empty string if this information
- // cannot be determined. If cpu_info is non-NULL, it will be set to
- // contain additional identifying information about the CPU, or it will
- // be set empty if additional information cannot be determined.
- static string GetCPUInfo(Minidump *dump, string *cpu_info);
+ // Populates the cpu_* fields of the |info| parameter with textual
+ // representations of the CPU type that the minidump in |dump| was
+ // produced on.
+ static void GetCPUInfo(Minidump *dump, SystemInfo *info);
- // Returns a textual representation of the operating system that the
- // minidump in dump was produced on. Returns an empty string if this
- // information cannot be determined. If os_version is non-NULL, it
- // will be set to contain information about the specific version of the
- // OS, or it will be set empty if version information cannot be determined.
- static string GetOSInfo(Minidump *dump, string *os_version);
+ // Populates the os_* fields of the |info| parameter with textual
+ // representations of the operating system that the minidump in |dump|
+ // was produced on.
+ static void GetOSInfo(Minidump *dump, SystemInfo *info);
// Returns a textual representation of the reason that a crash occurred,
// if the minidump in dump was produced as a result of a crash. Returns
diff --git a/src/google_airbag/processor/process_state.h b/src/google_airbag/processor/process_state.h
index 6fe12155..5ef8047f 100644
--- a/src/google_airbag/processor/process_state.h
+++ b/src/google_airbag/processor/process_state.h
@@ -36,6 +36,7 @@
#include <string>
#include <vector>
+#include "google_airbag/processor/system_info.h"
namespace google_airbag {
@@ -60,10 +61,7 @@ class ProcessState {
u_int64_t crash_address() const { return crash_address_; }
int requesting_thread() const { return requesting_thread_; }
const vector<CallStack*>* threads() const { return &threads_; }
- string os() const { return os_; }
- string os_version() const { return os_version_; }
- string cpu() const { return cpu_; }
- string cpu_info() const { return cpu_info_; }
+ const SystemInfo* system_info() const { return &system_info_; }
const CodeModules* modules() const { return modules_; }
private:
@@ -103,28 +101,8 @@ class ProcessState {
// thread) at the time of the crash.
vector<CallStack*> threads_;
- // A string identifying the operating system, such as "Windows NT",
- // "Mac OS X", or "Linux". If the information is present in the dump but
- // its value is unknown, this field will contain a numeric value. If
- // the information is not present in the dump, this field will be empty.
- string os_;
-
- // A string identifying the version of the operating system, such as
- // "5.1.2600 Service Pack 2" or "10.4.8 8L2127". If the dump does not
- // contain this information, this field will be empty.
- string os_version_;
-
- // A string identifying the basic CPU family, such as "x86" or "ppc".
- // If this information is present in the dump but its value is unknown,
- // this field will contain a numeric value. If the information is not
- // present in the dump, this field will be empty.
- string cpu_;
-
- // A string further identifying the specific CPU, such as
- // "GenuineIntel level 6 model 13 stepping 8". If the information is not
- // present in the dump, or additional identifying information is not
- // defined for the CPU family, this field will be empty.
- string cpu_info_;
+ // OS and CPU information.
+ SystemInfo system_info_;
// The modules that were loaded into the process represented by the
// ProcessState.
@@ -133,4 +111,4 @@ class ProcessState {
} // namespace google_airbag
-#endif // GOOGLE_AIRBAG_PROCESSOR_CALL_STACK_H__
+#endif // GOOGLE_AIRBAG_PROCESSOR_PROCESS_STATE_H__
diff --git a/src/google_airbag/processor/stackwalker.h b/src/google_airbag/processor/stackwalker.h
index 381b9e29..c058f09a 100644
--- a/src/google_airbag/processor/stackwalker.h
+++ b/src/google_airbag/processor/stackwalker.h
@@ -54,6 +54,7 @@ class SourceLineResolverInterface;
struct StackFrame;
struct StackFrameInfo;
class SymbolSupplier;
+class SystemInfo;
using std::vector;
@@ -71,13 +72,15 @@ class Stackwalker {
// Returns a new concrete subclass suitable for the CPU that a stack was
// generated on, according to the CPU type indicated by the context
// argument. If no suitable concrete subclass exists, returns NULL.
- static Stackwalker* StackwalkerForCPU(MinidumpContext *context,
+ static Stackwalker* StackwalkerForCPU(const SystemInfo *system_info,
+ MinidumpContext *context,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver);
protected:
+ // system_info identifies the operating system, NULL or empty if unknown.
// memory identifies a MemoryRegion that provides the stack memory
// for the stack to walk. modules, if non-NULL, is a CodeModules
// object that is used to look up which code module each stack frame is
@@ -86,11 +89,16 @@ class Stackwalker {
// resolved. resolver is an instance of SourceLineResolverInterface
// (see source_line_resolver_interface.h and basic_source_line_resolver.h).
// If resolver is NULL, source line info will not be resolved.
- Stackwalker(MemoryRegion *memory,
+ Stackwalker(const SystemInfo *system_info,
+ MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver);
+ // Information about the system that produced the minidump. Subclasses
+ // and the SymbolSupplier may find this information useful.
+ const SystemInfo *system_info_;
+
// The stack memory to walk. Subclasses will require this region to
// get information from the stack.
MemoryRegion *memory_;
diff --git a/src/google_airbag/processor/symbol_supplier.h b/src/google_airbag/processor/symbol_supplier.h
index d456174b..b5ced8ca 100644
--- a/src/google_airbag/processor/symbol_supplier.h
+++ b/src/google_airbag/processor/symbol_supplier.h
@@ -39,6 +39,7 @@ namespace google_airbag {
using std::string;
class CodeModule;
+class SystemInfo;
class SymbolSupplier {
public:
@@ -57,8 +58,12 @@ class SymbolSupplier {
virtual ~SymbolSupplier() {}
// Retrieves the symbol file for the given CodeModule, placing the
- // path in symbol_file if successful.
+ // path in symbol_file if successful. system_info contains strings
+ // identifying the operating system and CPU; SymbolSupplier may use to help
+ // locate the symbol file. system_info may be NULL or its fields may be
+ // empty if these values are unknown.
virtual SymbolResult GetSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info,
string *symbol_file) = 0;
};
diff --git a/src/google_airbag/processor/system_info.h b/src/google_airbag/processor/system_info.h
new file mode 100644
index 00000000..faa4502c
--- /dev/null
+++ b/src/google_airbag/processor/system_info.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// system_info.h: Information about the system that was running a program
+// when a crash report was produced.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_AIRBAG_PROCESSOR_SYSTEM_INFO_H__
+#define GOOGLE_AIRBAG_PROCESSOR_SYSTEM_INFO_H__
+
+#include <string>
+
+namespace google_airbag {
+
+using std::string;
+
+struct SystemInfo {
+ public:
+ // Resets the SystemInfo object to its default values.
+ void Clear() {
+ os.clear();
+ os_short.clear();
+ os_version.clear();
+ cpu.clear();
+ cpu_info.clear();
+ }
+
+ // A string identifying the operating system, such as "Windows NT",
+ // "Mac OS X", or "Linux". If the information is present in the dump but
+ // its value is unknown, this field will contain a numeric value. If
+ // the information is not present in the dump, this field will be empty.
+ string os;
+
+ // A short form of the os string, using lowercase letters and no spaces,
+ // suitable for use in a filesystem. Possible values are "windows",
+ // "mac", and "linux". Empty if the information is not present in the dump
+ // or if the OS given by the dump is unknown. The values stored in this
+ // field should match those used by MinidumpSystemInfo::GetOS.
+ string os_short;
+
+ // A string identifying the version of the operating system, such as
+ // "5.1.2600 Service Pack 2" or "10.4.8 8L2127". If the dump does not
+ // contain this information, this field will be empty.
+ string os_version;
+
+ // A string identifying the basic CPU family, such as "x86" or "ppc".
+ // If this information is present in the dump but its value is unknown,
+ // this field will contain a numeric value. If the information is not
+ // present in the dump, this field will be empty. The values stored in
+ // this field should match those used by MinidumpSystemInfo::GetCPU.
+ string cpu;
+
+ // A string further identifying the specific CPU, such as
+ // "GenuineIntel level 6 model 13 stepping 8". If the information is not
+ // present in the dump, or additional identifying information is not
+ // defined for the CPU family, this field will be empty.
+ string cpu_info;
+};
+
+} // namespace google_airbag
+
+#endif // GOOGLE_AIRBAG_PROCESSOR_SYSTEM_INFO_H__
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(
- 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 <cstdlib>
#include <string>
#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,