diff options
author | benchan@chromium.org <benchan@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2011-12-21 22:33:21 +0000 |
---|---|---|
committer | benchan@chromium.org <benchan@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2011-12-21 22:33:21 +0000 |
commit | 33c135a16fb1d8869af561aacfa23a3b1fb53c07 (patch) | |
tree | 7a10f3a6ca688209eaa19d80bdd0d4921f6e63d7 /src/tools/linux/md2core/minidump-2-core.cc | |
parent | Eliminate another source of UnspecifiedStackSignature crash dumps. (diff) | |
download | breakpad-33c135a16fb1d8869af561aacfa23a3b1fb53c07.tar.xz |
Replace MMappedRange with MinidumpMemoryRange.
This patch is part of a bigger patch that helps merging the breakpad code
with the modified version in Chromium OS.
The MemoryRange class was added in r895 (http://breakpad.appspot.com/332001),
which is largely based on MMappedRange but generalized to be used in other
code. However, MemoryRange does not support minidump data structures. This
patch adds a MinidumpMemoryRange class that extends MemoryRange to handle
minidump data structures, which can then replace MMappedRange.
As with MemoryRange, MinidumpMemoryRange is unit tested.
BUG=455
TEST=Tested the following:
1. Build on 32-bit and 64-bit Linux with gcc 4.4.3 and gcc 4.6.
2. Build on Mac OS X 10.6.8 with gcc 4.2 and clang 3.0 (with latest gmock).
3. All unit tests pass.
4. Run minidump-2-core to covnert a minidump file to a core file.
Review URL: http://breakpad.appspot.com/335001
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@898 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/tools/linux/md2core/minidump-2-core.cc')
-rw-r--r-- | src/tools/linux/md2core/minidump-2-core.cc | 166 |
1 files changed, 52 insertions, 114 deletions
diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc index ddefecc0..0a0343fb 100644 --- a/src/tools/linux/md2core/minidump-2-core.cc +++ b/src/tools/linux/md2core/minidump-2-core.cc @@ -48,9 +48,10 @@ #include "client/linux/minidump_writer/minidump_extension_linux.h" #include "common/linux/memory_mapped_file.h" -#include "google_breakpad/common/minidump_format.h" #include "google_breakpad/common/minidump_cpu_x86.h" +#include "google_breakpad/common/minidump_format.h" #include "third_party/lss/linux_syscall_support.h" +#include "tools/linux/md2core/minidump_memory_range.h" #if __WORDSIZE == 64 @@ -76,6 +77,7 @@ #endif using google_breakpad::MemoryMappedFile; +using google_breakpad::MinidumpMemoryRange; static const MDRVA kInvalidMDRVA = static_cast<MDRVA>(-1); static bool verbose; @@ -106,63 +108,6 @@ writea(int fd, const void* idata, size_t length) { return true; } -// A range of a mmaped file. -class MMappedRange { - public: - MMappedRange(const void* data, size_t length) - : data_(reinterpret_cast<const uint8_t*>(data)), - length_(length) { - } - - // Get an object of |length| bytes at |offset| and return a pointer to it - // unless it's out of bounds. - const void* GetObject(size_t offset, size_t length) const { - if (offset + length < offset) - return NULL; - if (offset + length > length_) - return NULL; - return data_ + offset; - } - - // Get element |index| of an array of objects of length |length| starting at - // |offset| bytes. Return NULL if out of bounds. - const void* GetArrayElement(size_t offset, size_t length, - unsigned index) const { - const size_t element_offset = offset + index * length; - return GetObject(element_offset, length); - } - - // Get a zero-terminated string. This method only works correctly for ASCII - // characters and does not convert between UTF-16 and UTF-8. - const std::string GetString(size_t offset) const { - const MDString* s = (const MDString*) GetObject(offset, sizeof(MDString)); - const u_int16_t* buf = &s->buffer[0]; - std::string str; - for (unsigned i = 0; i < s->length && buf[i]; ++i) { - str.push_back(buf[i]); - } - return str; - } - - // Return a new range which is a subset of this range. - MMappedRange Subrange(const MDLocationDescriptor& location) const { - if (location.rva > length_ || - location.rva + location.data_size < location.rva || - location.rva + location.data_size > length_) { - return MMappedRange(NULL, 0); - } - - return MMappedRange(data_ + location.rva, location.data_size); - } - - const uint8_t* data() const { return data_; } - size_t length() const { return length_; } - - private: - const uint8_t* const data_; - const size_t length_; -}; - /* Dynamically determines the byte sex of the system. Returns non-zero * for big-endian machines. */ @@ -290,9 +235,9 @@ U16(const uint8_t* data) { } static void -ParseThreadRegisters(CrashedProcess::Thread* thread, MMappedRange range) { - const MDRawContextX86* rawregs = - (const MDRawContextX86*) range.GetObject(0, sizeof(MDRawContextX86)); +ParseThreadRegisters(CrashedProcess::Thread* thread, + const MinidumpMemoryRange& range) { + const MDRawContextX86* rawregs = range.GetData<MDRawContextX86>(0); thread->regs.ebx = rawregs->ebx; thread->regs.ecx = rawregs->ecx; @@ -336,9 +281,9 @@ ParseThreadRegisters(CrashedProcess::Thread* thread, MMappedRange range) { } #elif defined(__x86_64__) static void -ParseThreadRegisters(CrashedProcess::Thread* thread, MMappedRange range) { - const MDRawContextAMD64* rawregs = - (const MDRawContextAMD64*) range.GetObject(0, sizeof(MDRawContextAMD64)); +ParseThreadRegisters(CrashedProcess::Thread* thread, + const MinidumpMemoryRange& range) { + const MDRawContextAMD64* rawregs = range.GetData<MDRawContextAMD64>(0); thread->regs.r15 = rawregs->r15; thread->regs.r14 = rawregs->r14; @@ -384,10 +329,9 @@ ParseThreadRegisters(CrashedProcess::Thread* thread, MMappedRange range) { #endif static void -ParseThreadList(CrashedProcess* crashinfo, MMappedRange range, - const MMappedRange& full_file) { - const uint32_t num_threads = - *(const uint32_t*) range.GetObject(0, sizeof(uint32_t)); +ParseThreadList(CrashedProcess* crashinfo, const MinidumpMemoryRange& range, + const MinidumpMemoryRange& full_file) { + const uint32_t num_threads = *range.GetData<uint32_t>(0); if (verbose) { fprintf(stderr, "MD_THREAD_LIST_STREAM:\n" @@ -399,11 +343,11 @@ ParseThreadList(CrashedProcess* crashinfo, MMappedRange range, CrashedProcess::Thread thread; memset(&thread, 0, sizeof(thread)); const MDRawThread* rawthread = - (MDRawThread*) range.GetArrayElement(sizeof(uint32_t), - sizeof(MDRawThread), i); + range.GetArrayElement<MDRawThread>(sizeof(uint32_t), i); thread.tid = rawthread->thread_id; thread.stack_addr = rawthread->stack.start_of_memory_range; - MMappedRange stack_range = full_file.Subrange(rawthread->stack.memory); + MinidumpMemoryRange stack_range = + full_file.Subrange(rawthread->stack.memory); thread.stack = stack_range.data(); thread.stack_length = rawthread->stack.memory.data_size; @@ -415,10 +359,9 @@ ParseThreadList(CrashedProcess* crashinfo, MMappedRange range, } static void -ParseSystemInfo(CrashedProcess* crashinfo, MMappedRange range, - const MMappedRange &full_file) { - const MDRawSystemInfo* sysinfo = - (MDRawSystemInfo*) range.GetObject(0, sizeof(MDRawSystemInfo)); +ParseSystemInfo(CrashedProcess* crashinfo, const MinidumpMemoryRange& range, + const MinidumpMemoryRange& full_file) { + const MDRawSystemInfo* sysinfo = range.GetData<MDRawSystemInfo>(0); if (!sysinfo) { fprintf(stderr, "Failed to access MD_SYSTEM_INFO_STREAM\n"); _exit(1); @@ -442,7 +385,8 @@ ParseSystemInfo(CrashedProcess* crashinfo, MMappedRange range, #else #error "This code has not been ported to your platform yet" #endif - if (!strstr(full_file.GetString(sysinfo->csd_version_rva).c_str(), "Linux")) { + if (!strstr(full_file.GetAsciiMDString(sysinfo->csd_version_rva).c_str(), + "Linux")) { fprintf(stderr, "This minidump was not generated by Linux.\n"); _exit(1); } @@ -478,13 +422,13 @@ ParseSystemInfo(CrashedProcess* crashinfo, MMappedRange range, fputs("\n", stderr); } fprintf(stderr, "OS: %s\n", - full_file.GetString(sysinfo->csd_version_rva).c_str()); + full_file.GetAsciiMDString(sysinfo->csd_version_rva).c_str()); fputs("\n\n", stderr); } } static void -ParseCPUInfo(CrashedProcess* crashinfo, MMappedRange range) { +ParseCPUInfo(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { if (verbose) { fputs("MD_LINUX_CPU_INFO:\n", stderr); fwrite(range.data(), range.length(), 1, stderr); @@ -493,7 +437,8 @@ ParseCPUInfo(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseProcessStatus(CrashedProcess* crashinfo, MMappedRange range) { +ParseProcessStatus(CrashedProcess* crashinfo, + const MinidumpMemoryRange& range) { if (verbose) { fputs("MD_LINUX_PROC_STATUS:\n", stderr); fwrite(range.data(), range.length(), 1, stderr); @@ -502,7 +447,7 @@ ParseProcessStatus(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseLSBRelease(CrashedProcess* crashinfo, MMappedRange range) { +ParseLSBRelease(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { if (verbose) { fputs("MD_LINUX_LSB_RELEASE:\n", stderr); fwrite(range.data(), range.length(), 1, stderr); @@ -511,7 +456,7 @@ ParseLSBRelease(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseMaps(CrashedProcess* crashinfo, MMappedRange range) { +ParseMaps(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { if (verbose) { fputs("MD_LINUX_MAPS:\n", stderr); fwrite(range.data(), range.length(), 1, stderr); @@ -557,7 +502,7 @@ ParseMaps(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseEnvironment(CrashedProcess* crashinfo, MMappedRange range) { +ParseEnvironment(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { if (verbose) { fputs("MD_LINUX_ENVIRON:\n", stderr); char *env = new char[range.length()]; @@ -595,7 +540,7 @@ ParseEnvironment(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseAuxVector(CrashedProcess* crashinfo, MMappedRange range) { +ParseAuxVector(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { // Some versions of Chrome erroneously used the MD_LINUX_AUXV stream value // when dumping /proc/$x/maps if (range.length() > 17) { @@ -616,7 +561,7 @@ ParseAuxVector(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseCmdLine(CrashedProcess* crashinfo, MMappedRange range) { +ParseCmdLine(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) { // The command line is supposed to use NUL bytes to separate arguments. // As Chrome rewrites its own command line and (incorrectly) substitutes // spaces, this is often not the case in our minidump files. @@ -664,10 +609,9 @@ ParseCmdLine(CrashedProcess* crashinfo, MMappedRange range) { } static void -ParseDSODebugInfo(CrashedProcess* crashinfo, MMappedRange range, - const MMappedRange &full_file) { - const MDRawDebug* debug = - (MDRawDebug*) range.GetObject(0, sizeof(MDRawDebug)); +ParseDSODebugInfo(CrashedProcess* crashinfo, const MinidumpMemoryRange& range, + const MinidumpMemoryRange& full_file) { + const MDRawDebug* debug = range.GetData<MDRawDebug>(0); if (!debug) { return; } @@ -694,14 +638,13 @@ ParseDSODebugInfo(CrashedProcess* crashinfo, MMappedRange range, if (debug->map != kInvalidMDRVA) { for (int i = 0; i < debug->dso_count; ++i) { const MDRawLinkMap* link_map = - (MDRawLinkMap*) full_file.GetArrayElement(debug->map, - sizeof(MDRawLinkMap), i); + full_file.GetArrayElement<MDRawLinkMap>(debug->map, i); if (link_map) { if (verbose) { fprintf(stderr, "#%03d: %p, %p, \"%s\"\n", i, link_map->addr, link_map->ld, - full_file.GetString(link_map->name).c_str()); + full_file.GetAsciiMDString(link_map->name).c_str()); } crashinfo->link_map.push_back(*link_map); } @@ -713,9 +656,9 @@ ParseDSODebugInfo(CrashedProcess* crashinfo, MMappedRange range, } static void -ParseExceptionStream(CrashedProcess* crashinfo, MMappedRange range) { - const MDRawExceptionStream* exp = - (MDRawExceptionStream*) range.GetObject(0, sizeof(MDRawExceptionStream)); +ParseExceptionStream(CrashedProcess* crashinfo, + const MinidumpMemoryRange& range) { + const MDRawExceptionStream* exp = range.GetData<MDRawExceptionStream>(0); crashinfo->crashing_tid = exp->thread_id; crashinfo->fatal_signal = (int) exp->exception_record.exception_code; } @@ -763,18 +706,16 @@ WriteThread(const CrashedProcess::Thread& thread, int fatal_signal) { } static void -ParseModuleStream(CrashedProcess* crashinfo, MMappedRange range, - const MMappedRange &full_file) { +ParseModuleStream(CrashedProcess* crashinfo, const MinidumpMemoryRange& range, + const MinidumpMemoryRange& full_file) { if (verbose) { fputs("MD_MODULE_LIST_STREAM:\n", stderr); } - const uint32_t num_mappings = - *(const uint32_t*) range.GetObject(0, sizeof(uint32_t)); + const uint32_t num_mappings = *range.GetData<uint32_t>(0); for (unsigned i = 0; i < num_mappings; ++i) { CrashedProcess::Mapping mapping; - const MDRawModule* rawmodule = - (MDRawModule*) range.GetArrayElement(sizeof(uint32_t), - MD_MODULE_SIZE, i); + const MDRawModule* rawmodule = reinterpret_cast<const MDRawModule*>( + range.GetArrayElement(sizeof(uint32_t), MD_MODULE_SIZE, i)); mapping.start_address = rawmodule->base_of_image; mapping.end_address = rawmodule->size_of_image + rawmodule->base_of_image; @@ -785,9 +726,8 @@ ParseModuleStream(CrashedProcess* crashinfo, MMappedRange range, crashinfo->mappings[mapping.start_address] = mapping; } - const MDCVInfoPDB70* record = - (const MDCVInfoPDB70*)full_file.GetObject(rawmodule->cv_record.rva, - MDCVInfoPDB70_minsize); + const MDCVInfoPDB70* record = reinterpret_cast<const MDCVInfoPDB70*>( + full_file.GetData(rawmodule->cv_record.rva, MDCVInfoPDB70_minsize)); char guid[40]; sprintf(guid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", record->signature.data1, record->signature.data2, @@ -796,7 +736,8 @@ ParseModuleStream(CrashedProcess* crashinfo, MMappedRange range, record->signature.data4[2], record->signature.data4[3], record->signature.data4[4], record->signature.data4[5], record->signature.data4[6], record->signature.data4[7]); - std::string filename = full_file.GetString(rawmodule->module_name_rva); + std::string filename = + full_file.GetAsciiMDString(rawmodule->module_name_rva); size_t slash = filename.find_last_of('/'); std::string basename = slash == std::string::npos ? filename : filename.substr(slash + 1); @@ -869,7 +810,7 @@ AddDataToMapping(CrashedProcess* crashinfo, const std::string& data, static void AugmentMappings(CrashedProcess* crashinfo, - const MMappedRange &full_file) { + const MinidumpMemoryRange& full_file) { // For each thread, find the memory mapping that matches the thread's stack. // Then adjust the mapping to include the stack dump. for (unsigned i = 0; i < crashinfo->threads.size(); ++i) { @@ -903,7 +844,7 @@ AugmentMappings(CrashedProcess* crashinfo, link_map.l_ld = (ElfW(Dyn)*)iter->ld; link_map.l_prev = prev; prev = (struct link_map*)(start_addr + data.size()); - std::string filename = full_file.GetString(iter->name); + std::string filename = full_file.GetAsciiMDString(iter->name); // Look up signature for this filename. If available, change filename // to point to GUID, instead. @@ -976,10 +917,9 @@ main(int argc, char** argv) { return 1; } - MMappedRange dump(mapped_file.data(), mapped_file.size()); + MinidumpMemoryRange dump(mapped_file.data(), mapped_file.size()); - const MDRawHeader* header = - (const MDRawHeader*) dump.GetObject(0, sizeof(MDRawHeader)); + const MDRawHeader* header = dump.GetData<MDRawHeader>(0); CrashedProcess crashinfo; @@ -988,8 +928,7 @@ main(int argc, char** argv) { bool ok = false; for (unsigned i = 0; i < header->stream_count; ++i) { const MDRawDirectory* dirent = - (const MDRawDirectory*) dump.GetArrayElement( - header->stream_directory_rva, sizeof(MDRawDirectory), i); + dump.GetArrayElement<MDRawDirectory>(header->stream_directory_rva, i); switch (dirent->stream_type) { case MD_SYSTEM_INFO_STREAM: ParseSystemInfo(&crashinfo, dump.Subrange(dirent->location), dump); @@ -1006,8 +945,7 @@ main(int argc, char** argv) { for (unsigned i = 0; i < header->stream_count; ++i) { const MDRawDirectory* dirent = - (const MDRawDirectory*) dump.GetArrayElement( - header->stream_directory_rva, sizeof(MDRawDirectory), i); + dump.GetArrayElement<MDRawDirectory>(header->stream_directory_rva, i); switch (dirent->stream_type) { case MD_THREAD_LIST_STREAM: ParseThreadList(&crashinfo, dump.Subrange(dirent->location), dump); |