Bug 1497669 - Relax breakpad's constraints when merging module mappings on Linux r=ted
authorGabriele Svelto <gsvelto@mozilla.com>
Fri, 16 Nov 2018 22:43:32 +0000
changeset 446887 3a993e60513ec57eecb4be86c14f9d2303dfc04b
parent 446886 563e860bea95f6696ac5a90c0e7b35b7874a4184
child 446888 eb21007e7da0cc392906a517602935cb77a6c37e
push id109932
push userapavel@mozilla.com
push dateSat, 17 Nov 2018 11:35:32 +0000
treeherdermozilla-inbound@e4deec61fc8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1497669
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1497669 - Relax breakpad's constraints when merging module mappings on Linux r=ted This makes a few small but significant changes to the logic breakpad uses to merge module memory mappings: - First of all we merge areas of reserved space if their offset is either 0 or the end of the previous non-reserved mapping. - Whenever we encounter an executable mapping we flag all the merged modules as executable. This shouldn't happen but apparently some older Android linkers suffered from a bug that caused the first mapping not to be executable. - Last but not least we record the raw end address of a module on Android. This shouldn't affect us but it's done in upstream breakpad so it probably doesn't hurt. Differential Revision: https://phabricator.services.mozilla.com/D12113
toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc
@@ -612,40 +612,43 @@ bool LinuxDumper::EnumerateMappings() {
           // Only copy name if the name is a valid path name, or if
           // it's the VDSO image.
           if (((name = my_strchr(line, '/')) == NULL) &&
               linux_gate_loc &&
               reinterpret_cast<void*>(start_addr) == linux_gate_loc) {
             name = kLinuxGateLibraryName;
             offset = 0;
           }
-          // Merge adjacent mappings with the same name into one module,
-          // assuming they're a single library mapped by the dynamic linker
+          // Merge adjacent mappings into one module, assuming they're a single
+          // library mapped by the dynamic linker.
           if (name && !mappings_.empty()) {
             MappingInfo* module = mappings_.back();
             if ((start_addr == module->start_addr + module->size) &&
                 (my_strlen(name) == my_strlen(module->name)) &&
                 (my_strncmp(name, module->name, my_strlen(name)) == 0)) {
+              module->system_mapping_info.end_addr = end_addr;
               module->size = end_addr - module->start_addr;
+              module->exec |= exec;
               line_reader->PopLine(line_len);
               continue;
             }
           }
           // Also merge mappings that result from address ranges that the
           // linker reserved but which a loaded library did not use. These
           // appear as an anonymous private mapping with no access flags set
           // and which directly follow an executable mapping.
           if (!name && !mappings_.empty()) {
             MappingInfo* module = mappings_.back();
-            if ((start_addr == module->start_addr + module->size) &&
+            uintptr_t module_end_addr = module->start_addr + module->size;
+            if ((start_addr == module_end_addr) &&
                 module->exec &&
                 module->name[0] == '/' &&
-                offset == 0 && my_strncmp(i2,
-                                          kReservedFlags,
-                                          sizeof(kReservedFlags) - 1) == 0) {
+                ((offset == 0) || (offset == module_end_addr)) &&
+                my_strncmp(i2, kReservedFlags,
+                           sizeof(kReservedFlags) - 1) == 0) {
               module->size = end_addr - module->start_addr;
               line_reader->PopLine(line_len);
               continue;
             }
           }
           MappingInfo* const module = new(allocator_) MappingInfo;
           mappings_.push_back(module);
           my_memset(module, 0, sizeof(MappingInfo));