Conform to style guidelines.

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


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

View File

@ -31,31 +31,27 @@ namespace google_airbag {
class MemoryRegion {
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;
};

View File

@ -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) {
}

View File

@ -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_;
};

View File

@ -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_;
};

View File

@ -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

View File

@ -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_;
};

View File

@ -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.

View File

@ -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_;
};