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