From 1bf62b24abdba18985217efeee907be8de4121f0 Mon Sep 17 00:00:00 2001 From: Vic Yang Date: Tue, 13 Aug 2019 14:53:28 -0700 Subject: 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//maps. Change-Id: I62d9996ab256f46e2d82cac581c17fa94836a228 --- linker/linker_main.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'linker/linker_main.cpp') 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(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(); -- cgit v1.2.3