diff options
author | rmcilroy@chromium.org <rmcilroy@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2014-07-22 11:34:11 +0000 |
---|---|---|
committer | rmcilroy@chromium.org <rmcilroy@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2014-07-22 11:34:11 +0000 |
commit | 561f81873562d407ac1c39144b30e26163e0045d (patch) | |
tree | 7f2c072ddac47a40a34e46a36784dfcdd4fc411e /src/client/linux/minidump_writer/minidump_writer.cc | |
parent | Both std::tr1::unordered_set and std::unordered_set are not allowed in (diff) | |
download | breakpad-561f81873562d407ac1c39144b30e26163e0045d.tar.xz |
Chrome on Android now supports loading the shared library directly from the APK file.
This patch makes two changes to breakpad to enable crash reporting to work correctly when the library is inside another file (an archive):
- Do not filter mappings which map an executable at a non-zero offset.
- If such an executable is mapped look in the ELF information for the
shared object name and use that name in the minidump.
Note this change doesn't care about the archive format and isn't Android
specific (though loading the shared library this way is currently only done on Android).
BUG=390618
R=thestig@chromium.org
Review URL: https://breakpad.appspot.com/7684002
Patch from Anton Carver <anton@chromium.org>.
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1355 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/linux/minidump_writer/minidump_writer.cc')
-rw-r--r-- | src/client/linux/minidump_writer/minidump_writer.cc | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc index fa2ad9e1..86cec55b 100644 --- a/src/client/linux/minidump_writer/minidump_writer.cc +++ b/src/client/linux/minidump_writer/minidump_writer.cc @@ -938,7 +938,9 @@ class MinidumpWriter { static bool ShouldIncludeMapping(const MappingInfo& mapping) { if (mapping.name[0] == 0 || // only want modules with filenames. - mapping.offset || // only want to include one mapping per shared lib. + // Only want to include one mapping per shared lib. + // Avoid filtering executable mappings. + (mapping.offset != 0 && !mapping.exec) || mapping.size < 4096) { // too small to get a signature for. return false; } @@ -1029,7 +1031,8 @@ class MinidumpWriter { mod.base_of_image = mapping.start_addr; mod.size_of_image = mapping.size; - const size_t filepath_len = my_strlen(mapping.name); + const char* filepath_ptr = mapping.name; + size_t filepath_len = my_strlen(mapping.name); // Figure out file name from path const char* filename_ptr = mapping.name + filepath_len - 1; @@ -1040,7 +1043,31 @@ class MinidumpWriter { } filename_ptr++; - const size_t filename_len = mapping.name + filepath_len - filename_ptr; + size_t filename_len = mapping.name + filepath_len - filename_ptr; + + // If an executable is mapped from a non-zero offset, this is likely + // because the executable was loaded directly from inside an archive + // file. We try to find the name of the shared object (SONAME) by + // looking in the file for ELF sections. + + char soname[NAME_MAX]; + char pathname[NAME_MAX]; + if (mapping.exec && mapping.offset != 0 && + LinuxDumper::ElfFileSoName(mapping, soname, sizeof(soname))) { + filename_ptr = soname; + filename_len = my_strlen(soname); + + if (filepath_len + filename_len + 1 < NAME_MAX) { + // It doesn't have a real pathname, but tools such as stackwalk + // extract the basename, so simulating a pathname is helpful. + my_memcpy(pathname, filepath_ptr, filepath_len); + pathname[filepath_len] = '/'; + my_memcpy(pathname + filepath_len + 1, filename_ptr, filename_len); + pathname[filepath_len + filename_len + 1] = '\0'; + filepath_ptr = pathname; + filepath_len = filepath_len + filename_len + 1; + } + } uint8_t cv_buf[MDCVInfoPDB70_minsize + NAME_MAX]; uint8_t* cv_ptr = cv_buf; @@ -1070,7 +1097,7 @@ class MinidumpWriter { mod.cv_record = cv.location(); MDLocationDescriptor ld; - if (!minidump_writer_.WriteString(mapping.name, filepath_len, &ld)) + if (!minidump_writer_.WriteString(filepath_ptr, filepath_len, &ld)) return false; mod.module_name_rva = ld.rva; return true; |