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 {
|
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue