aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/minidump_writer/linux_dumper.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/linux/minidump_writer/linux_dumper.cc')
-rw-r--r--src/client/linux/minidump_writer/linux_dumper.cc46
1 files changed, 43 insertions, 3 deletions
diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc
index d565c741..ebb008d6 100644
--- a/src/client/linux/minidump_writer/linux_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_dumper.cc
@@ -184,10 +184,12 @@ bool ElfFileSoNameFromMappedFile(
// Did not find SONAME
return false;
}
-} // namespace
-// static
-bool LinuxDumper::ElfFileSoName(
+// Find the shared object name (SONAME) by examining the ELF information
+// 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(
const MappingInfo& mapping, char* soname, size_t soname_size) {
if (IsMappedFileOpenUnsafe(mapping)) {
// Not safe
@@ -214,6 +216,44 @@ bool LinuxDumper::ElfFileSoName(
return ElfFileSoNameFromMappedFile(mapped_file.data(), soname, soname_size);
}
+} // namespace
+
+
+// static
+void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
+ char* file_path,
+ size_t file_path_size,
+ char* file_name,
+ size_t file_name_size) {
+ my_strlcpy(file_path, mapping.name, file_path_size);
+
+ // If an executable is mapped from a non-zero offset, this is likely because
+ // the executable was loaded directly from inside an archive file (e.g., an
+ // 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 (mapped_from_archive) {
+ // Some tools (e.g., stackwalk) extract the basename from the pathname. In
+ // this case, we append the file_name to the mapped archive path as follows:
+ // file_name := libname.so
+ // file_path := /path/to/ARCHIVE.APK/libname.so
+ if (my_strlen(file_path) + 1 + my_strlen(file_name) < file_path_size) {
+ my_strlcat(file_path, "/", file_path_size);
+ my_strlcat(file_path, file_name, file_path_size);
+ }
+ } else {
+ // Common case:
+ // file_path := /path/to/libname.so
+ // file_name := libname.so
+ const char* basename = my_strrchr(file_path, '/');
+ basename = basename == NULL ? file_path : (basename + 1);
+ my_strlcpy(file_name, basename, file_name_size);
+ }
+}
+
bool LinuxDumper::ReadAuxv() {
char auxv_path[NAME_MAX];
if (!BuildProcPath(auxv_path, pid_, "auxv")) {