Index: src/processor/minidump.cc |
=================================================================== |
--- src/processor/minidump.cc (revision 1474) |
+++ src/processor/minidump.cc (working copy) |
@@ -55,6 +55,7 @@ |
#include <iostream> |
#include <limits> |
#include <map> |
+#include <sstream> |
#include <vector> |
#include "processor/range_map-inl.h" |
@@ -71,6 +72,7 @@ |
using std::istream; |
using std::ifstream; |
using std::numeric_limits; |
+using std::stringstream; |
using std::vector; |
// Returns true iff |context_size| matches exactly one of the sizes of the |
@@ -3972,8 +3974,144 @@ |
} |
} |
+// |
+// MinidumpLinuxMaps |
+// |
+MinidumpLinuxMaps::MinidumpLinuxMaps(Minidump *minidump) |
+ : MinidumpObject(minidump) { |
+} |
+ |
+void MinidumpLinuxMaps::Print() { |
+ if (!valid_) { |
+ BPLOG(ERROR) << "MinidumpLinuxMaps cannot print invalid data"; |
+ return; |
+ } |
+ std::cout << GetPathname() << std::endl; |
+} |
+ |
// |
+// MinidumpLinuxMapsList |
+// |
+ |
+MinidumpLinuxMapsList::MinidumpLinuxMapsList(Minidump *minidump) |
+ : MinidumpStream(minidump), |
+ maps_(NULL), |
+ maps_count_(0) { |
+} |
+ |
+MinidumpLinuxMapsList::~MinidumpLinuxMapsList() { |
+ for (unsigned int i = 0; i < maps_->size(); i++) { |
+ delete (*maps_)[i]; |
+ } |
+ delete maps_; |
+} |
+ |
+const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsForAddress( |
+ uint64_t address) const { |
+ if (!valid_) { |
+ BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsForAddress"; |
+ return NULL; |
+ } |
+ |
+ // Search every memory mapping. |
+ for (unsigned int index = 0; index < maps_count_; index++) { |
+ // Check if address is within bounds of the current memory region. |
+ if ((*maps_)[index]->GetBase() <= address && |
+ (*maps_)[index]->GetBase() + (*maps_)[index]->GetSize() > address) { |
+ return (*maps_)[index]; |
+ } |
+ } |
+ |
+ // No mapping encloses the memory address. |
+ BPLOG(ERROR) << "MinidumpLinuxMapsList has no mapping at " |
+ << HexString(address); |
+ return NULL; |
+} |
+ |
+const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsAtIndex( |
+ unsigned int index) const { |
+ if (!valid_) { |
+ BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsAtIndex"; |
+ return NULL; |
+ } |
+ |
+ // Index out of bounds. |
+ if (index >= maps_count_) { |
+ BPLOG(ERROR) << "MinidumpLinuxMapsList index of out range: " |
+ << index |
+ << "/" |
+ << maps_count_; |
+ return NULL; |
+ } |
+ return (*maps_)[index]; |
+} |
+ |
+bool MinidumpLinuxMapsList::Read(uint32_t expected_size) { |
+ // Invalidate cached data. |
+ delete maps_; |
+ maps_ = NULL; |
+ maps_count_ = 0; |
+ |
+ valid_ = false; |
+ |
+ // Load and check expected stream length. |
+ uint32_t length = 0; |
+ if (!minidump_->SeekToStreamType(MD_LINUX_MAPS, &length)) { |
+ BPLOG(ERROR) << "MinidumpLinuxMapsList stream type not found"; |
+ return false; |
+ } |
+ if (expected_size != length) { |
+ BPLOG(ERROR) << "MinidumpLinuxMapsList size mismatch: " |
+ << expected_size |
+ << " != " |
+ << length; |
+ return false; |
+ } |
+ |
+ // Create a vector to read stream data. The vector needs to have |
+ // at least enough capacity to read all the data. |
+ vector<char> mapping_bytes(length); |
+ if (!minidump_->ReadBytes(&mapping_bytes[0], length)) { |
+ BPLOG(ERROR) << "MinidumpLinuxMapsList failed to read bytes"; |
+ return false; |
+ } |
+ string map_string(mapping_bytes.begin(), mapping_bytes.end()); |
+ vector<MappedMemoryRegion> all_regions; |
+ |
+ // Parse string into mapping data. |
+ if (!ParseProcMaps(map_string, &all_regions)) { |
+ return false; |
+ } |
+ |
+ scoped_ptr<MinidumpLinuxMappings> maps(new MinidumpLinuxMappings()); |
+ |
+ // Push mapping data into wrapper classes. |
+ for (size_t i = 0; i < all_regions.size(); i++) { |
+ scoped_ptr<MinidumpLinuxMaps> ele(new MinidumpLinuxMaps(minidump_)); |
+ ele->region_ = all_regions[i]; |
+ ele->valid_ = true; |
+ maps->push_back(ele.release()); |
+ } |
+ |
+ // Set instance variables. |
+ maps_ = maps.release(); |
+ maps_count_ = maps_->size(); |
+ valid_ = true; |
+ return true; |
+} |
+ |
+void MinidumpLinuxMapsList::Print() { |
+ if (!valid_) { |
+ BPLOG(ERROR) << "MinidumpLinuxMapsList cannot print valid data"; |
+ return; |
+ } |
+ for (size_t i = 0; i < maps_->size(); i++) { |
+ (*maps_)[i]->Print(); |
+ } |
+} |
+ |
+// |
// Minidump |
// |
@@ -4292,6 +4430,11 @@ |
return GetStream(&memory_info_list); |
} |
+MinidumpLinuxMapsList *Minidump::GetLinuxMapsList() { |
+ MinidumpLinuxMapsList *linux_maps_list; |
+ return GetStream(&linux_maps_list); |
+} |
+ |
static const char* get_stream_name(uint32_t stream_type) { |
switch (stream_type) { |
case MD_UNUSED_STREAM: |