diff options
author | mkrebs@chromium.org <mkrebs@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2012-03-30 23:53:32 +0000 |
---|---|---|
committer | mkrebs@chromium.org <mkrebs@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2012-03-30 23:53:32 +0000 |
commit | 78373e45c5f29416ce9e2f092f92b57cfefe88ed (patch) | |
tree | 46c1cb9aa82a8231d4e0c1cf6c1b50a58f1484a6 | |
parent | Fix GetMainModule() to properly get first module (diff) | |
download | breakpad-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
-rw-r--r-- | src/client/linux/minidump_writer/linux_dumper.cc | 52 | ||||
-rw-r--r-- | src/client/linux/minidump_writer/linux_dumper.h | 4 |
2 files changed, 53 insertions, 3 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); + } } } } diff --git a/src/client/linux/minidump_writer/linux_dumper.h b/src/client/linux/minidump_writer/linux_dumper.h index 45779699..42b2a991 100644 --- a/src/client/linux/minidump_writer/linux_dumper.h +++ b/src/client/linux/minidump_writer/linux_dumper.h @@ -178,7 +178,9 @@ class LinuxDumper { // [vdso], but we can't guarantee that it's the only virtual dynamic // shared object. Parsing the auxilary vector for AT_SYSINFO_EHDR // is the safest way to go.) - void* FindBeginningOfLinuxGateSharedLibrary(const pid_t pid) const; + void* FindBeginningOfLinuxGateSharedLibrary(pid_t pid) const; + // Utility method to find the entry point location. + void* FindEntryPoint(pid_t pid) const; uintptr_t crash_address() const { return crash_address_; } void set_crash_address(uintptr_t crash_address) { |