summaryrefslogtreecommitdiff
path: root/linker/linker_main.cpp
diff options
context:
space:
mode:
authorVic Yang <victoryang@google.com>2019-08-13 14:53:28 -0700
committerVic Yang <victoryang@google.com>2019-08-14 13:52:48 -0700
commit1bf62b24abdba18985217efeee907be8de4121f0 (patch)
treee315d7d725bccaeb4751a4553f53a5e1d8345f91 /linker/linker_main.cpp
parent6864fc8d065f647b56297e71d928aab0800d0879 (diff)
linker: Set VMA name for bss sections
The linker currently sets VMA name ".bss" for bss sections in DSOs loaded by the linker. With this change, the linker now also sets VMA name for bss sections in the linker itself and the main executable, so that they don't get left out in various accounting. Test: Run 'dd' and check its /proc/<pid>/maps. Change-Id: I62d9996ab256f46e2d82cac581c17fa94836a228
Diffstat (limited to 'linker/linker_main.cpp')
-rw-r--r--linker/linker_main.cpp32
1 files changed, 32 insertions, 0 deletions
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 11d3d2914..fd1592d33 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -63,6 +63,8 @@ static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf);
static void get_elf_base_from_phdr(const ElfW(Phdr)* phdr_table, size_t phdr_count,
ElfW(Addr)* base, ElfW(Addr)* load_bias);
+static void set_bss_vma_name(soinfo* si);
+
// These should be preserved static to avoid emitting
// RELATIVE relocations for the part of the code running
// before linker links itself.
@@ -366,6 +368,8 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load
si->set_main_executable();
init_link_map_head(*si);
+ set_bss_vma_name(si);
+
// Use the executable's PT_INTERP string as the solinker filename in the
// dynamic linker's module list. gdb reads both PT_INTERP and the module list,
// and if the paths for the linker are different, gdb will report that the
@@ -570,6 +574,31 @@ static void get_elf_base_from_phdr(const ElfW(Phdr)* phdr_table, size_t phdr_cou
async_safe_fatal("Could not find a PHDR: broken executable?");
}
+/*
+ * Set anonymous VMA name for .bss section. For DSOs loaded by the linker, this
+ * is done by ElfReader. This function is here for DSOs loaded by the kernel,
+ * namely the linker itself and the main executable.
+ */
+static void set_bss_vma_name(soinfo* si) {
+ for (size_t i = 0; i < si->phnum; ++i) {
+ auto phdr = &si->phdr[i];
+
+ if (phdr->p_type != PT_LOAD) {
+ continue;
+ }
+
+ ElfW(Addr) seg_start = phdr->p_vaddr + si->load_bias;
+ ElfW(Addr) seg_page_end = PAGE_END(seg_start + phdr->p_memsz);
+ ElfW(Addr) seg_file_end = PAGE_END(seg_start + phdr->p_filesz);
+
+ if (seg_page_end > seg_file_end) {
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME,
+ reinterpret_cast<void*>(seg_file_end), seg_page_end - seg_file_end,
+ ".bss");
+ }
+ }
+}
+
// Detect an attempt to run the linker on itself. e.g.:
// /system/bin/linker64 /system/bin/linker64
// Use priority-1 to run this constructor before other constructors.
@@ -660,6 +689,9 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so)
// couldn't make system calls on x86 at that point, but we can now...
if (!tmp_linker_so.protect_relro()) __linker_cannot_link(args.argv[0]);
+ // And we can set VMA name for the bss section now
+ set_bss_vma_name(&tmp_linker_so);
+
// Initialize the linker's static libc's globals
__libc_init_globals();