aboutsummaryrefslogtreecommitdiff
path: root/src/google_airbag/processor
diff options
context:
space:
mode:
Diffstat (limited to 'src/google_airbag/processor')
-rw-r--r--src/google_airbag/processor/code_module.h93
-rw-r--r--src/google_airbag/processor/code_modules.h98
-rw-r--r--src/google_airbag/processor/minidump.h84
-rw-r--r--src/google_airbag/processor/process_state.h8
-rw-r--r--src/google_airbag/processor/stack_frame.h18
-rw-r--r--src/google_airbag/processor/stackwalker.h12
-rw-r--r--src/google_airbag/processor/symbol_supplier.h4
7 files changed, 264 insertions, 53 deletions
diff --git a/src/google_airbag/processor/code_module.h b/src/google_airbag/processor/code_module.h
new file mode 100644
index 00000000..2f6be0d6
--- /dev/null
+++ b/src/google_airbag/processor/code_module.h
@@ -0,0 +1,93 @@
+// 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.
+
+// code_module.h: Carries information about code modules that are loaded
+// into a process.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_AIRBAG_PROCESSOR_CODE_MODULE_H__
+#define GOOGLE_AIRBAG_PROCESSOR_CODE_MODULE_H__
+
+#include <string>
+
+namespace google_airbag {
+
+using std::string;
+
+class CodeModule {
+ public:
+ virtual ~CodeModule() {}
+
+ // The base address of this code module as it was loaded by the process.
+ // (u_int64_t)-1 on error.
+ virtual u_int64_t base_address() const = 0;
+
+ // The size of the code module. 0 on error.
+ virtual u_int64_t size() const = 0;
+
+ // The path or file name that the code module was loaded from. Empty on
+ // error.
+ virtual string code_file() const = 0;
+
+ // An identifying string used to discriminate between multiple versions and
+ // builds of the same code module. This may contain a uuid, timestamp,
+ // version number, or any combination of this or other information, in an
+ // implementation-defined format. Empty on error.
+ virtual string code_identifier() const = 0;
+
+ // The filename containing debugging information associated with the code
+ // module. If debugging information is stored in a file separate from the
+ // code module itself (as is the case when .pdb or .dSYM files are used),
+ // this will be different from code_file. If debugging information is
+ // stored in the code module itself (possibly prior to stripping), this
+ // will be the same as code_file. Empty on error.
+ virtual string debug_file() const = 0;
+
+ // An identifying string similar to code_identifier, but identifies a
+ // specific version and build of the associated debug file. This may be
+ // the same as code_identifier when the debug_file and code_file are
+ // identical or when the same identifier is used to identify distinct
+ // debug and code files.
+ virtual string debug_identifier() const = 0;
+
+ // A human-readable representation of the code module's version. Empty on
+ // error.
+ virtual string version() const = 0;
+
+ // Creates a new copy of this CodeModule object, which the caller takes
+ // ownership of. The new CodeModule may be of a different concrete class
+ // than the CodeModule being copied, but will behave identically to the
+ // copied CodeModule as far as the CodeModule interface is concerned.
+ virtual const CodeModule* Copy() const = 0;
+};
+
+} // namespace google_airbag
+
+#endif // GOOGLE_AIRBAG_PROCESSOR_CODE_MODULE_H__
diff --git a/src/google_airbag/processor/code_modules.h b/src/google_airbag/processor/code_modules.h
new file mode 100644
index 00000000..9373adaf
--- /dev/null
+++ b/src/google_airbag/processor/code_modules.h
@@ -0,0 +1,98 @@
+// 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.
+
+// code_modules.h: Contains all of the CodeModule objects that were loaded
+// into a single process.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_AIRBAG_PROCESSOR_CODE_MODULES_H__
+#define GOOGLE_AIRBAG_PROCESSOR_CODE_MODULES_H__
+
+#include "google_airbag/common/airbag_types.h"
+
+namespace google_airbag {
+
+class CodeModule;
+
+class CodeModules {
+ public:
+ virtual ~CodeModules() {}
+
+ // The number of contained CodeModule objects.
+ virtual unsigned int module_count() const = 0;
+
+ // Random access to modules. Returns the module whose code is present
+ // at the address indicated by |address|. If no module is present at this
+ // address, returns NULL. Ownership of the returned CodeModule is retained
+ // by the CodeModules object; pointers returned by this method are valid for
+ // comparison with pointers returned by the other Get methods.
+ virtual const CodeModule* GetModuleForAddress(u_int64_t address) const = 0;
+
+ // Returns the module corresponding to the main executable. If there is
+ // no main executable, returns NULL. Ownership of the returned CodeModule
+ // is retained by the CodeModules object; pointers returned by this method
+ // are valid for comparison with pointers returned by the other Get
+ // methods.
+ virtual const CodeModule* GetMainModule() const = 0;
+
+ // Sequential access to modules. A sequence number of 0 corresponds to the
+ // module residing lowest in memory. If the sequence number is out of
+ // range, returns NULL. Ownership of the returned CodeModule is retained
+ // by the CodeModules object; pointers returned by this method are valid for
+ // comparison with pointers returned by the other Get methods.
+ virtual const CodeModule* GetModuleAtSequence(
+ unsigned int sequence) const = 0;
+
+ // Sequential access to modules. This is similar to GetModuleAtSequence,
+ // except no ordering requirement is enforced. A CodeModules implementation
+ // may return CodeModule objects from GetModuleAtIndex in any order it
+ // wishes, provided that the order remain the same throughout the life of
+ // the CodeModules object. Typically, GetModuleAtIndex would be used by
+ // a caller to enumerate all CodeModule objects quickly when the enumeration
+ // does not require any ordering. If the index argument is out of range,
+ // returns NULL. Ownership of the returned CodeModule is retained by
+ // the CodeModules object; pointers returned by this method are valid for
+ // comparison with pointers returned by the other Get methods.
+ virtual const CodeModule* GetModuleAtIndex(unsigned int index) const = 0;
+
+ // Creates a new copy of this CodeModules object, which the caller takes
+ // ownership of. The new object will also contain copies of the existing
+ // object's child CodeModule objects. The new CodeModules object may be of
+ // a different concrete class than the object being copied, but will behave
+ // identically to the copied object as far as the CodeModules and CodeModule
+ // interfaces are concerned, except that the order that GetModuleAtIndex
+ // returns objects in may differ between a copy and the original CodeModules
+ // object.
+ virtual const CodeModules* Copy() const = 0;
+};
+
+} // namespace google_airbag
+
+#endif // GOOGLE_AIRBAG_PROCESSOR_CODE_MODULES_H__
diff --git a/src/google_airbag/processor/minidump.h b/src/google_airbag/processor/minidump.h
index 2a666fe7..d9392655 100644
--- a/src/google_airbag/processor/minidump.h
+++ b/src/google_airbag/processor/minidump.h
@@ -85,6 +85,8 @@
#include <vector>
#include "google_airbag/common/minidump_format.h"
+#include "google_airbag/processor/code_module.h"
+#include "google_airbag/processor/code_modules.h"
#include "google_airbag/processor/memory_region.h"
@@ -162,7 +164,7 @@ class MinidumpStream : public MinidumpObject {
// user wants).
class MinidumpContext : public MinidumpStream {
public:
- ~MinidumpContext();
+ virtual ~MinidumpContext();
// Returns an MD_CONTEXT_* value such as MD_CONTEXT_X86 or MD_CONTEXT_PPC
// identifying the CPU type that the context was collected from. The
@@ -217,7 +219,7 @@ class MinidumpContext : public MinidumpStream {
class MinidumpMemoryRegion : public MinidumpObject,
public MemoryRegion {
public:
- ~MinidumpMemoryRegion();
+ virtual ~MinidumpMemoryRegion();
// Returns a pointer to the base of the memory region. Returns the
// cached value if available, otherwise, reads the minidump file and
@@ -272,7 +274,7 @@ class MinidumpMemoryRegion : public MinidumpObject,
// provided here.
class MinidumpThread : public MinidumpObject {
public:
- ~MinidumpThread();
+ virtual ~MinidumpThread();
const MDRawThread* thread() const { return valid_ ? &thread_ : NULL; }
MinidumpMemoryRegion* GetMemory();
@@ -308,7 +310,7 @@ class MinidumpThread : public MinidumpObject {
// a process.
class MinidumpThreadList : public MinidumpStream {
public:
- ~MinidumpThreadList();
+ virtual ~MinidumpThreadList();
unsigned int thread_count() const { return valid_ ? thread_count_ : 0; }
@@ -346,19 +348,24 @@ class MinidumpThreadList : public MinidumpStream {
// code modules. Access is provided to various data referenced indirectly
// by MDRawModule, such as the module's name and a specification for where
// to locate debugging information for the module.
-class MinidumpModule : public MinidumpObject {
+class MinidumpModule : public MinidumpObject,
+ public CodeModule {
public:
- ~MinidumpModule();
+ virtual ~MinidumpModule();
const MDRawModule* module() const { return valid_ ? &module_ : NULL; }
- u_int64_t base_address() const {
+
+ // CodeModule implementation
+ virtual u_int64_t base_address() const {
return valid_ ? module_.base_of_image : static_cast<u_int64_t>(-1);
}
- u_int32_t size() const { return valid_ ? module_.size_of_image : 0; }
-
- // The name of the file containing this module's code (exe, dll, so,
- // dylib).
- const string* GetName();
+ virtual u_int64_t size() const { return valid_ ? module_.size_of_image : 0; }
+ virtual string code_file() const;
+ virtual string code_identifier() const;
+ virtual string debug_file() const;
+ virtual string debug_identifier() const;
+ virtual string version() const;
+ virtual const CodeModule* Copy() const;
// The CodeView record, which contains information to locate the module's
// debugging information (pdb). This is returned as u_int8_t* because
@@ -372,12 +379,6 @@ class MinidumpModule : public MinidumpObject {
// field is not expected to be present.
const MDImageDebugMisc* GetMiscRecord();
- // The filename of the file containing debugging information for this
- // module. This data is supplied by the CodeView record, if present, or
- // the miscellaneous debug record. As such, it will reference either a
- // pdb or dbg file.
- const string* GetDebugFilename();
-
// Print a human-readable representation of the object to stdout.
void Print();
@@ -392,6 +393,21 @@ class MinidumpModule : public MinidumpObject {
// MinidumpModuleList handles that directly.
bool Read();
+ // Reads indirectly-referenced data, including the module name, CodeView
+ // record, and miscellaneous debugging record. This is necessary to allow
+ // MinidumpModuleList to fully construct MinidumpModule objects without
+ // requiring seeks to read a contiguous set of MinidumpModule objects.
+ // All auxiliary data should be available when Read is called, in order to
+ // allow the CodeModule getters to be const methods.
+ bool ReadAuxiliaryData();
+
+ // True after a successful Read. This is different from valid_, which is
+ // not set true until ReadAuxiliaryData also completes successfully.
+ // module_valid_ is only used by ReadAuxiliaryData and the functions it
+ // calls to determine whether the object is ready for auxiliary data to
+ // be read.
+ bool module_valid_;
+
MDRawModule module_;
// Cached module name.
@@ -407,9 +423,6 @@ class MinidumpModule : public MinidumpObject {
// because the structure contains a variable-sized string and its exact
// size cannot be known until it is processed.
vector<u_int8_t>* misc_record_;
-
- // Cached debug filename.
- const string* debug_filename_;
};
@@ -417,18 +430,21 @@ class MinidumpModule : public MinidumpObject {
// in the form of MinidumpModules. It maintains a map of these modules
// so that it may easily provide a code module corresponding to a specific
// address.
-class MinidumpModuleList : public MinidumpStream {
+class MinidumpModuleList : public MinidumpStream,
+ public CodeModules {
public:
- ~MinidumpModuleList();
-
- unsigned int module_count() const { return valid_ ? module_count_ : 0; }
+ virtual ~MinidumpModuleList();
- // Sequential access to modules.
- MinidumpModule* GetModuleAtIndex(unsigned int index) const;
-
- // Random access to modules. Returns the module whose code is present
- // at the address identified by address.
- MinidumpModule* GetModuleForAddress(u_int64_t address);
+ // CodeModules implementation.
+ virtual unsigned int module_count() const {
+ return valid_ ? module_count_ : 0;
+ }
+ virtual const MinidumpModule* GetModuleForAddress(u_int64_t address) const;
+ virtual const MinidumpModule* GetMainModule() const;
+ virtual const MinidumpModule* GetModuleAtSequence(
+ unsigned int sequence) const;
+ virtual const MinidumpModule* GetModuleAtIndex(unsigned int index) const;
+ virtual const CodeModules* Copy() const;
// Print a human-readable representation of the object to stdout.
void Print();
@@ -463,7 +479,7 @@ class MinidumpModuleList : public MinidumpStream {
// memory minidumps contain all of a process' mapped memory.
class MinidumpMemoryList : public MinidumpStream {
public:
- ~MinidumpMemoryList();
+ virtual ~MinidumpMemoryList();
unsigned int region_count() const { return valid_ ? region_count_ : 0; }
@@ -512,7 +528,7 @@ class MinidumpMemoryList : public MinidumpStream {
// the exception occurred.
class MinidumpException : public MinidumpStream {
public:
- ~MinidumpException();
+ virtual ~MinidumpException();
const MDRawExceptionStream* exception() const {
return valid_ ? &exception_ : NULL;
@@ -547,7 +563,7 @@ class MinidumpException : public MinidumpStream {
// the system on which the minidump was generated. See also MinidumpMiscInfo.
class MinidumpSystemInfo : public MinidumpStream {
public:
- ~MinidumpSystemInfo();
+ virtual ~MinidumpSystemInfo();
const MDRawSystemInfo* system_info() const {
return valid_ ? &system_info_ : NULL;
diff --git a/src/google_airbag/processor/process_state.h b/src/google_airbag/processor/process_state.h
index eb75703a..6fd005b7 100644
--- a/src/google_airbag/processor/process_state.h
+++ b/src/google_airbag/processor/process_state.h
@@ -43,6 +43,7 @@ using std::string;
using std::vector;
class CallStack;
+class CodeModules;
class ProcessState {
public:
@@ -58,6 +59,7 @@ class ProcessState {
string os_version() const { return os_version_; }
string cpu() const { return cpu_; }
string cpu_info() const { return cpu_info_; }
+ const CodeModules* modules() const { return modules_; }
private:
// MinidumpProcessor is responsible for building ProcessState objects.
@@ -66,7 +68,7 @@ class ProcessState {
// Disallow instantiation other than by friends.
ProcessState() : crashed_(false), crash_reason_(), crash_address_(0),
requesting_thread_(-1), threads_(), os_(), os_version_(),
- cpu_(), cpu_info_() {}
+ cpu_(), cpu_info_(), modules_(NULL) {}
// True if the process crashed, false if the dump was produced outside
// of an exception handler.
@@ -120,6 +122,10 @@ class ProcessState {
// present in the dump, or additional identifying information is not
// defined for the CPU family, this field will be empty.
string cpu_info_;
+
+ // The modules that were loaded into the process represented by the
+ // ProcessState.
+ const CodeModules *modules_;
};
} // namespace google_airbag
diff --git a/src/google_airbag/processor/stack_frame.h b/src/google_airbag/processor/stack_frame.h
index fd9e9f40..5d75b9f3 100644
--- a/src/google_airbag/processor/stack_frame.h
+++ b/src/google_airbag/processor/stack_frame.h
@@ -35,15 +35,16 @@
namespace google_airbag {
+class CodeModule;
+
using std::string;
struct StackFrame {
StackFrame()
: instruction(),
- module_base(),
- module_name(),
- function_base(),
+ module(NULL),
function_name(),
+ function_base(),
source_file_name(),
source_line(),
source_line_base() {}
@@ -56,19 +57,16 @@ struct StackFrame {
// but may not necessarily point to the exact beginning of that instruction.
u_int64_t instruction;
- // The base address of the module.
- u_int64_t module_base;
-
// The module in which the instruction resides.
- string module_name;
+ const CodeModule *module;
+
+ // The function name, may be omitted if debug symbols are not available.
+ string function_name;
// The start address of the function, may be omitted if debug symbols
// are not available.
u_int64_t function_base;
- // The function name, may be omitted if debug symbols are not available.
- string function_name;
-
// The source file name, may be omitted if debug symbols are not available.
string source_file_name;
diff --git a/src/google_airbag/processor/stackwalker.h b/src/google_airbag/processor/stackwalker.h
index e6c6e6e8..b3f2333e 100644
--- a/src/google_airbag/processor/stackwalker.h
+++ b/src/google_airbag/processor/stackwalker.h
@@ -46,10 +46,10 @@
namespace google_airbag {
class CallStack;
+class CodeModules;
template<typename T> class linked_ptr;
class MemoryRegion;
class MinidumpContext;
-class MinidumpModuleList;
struct StackFrame;
struct StackFrameInfo;
class SymbolSupplier;
@@ -71,18 +71,18 @@ class Stackwalker {
// argument. If no suitable concrete subclass exists, returns NULL.
static Stackwalker* StackwalkerForCPU(MinidumpContext *context,
MemoryRegion *memory,
- MinidumpModuleList *modules,
+ const CodeModules *modules,
SymbolSupplier *supplier);
protected:
// memory identifies a MemoryRegion that provides the stack memory
- // for the stack to walk. modules, if non-NULL, is a MinidumpModuleList
- // that is used to look up which code module each stack frame is
+ // 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
// associated with. supplier is an optional caller-supplied SymbolSupplier
// implementation. If supplier is NULL, source line info will not be
// resolved.
Stackwalker(MemoryRegion *memory,
- MinidumpModuleList *modules,
+ const CodeModules *modules,
SymbolSupplier *supplier);
// The stack memory to walk. Subclasses will require this region to
@@ -110,7 +110,7 @@ class Stackwalker {
// A list of modules, for populating each StackFrame's module information.
// This field is optional and may be NULL.
- MinidumpModuleList *modules_;
+ const CodeModules *modules_;
// The optional SymbolSupplier for resolving source line info.
SymbolSupplier *supplier_;
diff --git a/src/google_airbag/processor/symbol_supplier.h b/src/google_airbag/processor/symbol_supplier.h
index 264dfcf2..47a2be08 100644
--- a/src/google_airbag/processor/symbol_supplier.h
+++ b/src/google_airbag/processor/symbol_supplier.h
@@ -38,14 +38,14 @@
namespace google_airbag {
using std::string;
-class MinidumpModule;
+class CodeModule;
class SymbolSupplier {
public:
virtual ~SymbolSupplier() {}
// Returns the path to the symbol file for the given module.
- virtual string GetSymbolFile(MinidumpModule *module) = 0;
+ virtual string GetSymbolFile(const CodeModule *module) = 0;
};
} // namespace google_airbag