aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/minidump_writer/linux_dumper.h
diff options
context:
space:
mode:
authorrmcilroy@chromium.org <rmcilroy@chromium.org>2015-06-19 16:30:42 +0000
committerrmcilroy@chromium.org <rmcilroy@chromium.org>2015-06-19 16:30:42 +0000
commit8785c0cb8fc1ccfb20c143026c5fbb8361354c09 (patch)
treec928423f412adfc0c186dbeb9ce9a742102f305d /src/client/linux/minidump_writer/linux_dumper.h
parentupdate more ignore files (diff)
downloadbreakpad-8785c0cb8fc1ccfb20c143026c5fbb8361354c09.tar.xz
Update breakpad for Android packed relocations.
Shared libraries containing Android packed relocations have a load bias that differs from the start address in /proc/$$/maps. Current breakpad assumes that the load bias and mapping start address are the same. Fixed by changing the client to detect the presence of Android packed relocations in the address space of a loaded library, and adjusting the stored mapping start address of any that are packed so that it contains the linker's load bias. For this to work properly, it is important that the non-packed library is symbolized for breakpad. Either packed or non-packed libraries may be run on the device; the client detects which has been loaded by the linker. BUG=499747 R=primiano@chromium.org, rmcilroy@chromium.org Review URL: https://codereview.chromium.org/1189823002. Patch from Simon Baldwin <simonb@chromium.org>. git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1459 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/linux/minidump_writer/linux_dumper.h')
-rw-r--r--src/client/linux/minidump_writer/linux_dumper.h65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/client/linux/minidump_writer/linux_dumper.h b/src/client/linux/minidump_writer/linux_dumper.h
index 87dfadb4..6a3a100f 100644
--- a/src/client/linux/minidump_writer/linux_dumper.h
+++ b/src/client/linux/minidump_writer/linux_dumper.h
@@ -39,6 +39,9 @@
#define CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_
#include <elf.h>
+#if defined(__ANDROID__)
+#include <link.h>
+#endif
#include <linux/limits.h>
#include <stdint.h>
#include <sys/types.h>
@@ -76,6 +79,12 @@ class LinuxDumper {
// Parse the data for |threads| and |mappings|.
virtual bool Init();
+ // Take any actions that could not be taken in Init(). LateInit() is
+ // called after all other caller's initialization is complete, and in
+ // particular after it has called ThreadsSuspend(), so that ptrace is
+ // available.
+ virtual bool LateInit();
+
// Return true if the dumper performs a post-mortem dump.
virtual bool IsPostMortem() const = 0;
@@ -182,6 +191,62 @@ class LinuxDumper {
// Info from /proc/<pid>/auxv
wasteful_vector<elf_aux_val_t> auxv_;
+
+#if defined(__ANDROID__)
+ private:
+ // Android M and later support packed ELF relocations in shared libraries.
+ // Packing relocations changes the vaddr of the LOAD segments, such that
+ // the effective load bias is no longer the same as the start address of
+ // the memory mapping containing the executable parts of the library. The
+ // packing is applied to the stripped library run on the target, but not to
+ // any other library, and in particular not to the library used to generate
+ // breakpad symbols. As a result, we need to adjust the |start_addr| for
+ // any mapping that results from a shared library that contains Android
+ // packed relocations, so that it properly represents the effective library
+ // load bias. The following functions support this adjustment.
+
+ // Check that a given mapping at |start_addr| is for an ELF shared library.
+ // If it is, place the ELF header in |ehdr| and return true.
+ // The first LOAD segment in an ELF shared library has offset zero, so the
+ // ELF file header is at the start of this map entry, and in already mapped
+ // memory.
+ bool GetLoadedElfHeader(uintptr_t start_addr, ElfW(Ehdr)* ehdr);
+
+ // For the ELF file mapped at |start_addr|, iterate ELF program headers to
+ // find the min vaddr of all program header LOAD segments, the vaddr for
+ // the DYNAMIC segment, and a count of DYNAMIC entries. Return values in
+ // |min_vaddr_ptr|, |dyn_vaddr_ptr|, and |dyn_count_ptr|.
+ // The program header table is also in already mapped memory.
+ void ParseLoadedElfProgramHeaders(ElfW(Ehdr)* ehdr,
+ uintptr_t start_addr,
+ uintptr_t* min_vaddr_ptr,
+ uintptr_t* dyn_vaddr_ptr,
+ size_t* dyn_count_ptr);
+
+ // Search the DYNAMIC tags for the ELF file with the given |load_bias|, and
+ // return true if the tags indicate that the file contains Android packed
+ // relocations. Dynamic tags are found at |dyn_vaddr| past the |load_bias|.
+ bool HasAndroidPackedRelocations(uintptr_t load_bias,
+ uintptr_t dyn_vaddr,
+ size_t dyn_count);
+
+ // If the ELF file mapped at |start_addr| contained Android packed
+ // relocations, return the load bias that the system linker (or Chromium
+ // crazy linker) will have used. If the file did not contain Android
+ // packed relocations, returns |start_addr|, indicating that no adjustment
+ // is necessary.
+ // The effective load bias is |start_addr| adjusted downwards by the
+ // min vaddr in the library LOAD segments.
+ uintptr_t GetEffectiveLoadBias(ElfW(Ehdr)* ehdr, uintptr_t start_addr);
+
+ // Called from LateInit(). Iterates |mappings_| and rewrites the |start_addr|
+ // field of any that represent ELF shared libraries with Android packed
+ // relocations, so that |start_addr| is the load bias that the system linker
+ // (or Chromium crazy linker) used. This value matches the addresses produced
+ // when the non-relocation-packed library is used for breakpad symbol
+ // generation.
+ void LatePostprocessMappings();
+#endif // __ANDROID__
};
} // namespace google_breakpad