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:
parent
8d2f465c8a
commit
53d0f69d35
8 changed files with 506 additions and 527 deletions
|
@ -31,31 +31,27 @@ namespace google_airbag {
|
|||
|
||||
|
||||
class MemoryRegion {
|
||||
public:
|
||||
virtual ~MemoryRegion() {}
|
||||
public:
|
||||
virtual ~MemoryRegion() {}
|
||||
|
||||
// The base address of this memory region.
|
||||
virtual u_int64_t GetBase() = 0;
|
||||
// The base address of this memory region.
|
||||
virtual u_int64_t GetBase() = 0;
|
||||
|
||||
// The size of this memory region.
|
||||
virtual u_int32_t GetSize() = 0;
|
||||
// The size of this memory region.
|
||||
virtual u_int32_t GetSize() = 0;
|
||||
|
||||
// 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
|
||||
// defined by its base address and size. The location pointed to by
|
||||
// value is set to the value at address. Byte-swapping is performed
|
||||
// if necessary so that the value is appropriate for the running
|
||||
// program. Returns true on success. Fails and returns false if address
|
||||
// is out of the region's bounds (after considering the width of value),
|
||||
// or for other types of errors.
|
||||
virtual bool GetMemoryAtAddress(u_int64_t address,
|
||||
u_int8_t* value) = 0;
|
||||
virtual bool GetMemoryAtAddress(u_int64_t address,
|
||||
u_int16_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;
|
||||
// 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
|
||||
// defined by its base address and size. The location pointed to by
|
||||
// value is set to the value at address. Byte-swapping is performed
|
||||
// if necessary so that the value is appropriate for the running
|
||||
// program. Returns true on success. Fails and returns false if address
|
||||
// is out of the region's bounds (after considering the width of value),
|
||||
// or for other types of errors.
|
||||
virtual bool GetMemoryAtAddress(u_int64_t address, u_int8_t* value) = 0;
|
||||
virtual bool GetMemoryAtAddress(u_int64_t address, u_int16_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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -199,8 +199,8 @@ static string* UTF16ToUTF8(const vector<u_int16_t>& in,
|
|||
|
||||
|
||||
MinidumpObject::MinidumpObject(Minidump* minidump)
|
||||
: minidump_(minidump)
|
||||
, valid_(false) {
|
||||
: minidump_(minidump),
|
||||
valid_(false) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -220,8 +220,8 @@ MinidumpStream::MinidumpStream(Minidump* minidump)
|
|||
|
||||
|
||||
MinidumpContext::MinidumpContext(Minidump* minidump)
|
||||
: MinidumpStream(minidump)
|
||||
, context_() {
|
||||
: MinidumpStream(minidump),
|
||||
context_() {
|
||||
}
|
||||
|
||||
|
||||
|
@ -346,9 +346,9 @@ void MinidumpContext::Print() {
|
|||
|
||||
|
||||
MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
|
||||
: MinidumpObject(minidump)
|
||||
, descriptor_(NULL)
|
||||
, memory_(NULL) {
|
||||
: MinidumpObject(minidump),
|
||||
descriptor_(NULL),
|
||||
memory_(NULL) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -481,10 +481,10 @@ void MinidumpMemoryRegion::Print() {
|
|||
|
||||
|
||||
MinidumpThread::MinidumpThread(Minidump* minidump)
|
||||
: MinidumpObject(minidump)
|
||||
, thread_()
|
||||
, memory_(NULL)
|
||||
, context_(NULL) {
|
||||
: MinidumpObject(minidump),
|
||||
thread_(),
|
||||
memory_(NULL),
|
||||
context_(NULL) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -608,10 +608,10 @@ void MinidumpThread::Print() {
|
|||
|
||||
|
||||
MinidumpThreadList::MinidumpThreadList(Minidump* minidump)
|
||||
: MinidumpStream(minidump)
|
||||
, id_to_thread_map_()
|
||||
, threads_(NULL)
|
||||
, thread_count_(0) {
|
||||
: MinidumpStream(minidump),
|
||||
id_to_thread_map_(),
|
||||
threads_(NULL),
|
||||
thread_count_(0) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -712,12 +712,12 @@ void MinidumpThreadList::Print() {
|
|||
|
||||
|
||||
MinidumpModule::MinidumpModule(Minidump* minidump)
|
||||
: MinidumpObject(minidump)
|
||||
, module_()
|
||||
, name_(NULL)
|
||||
, cv_record_(NULL)
|
||||
, misc_record_(NULL)
|
||||
, debug_filename_(NULL) {
|
||||
: MinidumpObject(minidump),
|
||||
module_(),
|
||||
name_(NULL),
|
||||
cv_record_(NULL),
|
||||
misc_record_(NULL),
|
||||
debug_filename_(NULL) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -1135,10 +1135,10 @@ void MinidumpModule::Print() {
|
|||
|
||||
|
||||
MinidumpModuleList::MinidumpModuleList(Minidump* minidump)
|
||||
: MinidumpStream(minidump)
|
||||
, range_map_()
|
||||
, modules_(NULL)
|
||||
, module_count_(0) {
|
||||
: MinidumpStream(minidump),
|
||||
range_map_(),
|
||||
modules_(NULL),
|
||||
module_count_(0) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -1245,11 +1245,11 @@ void MinidumpModuleList::Print() {
|
|||
|
||||
|
||||
MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump)
|
||||
: MinidumpStream(minidump)
|
||||
, range_map_()
|
||||
, descriptors_(NULL)
|
||||
, regions_(NULL)
|
||||
, region_count_(0) {
|
||||
: MinidumpStream(minidump),
|
||||
range_map_(),
|
||||
descriptors_(NULL),
|
||||
regions_(NULL),
|
||||
region_count_(0) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -1387,9 +1387,9 @@ void MinidumpMemoryList::Print() {
|
|||
|
||||
|
||||
MinidumpException::MinidumpException(Minidump* minidump)
|
||||
: MinidumpStream(minidump)
|
||||
, exception_()
|
||||
, context_(NULL) {
|
||||
: MinidumpStream(minidump),
|
||||
exception_(),
|
||||
context_(NULL) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -1505,9 +1505,9 @@ void MinidumpException::Print() {
|
|||
|
||||
|
||||
MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump)
|
||||
: MinidumpStream(minidump)
|
||||
, system_info_()
|
||||
, csd_version_(NULL) {
|
||||
: MinidumpStream(minidump),
|
||||
system_info_(),
|
||||
csd_version_(NULL) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -1619,8 +1619,8 @@ void MinidumpSystemInfo::Print() {
|
|||
|
||||
|
||||
MinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump)
|
||||
: MinidumpStream(minidump)
|
||||
, misc_info_() {
|
||||
: MinidumpStream(minidump),
|
||||
misc_info_() {
|
||||
}
|
||||
|
||||
|
||||
|
@ -1694,12 +1694,12 @@ void MinidumpMiscInfo::Print() {
|
|||
|
||||
|
||||
Minidump::Minidump(int fd)
|
||||
: header_()
|
||||
, directory_(NULL)
|
||||
, stream_map_(NULL)
|
||||
, fd_(fd)
|
||||
, swap_(false)
|
||||
, valid_(false) {
|
||||
: header_(),
|
||||
directory_(NULL),
|
||||
stream_map_(NULL),
|
||||
fd_(fd),
|
||||
swap_(false),
|
||||
valid_(false) {
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -89,25 +89,25 @@ class Minidump;
|
|||
// MinidumpObject is the base of all Minidump* objects except for Minidump
|
||||
// itself.
|
||||
class MinidumpObject {
|
||||
public:
|
||||
virtual ~MinidumpObject() {}
|
||||
public:
|
||||
virtual ~MinidumpObject() {}
|
||||
|
||||
protected:
|
||||
MinidumpObject(Minidump* minidump);
|
||||
protected:
|
||||
MinidumpObject(Minidump* minidump);
|
||||
|
||||
// Refers to the Minidump object that is the ultimate parent of this
|
||||
// Some MinidumpObjects are owned by other MinidumpObjects, but at the
|
||||
// root of the ownership tree is always a Minidump. The Minidump object
|
||||
// is kept here for access to its seeking and reading facilities, and
|
||||
// for access to data about the minidump file itself, such as whether
|
||||
// it should be byte-swapped.
|
||||
Minidump* minidump_;
|
||||
// Refers to the Minidump object that is the ultimate parent of this
|
||||
// Some MinidumpObjects are owned by other MinidumpObjects, but at the
|
||||
// root of the ownership tree is always a Minidump. The Minidump object
|
||||
// is kept here for access to its seeking and reading facilities, and
|
||||
// for access to data about the minidump file itself, such as whether
|
||||
// it should be byte-swapped.
|
||||
Minidump* minidump_;
|
||||
|
||||
// MinidumpObjects are not valid when created. When a subclass populates
|
||||
// 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
|
||||
// objects.
|
||||
bool valid_;
|
||||
// MinidumpObjects are not valid when created. When a subclass populates
|
||||
// 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
|
||||
// objects.
|
||||
bool valid_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -118,21 +118,21 @@ class MinidumpObject {
|
|||
// streams and adhere to the same interface, and may be derived from
|
||||
// this class.
|
||||
class MinidumpStream : public MinidumpObject {
|
||||
public:
|
||||
virtual ~MinidumpStream() {}
|
||||
public:
|
||||
virtual ~MinidumpStream() {}
|
||||
|
||||
protected:
|
||||
MinidumpStream(Minidump* minidump);
|
||||
protected:
|
||||
MinidumpStream(Minidump* minidump);
|
||||
|
||||
private:
|
||||
// Populate (and validate) the MinidumpStream. minidump_ is expected
|
||||
// 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.
|
||||
// expected_size should be set to the stream's length as contained in
|
||||
// the MDRawDirectory record or other identifying record. A class
|
||||
// that implements MinidumpStream can compare expected_size to a
|
||||
// known size as an integrity check.
|
||||
virtual bool Read(u_int32_t expected_size) = 0;
|
||||
private:
|
||||
// Populate (and validate) the MinidumpStream. minidump_ is expected
|
||||
// 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.
|
||||
// expected_size should be set to the stream's length as contained in
|
||||
// the MDRawDirectory record or other identifying record. A class
|
||||
// that implements MinidumpStream can compare expected_size to a
|
||||
// known size as an integrity check.
|
||||
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
|
||||
// user wants).
|
||||
class MinidumpContext : public MinidumpStream {
|
||||
public:
|
||||
const MDRawContextX86* context() const {
|
||||
return valid_ ? &context_ : NULL; }
|
||||
public:
|
||||
const MDRawContextX86* context() const { return valid_ ? &context_ : NULL; }
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
private:
|
||||
friend class MinidumpThread;
|
||||
friend class MinidumpException;
|
||||
private:
|
||||
friend class MinidumpThread;
|
||||
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
|
||||
// supported, this class can move to MinidumpContext_x86 and derive from
|
||||
// a new abstract MinidumpContext.
|
||||
MDRawContextX86 context_;
|
||||
// TODO(mmentovai): This is x86-only for now. When other CPUs are
|
||||
// supported, this class can move to MinidumpContext_x86 and derive from
|
||||
// a new abstract MinidumpContext.
|
||||
MDRawContextX86 context_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -179,52 +178,52 @@ class MinidumpContext : public MinidumpStream {
|
|||
// the Stackwalker family of classes.
|
||||
class MinidumpMemoryRegion : public MinidumpObject,
|
||||
public MemoryRegion {
|
||||
public:
|
||||
~MinidumpMemoryRegion();
|
||||
public:
|
||||
~MinidumpMemoryRegion();
|
||||
|
||||
// Returns a pointer to the base of the memory region. Returns the
|
||||
// cached value if available, otherwise, reads the minidump file and
|
||||
// caches the memory region.
|
||||
const u_int8_t* GetMemory();
|
||||
// Returns a pointer to the base of the memory region. Returns the
|
||||
// cached value if available, otherwise, reads the minidump file and
|
||||
// caches the memory region.
|
||||
const u_int8_t* GetMemory();
|
||||
|
||||
// The address of the base of the memory region.
|
||||
u_int64_t GetBase();
|
||||
// The address of the base of the memory region.
|
||||
u_int64_t GetBase();
|
||||
|
||||
// The size, in bytes, of the memory region.
|
||||
u_int32_t GetSize();
|
||||
// The size, in bytes, of the memory region.
|
||||
u_int32_t GetSize();
|
||||
|
||||
// Frees the cached memory region, if cached.
|
||||
void FreeMemory();
|
||||
// Frees the cached memory region, if cached.
|
||||
void FreeMemory();
|
||||
|
||||
// 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_int16_t* value);
|
||||
bool GetMemoryAtAddress(u_int64_t address, u_int32_t* value);
|
||||
bool GetMemoryAtAddress(u_int64_t address, u_int64_t* value);
|
||||
// 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_int16_t* value);
|
||||
bool GetMemoryAtAddress(u_int64_t address, u_int32_t* value);
|
||||
bool GetMemoryAtAddress(u_int64_t address, u_int64_t* value);
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
private:
|
||||
friend class MinidumpThread;
|
||||
friend class MinidumpMemoryList;
|
||||
private:
|
||||
friend class MinidumpThread;
|
||||
friend class MinidumpMemoryList;
|
||||
|
||||
MinidumpMemoryRegion(Minidump* minidump);
|
||||
MinidumpMemoryRegion(Minidump* minidump);
|
||||
|
||||
// Identify the base address and size of the memory region, and the
|
||||
// location it may be found in the minidump file.
|
||||
void SetDescriptor(MDMemoryDescriptor* descriptor);
|
||||
// Identify the base address and size of the memory region, and the
|
||||
// location it may be found in the minidump file.
|
||||
void SetDescriptor(MDMemoryDescriptor* descriptor);
|
||||
|
||||
// Implementation for GetMemoryAtAddress
|
||||
template<typename T> bool GetMemoryAtAddressInternal(u_int64_t address,
|
||||
T* value);
|
||||
// Implementation for GetMemoryAtAddress
|
||||
template<typename T> bool GetMemoryAtAddressInternal(u_int64_t address,
|
||||
T* value);
|
||||
|
||||
// Base address and size of the memory region, and its position in the
|
||||
// minidump file.
|
||||
MDMemoryDescriptor* descriptor_;
|
||||
// Base address and size of the memory region, and its position in the
|
||||
// minidump file.
|
||||
MDMemoryDescriptor* descriptor_;
|
||||
|
||||
// Cached memory.
|
||||
vector<u_int8_t>* memory_;
|
||||
// Cached memory.
|
||||
vector<u_int8_t>* memory_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -234,73 +233,73 @@ class MinidumpMemoryRegion : public MinidumpObject,
|
|||
// MinidumpException is probably desired instead of the CPU context
|
||||
// provided here.
|
||||
class MinidumpThread : public MinidumpObject {
|
||||
public:
|
||||
~MinidumpThread();
|
||||
public:
|
||||
~MinidumpThread();
|
||||
|
||||
const MDRawThread* thread() const { return valid_ ? &thread_ : NULL; }
|
||||
MinidumpMemoryRegion* GetMemory();
|
||||
MinidumpContext* GetContext();
|
||||
const MDRawThread* thread() const { return valid_ ? &thread_ : NULL; }
|
||||
MinidumpMemoryRegion* GetMemory();
|
||||
MinidumpContext* GetContext();
|
||||
|
||||
// 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
|
||||
// MDRawThread structure.
|
||||
u_int32_t GetThreadID();
|
||||
// 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
|
||||
// MDRawThread structure.
|
||||
u_int32_t GetThreadID();
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
private:
|
||||
// This objects are managed by MinidumpThreadList.
|
||||
friend class MinidumpThreadList;
|
||||
private:
|
||||
// These objects are managed by MinidumpThreadList.
|
||||
friend class MinidumpThreadList;
|
||||
|
||||
MinidumpThread(Minidump* minidump);
|
||||
MinidumpThread(Minidump* minidump);
|
||||
|
||||
// This works like MinidumpStream::Read, but is driven by
|
||||
// MinidumpThreadList. No size checking is done, because
|
||||
// MinidumpThreadList handles that directly.
|
||||
bool Read();
|
||||
// This works like MinidumpStream::Read, but is driven by
|
||||
// MinidumpThreadList. No size checking is done, because
|
||||
// MinidumpThreadList handles that directly.
|
||||
bool Read();
|
||||
|
||||
MDRawThread thread_;
|
||||
MinidumpMemoryRegion* memory_;
|
||||
MinidumpContext* context_;
|
||||
MDRawThread thread_;
|
||||
MinidumpMemoryRegion* memory_;
|
||||
MinidumpContext* context_;
|
||||
};
|
||||
|
||||
|
||||
// MinidumpThreadList contains all of the threads (as MinidumpThreads) in
|
||||
// a process.
|
||||
class MinidumpThreadList : public MinidumpStream {
|
||||
public:
|
||||
~MinidumpThreadList();
|
||||
public:
|
||||
~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.
|
||||
MinidumpThread* GetThreadAtIndex(unsigned int index) const;
|
||||
// Sequential access to threads.
|
||||
MinidumpThread* GetThreadAtIndex(unsigned int index) const;
|
||||
|
||||
// Random access to threads.
|
||||
MinidumpThread* GetThreadByID(u_int32_t thread_id);
|
||||
// Random access to threads.
|
||||
MinidumpThread* GetThreadByID(u_int32_t thread_id);
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
private:
|
||||
friend class Minidump;
|
||||
private:
|
||||
friend class Minidump;
|
||||
|
||||
typedef map<u_int32_t, MinidumpThread*> IDToThreadMap;
|
||||
typedef vector<MinidumpThread> MinidumpThreads;
|
||||
typedef map<u_int32_t, MinidumpThread*> IDToThreadMap;
|
||||
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.
|
||||
IDToThreadMap id_to_thread_map_;
|
||||
// Access to threads using the thread ID as the key.
|
||||
IDToThreadMap id_to_thread_map_;
|
||||
|
||||
// The list of threads.
|
||||
MinidumpThreads* threads_;
|
||||
u_int32_t thread_count_;
|
||||
// The list of threads.
|
||||
MinidumpThreads* threads_;
|
||||
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
|
||||
// to locate debugging information for the module.
|
||||
class MinidumpModule : public MinidumpObject {
|
||||
public:
|
||||
~MinidumpModule();
|
||||
public:
|
||||
~MinidumpModule();
|
||||
|
||||
const MDRawModule* module() const { return valid_ ? &module_ : 0; }
|
||||
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; }
|
||||
const MDRawModule* module() const { return valid_ ? &module_ : 0; }
|
||||
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();
|
||||
// The name of the file containing this module's code (exe, dll, so,
|
||||
// dylib).
|
||||
const string* GetName();
|
||||
|
||||
// The CodeView record, which contains information to locate the module's
|
||||
// debugging information (pdb). This is returned as u_int8_t* because
|
||||
// the data can be one of two types: MDCVInfoPDB20* or MDCVInfoPDB70*.
|
||||
// Check the record's signature in the first four bytes to differentiate.
|
||||
// Current toolchains generate modules which carry MDCVInfoPDB70.
|
||||
const u_int8_t* GetCVRecord();
|
||||
// The CodeView record, which contains information to locate the module's
|
||||
// debugging information (pdb). This is returned as u_int8_t* because
|
||||
// the data can be one of two types: MDCVInfoPDB20* or MDCVInfoPDB70*.
|
||||
// Check the record's signature in the first four bytes to differentiate.
|
||||
// Current toolchains generate modules which carry MDCVInfoPDB70.
|
||||
const u_int8_t* GetCVRecord();
|
||||
|
||||
// The miscellaneous debug record, which is obsolete. Current toolchains
|
||||
// do not generate this type of debugging information (dbg), and this
|
||||
// field is not expected to be present.
|
||||
const MDImageDebugMisc* GetMiscRecord();
|
||||
// The miscellaneous debug record, which is obsolete. Current toolchains
|
||||
// do not generate this type of debugging information (dbg), and this
|
||||
// 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();
|
||||
// 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();
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
private:
|
||||
// These objects are managed by MinidumpModuleList.
|
||||
friend class MinidumpModuleList;
|
||||
private:
|
||||
// These objects are managed by MinidumpModuleList.
|
||||
friend class MinidumpModuleList;
|
||||
|
||||
MinidumpModule(Minidump* minidump);
|
||||
MinidumpModule(Minidump* minidump);
|
||||
|
||||
// This works like MinidumpStream::Read, but is driven by
|
||||
// MinidumpModuleList. No size checking is done, because
|
||||
// MinidumpModuleList handles that directly.
|
||||
bool Read();
|
||||
// This works like MinidumpStream::Read, but is driven by
|
||||
// MinidumpModuleList. No size checking is done, because
|
||||
// MinidumpModuleList handles that directly.
|
||||
bool Read();
|
||||
|
||||
MDRawModule module_;
|
||||
MDRawModule module_;
|
||||
|
||||
// Cached module name.
|
||||
const string* name_;
|
||||
// Cached module name.
|
||||
const string* name_;
|
||||
|
||||
// Cached CodeView record - this is MDCVInfoPDB20 or (likely)
|
||||
// MDCVInfoPDB70. Stored as a u_int8_t because the structure contains
|
||||
// a variable-sized string and its exact size cannot be known until it
|
||||
// is processed.
|
||||
vector<u_int8_t>* cv_record_;
|
||||
// Cached CodeView record - this is MDCVInfoPDB20 or (likely)
|
||||
// MDCVInfoPDB70. Stored as a u_int8_t because the structure contains
|
||||
// a variable-sized string and its exact size cannot be known until it
|
||||
// is processed.
|
||||
vector<u_int8_t>* cv_record_;
|
||||
|
||||
// Cached MDImageDebugMisc (usually not present), stored as u_int8_t
|
||||
// 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 MDImageDebugMisc (usually not present), stored as u_int8_t
|
||||
// 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_;
|
||||
// Cached 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
|
||||
// address.
|
||||
class MinidumpModuleList : public MinidumpStream {
|
||||
public:
|
||||
~MinidumpModuleList();
|
||||
public:
|
||||
~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.
|
||||
MinidumpModule* GetModuleAtIndex(unsigned int index) const;
|
||||
// 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);
|
||||
// Random access to modules. Returns the module whose code is present
|
||||
// at the address identified by address.
|
||||
MinidumpModule* GetModuleForAddress(u_int64_t address);
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
private:
|
||||
friend class Minidump;
|
||||
private:
|
||||
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.
|
||||
RangeMap<u_int64_t, unsigned int> range_map_;
|
||||
// Access to modules using addresses as the key.
|
||||
RangeMap<u_int64_t, unsigned int> range_map_;
|
||||
|
||||
MinidumpModules* modules_;
|
||||
u_int32_t module_count_;
|
||||
MinidumpModules* modules_;
|
||||
u_int32_t module_count_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -423,45 +422,45 @@ class MinidumpModuleList : public MinidumpStream {
|
|||
// types of minidumps may contain significantly more memory regions. Full-
|
||||
// memory minidumps contain all of a process' mapped memory.
|
||||
class MinidumpMemoryList : public MinidumpStream {
|
||||
public:
|
||||
~MinidumpMemoryList();
|
||||
public:
|
||||
~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.
|
||||
MinidumpMemoryRegion* GetMemoryRegionAtIndex(unsigned int index);
|
||||
// Sequential access to memory regions.
|
||||
MinidumpMemoryRegion* GetMemoryRegionAtIndex(unsigned int index);
|
||||
|
||||
// Random access to memory regions. Returns the region encompassing
|
||||
// the address identified by address.
|
||||
MinidumpMemoryRegion* GetMemoryRegionForAddress(u_int64_t address);
|
||||
// Random access to memory regions. Returns the region encompassing
|
||||
// the address identified by address.
|
||||
MinidumpMemoryRegion* GetMemoryRegionForAddress(u_int64_t address);
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
private:
|
||||
friend class Minidump;
|
||||
private:
|
||||
friend class Minidump;
|
||||
|
||||
typedef vector<MDMemoryDescriptor> MemoryDescriptors;
|
||||
typedef vector<MinidumpMemoryRegion> MemoryRegions;
|
||||
typedef vector<MDMemoryDescriptor> MemoryDescriptors;
|
||||
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.
|
||||
RangeMap<u_int64_t, unsigned int> range_map_;
|
||||
// Access to memory regions using addresses as the key.
|
||||
RangeMap<u_int64_t, unsigned int> range_map_;
|
||||
|
||||
// The list of descriptors. This is maintained separately from the list
|
||||
// of regions, because MemoryRegion doesn't own its MemoryDescriptor, it
|
||||
// maintains a pointer to it. descriptors_ provides the storage for this
|
||||
// purpose.
|
||||
MemoryDescriptors* descriptors_;
|
||||
// The list of descriptors. This is maintained separately from the list
|
||||
// of regions, because MemoryRegion doesn't own its MemoryDescriptor, it
|
||||
// maintains a pointer to it. descriptors_ provides the storage for this
|
||||
// purpose.
|
||||
MemoryDescriptors* descriptors_;
|
||||
|
||||
// The list of regions.
|
||||
MemoryRegions* regions_;
|
||||
u_int32_t region_count_;
|
||||
// The list of regions.
|
||||
MemoryRegions* regions_;
|
||||
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
|
||||
// the exception occurred.
|
||||
class MinidumpException : public MinidumpStream {
|
||||
public:
|
||||
~MinidumpException();
|
||||
public:
|
||||
~MinidumpException();
|
||||
|
||||
const MDRawExceptionStream* exception() const {
|
||||
return valid_ ? &exception_ : 0; }
|
||||
const MDRawExceptionStream* exception() const {
|
||||
return valid_ ? &exception_ : 0; }
|
||||
|
||||
// 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
|
||||
// MDRawExceptionStream structure.
|
||||
u_int32_t GetThreadID();
|
||||
// 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
|
||||
// MDRawExceptionStream structure.
|
||||
u_int32_t GetThreadID();
|
||||
|
||||
MinidumpContext* GetContext();
|
||||
MinidumpContext* GetContext();
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
private:
|
||||
friend class Minidump;
|
||||
private:
|
||||
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_;
|
||||
MinidumpContext* context_;
|
||||
MDRawExceptionStream exception_;
|
||||
MinidumpContext* context_;
|
||||
};
|
||||
|
||||
|
||||
// MinidumpSystemInfo wraps MDRawSystemInfo and provides information about
|
||||
// the system on which the minidump was generated. See also MinidumpMiscInfo.
|
||||
class MinidumpSystemInfo : public MinidumpStream {
|
||||
public:
|
||||
~MinidumpSystemInfo();
|
||||
public:
|
||||
~MinidumpSystemInfo();
|
||||
|
||||
const MDRawSystemInfo* system_info() const {
|
||||
return valid_ ? &system_info_ : 0; }
|
||||
const MDRawSystemInfo* system_info() const {
|
||||
return valid_ ? &system_info_ : 0; }
|
||||
|
||||
// I don't know what CSD stands for, but this field is documented as
|
||||
// returning a textual representation of the OS service pack.
|
||||
const string* GetCSDVersion();
|
||||
// I don't know what CSD stands for, but this field is documented as
|
||||
// returning a textual representation of the OS service pack.
|
||||
const string* GetCSDVersion();
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
private:
|
||||
friend class Minidump;
|
||||
private:
|
||||
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
|
||||
// by MiniDumpWriteDump on Windows.
|
||||
const string* csd_version_;
|
||||
// Textual representation of the OS service pack, for minidumps produced
|
||||
// by MiniDumpWriteDump on Windows.
|
||||
const string* csd_version_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -539,157 +538,141 @@ class MinidumpSystemInfo : public MinidumpStream {
|
|||
// the process that generated the minidump, and optionally additional system
|
||||
// information. See also MinidumpSystemInfo.
|
||||
class MinidumpMiscInfo : public MinidumpStream {
|
||||
public:
|
||||
const MDRawMiscInfo* misc_info() const {
|
||||
return valid_ ? &misc_info_ : 0; }
|
||||
public:
|
||||
const MDRawMiscInfo* misc_info() const { return valid_ ? &misc_info_ : 0; }
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
private:
|
||||
friend class Minidump;
|
||||
private:
|
||||
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
|
||||
// and provides access to the minidump's top-level stream directory.
|
||||
class Minidump {
|
||||
public:
|
||||
// fd is a randomly seekable file descriptor that is open and is
|
||||
// positioned at the beginning of the MDRawHeader structure (byte offset
|
||||
// 0).
|
||||
Minidump(int fd);
|
||||
public:
|
||||
// fd is a randomly seekable file descriptor that is open and is
|
||||
// positioned at the beginning of the MDRawHeader structure (byte offset
|
||||
// 0).
|
||||
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.
|
||||
// The minidump is expected to be positioned at the beginning of the
|
||||
// header. Read() sets up the stream list and map, and validates the
|
||||
// Minidump object.
|
||||
bool Read();
|
||||
// Reads the minidump file's header and top-level stream directory.
|
||||
// The minidump is expected to be positioned at the beginning of the
|
||||
// header. Read() sets up the stream list and map, and validates the
|
||||
// Minidump object.
|
||||
bool Read();
|
||||
|
||||
// The next 6 methods are stubs that call GetStream. They exist to
|
||||
// force code generation of the templatized API within the module, and
|
||||
// to avoid exposing an ugly API (GetStream needs to accept a garbage
|
||||
// parameter).
|
||||
MinidumpThreadList* GetThreadList();
|
||||
MinidumpModuleList* GetModuleList();
|
||||
MinidumpMemoryList* GetMemoryList();
|
||||
MinidumpException* GetException();
|
||||
MinidumpSystemInfo* GetSystemInfo();
|
||||
MinidumpMiscInfo* GetMiscInfo();
|
||||
// The next 6 methods are stubs that call GetStream. They exist to
|
||||
// force code generation of the templatized API within the module, and
|
||||
// to avoid exposing an ugly API (GetStream needs to accept a garbage
|
||||
// parameter).
|
||||
MinidumpThreadList* GetThreadList();
|
||||
MinidumpModuleList* GetModuleList();
|
||||
MinidumpMemoryList* GetMemoryList();
|
||||
MinidumpException* GetException();
|
||||
MinidumpSystemInfo* GetSystemInfo();
|
||||
MinidumpMiscInfo* GetMiscInfo();
|
||||
|
||||
// The next set of methods are provided for users who wish to access
|
||||
// data in minidump files directly, while leveraging the rest of
|
||||
// this class and related classes to handle the basic minidump
|
||||
// structure and known stream types.
|
||||
// The next set of methods are provided for users who wish to access
|
||||
// data in minidump files directly, while leveraging the rest of
|
||||
// this class and related classes to handle the basic minidump
|
||||
// structure and known stream types.
|
||||
|
||||
unsigned int GetDirectoryEntryCount() const {
|
||||
return valid_ ? header_.stream_count : 0; }
|
||||
const MDRawDirectory* GetDirectoryEntryAtIndex(unsigned int index) const;
|
||||
unsigned int GetDirectoryEntryCount() const {
|
||||
return valid_ ? header_.stream_count : 0; }
|
||||
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
|
||||
// the storage area pointed to by bytes. bytes must be of sufficient
|
||||
// size. After the read, the file position is advanced by count.
|
||||
bool ReadBytes(void* bytes, size_t count);
|
||||
// Reads count bytes from the minidump at the current position into
|
||||
// the storage area pointed to by bytes. bytes must be of sufficient
|
||||
// size. After the read, the file position is advanced by count.
|
||||
bool ReadBytes(void* bytes, size_t count);
|
||||
|
||||
// Sets the position of the minidump file to offset.
|
||||
bool SeekSet(off_t offset);
|
||||
// Sets the position of the minidump file to 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
|
||||
// specifies the offset that a length-encoded string is stored at in the
|
||||
// minidump file.
|
||||
string* ReadString(off_t 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
|
||||
// minidump file.
|
||||
string* ReadString(off_t offset);
|
||||
|
||||
// SeekToStreamType positions the file at the beginning of a stream
|
||||
// identified by stream_type, and informs the caller of the stream's
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// are looking for other stream types should be aware of this
|
||||
// possibility, and consider using GetDirectoryEntryAtIndex (possibly
|
||||
// with GetDirectoryEntryCount) if expecting multiple streams of the same
|
||||
// type in a single minidump file.
|
||||
bool SeekToStreamType(u_int32_t stream_type, u_int32_t* stream_length);
|
||||
// SeekToStreamType positions the file at the beginning of a stream
|
||||
// identified by stream_type, and informs the caller of the stream's
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// are looking for other stream types should be aware of this
|
||||
// possibility, and consider using GetDirectoryEntryAtIndex (possibly
|
||||
// with GetDirectoryEntryCount) if expecting multiple streams of the same
|
||||
// type in a single minidump file.
|
||||
bool SeekToStreamType(u_int32_t stream_type, u_int32_t* stream_length);
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
bool swap() const { return valid_ ? swap_ : false; }
|
||||
|
||||
private:
|
||||
// These classes are friends to give them access to this class' file
|
||||
// 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;
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
// MinidumpStreamInfo is used in the MinidumpStreamMap. It lets
|
||||
// the Minidump object locate interesting streams quickly, and
|
||||
// provides a convenient place to stash MinidumpStream objects.
|
||||
struct MinidumpStreamInfo {
|
||||
MinidumpStreamInfo()
|
||||
: stream_index(0)
|
||||
, stream(NULL) {}
|
||||
~MinidumpStreamInfo() { delete stream; }
|
||||
private:
|
||||
// MinidumpStreamInfo is used in the MinidumpStreamMap. It lets
|
||||
// the Minidump object locate interesting streams quickly, and
|
||||
// provides a convenient place to stash MinidumpStream objects.
|
||||
struct MinidumpStreamInfo {
|
||||
MinidumpStreamInfo() : stream_index(0), stream(NULL) {}
|
||||
~MinidumpStreamInfo() { delete stream; }
|
||||
|
||||
// Index into the MinidumpDirectoryEntries vector
|
||||
unsigned int stream_index;
|
||||
// Index into the MinidumpDirectoryEntries vector
|
||||
unsigned int stream_index;
|
||||
|
||||
// Pointer to the stream if cached, or NULL if not yet populated
|
||||
MinidumpStream* stream;
|
||||
};
|
||||
// Pointer to the stream if cached, or NULL if not yet populated
|
||||
MinidumpStream* stream;
|
||||
};
|
||||
|
||||
typedef vector<MDRawDirectory> MinidumpDirectoryEntries;
|
||||
typedef map<u_int32_t, MinidumpStreamInfo> MinidumpStreamMap;
|
||||
typedef vector<MDRawDirectory> MinidumpDirectoryEntries;
|
||||
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.
|
||||
MinidumpDirectoryEntries* directory_;
|
||||
// Access to streams using the stream type as the key.
|
||||
MinidumpStreamMap* stream_map_;
|
||||
|
||||
// Access to streams using the stream type as the key.
|
||||
MinidumpStreamMap* stream_map_;
|
||||
// The file descriptor for all file I/O. Used by ReadBytes and SeekSet.
|
||||
int fd_;
|
||||
|
||||
// The file descriptor for all file I/O. Used by ReadBytes and SeekSet.
|
||||
int fd_;
|
||||
// swap_ is true if the minidump file should be byte-swapped. If the
|
||||
// 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
|
||||
// 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_;
|
||||
|
||||
// Validity of the Minidump structure, false immediately after
|
||||
// construction or after a failed Read(); true following a successful
|
||||
// Read().
|
||||
bool valid_;
|
||||
// Validity of the Minidump structure, false immediately after
|
||||
// construction or after a failed Read(); true following a successful
|
||||
// Read().
|
||||
bool valid_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -37,50 +37,50 @@ using std::map;
|
|||
|
||||
template<typename AddressType, typename EntryType>
|
||||
class RangeMap {
|
||||
public:
|
||||
RangeMap() : map_() {}
|
||||
public:
|
||||
RangeMap() : map_() {}
|
||||
|
||||
// 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
|
||||
// stored in the map.
|
||||
bool StoreRange(const AddressType& base,
|
||||
const AddressType& size,
|
||||
const EntryType& entry);
|
||||
// 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
|
||||
// stored in the map.
|
||||
bool StoreRange(const AddressType& base,
|
||||
const AddressType& size,
|
||||
const EntryType& entry);
|
||||
|
||||
// Locates the range encompassing the supplied address. If there is
|
||||
// no such range, or if there is a parameter error, returns false.
|
||||
bool RetrieveRange(const AddressType& address, EntryType* entry);
|
||||
// Locates the range encompassing the supplied address. If there is
|
||||
// no such range, or if there is a parameter error, returns false.
|
||||
bool RetrieveRange(const AddressType& address, EntryType* entry);
|
||||
|
||||
// Empties the range map, restoring it to the state it was when it was
|
||||
// initially created.
|
||||
void Clear();
|
||||
// Empties the range map, restoring it to the state it was when it was
|
||||
// initially created.
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
class Range {
|
||||
public:
|
||||
Range(const AddressType& base, const EntryType& entry)
|
||||
: base_(base), entry_(entry) {}
|
||||
private:
|
||||
class Range {
|
||||
public:
|
||||
Range(const AddressType& base, const EntryType& entry)
|
||||
: base_(base), entry_(entry) {}
|
||||
|
||||
AddressType base() const { return base_; }
|
||||
EntryType entry() const { return entry_; }
|
||||
AddressType base() const { return base_; }
|
||||
EntryType entry() const { return entry_; }
|
||||
|
||||
private:
|
||||
// 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.
|
||||
const AddressType base_;
|
||||
private:
|
||||
// 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.
|
||||
const AddressType base_;
|
||||
|
||||
// The entry, owned by the Range object.
|
||||
const EntryType entry_;
|
||||
};
|
||||
// The entry, owned by the Range object.
|
||||
const EntryType entry_;
|
||||
};
|
||||
|
||||
typedef map<AddressType, Range> AddressToRangeMap;
|
||||
typedef map<AddressType, Range> AddressToRangeMap;
|
||||
|
||||
// Can't depend on implicit typenames in a template
|
||||
typedef typename AddressToRangeMap::const_iterator const_iterator;
|
||||
typedef typename AddressToRangeMap::value_type value_type;
|
||||
// Can't depend on implicit typenames in a template
|
||||
typedef typename AddressToRangeMap::const_iterator const_iterator;
|
||||
typedef typename AddressToRangeMap::value_type value_type;
|
||||
|
||||
// Maps the high address of each range to a EntryType.
|
||||
AddressToRangeMap map_;
|
||||
// Maps the high address of each range to a EntryType.
|
||||
AddressToRangeMap map_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -32,17 +32,17 @@ using google_airbag::RangeMap;
|
|||
// A CountedObject holds an int. A global (not thread safe!) count of
|
||||
// allocated CountedObjects is maintained to help test memory management.
|
||||
class CountedObject {
|
||||
public:
|
||||
CountedObject(int id) : id_(id) { ++count_; }
|
||||
CountedObject(const CountedObject& that) : id_(that.id_) { ++count_; }
|
||||
~CountedObject() { --count_; }
|
||||
public:
|
||||
CountedObject(int id) : id_(id) { ++count_; }
|
||||
CountedObject(const CountedObject& that) : id_(that.id_) { ++count_; }
|
||||
~CountedObject() { --count_; }
|
||||
|
||||
static int count() { return count_; }
|
||||
int id() const { return id_; }
|
||||
static int count() { return count_; }
|
||||
int id() const { return id_; }
|
||||
|
||||
private:
|
||||
static int count_;
|
||||
int id_;
|
||||
private:
|
||||
static int count_;
|
||||
int id_;
|
||||
};
|
||||
|
||||
int CountedObject::count_;
|
||||
|
@ -210,7 +210,7 @@ bool RunTests() {
|
|||
{ 20000, 20000, 34, true }, // > 8-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
|
||||
|
@ -254,7 +254,7 @@ bool RunTests() {
|
|||
{ range_tests_1, sizeof(range_tests_1) / sizeof(RangeTest) },
|
||||
{ range_tests_2, sizeof(range_tests_2) / 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
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// stackwalker.cc: Generic stackwalker.
|
||||
// stackwalker.h: Generic stackwalker.
|
||||
//
|
||||
// The Stackwalker class is an abstract base class providing common generic
|
||||
// methods that apply to stacks from all systems. Specific implementations
|
||||
|
@ -39,41 +39,41 @@ class MinidumpModuleList;
|
|||
|
||||
|
||||
class Stackwalker {
|
||||
public:
|
||||
virtual ~Stackwalker() {}
|
||||
public:
|
||||
virtual ~Stackwalker() {}
|
||||
|
||||
// Produces a vector of StackFrames by calling GetContextFrame and
|
||||
// GetCallerFrame, and populating the returned frames with module
|
||||
// offset and name information if possible. The caller takes ownership
|
||||
// of the StackFrames object and is responsible for freeing it.
|
||||
StackFrames* Walk();
|
||||
// Produces a vector of StackFrames by calling GetContextFrame and
|
||||
// GetCallerFrame, and populating the returned frames with module
|
||||
// offset and name information if possible. The caller takes ownership
|
||||
// of the StackFrames object and is responsible for freeing it.
|
||||
StackFrames* Walk();
|
||||
|
||||
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
|
||||
// associated with.
|
||||
Stackwalker(MemoryRegion* memory, MinidumpModuleList* modules);
|
||||
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
|
||||
// associated with.
|
||||
Stackwalker(MemoryRegion* memory, MinidumpModuleList* modules);
|
||||
|
||||
// The stack memory to walk. Subclasses will require this region to
|
||||
// get information from the stack.
|
||||
MemoryRegion* memory_;
|
||||
// The stack memory to walk. Subclasses will require this region to
|
||||
// get information from the stack.
|
||||
MemoryRegion* memory_;
|
||||
|
||||
private:
|
||||
// Obtains the context frame, the innermost called procedure in a stack
|
||||
// trace. Returns false on failure.
|
||||
virtual bool GetContextFrame(StackFrame* frame) = 0;
|
||||
private:
|
||||
// Obtains the context frame, the innermost called procedure in a stack
|
||||
// trace. Returns false on failure.
|
||||
virtual bool GetContextFrame(StackFrame* frame) = 0;
|
||||
|
||||
// Obtains a caller frame. Each call to GetCallerFrame should return the
|
||||
// frame that called the last frame returned by GetContextFrame or
|
||||
// GetCallerFrame. GetCallerFrame should return false on failure or
|
||||
// when there are no more caller frames (when the end of the stack has
|
||||
// been reached).
|
||||
virtual bool GetCallerFrame(StackFrame* frame) = 0;
|
||||
// Obtains a caller frame. Each call to GetCallerFrame should return the
|
||||
// frame that called the last frame returned by GetContextFrame or
|
||||
// GetCallerFrame. GetCallerFrame should return false on failure or
|
||||
// when there are no more caller frames (when the end of the stack has
|
||||
// been reached).
|
||||
virtual bool GetCallerFrame(StackFrame* frame) = 0;
|
||||
|
||||
// A list of modules, for populating each StackFrame's module information.
|
||||
// This field is optional and may be NULL.
|
||||
MinidumpModuleList* modules_;
|
||||
// A list of modules, for populating each StackFrame's module information.
|
||||
// This field is optional and may be NULL.
|
||||
MinidumpModuleList* modules_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ namespace google_airbag {
|
|||
StackwalkerX86::StackwalkerX86(MinidumpContext* context,
|
||||
MemoryRegion* memory,
|
||||
MinidumpModuleList* modules)
|
||||
: Stackwalker(memory, modules)
|
||||
, last_frame_pointer_(0) {
|
||||
: Stackwalker(memory, modules),
|
||||
last_frame_pointer_(0) {
|
||||
if (memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) {
|
||||
// The x86 is a 32-bit CPU, the limits of the supplied stack are invalid.
|
||||
// Mark memory_ = NULL, which will cause stackwalking to fail.
|
||||
|
|
|
@ -37,28 +37,28 @@ class MinidumpModuleList;
|
|||
|
||||
|
||||
class StackwalkerX86 : public Stackwalker {
|
||||
public:
|
||||
// context is a MinidumpContext object that gives access to x86-specific
|
||||
// register state corresponding to the innermost called frame to be
|
||||
// included in the stack. memory and modules are passed directly through
|
||||
// to the base Stackwalker constructor.
|
||||
StackwalkerX86(MinidumpContext* context,
|
||||
MemoryRegion* memory,
|
||||
MinidumpModuleList* modules);
|
||||
public:
|
||||
// context is a MinidumpContext object that gives access to x86-specific
|
||||
// register state corresponding to the innermost called frame to be
|
||||
// included in the stack. memory and modules are passed directly through
|
||||
// to the base Stackwalker constructor.
|
||||
StackwalkerX86(MinidumpContext* context,
|
||||
MemoryRegion* memory,
|
||||
MinidumpModuleList* modules);
|
||||
|
||||
private:
|
||||
// Implementation of Stackwalker, using x86 context (%ebp, %eip) and
|
||||
// stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp]).
|
||||
virtual bool GetContextFrame(StackFrame* frame);
|
||||
virtual bool GetCallerFrame(StackFrame* frame);
|
||||
private:
|
||||
// Implementation of Stackwalker, using x86 context (%ebp, %eip) and
|
||||
// stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp]).
|
||||
virtual bool GetContextFrame(StackFrame* frame);
|
||||
virtual bool GetCallerFrame(StackFrame* frame);
|
||||
|
||||
// Stores the CPU context corresponding to the innermost stack frame to
|
||||
// be returned by GetContextFrame.
|
||||
const MDRawContextX86* context_;
|
||||
// Stores the CPU context corresponding to the innermost stack frame to
|
||||
// be returned by GetContextFrame.
|
||||
const MDRawContextX86* context_;
|
||||
|
||||
// Stores the frame pointer returned in the last stack frame returned by
|
||||
// GetContextFrame or GetCallerFrame.
|
||||
u_int32_t last_frame_pointer_;
|
||||
// Stores the frame pointer returned in the last stack frame returned by
|
||||
// GetContextFrame or GetCallerFrame.
|
||||
u_int32_t last_frame_pointer_;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue