aboutsummaryrefslogtreecommitdiff
path: root/src/processor/minidump.cc
diff options
context:
space:
mode:
authorted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2011-01-13 19:05:33 +0000
committerted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2011-01-13 19:05:33 +0000
commit7b8e2b7e090b2d1223d0944d1e7da1d4c571bb5d (patch)
treeb181c7a3ebd4af86a2d1e2cbd3d10561660c7a29 /src/processor/minidump.cc
parentAdd structure definitions for the memory info list, as well as some other new... (diff)
downloadbreakpad-7b8e2b7e090b2d1223d0944d1e7da1d4c571bb5d.tar.xz
Add MinidumpMemoryInfo / MinidumpMemoryInfoList classes to expose MDRawMemoryInfo / MDRawMemoryInfoList via the Minidump class
R=mark at http://breakpad.appspot.com/255001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@755 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/processor/minidump.cc')
-rw-r--r--src/processor/minidump.cc263
1 files changed, 263 insertions, 0 deletions
diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
index 3d42c428..9e084401 100644
--- a/src/processor/minidump.cc
+++ b/src/processor/minidump.cc
@@ -3440,6 +3440,264 @@ void MinidumpBreakpadInfo::Print() {
//
+// MinidumpMemoryInfo
+//
+
+
+MinidumpMemoryInfo::MinidumpMemoryInfo(Minidump* minidump)
+ : MinidumpObject(minidump),
+ memory_info_() {
+}
+
+
+bool MinidumpMemoryInfo::IsExecutable() const {
+ u_int32_t protection =
+ memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
+ return protection == MD_MEMORY_PROTECT_EXECUTE ||
+ protection == MD_MEMORY_PROTECT_EXECUTE_READ ||
+ protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE;
+}
+
+
+bool MinidumpMemoryInfo::IsWritable() const {
+ u_int32_t protection =
+ memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
+ return protection == MD_MEMORY_PROTECT_READWRITE ||
+ protection == MD_MEMORY_PROTECT_WRITECOPY ||
+ protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE ||
+ protection == MD_MEMORY_PROTECT_EXECUTE_WRITECOPY;
+}
+
+
+bool MinidumpMemoryInfo::Read() {
+ valid_ = false;
+
+ if (!minidump_->ReadBytes(&memory_info_, sizeof(memory_info_))) {
+ BPLOG(ERROR) << "MinidumpMemoryInfo cannot read memory info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&memory_info_.base_address);
+ Swap(&memory_info_.allocation_base);
+ Swap(&memory_info_.allocation_protection);
+ Swap(&memory_info_.region_size);
+ Swap(&memory_info_.state);
+ Swap(&memory_info_.protection);
+ Swap(&memory_info_.type);
+ }
+
+ // Check for base + size overflow or undersize.
+ if (memory_info_.region_size == 0 ||
+ memory_info_.region_size > numeric_limits<u_int64_t>::max() -
+ memory_info_.base_address) {
+ BPLOG(ERROR) << "MinidumpMemoryInfo has a memory region problem, " <<
+ HexString(memory_info_.base_address) << "+" <<
+ HexString(memory_info_.region_size);
+ return false;
+ }
+
+ valid_ = true;
+ return true;
+}
+
+
+void MinidumpMemoryInfo::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpMemoryInfo cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawMemoryInfo\n");
+ printf(" base_address = 0x%" PRIx64 "\n",
+ memory_info_.base_address);
+ printf(" allocation_base = 0x%" PRIx64 "\n",
+ memory_info_.allocation_base);
+ printf(" allocation_protection = 0x%x\n",
+ memory_info_.allocation_protection);
+ printf(" region_size = 0x%" PRIx64 "\n", memory_info_.region_size);
+ printf(" state = 0x%x\n", memory_info_.state);
+ printf(" protection = 0x%x\n", memory_info_.protection);
+ printf(" type = 0x%x\n", memory_info_.type);
+}
+
+
+//
+// MinidumpMemoryInfoList
+//
+
+
+MinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump)
+ : MinidumpStream(minidump),
+ range_map_(new RangeMap<u_int64_t, unsigned int>()),
+ infos_(NULL),
+ info_count_(0) {
+}
+
+
+MinidumpMemoryInfoList::~MinidumpMemoryInfoList() {
+ delete range_map_;
+ delete infos_;
+}
+
+
+bool MinidumpMemoryInfoList::Read(u_int32_t expected_size) {
+ // Invalidate cached data.
+ delete infos_;
+ infos_ = NULL;
+ range_map_->Clear();
+ info_count_ = 0;
+
+ valid_ = false;
+
+ MDRawMemoryInfoList header;
+ if (expected_size < sizeof(MDRawMemoryInfoList)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
+ expected_size << " < " << sizeof(MDRawMemoryInfoList);
+ return false;
+ }
+ if (!minidump_->ReadBytes(&header, sizeof(header))) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList could not read header";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&header.size_of_header);
+ Swap(&header.size_of_entry);
+ Swap(&header.number_of_entries);
+ }
+
+ // Sanity check that the header is the expected size.
+ //TODO(ted): could possibly handle this more gracefully, assuming
+ // that future versions of the structs would be backwards-compatible.
+ if (header.size_of_header != sizeof(MDRawMemoryInfoList)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
+ header.size_of_header << " != " <<
+ sizeof(MDRawMemoryInfoList);
+ return false;
+ }
+
+ // Sanity check that the entries are the expected size.
+ if (header.size_of_entry != sizeof(MDRawMemoryInfo)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList entry size mismatch, " <<
+ header.size_of_entry << " != " <<
+ sizeof(MDRawMemoryInfo);
+ return false;
+ }
+
+ if (header.number_of_entries >
+ numeric_limits<u_int32_t>::max() / sizeof(MDRawMemoryInfo)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList info count " <<
+ header.number_of_entries <<
+ " would cause multiplication overflow";
+ return false;
+ }
+
+ if (expected_size != sizeof(MDRawMemoryInfoList) +
+ header.number_of_entries * sizeof(MDRawMemoryInfo)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList size mismatch, " << expected_size <<
+ " != " << sizeof(MDRawMemoryInfoList) +
+ header.number_of_entries * sizeof(MDRawMemoryInfo);
+ return false;
+ }
+
+ if (header.number_of_entries != 0) {
+ scoped_ptr<MinidumpMemoryInfos> infos(
+ new MinidumpMemoryInfos(header.number_of_entries,
+ MinidumpMemoryInfo(minidump_)));
+
+ for (unsigned int index = 0;
+ index < header.number_of_entries;
+ ++index) {
+ MinidumpMemoryInfo* info = &(*infos)[index];
+
+ // Assume that the file offset is correct after the last read.
+ if (!info->Read()) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList cannot read info " <<
+ index << "/" << header.number_of_entries;
+ return false;
+ }
+
+ u_int64_t base_address = info->GetBase();
+ u_int32_t region_size = info->GetSize();
+
+ if (!range_map_->StoreRange(base_address, region_size, index)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList could not store"
+ " memory region " <<
+ index << "/" << header.number_of_entries << ", " <<
+ HexString(base_address) << "+" <<
+ HexString(region_size);
+ return false;
+ }
+ }
+
+ infos_ = infos.release();
+ }
+
+ info_count_ = header.number_of_entries;
+
+ valid_ = true;
+ return true;
+}
+
+
+const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex(
+ unsigned int index) const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex";
+ return NULL;
+ }
+
+ if (index >= info_count_) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList index out of range: " <<
+ index << "/" << info_count_;
+ return NULL;
+ }
+
+ return &(*infos_)[index];
+}
+
+
+const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress(
+ u_int64_t address) const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for"
+ " GetMemoryInfoForAddress";
+ return NULL;
+ }
+
+ unsigned int info_index;
+ if (!range_map_->RetrieveRange(address, &info_index, NULL, NULL)) {
+ BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " <<
+ HexString(address);
+ return NULL;
+ }
+
+ return GetMemoryInfoAtIndex(info_index);
+}
+
+
+void MinidumpMemoryInfoList::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList cannot print invalid data";
+ return;
+ }
+
+ printf("MinidumpMemoryInfoList\n");
+ printf(" info_count = %d\n", info_count_);
+ printf("\n");
+
+ for (unsigned int info_index = 0;
+ info_index < info_count_;
+ ++info_index) {
+ printf("info[%d]\n", info_index);
+ (*infos_)[info_index].Print();
+ printf("\n");
+ }
+}
+
+
+//
// Minidump
//
@@ -3681,6 +3939,11 @@ MinidumpBreakpadInfo* Minidump::GetBreakpadInfo() {
return GetStream(&breakpad_info);
}
+MinidumpMemoryInfoList* Minidump::GetMemoryInfoList() {
+ MinidumpMemoryInfoList* memory_info_list;
+ return GetStream(&memory_info_list);
+}
+
void Minidump::Print() {
if (!valid_) {