Conform to style guidelines.

- In class definitions, one-space indent for public/protected/private.
 - Multi-line initializer format puts comma at end of line.
Also:
 - Eliminate the long list of friends in Minidump by making swap() public.
   (People who need to access unknown stream types directly will need 
   access to swap() too.)


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@16 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
mmentovai 2006-09-07 15:56:38 +00:00
parent 8d2f465c8a
commit 53d0f69d35
8 changed files with 506 additions and 527 deletions

View file

@ -31,31 +31,27 @@ namespace google_airbag {
class MemoryRegion { class MemoryRegion {
public: public:
virtual ~MemoryRegion() {} virtual ~MemoryRegion() {}
// The base address of this memory region. // The base address of this memory region.
virtual u_int64_t GetBase() = 0; virtual u_int64_t GetBase() = 0;
// The size of this memory region. // The size of this memory region.
virtual u_int32_t GetSize() = 0; virtual u_int32_t GetSize() = 0;
// Access to data of various sizes within the memory region. address // Access to data of various sizes within the memory region. address
// is a pointer to read, and it must lie within the memory region as // is a pointer to read, and it must lie within the memory region as
// defined by its base address and size. The location pointed to by // defined by its base address and size. The location pointed to by
// value is set to the value at address. Byte-swapping is performed // value is set to the value at address. Byte-swapping is performed
// if necessary so that the value is appropriate for the running // if necessary so that the value is appropriate for the running
// program. Returns true on success. Fails and returns false if address // program. Returns true on success. Fails and returns false if address
// is out of the region's bounds (after considering the width of value), // is out of the region's bounds (after considering the width of value),
// or for other types of errors. // or for other types of errors.
virtual bool GetMemoryAtAddress(u_int64_t address, virtual bool GetMemoryAtAddress(u_int64_t address, u_int8_t* value) = 0;
u_int8_t* value) = 0; virtual bool GetMemoryAtAddress(u_int64_t address, u_int16_t* value) = 0;
virtual bool GetMemoryAtAddress(u_int64_t address, virtual bool GetMemoryAtAddress(u_int64_t address, u_int32_t* value) = 0;
u_int16_t* value) = 0; virtual bool GetMemoryAtAddress(u_int64_t address, u_int64_t* value) = 0;
virtual bool GetMemoryAtAddress(u_int64_t address,
u_int32_t* value) = 0;
virtual bool GetMemoryAtAddress(u_int64_t address,
u_int64_t* value) = 0;
}; };

View file

@ -199,8 +199,8 @@ static string* UTF16ToUTF8(const vector<u_int16_t>& in,
MinidumpObject::MinidumpObject(Minidump* minidump) MinidumpObject::MinidumpObject(Minidump* minidump)
: minidump_(minidump) : minidump_(minidump),
, valid_(false) { valid_(false) {
} }
@ -220,8 +220,8 @@ MinidumpStream::MinidumpStream(Minidump* minidump)
MinidumpContext::MinidumpContext(Minidump* minidump) MinidumpContext::MinidumpContext(Minidump* minidump)
: MinidumpStream(minidump) : MinidumpStream(minidump),
, context_() { context_() {
} }
@ -346,9 +346,9 @@ void MinidumpContext::Print() {
MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump) MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
: MinidumpObject(minidump) : MinidumpObject(minidump),
, descriptor_(NULL) descriptor_(NULL),
, memory_(NULL) { memory_(NULL) {
} }
@ -481,10 +481,10 @@ void MinidumpMemoryRegion::Print() {
MinidumpThread::MinidumpThread(Minidump* minidump) MinidumpThread::MinidumpThread(Minidump* minidump)
: MinidumpObject(minidump) : MinidumpObject(minidump),
, thread_() thread_(),
, memory_(NULL) memory_(NULL),
, context_(NULL) { context_(NULL) {
} }
@ -608,10 +608,10 @@ void MinidumpThread::Print() {
MinidumpThreadList::MinidumpThreadList(Minidump* minidump) MinidumpThreadList::MinidumpThreadList(Minidump* minidump)
: MinidumpStream(minidump) : MinidumpStream(minidump),
, id_to_thread_map_() id_to_thread_map_(),
, threads_(NULL) threads_(NULL),
, thread_count_(0) { thread_count_(0) {
} }
@ -712,12 +712,12 @@ void MinidumpThreadList::Print() {
MinidumpModule::MinidumpModule(Minidump* minidump) MinidumpModule::MinidumpModule(Minidump* minidump)
: MinidumpObject(minidump) : MinidumpObject(minidump),
, module_() module_(),
, name_(NULL) name_(NULL),
, cv_record_(NULL) cv_record_(NULL),
, misc_record_(NULL) misc_record_(NULL),
, debug_filename_(NULL) { debug_filename_(NULL) {
} }
@ -1135,10 +1135,10 @@ void MinidumpModule::Print() {
MinidumpModuleList::MinidumpModuleList(Minidump* minidump) MinidumpModuleList::MinidumpModuleList(Minidump* minidump)
: MinidumpStream(minidump) : MinidumpStream(minidump),
, range_map_() range_map_(),
, modules_(NULL) modules_(NULL),
, module_count_(0) { module_count_(0) {
} }
@ -1245,11 +1245,11 @@ void MinidumpModuleList::Print() {
MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump) MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump)
: MinidumpStream(minidump) : MinidumpStream(minidump),
, range_map_() range_map_(),
, descriptors_(NULL) descriptors_(NULL),
, regions_(NULL) regions_(NULL),
, region_count_(0) { region_count_(0) {
} }
@ -1387,9 +1387,9 @@ void MinidumpMemoryList::Print() {
MinidumpException::MinidumpException(Minidump* minidump) MinidumpException::MinidumpException(Minidump* minidump)
: MinidumpStream(minidump) : MinidumpStream(minidump),
, exception_() exception_(),
, context_(NULL) { context_(NULL) {
} }
@ -1505,9 +1505,9 @@ void MinidumpException::Print() {
MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump) MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump)
: MinidumpStream(minidump) : MinidumpStream(minidump),
, system_info_() system_info_(),
, csd_version_(NULL) { csd_version_(NULL) {
} }
@ -1619,8 +1619,8 @@ void MinidumpSystemInfo::Print() {
MinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump) MinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump)
: MinidumpStream(minidump) : MinidumpStream(minidump),
, misc_info_() { misc_info_() {
} }
@ -1694,12 +1694,12 @@ void MinidumpMiscInfo::Print() {
Minidump::Minidump(int fd) Minidump::Minidump(int fd)
: header_() : header_(),
, directory_(NULL) directory_(NULL),
, stream_map_(NULL) stream_map_(NULL),
, fd_(fd) fd_(fd),
, swap_(false) swap_(false),
, valid_(false) { valid_(false) {
} }

View file

@ -89,25 +89,25 @@ class Minidump;
// MinidumpObject is the base of all Minidump* objects except for Minidump // MinidumpObject is the base of all Minidump* objects except for Minidump
// itself. // itself.
class MinidumpObject { class MinidumpObject {
public: public:
virtual ~MinidumpObject() {} virtual ~MinidumpObject() {}
protected: protected:
MinidumpObject(Minidump* minidump); MinidumpObject(Minidump* minidump);
// Refers to the Minidump object that is the ultimate parent of this // Refers to the Minidump object that is the ultimate parent of this
// Some MinidumpObjects are owned by other MinidumpObjects, but at the // Some MinidumpObjects are owned by other MinidumpObjects, but at the
// root of the ownership tree is always a Minidump. The Minidump object // root of the ownership tree is always a Minidump. The Minidump object
// is kept here for access to its seeking and reading facilities, and // is kept here for access to its seeking and reading facilities, and
// for access to data about the minidump file itself, such as whether // for access to data about the minidump file itself, such as whether
// it should be byte-swapped. // it should be byte-swapped.
Minidump* minidump_; Minidump* minidump_;
// MinidumpObjects are not valid when created. When a subclass populates // MinidumpObjects are not valid when created. When a subclass populates
// its own fields, it can set valid_ to true. Accessors and mutators may // its own fields, it can set valid_ to true. Accessors and mutators may
// wish to consider or alter the valid_ state as they interact with // wish to consider or alter the valid_ state as they interact with
// objects. // objects.
bool valid_; bool valid_;
}; };
@ -118,21 +118,21 @@ class MinidumpObject {
// streams and adhere to the same interface, and may be derived from // streams and adhere to the same interface, and may be derived from
// this class. // this class.
class MinidumpStream : public MinidumpObject { class MinidumpStream : public MinidumpObject {
public: public:
virtual ~MinidumpStream() {} virtual ~MinidumpStream() {}
protected: protected:
MinidumpStream(Minidump* minidump); MinidumpStream(Minidump* minidump);
private: private:
// Populate (and validate) the MinidumpStream. minidump_ is expected // Populate (and validate) the MinidumpStream. minidump_ is expected
// to be positioned at the beginning of the stream, so that the next // to be positioned at the beginning of the stream, so that the next
// read from the minidump will be at the beginning of the stream. // read from the minidump will be at the beginning of the stream.
// expected_size should be set to the stream's length as contained in // expected_size should be set to the stream's length as contained in
// the MDRawDirectory record or other identifying record. A class // the MDRawDirectory record or other identifying record. A class
// that implements MinidumpStream can compare expected_size to a // that implements MinidumpStream can compare expected_size to a
// known size as an integrity check. // known size as an integrity check.
virtual bool Read(u_int32_t expected_size) = 0; virtual bool Read(u_int32_t expected_size) = 0;
}; };
@ -147,25 +147,24 @@ class MinidumpStream : public MinidumpObject {
// and not the context that caused the exception (which is probably what the // and not the context that caused the exception (which is probably what the
// user wants). // user wants).
class MinidumpContext : public MinidumpStream { class MinidumpContext : public MinidumpStream {
public: public:
const MDRawContextX86* context() const { const MDRawContextX86* context() const { return valid_ ? &context_ : NULL; }
return valid_ ? &context_ : NULL; }
// Print a human-readable representation of the object to stdout. // Print a human-readable representation of the object to stdout.
void Print(); void Print();
private: private:
friend class MinidumpThread; friend class MinidumpThread;
friend class MinidumpException; friend class MinidumpException;
MinidumpContext(Minidump* minidump); MinidumpContext(Minidump* minidump);
bool Read(u_int32_t expected_size); bool Read(u_int32_t expected_size);
// TODO(mmentovai): This is x86-only for now. When other CPUs are // TODO(mmentovai): This is x86-only for now. When other CPUs are
// supported, this class can move to MinidumpContext_x86 and derive from // supported, this class can move to MinidumpContext_x86 and derive from
// a new abstract MinidumpContext. // a new abstract MinidumpContext.
MDRawContextX86 context_; MDRawContextX86 context_;
}; };
@ -179,52 +178,52 @@ class MinidumpContext : public MinidumpStream {
// the Stackwalker family of classes. // the Stackwalker family of classes.
class MinidumpMemoryRegion : public MinidumpObject, class MinidumpMemoryRegion : public MinidumpObject,
public MemoryRegion { public MemoryRegion {
public: public:
~MinidumpMemoryRegion(); ~MinidumpMemoryRegion();
// Returns a pointer to the base of the memory region. Returns the // Returns a pointer to the base of the memory region. Returns the
// cached value if available, otherwise, reads the minidump file and // cached value if available, otherwise, reads the minidump file and
// caches the memory region. // caches the memory region.
const u_int8_t* GetMemory(); const u_int8_t* GetMemory();
// The address of the base of the memory region. // The address of the base of the memory region.
u_int64_t GetBase(); u_int64_t GetBase();
// The size, in bytes, of the memory region. // The size, in bytes, of the memory region.
u_int32_t GetSize(); u_int32_t GetSize();
// Frees the cached memory region, if cached. // Frees the cached memory region, if cached.
void FreeMemory(); void FreeMemory();
// Obtains the value of memory at the pointer specified by address. // Obtains the value of memory at the pointer specified by address.
bool GetMemoryAtAddress(u_int64_t address, u_int8_t* value); bool GetMemoryAtAddress(u_int64_t address, u_int8_t* value);
bool GetMemoryAtAddress(u_int64_t address, u_int16_t* value); bool GetMemoryAtAddress(u_int64_t address, u_int16_t* value);
bool GetMemoryAtAddress(u_int64_t address, u_int32_t* value); bool GetMemoryAtAddress(u_int64_t address, u_int32_t* value);
bool GetMemoryAtAddress(u_int64_t address, u_int64_t* value); bool GetMemoryAtAddress(u_int64_t address, u_int64_t* value);
// Print a human-readable representation of the object to stdout. // Print a human-readable representation of the object to stdout.
void Print(); void Print();
private: private:
friend class MinidumpThread; friend class MinidumpThread;
friend class MinidumpMemoryList; friend class MinidumpMemoryList;
MinidumpMemoryRegion(Minidump* minidump); MinidumpMemoryRegion(Minidump* minidump);
// Identify the base address and size of the memory region, and the // Identify the base address and size of the memory region, and the
// location it may be found in the minidump file. // location it may be found in the minidump file.
void SetDescriptor(MDMemoryDescriptor* descriptor); void SetDescriptor(MDMemoryDescriptor* descriptor);
// Implementation for GetMemoryAtAddress // Implementation for GetMemoryAtAddress
template<typename T> bool GetMemoryAtAddressInternal(u_int64_t address, template<typename T> bool GetMemoryAtAddressInternal(u_int64_t address,
T* value); T* value);
// Base address and size of the memory region, and its position in the // Base address and size of the memory region, and its position in the
// minidump file. // minidump file.
MDMemoryDescriptor* descriptor_; MDMemoryDescriptor* descriptor_;
// Cached memory. // Cached memory.
vector<u_int8_t>* memory_; vector<u_int8_t>* memory_;
}; };
@ -234,73 +233,73 @@ class MinidumpMemoryRegion : public MinidumpObject,
// MinidumpException is probably desired instead of the CPU context // MinidumpException is probably desired instead of the CPU context
// provided here. // provided here.
class MinidumpThread : public MinidumpObject { class MinidumpThread : public MinidumpObject {
public: public:
~MinidumpThread(); ~MinidumpThread();
const MDRawThread* thread() const { return valid_ ? &thread_ : NULL; } const MDRawThread* thread() const { return valid_ ? &thread_ : NULL; }
MinidumpMemoryRegion* GetMemory(); MinidumpMemoryRegion* GetMemory();
MinidumpContext* GetContext(); MinidumpContext* GetContext();
// The thread ID is used to determine if a thread is the exception thread, // The thread ID is used to determine if a thread is the exception thread,
// so a special getter is provided to retrieve this data from the // so a special getter is provided to retrieve this data from the
// MDRawThread structure. // MDRawThread structure.
u_int32_t GetThreadID(); u_int32_t GetThreadID();
// Print a human-readable representation of the object to stdout. // Print a human-readable representation of the object to stdout.
void Print(); void Print();
private: private:
// This objects are managed by MinidumpThreadList. // These objects are managed by MinidumpThreadList.
friend class MinidumpThreadList; friend class MinidumpThreadList;
MinidumpThread(Minidump* minidump); MinidumpThread(Minidump* minidump);
// This works like MinidumpStream::Read, but is driven by // This works like MinidumpStream::Read, but is driven by
// MinidumpThreadList. No size checking is done, because // MinidumpThreadList. No size checking is done, because
// MinidumpThreadList handles that directly. // MinidumpThreadList handles that directly.
bool Read(); bool Read();
MDRawThread thread_; MDRawThread thread_;
MinidumpMemoryRegion* memory_; MinidumpMemoryRegion* memory_;
MinidumpContext* context_; MinidumpContext* context_;
}; };
// MinidumpThreadList contains all of the threads (as MinidumpThreads) in // MinidumpThreadList contains all of the threads (as MinidumpThreads) in
// a process. // a process.
class MinidumpThreadList : public MinidumpStream { class MinidumpThreadList : public MinidumpStream {
public: public:
~MinidumpThreadList(); ~MinidumpThreadList();
unsigned int thread_count() const { return valid_ ? thread_count_ : 0; } unsigned int thread_count() const { return valid_ ? thread_count_ : 0; }
// Sequential access to threads. // Sequential access to threads.
MinidumpThread* GetThreadAtIndex(unsigned int index) const; MinidumpThread* GetThreadAtIndex(unsigned int index) const;
// Random access to threads. // Random access to threads.
MinidumpThread* GetThreadByID(u_int32_t thread_id); MinidumpThread* GetThreadByID(u_int32_t thread_id);
// Print a human-readable representation of the object to stdout. // Print a human-readable representation of the object to stdout.
void Print(); void Print();
private: private:
friend class Minidump; friend class Minidump;
typedef map<u_int32_t, MinidumpThread*> IDToThreadMap; typedef map<u_int32_t, MinidumpThread*> IDToThreadMap;
typedef vector<MinidumpThread> MinidumpThreads; typedef vector<MinidumpThread> MinidumpThreads;
static const u_int32_t kStreamType = THREAD_LIST_STREAM; static const u_int32_t kStreamType = THREAD_LIST_STREAM;
MinidumpThreadList(Minidump* aMinidump); MinidumpThreadList(Minidump* aMinidump);
bool Read(u_int32_t aExpectedSize); bool Read(u_int32_t aExpectedSize);
// Access to threads using the thread ID as the key. // Access to threads using the thread ID as the key.
IDToThreadMap id_to_thread_map_; IDToThreadMap id_to_thread_map_;
// The list of threads. // The list of threads.
MinidumpThreads* threads_; MinidumpThreads* threads_;
u_int32_t thread_count_; u_int32_t thread_count_;
}; };
@ -309,68 +308,68 @@ class MinidumpThreadList : public MinidumpStream {
// by MDRawModule, such as the module's name and a specification for where // by MDRawModule, such as the module's name and a specification for where
// to locate debugging information for the module. // to locate debugging information for the module.
class MinidumpModule : public MinidumpObject { class MinidumpModule : public MinidumpObject {
public: public:
~MinidumpModule(); ~MinidumpModule();
const MDRawModule* module() const { return valid_ ? &module_ : 0; } const MDRawModule* module() const { return valid_ ? &module_ : 0; }
u_int64_t base_address() const { u_int64_t base_address() const {
return valid_ ? module_.base_of_image : static_cast<u_int64_t>(-1); } return valid_ ? module_.base_of_image : static_cast<u_int64_t>(-1); }
u_int32_t size() const { return valid_ ? module_.size_of_image : 0; } 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, // The name of the file containing this module's code (exe, dll, so,
// dylib). // dylib).
const string* GetName(); const string* GetName();
// The CodeView record, which contains information to locate the module's // The CodeView record, which contains information to locate the module's
// debugging information (pdb). This is returned as u_int8_t* because // debugging information (pdb). This is returned as u_int8_t* because
// the data can be one of two types: MDCVInfoPDB20* or MDCVInfoPDB70*. // the data can be one of two types: MDCVInfoPDB20* or MDCVInfoPDB70*.
// Check the record's signature in the first four bytes to differentiate. // Check the record's signature in the first four bytes to differentiate.
// Current toolchains generate modules which carry MDCVInfoPDB70. // Current toolchains generate modules which carry MDCVInfoPDB70.
const u_int8_t* GetCVRecord(); const u_int8_t* GetCVRecord();
// The miscellaneous debug record, which is obsolete. Current toolchains // The miscellaneous debug record, which is obsolete. Current toolchains
// do not generate this type of debugging information (dbg), and this // do not generate this type of debugging information (dbg), and this
// field is not expected to be present. // field is not expected to be present.
const MDImageDebugMisc* GetMiscRecord(); const MDImageDebugMisc* GetMiscRecord();
// The filename of the file containing debugging information for this // The filename of the file containing debugging information for this
// module. This data is supplied by the CodeView record, if present, or // module. This data is supplied by the CodeView record, if present, or
// the miscellaneous debug record. As such, it will reference either a // the miscellaneous debug record. As such, it will reference either a
// pdb or dbg file. // pdb or dbg file.
const string* GetDebugFilename(); const string* GetDebugFilename();
// Print a human-readable representation of the object to stdout. // Print a human-readable representation of the object to stdout.
void Print(); void Print();
private: private:
// These objects are managed by MinidumpModuleList. // These objects are managed by MinidumpModuleList.
friend class MinidumpModuleList; friend class MinidumpModuleList;
MinidumpModule(Minidump* minidump); MinidumpModule(Minidump* minidump);
// This works like MinidumpStream::Read, but is driven by // This works like MinidumpStream::Read, but is driven by
// MinidumpModuleList. No size checking is done, because // MinidumpModuleList. No size checking is done, because
// MinidumpModuleList handles that directly. // MinidumpModuleList handles that directly.
bool Read(); bool Read();
MDRawModule module_; MDRawModule module_;
// Cached module name. // Cached module name.
const string* name_; const string* name_;
// Cached CodeView record - this is MDCVInfoPDB20 or (likely) // Cached CodeView record - this is MDCVInfoPDB20 or (likely)
// MDCVInfoPDB70. Stored as a u_int8_t because the structure contains // MDCVInfoPDB70. Stored as a u_int8_t because the structure contains
// a variable-sized string and its exact size cannot be known until it // a variable-sized string and its exact size cannot be known until it
// is processed. // is processed.
vector<u_int8_t>* cv_record_; vector<u_int8_t>* cv_record_;
// Cached MDImageDebugMisc (usually not present), stored as u_int8_t // Cached MDImageDebugMisc (usually not present), stored as u_int8_t
// because the structure contains a variable-sized string and its exact // because the structure contains a variable-sized string and its exact
// size cannot be known until it is processed. // size cannot be known until it is processed.
vector<u_int8_t>* misc_record_; vector<u_int8_t>* misc_record_;
// Cached debug filename. // Cached debug filename.
const string* debug_filename_; const string* debug_filename_;
}; };
@ -379,37 +378,37 @@ class MinidumpModule : public MinidumpObject {
// so that it may easily provide a code module corresponding to a specific // so that it may easily provide a code module corresponding to a specific
// address. // address.
class MinidumpModuleList : public MinidumpStream { class MinidumpModuleList : public MinidumpStream {
public: public:
~MinidumpModuleList(); ~MinidumpModuleList();
unsigned int module_count() const { return valid_ ? module_count_ : 0; } unsigned int module_count() const { return valid_ ? module_count_ : 0; }
// Sequential access to modules. // Sequential access to modules.
MinidumpModule* GetModuleAtIndex(unsigned int index) const; MinidumpModule* GetModuleAtIndex(unsigned int index) const;
// Random access to modules. Returns the module whose code is present // Random access to modules. Returns the module whose code is present
// at the address identified by address. // at the address identified by address.
MinidumpModule* GetModuleForAddress(u_int64_t address); MinidumpModule* GetModuleForAddress(u_int64_t address);
// Print a human-readable representation of the object to stdout. // Print a human-readable representation of the object to stdout.
void Print(); void Print();
private: private:
friend class Minidump; friend class Minidump;
typedef vector<MinidumpModule> MinidumpModules; typedef vector<MinidumpModule> MinidumpModules;
static const u_int32_t kStreamType = MODULE_LIST_STREAM; static const u_int32_t kStreamType = MODULE_LIST_STREAM;
MinidumpModuleList(Minidump* minidump); MinidumpModuleList(Minidump* minidump);
bool Read(u_int32_t expected_size); bool Read(u_int32_t expected_size);
// Access to modules using addresses as the key. // Access to modules using addresses as the key.
RangeMap<u_int64_t, unsigned int> range_map_; RangeMap<u_int64_t, unsigned int> range_map_;
MinidumpModules* modules_; MinidumpModules* modules_;
u_int32_t module_count_; u_int32_t module_count_;
}; };
@ -423,45 +422,45 @@ class MinidumpModuleList : public MinidumpStream {
// types of minidumps may contain significantly more memory regions. Full- // types of minidumps may contain significantly more memory regions. Full-
// memory minidumps contain all of a process' mapped memory. // memory minidumps contain all of a process' mapped memory.
class MinidumpMemoryList : public MinidumpStream { class MinidumpMemoryList : public MinidumpStream {
public: public:
~MinidumpMemoryList(); ~MinidumpMemoryList();
unsigned int region_count() const { return valid_ ? region_count_ : 0; } unsigned int region_count() const { return valid_ ? region_count_ : 0; }
// Sequential access to memory regions. // Sequential access to memory regions.
MinidumpMemoryRegion* GetMemoryRegionAtIndex(unsigned int index); MinidumpMemoryRegion* GetMemoryRegionAtIndex(unsigned int index);
// Random access to memory regions. Returns the region encompassing // Random access to memory regions. Returns the region encompassing
// the address identified by address. // the address identified by address.
MinidumpMemoryRegion* GetMemoryRegionForAddress(u_int64_t address); MinidumpMemoryRegion* GetMemoryRegionForAddress(u_int64_t address);
// Print a human-readable representation of the object to stdout. // Print a human-readable representation of the object to stdout.
void Print(); void Print();
private: private:
friend class Minidump; friend class Minidump;
typedef vector<MDMemoryDescriptor> MemoryDescriptors; typedef vector<MDMemoryDescriptor> MemoryDescriptors;
typedef vector<MinidumpMemoryRegion> MemoryRegions; typedef vector<MinidumpMemoryRegion> MemoryRegions;
static const u_int32_t kStreamType = MEMORY_LIST_STREAM; static const u_int32_t kStreamType = MEMORY_LIST_STREAM;
MinidumpMemoryList(Minidump* minidump); MinidumpMemoryList(Minidump* minidump);
bool Read(u_int32_t expected_size); bool Read(u_int32_t expected_size);
// Access to memory regions using addresses as the key. // Access to memory regions using addresses as the key.
RangeMap<u_int64_t, unsigned int> range_map_; RangeMap<u_int64_t, unsigned int> range_map_;
// The list of descriptors. This is maintained separately from the list // The list of descriptors. This is maintained separately from the list
// of regions, because MemoryRegion doesn't own its MemoryDescriptor, it // of regions, because MemoryRegion doesn't own its MemoryDescriptor, it
// maintains a pointer to it. descriptors_ provides the storage for this // maintains a pointer to it. descriptors_ provides the storage for this
// purpose. // purpose.
MemoryDescriptors* descriptors_; MemoryDescriptors* descriptors_;
// The list of regions. // The list of regions.
MemoryRegions* regions_; MemoryRegions* regions_;
u_int32_t region_count_; u_int32_t region_count_;
}; };
@ -472,66 +471,66 @@ class MinidumpMemoryList : public MinidumpStream {
// which contains the CPU context for the exception thread at the time // which contains the CPU context for the exception thread at the time
// the exception occurred. // the exception occurred.
class MinidumpException : public MinidumpStream { class MinidumpException : public MinidumpStream {
public: public:
~MinidumpException(); ~MinidumpException();
const MDRawExceptionStream* exception() const { const MDRawExceptionStream* exception() const {
return valid_ ? &exception_ : 0; } return valid_ ? &exception_ : 0; }
// The thread ID is used to determine if a thread is the exception thread, // The thread ID is used to determine if a thread is the exception thread,
// so a special getter is provided to retrieve this data from the // so a special getter is provided to retrieve this data from the
// MDRawExceptionStream structure. // MDRawExceptionStream structure.
u_int32_t GetThreadID(); u_int32_t GetThreadID();
MinidumpContext* GetContext(); MinidumpContext* GetContext();
// Print a human-readable representation of the object to stdout. // Print a human-readable representation of the object to stdout.
void Print(); void Print();
private: private:
friend class Minidump; friend class Minidump;
static const u_int32_t kStreamType = EXCEPTION_STREAM; static const u_int32_t kStreamType = EXCEPTION_STREAM;
MinidumpException(Minidump* minidump); MinidumpException(Minidump* minidump);
bool Read(u_int32_t expected_size); bool Read(u_int32_t expected_size);
MDRawExceptionStream exception_; MDRawExceptionStream exception_;
MinidumpContext* context_; MinidumpContext* context_;
}; };
// MinidumpSystemInfo wraps MDRawSystemInfo and provides information about // MinidumpSystemInfo wraps MDRawSystemInfo and provides information about
// the system on which the minidump was generated. See also MinidumpMiscInfo. // the system on which the minidump was generated. See also MinidumpMiscInfo.
class MinidumpSystemInfo : public MinidumpStream { class MinidumpSystemInfo : public MinidumpStream {
public: public:
~MinidumpSystemInfo(); ~MinidumpSystemInfo();
const MDRawSystemInfo* system_info() const { const MDRawSystemInfo* system_info() const {
return valid_ ? &system_info_ : 0; } return valid_ ? &system_info_ : 0; }
// I don't know what CSD stands for, but this field is documented as // I don't know what CSD stands for, but this field is documented as
// returning a textual representation of the OS service pack. // returning a textual representation of the OS service pack.
const string* GetCSDVersion(); const string* GetCSDVersion();
// Print a human-readable representation of the object to stdout. // Print a human-readable representation of the object to stdout.
void Print(); void Print();
private: private:
friend class Minidump; friend class Minidump;
static const u_int32_t kStreamType = SYSTEM_INFO_STREAM; static const u_int32_t kStreamType = SYSTEM_INFO_STREAM;
MinidumpSystemInfo(Minidump* minidump); MinidumpSystemInfo(Minidump* minidump);
bool Read(u_int32_t expected_size); bool Read(u_int32_t expected_size);
MDRawSystemInfo system_info_; MDRawSystemInfo system_info_;
// Textual representation of the OS service pack, for minidumps produced // Textual representation of the OS service pack, for minidumps produced
// by MiniDumpWriteDump on Windows. // by MiniDumpWriteDump on Windows.
const string* csd_version_; const string* csd_version_;
}; };
@ -539,157 +538,141 @@ class MinidumpSystemInfo : public MinidumpStream {
// the process that generated the minidump, and optionally additional system // the process that generated the minidump, and optionally additional system
// information. See also MinidumpSystemInfo. // information. See also MinidumpSystemInfo.
class MinidumpMiscInfo : public MinidumpStream { class MinidumpMiscInfo : public MinidumpStream {
public: public:
const MDRawMiscInfo* misc_info() const { const MDRawMiscInfo* misc_info() const { return valid_ ? &misc_info_ : 0; }
return valid_ ? &misc_info_ : 0; }
// Print a human-readable representation of the object to stdout. // Print a human-readable representation of the object to stdout.
void Print(); void Print();
private: private:
friend class Minidump; friend class Minidump;
static const u_int32_t kStreamType = MISC_INFO_STREAM; static const u_int32_t kStreamType = MISC_INFO_STREAM;
MinidumpMiscInfo(Minidump* minidump_); MinidumpMiscInfo(Minidump* minidump_);
bool Read(u_int32_t expected_size_); bool Read(u_int32_t expected_size_);
MDRawMiscInfo misc_info_; MDRawMiscInfo misc_info_;
}; };
// Minidump is the user's interface to a minidump file. It wraps MDRawHeader // Minidump is the user's interface to a minidump file. It wraps MDRawHeader
// and provides access to the minidump's top-level stream directory. // and provides access to the minidump's top-level stream directory.
class Minidump { class Minidump {
public: public:
// fd is a randomly seekable file descriptor that is open and is // fd is a randomly seekable file descriptor that is open and is
// positioned at the beginning of the MDRawHeader structure (byte offset // positioned at the beginning of the MDRawHeader structure (byte offset
// 0). // 0).
Minidump(int fd); Minidump(int fd);
~Minidump(); ~Minidump();
const MDRawHeader* header() const { return valid_ ? &header_ : 0; } const MDRawHeader* header() const { return valid_ ? &header_ : 0; }
// Reads the minidump file's header and top-level stream directory. // Reads the minidump file's header and top-level stream directory.
// The minidump is expected to be positioned at the beginning of the // The minidump is expected to be positioned at the beginning of the
// header. Read() sets up the stream list and map, and validates the // header. Read() sets up the stream list and map, and validates the
// Minidump object. // Minidump object.
bool Read(); bool Read();
// The next 6 methods are stubs that call GetStream. They exist to // The next 6 methods are stubs that call GetStream. They exist to
// force code generation of the templatized API within the module, and // force code generation of the templatized API within the module, and
// to avoid exposing an ugly API (GetStream needs to accept a garbage // to avoid exposing an ugly API (GetStream needs to accept a garbage
// parameter). // parameter).
MinidumpThreadList* GetThreadList(); MinidumpThreadList* GetThreadList();
MinidumpModuleList* GetModuleList(); MinidumpModuleList* GetModuleList();
MinidumpMemoryList* GetMemoryList(); MinidumpMemoryList* GetMemoryList();
MinidumpException* GetException(); MinidumpException* GetException();
MinidumpSystemInfo* GetSystemInfo(); MinidumpSystemInfo* GetSystemInfo();
MinidumpMiscInfo* GetMiscInfo(); MinidumpMiscInfo* GetMiscInfo();
// The next set of methods are provided for users who wish to access // The next set of methods are provided for users who wish to access
// data in minidump files directly, while leveraging the rest of // data in minidump files directly, while leveraging the rest of
// this class and related classes to handle the basic minidump // this class and related classes to handle the basic minidump
// structure and known stream types. // structure and known stream types.
unsigned int GetDirectoryEntryCount() const { unsigned int GetDirectoryEntryCount() const {
return valid_ ? header_.stream_count : 0; } return valid_ ? header_.stream_count : 0; }
const MDRawDirectory* GetDirectoryEntryAtIndex(unsigned int index) const; const MDRawDirectory* GetDirectoryEntryAtIndex(unsigned int index) const;
// The next 2 methods are lower-level I/O routines. They use fd_. // The next 2 methods are lower-level I/O routines. They use fd_.
// Reads count bytes from the minidump at the current position into // Reads count bytes from the minidump at the current position into
// the storage area pointed to by bytes. bytes must be of sufficient // the storage area pointed to by bytes. bytes must be of sufficient
// size. After the read, the file position is advanced by count. // size. After the read, the file position is advanced by count.
bool ReadBytes(void* bytes, size_t count); bool ReadBytes(void* bytes, size_t count);
// Sets the position of the minidump file to offset. // Sets the position of the minidump file to offset.
bool SeekSet(off_t offset); bool SeekSet(off_t offset);
// The next 2 methods are medium-level I/O routines. // The next 2 methods are medium-level I/O routines.
// ReadString returns a string which is owned by the caller! offset // ReadString returns a string which is owned by the caller! offset
// specifies the offset that a length-encoded string is stored at in the // specifies the offset that a length-encoded string is stored at in the
// minidump file. // minidump file.
string* ReadString(off_t offset); string* ReadString(off_t offset);
// SeekToStreamType positions the file at the beginning of a stream // SeekToStreamType positions the file at the beginning of a stream
// identified by stream_type, and informs the caller of the stream's // identified by stream_type, and informs the caller of the stream's
// length by setting *stream_length. Because stream_map maps each stream // length by setting *stream_length. Because stream_map maps each stream
// type to only one stream in the file, this might mislead the user into // type to only one stream in the file, this might mislead the user into
// thinking that the stream that this seeks to is the only stream with // thinking that the stream that this seeks to is the only stream with
// type stream_type. That can't happen for streams that these classes // type stream_type. That can't happen for streams that these classes
// deal with directly, because they're only supposed to be present in the // deal with directly, because they're only supposed to be present in the
// file singly, and that's verified when stream_map_ is built. Users who // file singly, and that's verified when stream_map_ is built. Users who
// are looking for other stream types should be aware of this // are looking for other stream types should be aware of this
// possibility, and consider using GetDirectoryEntryAtIndex (possibly // possibility, and consider using GetDirectoryEntryAtIndex (possibly
// with GetDirectoryEntryCount) if expecting multiple streams of the same // with GetDirectoryEntryCount) if expecting multiple streams of the same
// type in a single minidump file. // type in a single minidump file.
bool SeekToStreamType(u_int32_t stream_type, u_int32_t* stream_length); bool SeekToStreamType(u_int32_t stream_type, u_int32_t* stream_length);
// Print a human-readable representation of the object to stdout. bool swap() const { return valid_ ? swap_ : false; }
void Print();
private: // Print a human-readable representation of the object to stdout.
// These classes are friends to give them access to this class' file void Print();
// I/O utility routines.
friend class MinidumpContext;
friend class MinidumpMemoryRegion;
friend class MinidumpThread;
friend class MinidumpThreadList;
friend class MinidumpModule;
friend class MinidumpModuleList;
friend class MinidumpMemoryList;
friend class MinidumpException;
friend class MinidumpSystemInfo;
friend class MinidumpMiscInfo;
// MinidumpStreamInfo is used in the MinidumpStreamMap. It lets private:
// the Minidump object locate interesting streams quickly, and // MinidumpStreamInfo is used in the MinidumpStreamMap. It lets
// provides a convenient place to stash MinidumpStream objects. // the Minidump object locate interesting streams quickly, and
struct MinidumpStreamInfo { // provides a convenient place to stash MinidumpStream objects.
MinidumpStreamInfo() struct MinidumpStreamInfo {
: stream_index(0) MinidumpStreamInfo() : stream_index(0), stream(NULL) {}
, stream(NULL) {} ~MinidumpStreamInfo() { delete stream; }
~MinidumpStreamInfo() { delete stream; }
// Index into the MinidumpDirectoryEntries vector // Index into the MinidumpDirectoryEntries vector
unsigned int stream_index; unsigned int stream_index;
// Pointer to the stream if cached, or NULL if not yet populated // Pointer to the stream if cached, or NULL if not yet populated
MinidumpStream* stream; MinidumpStream* stream;
}; };
typedef vector<MDRawDirectory> MinidumpDirectoryEntries; typedef vector<MDRawDirectory> MinidumpDirectoryEntries;
typedef map<u_int32_t, MinidumpStreamInfo> MinidumpStreamMap; typedef map<u_int32_t, MinidumpStreamInfo> MinidumpStreamMap;
bool swap() const { return valid_ ? swap_ : false; } template<typename T> T* GetStream(T** stream);
template<typename T> T* GetStream(T** stream); MDRawHeader header_;
MDRawHeader header_; // The list of streams.
MinidumpDirectoryEntries* directory_;
// The list of streams. // Access to streams using the stream type as the key.
MinidumpDirectoryEntries* directory_; MinidumpStreamMap* stream_map_;
// Access to streams using the stream type as the key. // The file descriptor for all file I/O. Used by ReadBytes and SeekSet.
MinidumpStreamMap* stream_map_; int fd_;
// The file descriptor for all file I/O. Used by ReadBytes and SeekSet. // swap_ is true if the minidump file should be byte-swapped. If the
int fd_; // minidump was produced by a CPU that is other-endian than the CPU
// processing the minidump, this will be true. If the two CPUs are
// same-endian, this will be false.
bool swap_;
// swap_ is true if the minidump file should be byte-swapped. If the // Validity of the Minidump structure, false immediately after
// minidump was produced by a CPU that is other-endian than the CPU // construction or after a failed Read(); true following a successful
// processing the minidump, this will be true. If the two CPUs are // Read().
// same-endian, this will be false. bool valid_;
bool swap_;
// Validity of the Minidump structure, false immediately after
// construction or after a failed Read(); true following a successful
// Read().
bool valid_;
}; };

View file

@ -37,50 +37,50 @@ using std::map;
template<typename AddressType, typename EntryType> template<typename AddressType, typename EntryType>
class RangeMap { class RangeMap {
public: public:
RangeMap() : map_() {} RangeMap() : map_() {}
// Inserts a range into the map. Returns false for a parameter error, // Inserts a range into the map. Returns false for a parameter error,
// or if the location of the range would conflict with a range already // or if the location of the range would conflict with a range already
// stored in the map. // stored in the map.
bool StoreRange(const AddressType& base, bool StoreRange(const AddressType& base,
const AddressType& size, const AddressType& size,
const EntryType& entry); const EntryType& entry);
// Locates the range encompassing the supplied address. If there is // Locates the range encompassing the supplied address. If there is
// no such range, or if there is a parameter error, returns false. // no such range, or if there is a parameter error, returns false.
bool RetrieveRange(const AddressType& address, EntryType* entry); bool RetrieveRange(const AddressType& address, EntryType* entry);
// Empties the range map, restoring it to the state it was when it was // Empties the range map, restoring it to the state it was when it was
// initially created. // initially created.
void Clear(); void Clear();
private: private:
class Range { class Range {
public: public:
Range(const AddressType& base, const EntryType& entry) Range(const AddressType& base, const EntryType& entry)
: base_(base), entry_(entry) {} : base_(base), entry_(entry) {}
AddressType base() const { return base_; } AddressType base() const { return base_; }
EntryType entry() const { return entry_; } EntryType entry() const { return entry_; }
private: private:
// The base address of the range. The high address does not need to // The base address of the range. The high address does not need to
// be stored, because RangeMap uses it as the key to the map. // be stored, because RangeMap uses it as the key to the map.
const AddressType base_; const AddressType base_;
// The entry, owned by the Range object. // The entry, owned by the Range object.
const EntryType entry_; const EntryType entry_;
}; };
typedef map<AddressType, Range> AddressToRangeMap; typedef map<AddressType, Range> AddressToRangeMap;
// Can't depend on implicit typenames in a template // Can't depend on implicit typenames in a template
typedef typename AddressToRangeMap::const_iterator const_iterator; typedef typename AddressToRangeMap::const_iterator const_iterator;
typedef typename AddressToRangeMap::value_type value_type; typedef typename AddressToRangeMap::value_type value_type;
// Maps the high address of each range to a EntryType. // Maps the high address of each range to a EntryType.
AddressToRangeMap map_; AddressToRangeMap map_;
}; };

View file

@ -32,17 +32,17 @@ using google_airbag::RangeMap;
// A CountedObject holds an int. A global (not thread safe!) count of // A CountedObject holds an int. A global (not thread safe!) count of
// allocated CountedObjects is maintained to help test memory management. // allocated CountedObjects is maintained to help test memory management.
class CountedObject { class CountedObject {
public: public:
CountedObject(int id) : id_(id) { ++count_; } CountedObject(int id) : id_(id) { ++count_; }
CountedObject(const CountedObject& that) : id_(that.id_) { ++count_; } CountedObject(const CountedObject& that) : id_(that.id_) { ++count_; }
~CountedObject() { --count_; } ~CountedObject() { --count_; }
static int count() { return count_; } static int count() { return count_; }
int id() const { return id_; } int id() const { return id_; }
private: private:
static int count_; static int count_;
int id_; int id_;
}; };
int CountedObject::count_; int CountedObject::count_;
@ -210,7 +210,7 @@ bool RunTests() {
{ 20000, 20000, 34, true }, // > 8-bit { 20000, 20000, 34, true }, // > 8-bit
{ 0x10001, 0x10001, 35, true }, // > 16-bit { 0x10001, 0x10001, 35, true }, // > 16-bit
{ 27, -1, 36, false } // tests high < base { 27, -1, 36, false } // tests high < base
}; };
// Attempt to fill the entire space. The entire space must be filled with // Attempt to fill the entire space. The entire space must be filled with
@ -254,7 +254,7 @@ bool RunTests() {
{ range_tests_1, sizeof(range_tests_1) / sizeof(RangeTest) }, { range_tests_1, sizeof(range_tests_1) / sizeof(RangeTest) },
{ range_tests_2, sizeof(range_tests_2) / sizeof(RangeTest) }, { range_tests_2, sizeof(range_tests_2) / sizeof(RangeTest) },
{ range_tests_3, sizeof(range_tests_3) / sizeof(RangeTest) }, { range_tests_3, sizeof(range_tests_3) / sizeof(RangeTest) },
{ range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) } // Run again { range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) } // Run again
}; };
// Maintain the range map in a pointer so that deletion can be meaningfully // Maintain the range map in a pointer so that deletion can be meaningfully

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// stackwalker.cc: Generic stackwalker. // stackwalker.h: Generic stackwalker.
// //
// The Stackwalker class is an abstract base class providing common generic // The Stackwalker class is an abstract base class providing common generic
// methods that apply to stacks from all systems. Specific implementations // methods that apply to stacks from all systems. Specific implementations
@ -39,41 +39,41 @@ class MinidumpModuleList;
class Stackwalker { class Stackwalker {
public: public:
virtual ~Stackwalker() {} virtual ~Stackwalker() {}
// Produces a vector of StackFrames by calling GetContextFrame and // Produces a vector of StackFrames by calling GetContextFrame and
// GetCallerFrame, and populating the returned frames with module // GetCallerFrame, and populating the returned frames with module
// offset and name information if possible. The caller takes ownership // offset and name information if possible. The caller takes ownership
// of the StackFrames object and is responsible for freeing it. // of the StackFrames object and is responsible for freeing it.
StackFrames* Walk(); StackFrames* Walk();
protected: protected:
// memory identifies a MemoryRegion that provides the stack memory // memory identifies a MemoryRegion that provides the stack memory
// for the stack to walk. modules, if non-NULL, is a MinidumpModuleList // 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 // that is used to look up which code module each stack frame is
// associated with. // associated with.
Stackwalker(MemoryRegion* memory, MinidumpModuleList* modules); Stackwalker(MemoryRegion* memory, MinidumpModuleList* modules);
// The stack memory to walk. Subclasses will require this region to // The stack memory to walk. Subclasses will require this region to
// get information from the stack. // get information from the stack.
MemoryRegion* memory_; MemoryRegion* memory_;
private: private:
// Obtains the context frame, the innermost called procedure in a stack // Obtains the context frame, the innermost called procedure in a stack
// trace. Returns false on failure. // trace. Returns false on failure.
virtual bool GetContextFrame(StackFrame* frame) = 0; virtual bool GetContextFrame(StackFrame* frame) = 0;
// Obtains a caller frame. Each call to GetCallerFrame should return the // Obtains a caller frame. Each call to GetCallerFrame should return the
// frame that called the last frame returned by GetContextFrame or // frame that called the last frame returned by GetContextFrame or
// GetCallerFrame. GetCallerFrame should return false on failure or // GetCallerFrame. GetCallerFrame should return false on failure or
// when there are no more caller frames (when the end of the stack has // when there are no more caller frames (when the end of the stack has
// been reached). // been reached).
virtual bool GetCallerFrame(StackFrame* frame) = 0; virtual bool GetCallerFrame(StackFrame* frame) = 0;
// A list of modules, for populating each StackFrame's module information. // A list of modules, for populating each StackFrame's module information.
// This field is optional and may be NULL. // This field is optional and may be NULL.
MinidumpModuleList* modules_; MinidumpModuleList* modules_;
}; };

View file

@ -29,8 +29,8 @@ namespace google_airbag {
StackwalkerX86::StackwalkerX86(MinidumpContext* context, StackwalkerX86::StackwalkerX86(MinidumpContext* context,
MemoryRegion* memory, MemoryRegion* memory,
MinidumpModuleList* modules) MinidumpModuleList* modules)
: Stackwalker(memory, modules) : Stackwalker(memory, modules),
, last_frame_pointer_(0) { last_frame_pointer_(0) {
if (memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) { if (memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) {
// The x86 is a 32-bit CPU, the limits of the supplied stack are invalid. // The x86 is a 32-bit CPU, the limits of the supplied stack are invalid.
// Mark memory_ = NULL, which will cause stackwalking to fail. // Mark memory_ = NULL, which will cause stackwalking to fail.

View file

@ -37,28 +37,28 @@ class MinidumpModuleList;
class StackwalkerX86 : public Stackwalker { class StackwalkerX86 : public Stackwalker {
public: public:
// context is a MinidumpContext object that gives access to x86-specific // context is a MinidumpContext object that gives access to x86-specific
// register state corresponding to the innermost called frame to be // register state corresponding to the innermost called frame to be
// included in the stack. memory and modules are passed directly through // included in the stack. memory and modules are passed directly through
// to the base Stackwalker constructor. // to the base Stackwalker constructor.
StackwalkerX86(MinidumpContext* context, StackwalkerX86(MinidumpContext* context,
MemoryRegion* memory, MemoryRegion* memory,
MinidumpModuleList* modules); MinidumpModuleList* modules);
private: private:
// Implementation of Stackwalker, using x86 context (%ebp, %eip) and // Implementation of Stackwalker, using x86 context (%ebp, %eip) and
// stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp]). // stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp]).
virtual bool GetContextFrame(StackFrame* frame); virtual bool GetContextFrame(StackFrame* frame);
virtual bool GetCallerFrame(StackFrame* frame); virtual bool GetCallerFrame(StackFrame* frame);
// Stores the CPU context corresponding to the innermost stack frame to // Stores the CPU context corresponding to the innermost stack frame to
// be returned by GetContextFrame. // be returned by GetContextFrame.
const MDRawContextX86* context_; const MDRawContextX86* context_;
// Stores the frame pointer returned in the last stack frame returned by // Stores the frame pointer returned in the last stack frame returned by
// GetContextFrame or GetCallerFrame. // GetContextFrame or GetCallerFrame.
u_int32_t last_frame_pointer_; u_int32_t last_frame_pointer_;
}; };