From cd510cbed9dc1e1b65b9d34676fdf6d85101f22c Mon Sep 17 00:00:00 2001 From: Dimitry Ivanov Date: Wed, 31 May 2017 15:07:41 -0700 Subject: [PATCH] Make dl_iterate_phdr return correct name for first entry Test: bionic-unit-tests --gtest_filter=link* Change-Id: Ib3f1e0fbc76fed9a5f27ffdd9bbf847a3e8d3665 --- linker/dlfcn.cpp | 5 ++++- linker/linker.h | 2 +- linker/linker_main.cpp | 21 +++++++++++---------- linker/linker_soinfo.h | 2 +- tests/link_test.cpp | 3 --- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp index 6195d4083..fde471714 100644 --- a/linker/dlfcn.cpp +++ b/linker/dlfcn.cpp @@ -322,7 +322,7 @@ static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8))); static soinfo* __libdl_info = nullptr; // This is used by the dynamic linker. Every process gets these symbols for free. -soinfo* get_libdl_info(const char* linker_path) { +soinfo* get_libdl_info(const char* linker_path, const link_map& linker_map) { if (__libdl_info == nullptr) { __libdl_info = new (__libdl_info_buf) soinfo(&g_default_namespace, linker_path, nullptr, 0, 0); __libdl_info->flags_ |= FLAG_LINKED; @@ -338,6 +338,9 @@ soinfo* get_libdl_info(const char* linker_path) { __libdl_info->soname_ = "ld-android.so"; __libdl_info->target_sdk_version_ = __ANDROID_API__; __libdl_info->generate_handle(); + __libdl_info->link_map_head.l_addr = linker_map.l_addr; + __libdl_info->link_map_head.l_name = linker_map.l_name; + __libdl_info->link_map_head.l_ld = linker_map.l_ld; #if defined(__work_around_b_24465209__) strlcpy(__libdl_info->old_name_, __libdl_info->soname_, sizeof(__libdl_info->old_name_)); #endif diff --git a/linker/linker.h b/linker/linker.h index ae1ae3c6a..43d345c45 100644 --- a/linker/linker.h +++ b/linker/linker.h @@ -100,7 +100,7 @@ enum RelocationKind { void count_relocation(RelocationKind kind); -soinfo* get_libdl_info(const char* linker_path); +soinfo* get_libdl_info(const char* linker_path, const link_map& linker_map); soinfo* find_containing_library(const void* p); diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp index 3d26e91f3..5dc215f9d 100644 --- a/linker/linker_main.cpp +++ b/linker/linker_main.cpp @@ -163,11 +163,11 @@ static void add_vdso(KernelArgumentBlock& args __unused) { * relocate the offset of our exported 'rtld_db_dlactivity' symbol. * Note that the linker shouldn't be on the soinfo list. */ -static void init_linker_info_for_gdb(ElfW(Addr) linker_base, char* linker_path) { - static link_map linker_link_map_for_gdb; +static link_map linker_link_map; - linker_link_map_for_gdb.l_addr = linker_base; - linker_link_map_for_gdb.l_name = linker_path; +static void init_linker_info_for_gdb(ElfW(Addr) linker_base, char* linker_path) { + linker_link_map.l_addr = linker_base; + linker_link_map.l_name = linker_path; /* * Set the dynamic field in the link map otherwise gdb will complain with @@ -178,9 +178,8 @@ static void init_linker_info_for_gdb(ElfW(Addr) linker_base, char* linker_path) ElfW(Ehdr)* elf_hdr = reinterpret_cast(linker_base); ElfW(Phdr)* phdr = reinterpret_cast(linker_base + elf_hdr->e_phoff); phdr_table_get_dynamic_section(phdr, elf_hdr->e_phnum, linker_base, - &linker_link_map_for_gdb.l_ld, nullptr); + &linker_link_map.l_ld, nullptr); - insert_link_map_into_debug_map(&linker_link_map_for_gdb); } extern "C" int __system_properties_init(void); @@ -210,7 +209,7 @@ static char kLinkerPath[] = "/system/bin/linker"; * fixed it's own GOT. It is safe to make references to externs * and other non-local data at this point. */ -static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(Addr) linker_base) { +static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) { ProtectedDataGuard guard; #if TIMING @@ -288,7 +287,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW( map->l_addr = 0; map->l_name = const_cast(executable_path); insert_link_map_into_debug_map(map); - init_linker_info_for_gdb(linker_base, kLinkerPath); + insert_link_map_into_debug_map(&linker_link_map); // Extract information passed from the kernel. si->phdr = reinterpret_cast(args.getauxval(AT_PHDR)); @@ -554,16 +553,18 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) { exit(0); } + init_linker_info_for_gdb(linker_addr, kLinkerPath); + // Initialize static variables. Note that in order to // get correct libdl_info we need to call constructors // before get_libdl_info(). - sonext = solist = get_libdl_info(kLinkerPath); + sonext = solist = get_libdl_info(kLinkerPath, linker_link_map); g_default_namespace.add_soinfo(solist); // We have successfully fixed our own relocations. It's safe to run // the main part of the linker now. args.abort_message_ptr = &g_abort_message; - ElfW(Addr) start_address = __linker_init_post_relocation(args, linker_addr); + ElfW(Addr) start_address = __linker_init_post_relocation(args); INFO("[ Jumping to _start (%p)... ]", reinterpret_cast(start_address)); diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h index 71eb5438b..29b5c2be1 100644 --- a/linker/linker_soinfo.h +++ b/linker/linker_soinfo.h @@ -337,7 +337,7 @@ struct soinfo { android_namespace_list_t secondary_namespaces_; uintptr_t handle_; - friend soinfo* get_libdl_info(const char* linker_path); + friend soinfo* get_libdl_info(const char* linker_path, const link_map& linker_map); }; // This function is used by dlvsym() to calculate hash of sym_ver diff --git a/tests/link_test.cpp b/tests/link_test.cpp index ac3ccb956..a5430a983 100644 --- a/tests/link_test.cpp +++ b/tests/link_test.cpp @@ -46,9 +46,6 @@ TEST(link, dl_iterate_phdr) { void DoChecks(dl_phdr_info* info, size_t s) { ASSERT_EQ(sizeof(dl_phdr_info), s); - // TODO: why does the entry for the main executable have a null dlpi_addr and no name anyway? - if (++count == 1 && info->dlpi_addr == 0) return; - ASSERT_TRUE(info->dlpi_name != nullptr); // Find the first PT_LOAD program header so we can find the ELF header. -- 2.11.0