aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/minidump_writer/linux_dumper.cc
diff options
context:
space:
mode:
authormkrebs@chromium.org <mkrebs@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2012-03-30 23:53:32 +0000
committermkrebs@chromium.org <mkrebs@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2012-03-30 23:53:32 +0000
commit78373e45c5f29416ce9e2f092f92b57cfefe88ed (patch)
tree46c1cb9aa82a8231d4e0c1cf6c1b50a58f1484a6 /src/client/linux/minidump_writer/linux_dumper.cc
parentFix GetMainModule() to properly get first module (diff)
downloadbreakpad-78373e45c5f29416ce9e2f092f92b57cfefe88ed.tar.xz
Fix for putting main module as first one in minidump
The first module in a minidump is expected to be for the main executable. We used to assume that /proc/<pid>/maps always showed that one first, but in some cases that is no longer true (see comment #7 of the bug). So this change makes use of the entry point stored in auxv to make sure we put the correct module first. BUG=chromium-os:25355 TEST=Ran Breakpad tests Review URL: https://breakpad.appspot.com/366002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@942 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/linux/minidump_writer/linux_dumper.cc')
-rw-r--r--src/client/linux/minidump_writer/linux_dumper.cc52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc
index 2cf1b40f..e9d211ec 100644
--- a/src/client/linux/minidump_writer/linux_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_dumper.cc
@@ -132,7 +132,7 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
}
void*
-LinuxDumper::FindBeginningOfLinuxGateSharedLibrary(const pid_t pid) const {
+LinuxDumper::FindBeginningOfLinuxGateSharedLibrary(pid_t pid) const {
char auxv_path[NAME_MAX];
if (!BuildProcPath(auxv_path, pid, "auxv"))
return NULL;
@@ -159,6 +159,32 @@ LinuxDumper::FindBeginningOfLinuxGateSharedLibrary(const pid_t pid) const {
return NULL;
}
+void*
+LinuxDumper::FindEntryPoint(pid_t pid) const {
+ char auxv_path[NAME_MAX];
+ if (!BuildProcPath(auxv_path, pid, "auxv"))
+ return NULL;
+
+ int fd = sys_open(auxv_path, O_RDONLY, 0);
+ if (fd < 0) {
+ return NULL;
+ }
+
+ // Find the AT_ENTRY entry
+ elf_aux_entry one_aux_entry;
+ while (sys_read(fd,
+ &one_aux_entry,
+ sizeof(elf_aux_entry)) == sizeof(elf_aux_entry) &&
+ one_aux_entry.a_type != AT_NULL) {
+ if (one_aux_entry.a_type == AT_ENTRY) {
+ close(fd);
+ return reinterpret_cast<void*>(one_aux_entry.a_un.a_val);
+ }
+ }
+ close(fd);
+ return NULL;
+}
+
bool LinuxDumper::EnumerateMappings() {
char maps_path[NAME_MAX];
if (!BuildProcPath(maps_path, pid_, "maps"))
@@ -171,6 +197,10 @@ bool LinuxDumper::EnumerateMappings() {
// of mappings.
const void* linux_gate_loc;
linux_gate_loc = FindBeginningOfLinuxGateSharedLibrary(pid_);
+ // Although the initial executable is usually the first mapping, it's not
+ // guaranteed (see http://crosbug.com/25355); therefore, try to use the
+ // actual entry point to find the mapping.
+ const void* entry_point_loc = FindEntryPoint(pid_);
const int fd = sys_open(maps_path, O_RDONLY, 0);
if (fd < 0)
@@ -219,7 +249,25 @@ bool LinuxDumper::EnumerateMappings() {
if (l < sizeof(module->name))
memcpy(module->name, name, l);
}
- mappings_.push_back(module);
+ // 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);
+ }
}
}
}