diff options
Diffstat (limited to 'src/processor/minidump.cc')
-rw-r--r-- | src/processor/minidump.cc | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc index 08f64652..1a997d6a 100644 --- a/src/processor/minidump.cc +++ b/src/processor/minidump.cc @@ -55,6 +55,7 @@ #include <iostream> #include <limits> #include <map> +#include <sstream> #include <vector> #include "processor/range_map-inl.h" @@ -71,6 +72,7 @@ namespace google_breakpad { 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,6 +3974,142 @@ void MinidumpMemoryInfoList::Print() { } } +// +// 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 @@ MinidumpMemoryInfoList* Minidump::GetMemoryInfoList() { 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: |