diff options
-rw-r--r-- | breakpad/linux/linux_dumper.cc | 31 | ||||
-rw-r--r-- | breakpad/linux/linux_dumper.h | 1 | ||||
-rw-r--r-- | breakpad/linux/minidump_writer.cc | 77 |
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() { |