aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/minidump_writer/linux_dumper.cc
diff options
context:
space:
mode:
authorDominik Laskowski <domlaskowski@chromium.org>2016-03-03 16:14:00 -0500
committerMike Frysinger <vapier@chromium.org>2016-03-07 21:35:43 -0500
commit4d690507171bff0f29dcf382b6909888d2f3bd17 (patch)
treefe354e7b4b6ca1885de68547cea5194e7f6da632 /src/client/linux/minidump_writer/linux_dumper.cc
parentHandle multiple microdumps in system log. (diff)
downloadbreakpad-4d690507171bff0f29dcf382b6909888d2f3bd17.tar.xz
Add an optional root prefix to Linux dumpers
The Linux dumpers use absolute paths for shared libraries referenced by dumps, so they fail to locate them if the crash originated in a chroot. This CL enables callers to specify a root prefix, which is prepended to mapping paths before opening them. BUG=chromium:591792 TEST=make check Review URL: https://codereview.chromium.org/1761023002/
Diffstat (limited to 'src/client/linux/minidump_writer/linux_dumper.cc')
-rw-r--r--src/client/linux/minidump_writer/linux_dumper.cc48
1 files changed, 24 insertions, 24 deletions
diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc
index 43b74ad9..8d4df9ad 100644
--- a/src/client/linux/minidump_writer/linux_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_dumper.cc
@@ -88,14 +88,16 @@ namespace google_breakpad {
// All interesting auvx entry types are below AT_SYSINFO_EHDR
#define AT_MAX AT_SYSINFO_EHDR
-LinuxDumper::LinuxDumper(pid_t pid)
+LinuxDumper::LinuxDumper(pid_t pid, const char* root_prefix)
: pid_(pid),
+ root_prefix_(root_prefix),
crash_address_(0),
crash_signal_(0),
crash_thread_(pid),
threads_(&allocator_, 8),
mappings_(&allocator_),
auxv_(&allocator_, AT_MAX + 1) {
+ assert(root_prefix_ && my_strlen(root_prefix_) < PATH_MAX);
// The passed-in size to the constructor (above) is only a hint.
// Must call .resize() to do actual initialization of the elements.
auxv_.resize(AT_MAX + 1);
@@ -139,14 +141,9 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
return FileID::ElfFileIdentifierFromMappedFile(linux_gate, identifier);
}
- char filename[NAME_MAX];
- size_t filename_len = my_strlen(mapping.name);
- if (filename_len >= NAME_MAX) {
- assert(false);
+ char filename[PATH_MAX];
+ if (!GetMappingAbsolutePath(mapping, filename))
return false;
- }
- my_memcpy(filename, mapping.name, filename_len);
- filename[filename_len] = '\0';
bool filename_modified = HandleDeletedFileInMapping(filename);
MemoryMappedFile mapped_file(filename, mapping.offset);
@@ -156,13 +153,19 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
bool success =
FileID::ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
if (success && member && filename_modified) {
- mappings_[mapping_id]->name[filename_len -
+ mappings_[mapping_id]->name[my_strlen(mapping.name) -
sizeof(kDeletedSuffix) + 1] = '\0';
}
return success;
}
+bool LinuxDumper::GetMappingAbsolutePath(const MappingInfo& mapping,
+ char path[PATH_MAX]) const {
+ return my_strlcpy(path, root_prefix_, PATH_MAX) < PATH_MAX &&
+ my_strlcat(path, mapping.name, PATH_MAX) < PATH_MAX;
+}
+
namespace {
bool ElfFileSoNameFromMappedFile(
const void* elf_base, char* soname, size_t soname_size) {
@@ -212,23 +215,16 @@ bool ElfFileSoNameFromMappedFile(
// for |mapping|. If the SONAME is found copy it into the passed buffer
// |soname| and return true. The size of the buffer is |soname_size|.
// The SONAME will be truncated if it is too long to fit in the buffer.
-bool ElfFileSoName(
+bool ElfFileSoName(const LinuxDumper& dumper,
const MappingInfo& mapping, char* soname, size_t soname_size) {
if (IsMappedFileOpenUnsafe(mapping)) {
// Not safe
return false;
}
- char filename[NAME_MAX];
- size_t filename_len = my_strlen(mapping.name);
- if (filename_len >= NAME_MAX) {
- assert(false);
- // name too long
+ char filename[PATH_MAX];
+ if (!dumper.GetMappingAbsolutePath(mapping, filename))
return false;
- }
-
- my_memcpy(filename, mapping.name, filename_len);
- filename[filename_len] = '\0';
MemoryMappedFile mapped_file(filename, mapping.offset);
if (!mapped_file.data() || mapped_file.size() < SELFMAG) {
@@ -242,7 +238,6 @@ bool ElfFileSoName(
} // namespace
-// static
void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
char* file_path,
size_t file_path_size,
@@ -255,8 +250,10 @@ void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
// apk on Android). We try to find the name of the shared object (SONAME) by
// looking in the file for ELF sections.
bool mapped_from_archive = false;
- if (mapping.exec && mapping.offset != 0)
- mapped_from_archive = ElfFileSoName(mapping, file_name, file_name_size);
+ if (mapping.exec && mapping.offset != 0) {
+ mapped_from_archive =
+ ElfFileSoName(*this, mapping, file_name, file_name_size);
+ }
if (mapped_from_archive) {
// Some tools (e.g., stackwalk) extract the basename from the pathname. In
@@ -580,10 +577,13 @@ bool LinuxDumper::HandleDeletedFileInMapping(char* path) const {
// Check |path| against the /proc/pid/exe 'symlink'.
char exe_link[NAME_MAX];
- char new_path[NAME_MAX];
if (!BuildProcPath(exe_link, pid_, "exe"))
return false;
- if (!SafeReadLink(exe_link, new_path))
+ MappingInfo new_mapping = {0};
+ if (!SafeReadLink(exe_link, new_mapping.name))
+ return false;
+ char new_path[PATH_MAX];
+ if (!GetMappingAbsolutePath(new_mapping, new_path))
return false;
if (my_strcmp(path, new_path) != 0)
return false;