diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-27 22:07:10 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-27 22:07:10 +0000 |
commit | c5e1c7a2d5e7c0bd8db8d7fc44dabea13a4a9721 (patch) | |
tree | 6cf07405f896b42cbd30a6be9517ec2eac7d0ed5 /breakpad | |
parent | 6128eae7d27e2fd1446fabe7af4f1033a2937934 (diff) | |
download | chromium_src-c5e1c7a2d5e7c0bd8db8d7fc44dabea13a4a9721.zip chromium_src-c5e1c7a2d5e7c0bd8db8d7fc44dabea13a4a9721.tar.gz chromium_src-c5e1c7a2d5e7c0bd8db8d7fc44dabea13a4a9721.tar.bz2 |
Linux: Breakpad updates.
The crash server requires an MDRawSystemInfo stream in order to process the
file, although it actually only needs a single value in it.
Additionally, it needs a PDB7 structure for each module, so we remove those
modules which probably aren't shared libraries and XOR the first page of data
to get a signature for them. The previous code opened the file and MD5 summed
the text segment. However, we can't know if the shared library is still linked
on disk, nor if the whole text segment is mapped in memory. Thus, we only
assume that a single page is mapped.
dump_syms will need to be forked and updated to match the signature scheme used
in this patch.
http://codereview.chromium.org/113875
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17030 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'breakpad')
-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() { |