aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux
diff options
context:
space:
mode:
authorPeter Collingbourne <pcc@google.com>2017-10-17 10:42:27 -0700
committerMike Frysinger <vapier@chromium.org>2017-10-17 20:19:03 +0000
commit9b23ca3a7cc4e3d310969dc9daa74b26327ac70f (patch)
treee78b2a0779f764e086d3c3e4c01344a4bd8185d2 /src/client/linux
parentRename src/common/memory.h to memory_allocator.h. (diff)
downloadbreakpad-9b23ca3a7cc4e3d310969dc9daa74b26327ac70f.tar.xz
Move main executable handling out of procmaps parser loop.
If the mapping for the main executable needed to be merged (for example, if it was linked with lld and therefore contains an r mapping followed by an r/x mapping), we would never reach the code that makes it the first module. Handle that situation by moving that code into a separate loop. This fixes an issue where breakpad_unittests fails on Android devices when linked with lld. It appears that the glibc dynamic loader happens to always load executables (or at least the executables that we create) at a lower address than DSOs, so we never hit this bug on desktop Linux. Testing: "make check" with both gold and lld as linker. Also breakpad_unittests when patched into Chromium on Linux (lld) and Android (gold and lld). Bug: chromium:469376 Change-Id: I6329e4afd2f1bf44c25a6c3e684495e21dba83a6 Reviewed-on: https://chromium-review.googlesource.com/722286 Reviewed-by: Mike Frysinger <vapier@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org>
Diffstat (limited to 'src/client/linux')
-rw-r--r--src/client/linux/minidump_writer/linux_dumper.cc40
1 files changed, 21 insertions, 19 deletions
diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc
index 0013824b..9a7a8542 100644
--- a/src/client/linux/minidump_writer/linux_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_dumper.cc
@@ -611,6 +611,7 @@ bool LinuxDumper::EnumerateMappings() {
}
}
MappingInfo* const module = new(allocator_) MappingInfo;
+ mappings_.push_back(module);
my_memset(module, 0, sizeof(MappingInfo));
module->system_mapping_info.start_addr = start_addr;
module->system_mapping_info.end_addr = end_addr;
@@ -623,31 +624,32 @@ bool LinuxDumper::EnumerateMappings() {
if (l < sizeof(module->name))
my_memcpy(module->name, name, l);
}
- // If this is the entry-point mapping, and it's not already the
- // first one, then we need to make it be first. This is because
- // the minidump format assumes the first module is the one that
- // corresponds to the main executable (as codified in
- // processor/minidump.cc:MinidumpModuleList::GetMainModule()).
- if (entry_point_loc &&
- (entry_point_loc >=
- reinterpret_cast<void*>(module->start_addr)) &&
- (entry_point_loc <
- reinterpret_cast<void*>(module->start_addr+module->size)) &&
- !mappings_.empty()) {
- // push the module onto the front of the list.
- mappings_.resize(mappings_.size() + 1);
- for (size_t idx = mappings_.size() - 1; idx > 0; idx--)
- mappings_[idx] = mappings_[idx - 1];
- mappings_[0] = module;
- } else {
- mappings_.push_back(module);
- }
}
}
}
line_reader->PopLine(line_len);
}
+ if (entry_point_loc) {
+ for (size_t i = 0; i < mappings_.size(); ++i) {
+ MappingInfo* module = mappings_[i];
+
+ // If this module contains the entry-point, and it's not already the first
+ // one, then we need to make it be first. This is because the minidump
+ // format assumes the first module is the one that corresponds to the main
+ // executable (as codified in
+ // processor/minidump.cc:MinidumpModuleList::GetMainModule()).
+ if ((entry_point_loc >= reinterpret_cast<void*>(module->start_addr)) &&
+ (entry_point_loc <
+ reinterpret_cast<void*>(module->start_addr + module->size))) {
+ for (size_t j = i; j > 0; j--)
+ mappings_[j] = mappings_[j - 1];
+ mappings_[0] = module;
+ break;
+ }
+ }
+ }
+
sys_close(fd);
return !mappings_.empty();