summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--breakpad/linux/linux_dumper.cc31
-rw-r--r--breakpad/linux/linux_dumper.h1
-rw-r--r--breakpad/linux/minidump_writer.cc77
3 files changed, 90 insertions, 19 deletions
diff --git a/breakpad/linux/linux_dumper.cc b/breakpad/linux/linux_dumper.cc
index 47465f2..a40f7cd 100644
--- a/breakpad/linux/linux_dumper.cc
+++ b/breakpad/linux/linux_dumper.cc
@@ -126,26 +126,29 @@ LinuxDumper::EnumerateMappings(wasteful_vector<MappingInfo*> *result) const {
const char *line;
unsigned line_len;
while (line_reader->GetNextLine(&line, &line_len)) {
- uintptr_t start_addr;
- uintptr_t end_addr;
+ uintptr_t start_addr, end_addr, offset;
const char* i1 = my_read_hex_ptr(&start_addr, line);
if (*i1 == '-') {
const char *i2 = my_read_hex_ptr(&end_addr, i1 + 1);
if (*i2 == ' ') {
- MappingInfo *const module = new(allocator_) MappingInfo;
- memset(module, 0, sizeof(MappingInfo));
- module->start_addr = start_addr;
- module->size = end_addr - start_addr;
- const char *name = NULL;
- // Only copy name if the name is a valid path name.
- if ((name = my_strchr(line, '/')) != NULL) {
- const unsigned l = my_strlen(name);
- if (l < sizeof(module->name))
- memcpy(module->name, name, l);
+ const char *i3 = my_read_hex_ptr(&offset, i2 + 6 /* skip ' rwxp ' */);
+ if (*i3 == ' ') {
+ MappingInfo *const module = new(allocator_) MappingInfo;
+ memset(module, 0, sizeof(MappingInfo));
+ module->start_addr = start_addr;
+ module->size = end_addr - start_addr;
+ module->offset = offset;
+ const char *name = NULL;
+ // Only copy name if the name is a valid path name.
+ if ((name = my_strchr(line, '/')) != NULL) {
+ const unsigned l = my_strlen(name);
+ if (l < sizeof(module->name))
+ memcpy(module->name, name, l);
+ }
+
+ result->push_back(module);
}
-
- result->push_back(module);
}
}
diff --git a/breakpad/linux/linux_dumper.h b/breakpad/linux/linux_dumper.h
index 1e39a6e..b6fc58a 100644
--- a/breakpad/linux/linux_dumper.h
+++ b/breakpad/linux/linux_dumper.h
@@ -65,6 +65,7 @@ struct ThreadInfo {
struct MappingInfo {
uintptr_t start_addr;
size_t size;
+ size_t offset; // offset into the backed file.
char name[NAME_MAX];
};
diff --git a/breakpad/linux/minidump_writer.cc b/breakpad/linux/minidump_writer.cc
index 5a1d6c6..3887841 100644
--- a/breakpad/linux/minidump_writer.cc
+++ b/breakpad/linux/minidump_writer.cc
@@ -325,7 +325,7 @@ class MinidumpWriter {
bool Dump() {
// A minidump file contains a number of tagged streams. This is the number
// of stream which we write.
- static const unsigned kNumWriters = 10;
+ static const unsigned kNumWriters = 11;
TypedMDRVA<MDRawHeader> header(&minidump_writer_);
TypedMDRVA<MDRawDirectory> dir(&minidump_writer_);
@@ -356,6 +356,10 @@ class MinidumpWriter {
return false;
dir.CopyIndex(dir_index++, &dirent);
+ if (!WriteSystemInfoStream(&dirent))
+ return false;
+ dir.CopyIndex(dir_index++, &dirent);
+
dirent.stream_type = MD_LINUX_CPU_INFO;
if (!WriteFile(&dirent.location, "/proc/cpuinfo"))
NullifyDirectoryEntry(&dirent);
@@ -467,23 +471,43 @@ class MinidumpWriter {
return true;
}
+ static bool ShouldIncludeMapping(const MappingInfo& mapping) {
+ if (mapping.name[0] == 0 || // we only want modules with filenames.
+ mapping.offset || // we only want to include one mapping per shared lib.
+ mapping.size < 4096) { // too small to get a signature for.
+ return false;
+ }
+
+ return true;
+ }
+
// Write information about the mappings in effect. Because we are using the
// minidump format, the information about the mappings is pretty limited.
// Because of this, we also include the full, unparsed, /proc/$x/maps file in
// another stream in the file.
bool WriteMappings(MDRawDirectory* dirent) {
const unsigned num_mappings = dumper_.mappings().size();
+ unsigned num_output_mappings = 0;
+
+ for (unsigned i = 0; i < dumper_.mappings().size(); ++i) {
+ const MappingInfo& mapping = *dumper_.mappings()[i];
+ if (ShouldIncludeMapping(mapping))
+ num_output_mappings++;
+ }
TypedMDRVA<uint32_t> list(&minidump_writer_);
- if (!list.AllocateObjectAndArray(num_mappings, sizeof(MDRawModule)))
+ if (!list.AllocateObjectAndArray(num_output_mappings, sizeof(MDRawModule)))
return false;
dirent->stream_type = MD_MODULE_LIST_STREAM;
dirent->location = list.location();
- *list.get() = num_mappings;
+ *list.get() = num_output_mappings;
- for (unsigned i = 0; i < num_mappings; ++i) {
+ for (unsigned i = 0, j = 0; i < num_mappings; ++i) {
const MappingInfo& mapping = *dumper_.mappings()[i];
+ if (!ShouldIncludeMapping(mapping))
+ continue;
+
MDRawModule mod;
my_memset(&mod, 0, sizeof(mod));
mod.base_of_image = mapping.start_addr;
@@ -491,6 +515,30 @@ class MinidumpWriter {
UntypedMDRVA memory(&minidump_writer_);
const size_t filename_len = my_strlen(mapping.name);
+ TypedMDRVA<MDCVInfoPDB70> cv(&minidump_writer_);
+ if (!cv.Allocate())
+ return false;
+ my_memset(cv.get(), 0, sizeof(MDCVInfoPDB70));
+ cv.get()->cv_signature = MD_CVINFOPDB70_SIGNATURE;
+
+ {
+ // We XOR the first page of the file to get a signature for it.
+ uint8_t xor_buf[sizeof(MDGUID)];
+ size_t done = 0;
+ uint8_t* const signature = (uint8_t*) &cv.get()->signature;
+
+ while (done < 4096) {
+ dumper_.CopyFromProcess(xor_buf, crashing_tid_,
+ (void *) (mod.base_of_image + done),
+ sizeof(xor_buf));
+ for (unsigned i = 0; i < sizeof(xor_buf); ++i)
+ signature[i] ^= xor_buf[i];
+ done += sizeof(xor_buf);
+ }
+ }
+
+ mod.cv_record = cv.location();
+
if (filename_len) {
MDLocationDescriptor ld;
if (!minidump_writer_.WriteString(mapping.name, filename_len, &ld))
@@ -498,7 +546,7 @@ class MinidumpWriter {
mod.module_name_rva = ld.rva;
}
- list.CopyIndexAfterObject(i, &mod, sizeof(mod));
+ list.CopyIndexAfterObject(j++, &mod, sizeof(mod));
}
return true;
@@ -522,6 +570,25 @@ class MinidumpWriter {
return true;
}
+ bool WriteSystemInfoStream(MDRawDirectory* dirent) {
+ TypedMDRVA<MDRawSystemInfo> si(&minidump_writer_);
+ if (!si.Allocate())
+ return false;
+ my_memset(si.get(), 0, sizeof(MDRawSystemInfo));
+
+ dirent->stream_type = MD_SYSTEM_INFO_STREAM;
+ dirent->location = si.location();
+
+ si.get()->processor_architecture =
+#if defined(__i386)
+ MD_CPU_ARCHITECTURE_X86;
+#elif defined(__x86_64)
+ MD_CPU_ARCHITECTURE_AMD64;
+#endif
+
+ return true;
+ }
+
private:
#if defined(__i386)
uintptr_t GetStackPointer() {