aboutsummaryrefslogtreecommitdiff
path: root/src/tools/linux/md2core/minidump-2-core.cc
diff options
context:
space:
mode:
authorbenchan@chromium.org <benchan@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2011-12-21 22:33:21 +0000
committerbenchan@chromium.org <benchan@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2011-12-21 22:33:21 +0000
commit33c135a16fb1d8869af561aacfa23a3b1fb53c07 (patch)
tree7a10f3a6ca688209eaa19d80bdd0d4921f6e63d7 /src/tools/linux/md2core/minidump-2-core.cc
parentEliminate another source of UnspecifiedStackSignature crash dumps. (diff)
downloadbreakpad-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.cc166
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);