OSDN Git Service

linker: the global group is added to all built-in namespaces
[android-x86/bionic.git] / linker / linker_main.cpp
index 5dc215f..0f691c3 100644 (file)
@@ -87,6 +87,7 @@ bool solist_remove_soinfo(soinfo* si) {
 
   // prev will never be null, because the first entry in solist is
   // always the static libdl_info.
+  CHECK(prev != nullptr);
   prev->next = si->next;
   if (si == sonext) {
     sonext = prev;
@@ -137,8 +138,7 @@ static void parse_LD_PRELOAD(const char* path) {
 // An empty list of soinfos
 static soinfo_list_t g_empty_list;
 
-static void add_vdso(KernelArgumentBlock& args __unused) {
-#if defined(AT_SYSINFO_EHDR)
+static void add_vdso(KernelArgumentBlock& args) {
   ElfW(Ehdr)* ehdr_vdso = reinterpret_cast<ElfW(Ehdr)*>(args.getauxval(AT_SYSINFO_EHDR));
   if (ehdr_vdso == nullptr) {
     return;
@@ -154,7 +154,6 @@ static void add_vdso(KernelArgumentBlock& args __unused) {
 
   si->prelink_image();
   si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr);
-#endif
 }
 
 /* gdb expects the linker to be in the debug shared object list.
@@ -307,6 +306,11 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) {
       break;
     }
   }
+
+  if (si->base == 0) {
+    async_safe_fatal("Could not find a PHDR: broken executable?");
+  }
+
   si->dynamic = nullptr;
 
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
@@ -333,7 +337,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) {
 
   somain = si;
 
-  init_default_namespace(executable_path);
+  std::vector<android_namespace_t*> namespaces = init_default_namespaces(executable_path);
 
   if (!si->prelink_image()) {
     async_safe_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
@@ -341,6 +345,13 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) {
 
   // add somain to global group
   si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
+  // ... and add it to all other linked namespaces
+  for (auto linked_ns : namespaces) {
+    if (linked_ns != &g_default_namespace) {
+      linked_ns->add_soinfo(somain);
+      somain->add_secondary_namespace(linked_ns);
+    }
+  }
 
   // Load ld_preloads and dependencies.
   std::vector<const char*> needed_library_name_list;
@@ -358,6 +369,9 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) {
   const char** needed_library_names = &needed_library_name_list[0];
   size_t needed_libraries_count = needed_library_name_list.size();
 
+  // readers_map is shared across recursive calls to find_libraries so that we
+  // don't need to re-load elf headers.
+  std::unordered_map<const soinfo*, ElfReader> readers_map;
   if (needed_libraries_count > 0 &&
       !find_libraries(&g_default_namespace,
                       si,
@@ -369,7 +383,9 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) {
                       RTLD_GLOBAL,
                       nullptr,
                       true /* add_as_children */,
-                      true /* search_linked_namespaces */)) {
+                      true /* search_linked_namespaces */,
+                      readers_map,
+                      &namespaces)) {
     async_safe_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
   } else if (needed_libraries_count == 0) {
     if (!si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr)) {
@@ -488,6 +504,15 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) {
   static uintptr_t linktime_addr = reinterpret_cast<uintptr_t>(&linktime_addr);
   ElfW(Addr) linker_addr = reinterpret_cast<uintptr_t>(&linktime_addr) - linktime_addr;
 
+#if defined(__clang_analyzer__)
+  // The analyzer assumes that linker_addr will always be null. Make it an
+  // unknown value so we don't have to mark N places with NOLINTs.
+  //
+  // (`+=`, rather than `=`, allows us to sidestep a potential "unused store"
+  // complaint)
+  linker_addr += reinterpret_cast<uintptr_t>(raw_args);
+#endif
+
   ElfW(Addr) entry_point = args.getauxval(AT_ENTRY);
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
   ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff);