* commit 'a334934f66386ecdf3ec07daf0b651fcf3b8dcce': Fix symbol lookup order during relocation
This commit is contained in:
		@@ -36,6 +36,12 @@ class LinkedList {
 | 
				
			|||||||
    clear();
 | 
					    clear();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  LinkedList(LinkedList&& that) {
 | 
				
			||||||
 | 
					    this->head_ = that.head_;
 | 
				
			||||||
 | 
					    this->tail_ = that.tail_;
 | 
				
			||||||
 | 
					    that.head_ = that.tail_ = nullptr;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void push_front(T* const element) {
 | 
					  void push_front(T* const element) {
 | 
				
			||||||
    LinkedListEntry<T>* new_entry = Allocator::alloc();
 | 
					    LinkedListEntry<T>* new_entry = Allocator::alloc();
 | 
				
			||||||
    new_entry->next = head_;
 | 
					    new_entry->next = head_;
 | 
				
			||||||
@@ -140,6 +146,12 @@ class LinkedList {
 | 
				
			|||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static LinkedList make_list(T* const element) {
 | 
				
			||||||
 | 
					    LinkedList<T, Allocator> one_element_list;
 | 
				
			||||||
 | 
					    one_element_list.push_back(element);
 | 
				
			||||||
 | 
					    return one_element_list;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 private:
 | 
					 private:
 | 
				
			||||||
  LinkedListEntry<T>* head_;
 | 
					  LinkedListEntry<T>* head_;
 | 
				
			||||||
  LinkedListEntry<T>* tail_;
 | 
					  LinkedListEntry<T>* tail_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -284,7 +284,7 @@ static void protect_data(int protection) {
 | 
				
			|||||||
  g_soinfo_links_allocator.protect_all(protection);
 | 
					  g_soinfo_links_allocator.protect_all(protection);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static soinfo* soinfo_alloc(const char* name, struct stat* file_stat, off64_t file_offset, int rtld_flags) {
 | 
					static soinfo* soinfo_alloc(const char* name, struct stat* file_stat, off64_t file_offset, uint32_t rtld_flags) {
 | 
				
			||||||
  if (strlen(name) >= SOINFO_NAME_LEN) {
 | 
					  if (strlen(name) >= SOINFO_NAME_LEN) {
 | 
				
			||||||
    DL_ERR("library name \"%s\" too long", name);
 | 
					    DL_ERR("library name \"%s\" too long", name);
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
@@ -483,7 +483,8 @@ static unsigned elfhash(const char* _name) {
 | 
				
			|||||||
  return h;
 | 
					  return h;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static ElfW(Sym)* soinfo_do_lookup(soinfo* si, const char* name, soinfo** lsi, const soinfo::soinfo_list_t& local_group) {
 | 
					static ElfW(Sym)* soinfo_do_lookup(soinfo* si_from, const char* name, soinfo** si_found_in,
 | 
				
			||||||
 | 
					    const soinfo::soinfo_list_t& global_group, const soinfo::soinfo_list_t& local_group) {
 | 
				
			||||||
  unsigned elf_hash = elfhash(name);
 | 
					  unsigned elf_hash = elfhash(name);
 | 
				
			||||||
  ElfW(Sym)* s = nullptr;
 | 
					  ElfW(Sym)* s = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -498,49 +499,40 @@ static ElfW(Sym)* soinfo_do_lookup(soinfo* si, const char* name, soinfo** lsi, c
 | 
				
			|||||||
   * Note that this is unlikely since static linker avoids generating
 | 
					   * Note that this is unlikely since static linker avoids generating
 | 
				
			||||||
   * relocations for -Bsymbolic linked dynamic executables.
 | 
					   * relocations for -Bsymbolic linked dynamic executables.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  if (si->has_DT_SYMBOLIC) {
 | 
					  if (si_from->has_DT_SYMBOLIC) {
 | 
				
			||||||
    DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si->name, name);
 | 
					    DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si_from->name, name);
 | 
				
			||||||
    s = soinfo_elf_lookup(si, elf_hash, name);
 | 
					    s = soinfo_elf_lookup(si_from, elf_hash, name);
 | 
				
			||||||
    if (s != nullptr) {
 | 
					    if (s != nullptr) {
 | 
				
			||||||
      *lsi = si;
 | 
					      *si_found_in = si_from;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (s == nullptr && somain != nullptr) {
 | 
					  // 1. Look for it in global_group
 | 
				
			||||||
    // 1. Look for it in the main executable unless we already did.
 | 
					 | 
				
			||||||
    if (si != somain || !si->has_DT_SYMBOLIC) {
 | 
					 | 
				
			||||||
      DEBUG("%s: looking up %s in executable %s",
 | 
					 | 
				
			||||||
            si->name, name, somain->name);
 | 
					 | 
				
			||||||
      s = soinfo_elf_lookup(somain, elf_hash, name);
 | 
					 | 
				
			||||||
      if (s != nullptr) {
 | 
					 | 
				
			||||||
        *lsi = somain;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // 2. Look for it in the ld_preloads
 | 
					 | 
				
			||||||
  if (s == nullptr) {
 | 
					  if (s == nullptr) {
 | 
				
			||||||
      for (int i = 0; g_ld_preloads[i] != NULL; i++) {
 | 
					    global_group.visit([&](soinfo* global_si) {
 | 
				
			||||||
        s = soinfo_elf_lookup(g_ld_preloads[i], elf_hash, name);
 | 
					      DEBUG("%s: looking up %s in %s (from global group)", si_from->name, name, global_si->name);
 | 
				
			||||||
 | 
					      s = soinfo_elf_lookup(global_si, elf_hash, name);
 | 
				
			||||||
      if (s != nullptr) {
 | 
					      if (s != nullptr) {
 | 
				
			||||||
          *lsi = g_ld_preloads[i];
 | 
					        *si_found_in = global_si;
 | 
				
			||||||
          break;
 | 
					        return false;
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // 3. Look for it in the local group
 | 
					      return true;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 2. Look for it in the local group
 | 
				
			||||||
  if (s == nullptr) {
 | 
					  if (s == nullptr) {
 | 
				
			||||||
    local_group.visit([&](soinfo* local_si) {
 | 
					    local_group.visit([&](soinfo* local_si) {
 | 
				
			||||||
      if (local_si == si && si->has_DT_SYMBOLIC) {
 | 
					      if (local_si == si_from && si_from->has_DT_SYMBOLIC) {
 | 
				
			||||||
        // we already did this - skip
 | 
					        // we already did this - skip
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      DEBUG("%s: looking up %s in %s (from local group)", si->name, name, local_si->name);
 | 
					      DEBUG("%s: looking up %s in %s (from local group)", si_from->name, name, local_si->name);
 | 
				
			||||||
      s = soinfo_elf_lookup(local_si, elf_hash, name);
 | 
					      s = soinfo_elf_lookup(local_si, elf_hash, name);
 | 
				
			||||||
      if (s != nullptr) {
 | 
					      if (s != nullptr) {
 | 
				
			||||||
        *lsi = local_si;
 | 
					        *si_found_in = local_si;
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -551,9 +543,9 @@ static ElfW(Sym)* soinfo_do_lookup(soinfo* si, const char* name, soinfo** lsi, c
 | 
				
			|||||||
  if (s != nullptr) {
 | 
					  if (s != nullptr) {
 | 
				
			||||||
    TRACE_TYPE(LOOKUP, "si %s sym %s s->st_value = %p, "
 | 
					    TRACE_TYPE(LOOKUP, "si %s sym %s s->st_value = %p, "
 | 
				
			||||||
               "found in %s, base = %p, load bias = %p",
 | 
					               "found in %s, base = %p, load bias = %p",
 | 
				
			||||||
               si->name, name, reinterpret_cast<void*>(s->st_value),
 | 
					               si_from->name, name, reinterpret_cast<void*>(s->st_value),
 | 
				
			||||||
               (*lsi)->name, reinterpret_cast<void*>((*lsi)->base),
 | 
					               (*si_found_in)->name, reinterpret_cast<void*>((*si_found_in)->base),
 | 
				
			||||||
               reinterpret_cast<void*>((*lsi)->load_bias));
 | 
					               reinterpret_cast<void*>((*si_found_in)->load_bias));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return s;
 | 
					  return s;
 | 
				
			||||||
@@ -918,6 +910,24 @@ static bool is_recursive(soinfo* si, soinfo* parent) {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: this is slightly unusual way to construct
 | 
				
			||||||
 | 
					// the global group for relocation. Not every RTLD_GLOBAL
 | 
				
			||||||
 | 
					// library is included in this group for backwards-compatibility
 | 
				
			||||||
 | 
					// reasons.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This group consists of the main executable, LD_PRELOADs
 | 
				
			||||||
 | 
					// and libraries with the DF_1_GLOBAL flag set.
 | 
				
			||||||
 | 
					static soinfo::soinfo_list_t make_global_group() {
 | 
				
			||||||
 | 
					  soinfo::soinfo_list_t global_group;
 | 
				
			||||||
 | 
					  for (soinfo* si = somain; si != nullptr; si = si->next) {
 | 
				
			||||||
 | 
					    if ((si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
 | 
				
			||||||
 | 
					      global_group.push_back(si);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return global_group;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool find_libraries(soinfo* start_with, const char* const library_names[], size_t library_names_count, soinfo* soinfos[],
 | 
					static bool find_libraries(soinfo* start_with, const char* const library_names[], size_t library_names_count, soinfo* soinfos[],
 | 
				
			||||||
    soinfo* ld_preloads[], size_t ld_preloads_count, int rtld_flags, const android_dlextinfo* extinfo) {
 | 
					    soinfo* ld_preloads[], size_t ld_preloads_count, int rtld_flags, const android_dlextinfo* extinfo) {
 | 
				
			||||||
  // Step 0: prepare.
 | 
					  // Step 0: prepare.
 | 
				
			||||||
@@ -927,6 +937,9 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
 | 
				
			|||||||
    load_tasks.push_back(LoadTask::create(name, start_with));
 | 
					    load_tasks.push_back(LoadTask::create(name, start_with));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Construct global_group.
 | 
				
			||||||
 | 
					  soinfo::soinfo_list_t global_group = make_global_group();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If soinfos array is null allocate one on stack.
 | 
					  // If soinfos array is null allocate one on stack.
 | 
				
			||||||
  // The array is needed in case of failure; for example
 | 
					  // The array is needed in case of failure; for example
 | 
				
			||||||
  // when library_names[] = {libone.so, libtwo.so} and libone.so
 | 
					  // when library_names[] = {libone.so, libtwo.so} and libone.so
 | 
				
			||||||
@@ -975,6 +988,11 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
 | 
				
			|||||||
    // When ld_preloads is not null, the first
 | 
					    // When ld_preloads is not null, the first
 | 
				
			||||||
    // ld_preloads_count libs are in fact ld_preloads.
 | 
					    // ld_preloads_count libs are in fact ld_preloads.
 | 
				
			||||||
    if (ld_preloads != nullptr && soinfos_count < ld_preloads_count) {
 | 
					    if (ld_preloads != nullptr && soinfos_count < ld_preloads_count) {
 | 
				
			||||||
 | 
					      // Add LD_PRELOADed libraries to the global group for future runs.
 | 
				
			||||||
 | 
					      // There is no need to explicitly add them to the global group
 | 
				
			||||||
 | 
					      // for this run because they are going to appear in the local
 | 
				
			||||||
 | 
					      // group in the correct order.
 | 
				
			||||||
 | 
					      si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
 | 
				
			||||||
      ld_preloads[soinfos_count] = si;
 | 
					      ld_preloads[soinfos_count] = si;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -995,7 +1013,7 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  bool linked = local_group.visit([&](soinfo* si) {
 | 
					  bool linked = local_group.visit([&](soinfo* si) {
 | 
				
			||||||
    if ((si->flags & FLAG_LINKED) == 0) {
 | 
					    if ((si->flags & FLAG_LINKED) == 0) {
 | 
				
			||||||
      if (!si->LinkImage(local_group, extinfo)) {
 | 
					      if (!si->LinkImage(global_group, local_group, extinfo)) {
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      si->flags |= FLAG_LINKED;
 | 
					      si->flags |= FLAG_LINKED;
 | 
				
			||||||
@@ -1140,7 +1158,7 @@ static ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(USE_RELA)
 | 
					#if defined(USE_RELA)
 | 
				
			||||||
int soinfo::Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& local_group) {
 | 
					int soinfo::Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
 | 
				
			||||||
  for (size_t idx = 0; idx < count; ++idx, ++rela) {
 | 
					  for (size_t idx = 0; idx < count; ++idx, ++rela) {
 | 
				
			||||||
    unsigned type = ELFW(R_TYPE)(rela->r_info);
 | 
					    unsigned type = ELFW(R_TYPE)(rela->r_info);
 | 
				
			||||||
    unsigned sym = ELFW(R_SYM)(rela->r_info);
 | 
					    unsigned sym = ELFW(R_SYM)(rela->r_info);
 | 
				
			||||||
@@ -1158,7 +1176,7 @@ int soinfo::Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& loca
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (sym != 0) {
 | 
					    if (sym != 0) {
 | 
				
			||||||
      sym_name = get_string(symtab[sym].st_name);
 | 
					      sym_name = get_string(symtab[sym].st_name);
 | 
				
			||||||
      s = soinfo_do_lookup(this, sym_name, &lsi, local_group);
 | 
					      s = soinfo_do_lookup(this, sym_name, &lsi, global_group,local_group);
 | 
				
			||||||
      if (s == nullptr) {
 | 
					      if (s == nullptr) {
 | 
				
			||||||
        // We only allow an undefined symbol if this is a weak reference...
 | 
					        // We only allow an undefined symbol if this is a weak reference...
 | 
				
			||||||
        s = &symtab[sym];
 | 
					        s = &symtab[sym];
 | 
				
			||||||
@@ -1417,7 +1435,7 @@ int soinfo::Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& loca
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else // REL, not RELA.
 | 
					#else // REL, not RELA.
 | 
				
			||||||
int soinfo::Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& local_group) {
 | 
					int soinfo::Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
 | 
				
			||||||
  for (size_t idx = 0; idx < count; ++idx, ++rel) {
 | 
					  for (size_t idx = 0; idx < count; ++idx, ++rel) {
 | 
				
			||||||
    unsigned type = ELFW(R_TYPE)(rel->r_info);
 | 
					    unsigned type = ELFW(R_TYPE)(rel->r_info);
 | 
				
			||||||
    // TODO: don't use unsigned for 'sym'. Use uint32_t or ElfW(Addr) instead.
 | 
					    // TODO: don't use unsigned for 'sym'. Use uint32_t or ElfW(Addr) instead.
 | 
				
			||||||
@@ -1436,7 +1454,7 @@ int soinfo::Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& local_
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (sym != 0) {
 | 
					    if (sym != 0) {
 | 
				
			||||||
      sym_name = get_string(symtab[sym].st_name);
 | 
					      sym_name = get_string(symtab[sym].st_name);
 | 
				
			||||||
      s = soinfo_do_lookup(this, sym_name, &lsi, local_group);
 | 
					      s = soinfo_do_lookup(this, sym_name, &lsi, global_group, local_group);
 | 
				
			||||||
      if (s == nullptr) {
 | 
					      if (s == nullptr) {
 | 
				
			||||||
        // We only allow an undefined symbol if this is a weak reference...
 | 
					        // We only allow an undefined symbol if this is a weak reference...
 | 
				
			||||||
        s = &symtab[sym];
 | 
					        s = &symtab[sym];
 | 
				
			||||||
@@ -1622,7 +1640,7 @@ int soinfo::Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& local_
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__mips__)
 | 
					#if defined(__mips__)
 | 
				
			||||||
static bool mips_relocate_got(soinfo* si, const soinfo::soinfo_list_t& local_group) {
 | 
					static bool mips_relocate_got(soinfo* si, const soinfo::soinfo_list_t& global_group, const soinfo::soinfo_list_t& local_group) {
 | 
				
			||||||
  ElfW(Addr)** got = si->plt_got;
 | 
					  ElfW(Addr)** got = si->plt_got;
 | 
				
			||||||
  if (got == nullptr) {
 | 
					  if (got == nullptr) {
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
@@ -1655,7 +1673,7 @@ static bool mips_relocate_got(soinfo* si, const soinfo::soinfo_list_t& local_gro
 | 
				
			|||||||
    // This is an undefined reference... try to locate it.
 | 
					    // This is an undefined reference... try to locate it.
 | 
				
			||||||
    const char* sym_name = si->get_string(sym->st_name);
 | 
					    const char* sym_name = si->get_string(sym->st_name);
 | 
				
			||||||
    soinfo* lsi = nullptr;
 | 
					    soinfo* lsi = nullptr;
 | 
				
			||||||
    ElfW(Sym)* s = soinfo_do_lookup(si, sym_name, &lsi, local_group);
 | 
					    ElfW(Sym)* s = soinfo_do_lookup(si, sym_name, &lsi, global_group, local_group);
 | 
				
			||||||
    if (s == nullptr) {
 | 
					    if (s == nullptr) {
 | 
				
			||||||
      // We only allow an undefined symbol if this is a weak reference.
 | 
					      // We only allow an undefined symbol if this is a weak reference.
 | 
				
			||||||
      s = &symtab[g];
 | 
					      s = &symtab[g];
 | 
				
			||||||
@@ -1795,7 +1813,7 @@ void soinfo::remove_all_links() {
 | 
				
			|||||||
  children.clear();
 | 
					  children.clear();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dev_t soinfo::get_st_dev() {
 | 
					dev_t soinfo::get_st_dev() const {
 | 
				
			||||||
  if (has_min_version(0)) {
 | 
					  if (has_min_version(0)) {
 | 
				
			||||||
    return st_dev;
 | 
					    return st_dev;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1803,7 +1821,7 @@ dev_t soinfo::get_st_dev() {
 | 
				
			|||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ino_t soinfo::get_st_ino() {
 | 
					ino_t soinfo::get_st_ino() const {
 | 
				
			||||||
  if (has_min_version(0)) {
 | 
					  if (has_min_version(0)) {
 | 
				
			||||||
    return st_ino;
 | 
					    return st_ino;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1811,7 +1829,7 @@ ino_t soinfo::get_st_ino() {
 | 
				
			|||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
off64_t soinfo::get_file_offset() {
 | 
					off64_t soinfo::get_file_offset() const {
 | 
				
			||||||
  if (has_min_version(1)) {
 | 
					  if (has_min_version(1)) {
 | 
				
			||||||
    return file_offset;
 | 
					    return file_offset;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1819,7 +1837,7 @@ off64_t soinfo::get_file_offset() {
 | 
				
			|||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int soinfo::get_rtld_flags() {
 | 
					uint32_t soinfo::get_rtld_flags() const {
 | 
				
			||||||
  if (has_min_version(1)) {
 | 
					  if (has_min_version(1)) {
 | 
				
			||||||
    return rtld_flags;
 | 
					    return rtld_flags;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1827,6 +1845,27 @@ int soinfo::get_rtld_flags() {
 | 
				
			|||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t soinfo::get_dt_flags_1() const {
 | 
				
			||||||
 | 
					  if (has_min_version(1)) {
 | 
				
			||||||
 | 
					    return dt_flags_1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void soinfo::set_dt_flags_1(uint32_t dt_flags_1) {
 | 
				
			||||||
 | 
					  if (has_min_version(1)) {
 | 
				
			||||||
 | 
					    if ((dt_flags_1 & DF_1_GLOBAL) != 0) {
 | 
				
			||||||
 | 
					      rtld_flags |= RTLD_GLOBAL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((dt_flags_1 & DF_1_NODELETE) != 0) {
 | 
				
			||||||
 | 
					      rtld_flags |= RTLD_NODELETE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this->dt_flags_1 = dt_flags_1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This is a return on get_children()/get_parents() if
 | 
					// This is a return on get_children()/get_parents() if
 | 
				
			||||||
// 'this->flags' does not have FLAG_NEW_SOINFO set.
 | 
					// 'this->flags' does not have FLAG_NEW_SOINFO set.
 | 
				
			||||||
static soinfo::soinfo_list_t g_empty_list;
 | 
					static soinfo::soinfo_list_t g_empty_list;
 | 
				
			||||||
@@ -1864,8 +1903,9 @@ const char* soinfo::get_string(ElfW(Word) index) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool soinfo::can_unload() const {
 | 
					bool soinfo::can_unload() const {
 | 
				
			||||||
  return (rtld_flags & (RTLD_NODELETE | RTLD_GLOBAL)) == 0;
 | 
					  return (get_rtld_flags() & (RTLD_NODELETE | RTLD_GLOBAL)) == 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Force any of the closed stdin, stdout and stderr to be associated with
 | 
					/* Force any of the closed stdin, stdout and stderr to be associated with
 | 
				
			||||||
   /dev/null. */
 | 
					   /dev/null. */
 | 
				
			||||||
static int nullify_closed_stdio() {
 | 
					static int nullify_closed_stdio() {
 | 
				
			||||||
@@ -2166,16 +2206,9 @@ bool soinfo::PrelinkImage() {
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case DT_FLAGS_1:
 | 
					      case DT_FLAGS_1:
 | 
				
			||||||
        if ((d->d_un.d_val & DF_1_GLOBAL) != 0) {
 | 
					        set_dt_flags_1(d->d_un.d_val);
 | 
				
			||||||
          rtld_flags |= RTLD_GLOBAL;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((d->d_un.d_val & DF_1_NODELETE) != 0) {
 | 
					        if ((d->d_un.d_val & ~SUPPORTED_DT_FLAGS_1) != 0) {
 | 
				
			||||||
          rtld_flags |= RTLD_NODELETE;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // TODO: Implement other flags
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ((d->d_un.d_val & ~(DF_1_NOW | DF_1_GLOBAL | DF_1_NODELETE)) != 0) {
 | 
					 | 
				
			||||||
          DL_WARN("Unsupported flags DT_FLAGS_1=%p", reinterpret_cast<void*>(d->d_un.d_val));
 | 
					          DL_WARN("Unsupported flags DT_FLAGS_1=%p", reinterpret_cast<void*>(d->d_un.d_val));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@@ -2248,7 +2281,7 @@ bool soinfo::PrelinkImage() {
 | 
				
			|||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool soinfo::LinkImage(const soinfo_list_t& local_group, const android_dlextinfo* extinfo) {
 | 
					bool soinfo::LinkImage(const soinfo_list_t& global_group, const soinfo_list_t& local_group, const android_dlextinfo* extinfo) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !defined(__LP64__)
 | 
					#if !defined(__LP64__)
 | 
				
			||||||
  if (has_text_relocations) {
 | 
					  if (has_text_relocations) {
 | 
				
			||||||
@@ -2267,33 +2300,33 @@ bool soinfo::LinkImage(const soinfo_list_t& local_group, const android_dlextinfo
 | 
				
			|||||||
#if defined(USE_RELA)
 | 
					#if defined(USE_RELA)
 | 
				
			||||||
  if (rela != nullptr) {
 | 
					  if (rela != nullptr) {
 | 
				
			||||||
    DEBUG("[ relocating %s ]", name);
 | 
					    DEBUG("[ relocating %s ]", name);
 | 
				
			||||||
    if (Relocate(rela, rela_count, local_group)) {
 | 
					    if (Relocate(rela, rela_count, global_group, local_group)) {
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (plt_rela != nullptr) {
 | 
					  if (plt_rela != nullptr) {
 | 
				
			||||||
    DEBUG("[ relocating %s plt ]", name);
 | 
					    DEBUG("[ relocating %s plt ]", name);
 | 
				
			||||||
    if (Relocate(plt_rela, plt_rela_count, local_group)) {
 | 
					    if (Relocate(plt_rela, plt_rela_count, global_group, local_group)) {
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  if (rel != nullptr) {
 | 
					  if (rel != nullptr) {
 | 
				
			||||||
    DEBUG("[ relocating %s ]", name);
 | 
					    DEBUG("[ relocating %s ]", name);
 | 
				
			||||||
    if (Relocate(rel, rel_count, local_group)) {
 | 
					    if (Relocate(rel, rel_count, global_group, local_group)) {
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (plt_rel != nullptr) {
 | 
					  if (plt_rel != nullptr) {
 | 
				
			||||||
    DEBUG("[ relocating %s plt ]", name);
 | 
					    DEBUG("[ relocating %s plt ]", name);
 | 
				
			||||||
    if (Relocate(plt_rel, plt_rel_count, local_group)) {
 | 
					    if (Relocate(plt_rel, plt_rel_count, global_group, local_group)) {
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__mips__)
 | 
					#if defined(__mips__)
 | 
				
			||||||
  if (!mips_relocate_got(this, local_group)) {
 | 
					  if (!mips_relocate_got(this, global_group, local_group)) {
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -2360,7 +2393,7 @@ static void add_vdso(KernelArgumentBlock& args __unused) {
 | 
				
			|||||||
  si->load_bias = get_elf_exec_load_bias(ehdr_vdso);
 | 
					  si->load_bias = get_elf_exec_load_bias(ehdr_vdso);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  si->PrelinkImage();
 | 
					  si->PrelinkImage();
 | 
				
			||||||
  si->LinkImage(g_empty_list, nullptr);
 | 
					  si->LinkImage(g_empty_list, soinfo::soinfo_list_t::make_list(si), nullptr);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2491,6 +2524,9 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  si->PrelinkImage();
 | 
					  si->PrelinkImage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // add somain to global group
 | 
				
			||||||
 | 
					  si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Load ld_preloads and dependencies.
 | 
					  // Load ld_preloads and dependencies.
 | 
				
			||||||
  StringLinkedList needed_library_name_list;
 | 
					  StringLinkedList needed_library_name_list;
 | 
				
			||||||
  size_t needed_libraries_count = 0;
 | 
					  size_t needed_libraries_count = 0;
 | 
				
			||||||
@@ -2634,7 +2670,13 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) {
 | 
				
			|||||||
  linker_so.phnum = elf_hdr->e_phnum;
 | 
					  linker_so.phnum = elf_hdr->e_phnum;
 | 
				
			||||||
  linker_so.flags |= FLAG_LINKER;
 | 
					  linker_so.flags |= FLAG_LINKER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!(linker_so.PrelinkImage() && linker_so.LinkImage(g_empty_list, nullptr))) {
 | 
					  // This might not be obvious... The reasons why we pass g_empty_list
 | 
				
			||||||
 | 
					  // in place of local_group here are (1) we do not really need it, because
 | 
				
			||||||
 | 
					  // linker is built with DT_SYMBOLIC and therefore relocates its symbols against
 | 
				
			||||||
 | 
					  // itself without having to look into local_group and (2) allocators
 | 
				
			||||||
 | 
					  // are not yet initialized, and therefore we cannot use linked_list.push_*
 | 
				
			||||||
 | 
					  // functions at this point.
 | 
				
			||||||
 | 
					  if (!(linker_so.PrelinkImage() && linker_so.LinkImage(g_empty_list, g_empty_list, nullptr))) {
 | 
				
			||||||
    // It would be nice to print an error message, but if the linker
 | 
					    // It would be nice to print an error message, but if the linker
 | 
				
			||||||
    // can't link itself, there's no guarantee that we'll be able to
 | 
					    // can't link itself, there's no guarantee that we'll be able to
 | 
				
			||||||
    // call write() (because it involves a GOT reference). We may as
 | 
					    // call write() (because it involves a GOT reference). We may as
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,6 +89,8 @@
 | 
				
			|||||||
#define FLAG_LINKER     0x00000010 // The linker itself
 | 
					#define FLAG_LINKER     0x00000010 // The linker itself
 | 
				
			||||||
#define FLAG_NEW_SOINFO 0x40000000 // new soinfo format
 | 
					#define FLAG_NEW_SOINFO 0x40000000 // new soinfo format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SUPPORTED_DT_FLAGS_1 (DF_1_NOW | DF_1_GLOBAL | DF_1_NODELETE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SOINFO_VERSION 1
 | 
					#define SOINFO_VERSION 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SOINFO_NAME_LEN 128
 | 
					#define SOINFO_NAME_LEN 128
 | 
				
			||||||
@@ -207,16 +209,18 @@ struct soinfo {
 | 
				
			|||||||
  void CallDestructors();
 | 
					  void CallDestructors();
 | 
				
			||||||
  void CallPreInitConstructors();
 | 
					  void CallPreInitConstructors();
 | 
				
			||||||
  bool PrelinkImage();
 | 
					  bool PrelinkImage();
 | 
				
			||||||
  bool LinkImage(const soinfo_list_t& local_group, const android_dlextinfo* extinfo);
 | 
					  bool LinkImage(const soinfo_list_t& global_group, const soinfo_list_t& local_group, const android_dlextinfo* extinfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void add_child(soinfo* child);
 | 
					  void add_child(soinfo* child);
 | 
				
			||||||
  void remove_all_links();
 | 
					  void remove_all_links();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ino_t get_st_ino();
 | 
					  ino_t get_st_ino() const;
 | 
				
			||||||
  dev_t get_st_dev();
 | 
					  dev_t get_st_dev() const;
 | 
				
			||||||
  off64_t get_file_offset();
 | 
					  off64_t get_file_offset() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int get_rtld_flags();
 | 
					  uint32_t get_rtld_flags() const;
 | 
				
			||||||
 | 
					  uint32_t get_dt_flags_1() const;
 | 
				
			||||||
 | 
					  void set_dt_flags_1(uint32_t dt_flags_1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  soinfo_list_t& get_children();
 | 
					  soinfo_list_t& get_children();
 | 
				
			||||||
  soinfo_list_t& get_parents();
 | 
					  soinfo_list_t& get_parents();
 | 
				
			||||||
@@ -234,9 +238,9 @@ struct soinfo {
 | 
				
			|||||||
  void CallArray(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
 | 
					  void CallArray(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
 | 
				
			||||||
  void CallFunction(const char* function_name, linker_function_t function);
 | 
					  void CallFunction(const char* function_name, linker_function_t function);
 | 
				
			||||||
#if defined(USE_RELA)
 | 
					#if defined(USE_RELA)
 | 
				
			||||||
  int Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& local_group);
 | 
					  int Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  int Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& local_group);
 | 
					  int Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 private:
 | 
					 private:
 | 
				
			||||||
@@ -254,7 +258,8 @@ struct soinfo {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // version >= 1
 | 
					  // version >= 1
 | 
				
			||||||
  off64_t file_offset;
 | 
					  off64_t file_offset;
 | 
				
			||||||
  int rtld_flags;
 | 
					  uint32_t rtld_flags;
 | 
				
			||||||
 | 
					  uint32_t dt_flags_1;
 | 
				
			||||||
  size_t strtab_size;
 | 
					  size_t strtab_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  friend soinfo* get_libdl_info();
 | 
					  friend soinfo* get_libdl_info();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -233,6 +233,7 @@ bionic-unit-tests_static_libraries := \
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bionic-unit-tests_src_files := \
 | 
					bionic-unit-tests_src_files := \
 | 
				
			||||||
    atexit_test.cpp \
 | 
					    atexit_test.cpp \
 | 
				
			||||||
 | 
					    dl_test.cpp \
 | 
				
			||||||
    dlext_test.cpp \
 | 
					    dlext_test.cpp \
 | 
				
			||||||
    dlfcn_test.cpp \
 | 
					    dlfcn_test.cpp \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -245,8 +246,7 @@ bionic-unit-tests_conlyflags := \
 | 
				
			|||||||
bionic-unit-tests_cppflags := $(test_cppflags)
 | 
					bionic-unit-tests_cppflags := $(test_cppflags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bionic-unit-tests_ldflags := \
 | 
					bionic-unit-tests_ldflags := \
 | 
				
			||||||
    -Wl,--export-dynamic \
 | 
					    -Wl,--export-dynamic
 | 
				
			||||||
    -Wl,-u,DlSymTestFunction \
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
bionic-unit-tests_c_includes := \
 | 
					bionic-unit-tests_c_includes := \
 | 
				
			||||||
    bionic/libc \
 | 
					    bionic/libc \
 | 
				
			||||||
@@ -255,6 +255,9 @@ bionic-unit-tests_c_includes := \
 | 
				
			|||||||
bionic-unit-tests_shared_libraries_target := \
 | 
					bionic-unit-tests_shared_libraries_target := \
 | 
				
			||||||
    libdl \
 | 
					    libdl \
 | 
				
			||||||
    libpagemap \
 | 
					    libpagemap \
 | 
				
			||||||
 | 
					    libdl_preempt_test_1 \
 | 
				
			||||||
 | 
					    libdl_preempt_test_2 \
 | 
				
			||||||
 | 
					    libdl_test_df_1_global
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module := bionic-unit-tests
 | 
					module := bionic-unit-tests
 | 
				
			||||||
module_tag := optional
 | 
					module_tag := optional
 | 
				
			||||||
@@ -302,6 +305,12 @@ ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x
 | 
				
			|||||||
bionic-unit-tests-glibc_src_files := \
 | 
					bionic-unit-tests-glibc_src_files := \
 | 
				
			||||||
    atexit_test.cpp \
 | 
					    atexit_test.cpp \
 | 
				
			||||||
    dlfcn_test.cpp \
 | 
					    dlfcn_test.cpp \
 | 
				
			||||||
 | 
					    dl_test.cpp \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bionic-unit-tests-glibc_shared_libraries := \
 | 
				
			||||||
 | 
					    libdl_preempt_test_1 \
 | 
				
			||||||
 | 
					    libdl_preempt_test_2 \
 | 
				
			||||||
 | 
					    libdl_test_df_1_global
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bionic-unit-tests-glibc_whole_static_libraries := \
 | 
					bionic-unit-tests-glibc_whole_static_libraries := \
 | 
				
			||||||
    libBionicStandardTests \
 | 
					    libBionicStandardTests \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										72
									
								
								tests/dl_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								tests/dl_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 The Android Open Source Project
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gtest/gtest.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <dlfcn.h>
 | 
				
			||||||
 | 
					#include <libgen.h>
 | 
				
			||||||
 | 
					#include <limits.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int main_global_default_serial() {
 | 
				
			||||||
 | 
					  return 3370318;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int main_global_protected_serial() {
 | 
				
			||||||
 | 
					  return 2716057;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The following functions are defined in DT_NEEDED
 | 
				
			||||||
 | 
					// libdl_preempt_test.so library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This one calls main_global_default_serial
 | 
				
			||||||
 | 
					extern "C" int main_global_default_get_serial();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This one calls main_global_protected_serial
 | 
				
			||||||
 | 
					extern "C" int main_global_protected_get_serial();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This one calls lib_global_default_serial
 | 
				
			||||||
 | 
					extern "C" int lib_global_default_get_serial();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This one calls lib_global_protected_serial
 | 
				
			||||||
 | 
					extern "C" int lib_global_protected_get_serial();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This test verifies that the global default function
 | 
				
			||||||
 | 
					// main_global_default_serial() is preempted by
 | 
				
			||||||
 | 
					// the function defined above.
 | 
				
			||||||
 | 
					TEST(dl, main_preempts_global_default) {
 | 
				
			||||||
 | 
					  ASSERT_EQ(3370318, main_global_default_get_serial());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This one makes sure that the global protected
 | 
				
			||||||
 | 
					// symbols do not get preempted
 | 
				
			||||||
 | 
					TEST(dl, main_does_not_preempt_global_protected) {
 | 
				
			||||||
 | 
					  ASSERT_EQ(3370318, main_global_protected_get_serial());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// check same things for lib
 | 
				
			||||||
 | 
					TEST(dl, lib_preempts_global_default) {
 | 
				
			||||||
 | 
					  ASSERT_EQ(3370318, lib_global_default_get_serial());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(dl, lib_does_not_preempt_global_protected) {
 | 
				
			||||||
 | 
					  ASSERT_EQ(3370318, lib_global_protected_get_serial());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: Add tests for LD_PRELOADs
 | 
				
			||||||
@@ -499,6 +499,20 @@ TEST(dlfcn, dlopen_nodelete_dt_flags_1) {
 | 
				
			|||||||
  ASSERT_TRUE(!is_unloaded);
 | 
					  ASSERT_TRUE(!is_unloaded);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(dlfcn, dlsym_df_1_global) {
 | 
				
			||||||
 | 
					#if !defined(__arm__)
 | 
				
			||||||
 | 
					  void* handle = dlopen("libtest_dlsym_df_1_global.so", RTLD_NOW);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(handle != nullptr) << dlerror();
 | 
				
			||||||
 | 
					  int (*get_answer)();
 | 
				
			||||||
 | 
					  get_answer = reinterpret_cast<int (*)()>(dlsym(handle, "dl_df_1_global_get_answer"));
 | 
				
			||||||
 | 
					  ASSERT_TRUE(get_answer != nullptr) << dlerror();
 | 
				
			||||||
 | 
					  ASSERT_EQ(42, get_answer());
 | 
				
			||||||
 | 
					  ASSERT_EQ(0, dlclose(handle));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  GTEST_LOG_(INFO) << "This test does nothing on arm (to be reenabled once b/18137520 or b/18130452 are fixed).\n";
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, dlopen_failure) {
 | 
					TEST(dlfcn, dlopen_failure) {
 | 
				
			||||||
  void* self = dlopen("/does/not/exist", RTLD_NOW);
 | 
					  void* self = dlopen("/does/not/exist", RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(self == NULL);
 | 
					  ASSERT_TRUE(self == NULL);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -290,6 +290,42 @@ libtest_atexit_src_files := \
 | 
				
			|||||||
module := libtest_atexit
 | 
					module := libtest_atexit
 | 
				
			||||||
include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# This library is used by dl_load test to check symbol preempting
 | 
				
			||||||
 | 
					# by main executable
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					libdl_preempt_test_1_src_files := dl_preempt_library_1.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module := libdl_preempt_test_1
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# This library is used by dl_load test to check symbol preempting
 | 
				
			||||||
 | 
					# by libdl_preempt_test_1.so
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					libdl_preempt_test_2_src_files := dl_preempt_library_2.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module := libdl_preempt_test_2
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Library with DF_1_GLOBAL
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# TODO: re-enable arm once b/18137520 or b/18130452 are fixed
 | 
				
			||||||
 | 
					ifeq ($(filter $(TARGET_ARCH),arm),)
 | 
				
			||||||
 | 
					libdl_test_df_1_global_src_files := dl_df_1_global.cpp
 | 
				
			||||||
 | 
					libdl_test_df_1_global_ldflags := -fuse-ld=bfd -Wl,-z,global
 | 
				
			||||||
 | 
					module := libdl_test_df_1_global
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Library using symbol from libdl_test_df_1_global
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					libtest_dlsym_df_1_global_src_files := dl_df_1_use_global.cpp
 | 
				
			||||||
 | 
					module := libtest_dlsym_df_1_global
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# -----------------------------------------------------------------------------
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
# Library with weak function
 | 
					# Library with weak function
 | 
				
			||||||
# -----------------------------------------------------------------------------
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								tests/libs/dl_df_1_global.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tests/libs/dl_df_1_global.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 The Android Open Source Project
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int dl_df_1_global_get_answer_impl() {
 | 
				
			||||||
 | 
					  return 42;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								tests/libs/dl_df_1_use_global.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/libs/dl_df_1_use_global.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 The Android Open Source Project
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int __attribute__((weak)) dl_df_1_global_get_answer_impl() {
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int dl_df_1_global_get_answer() {
 | 
				
			||||||
 | 
					  return dl_df_1_global_get_answer_impl();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										45
									
								
								tests/libs/dl_preempt_library_1.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								tests/libs/dl_preempt_library_1.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 The Android Open Source Project
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This one should be preempted by the function
 | 
				
			||||||
 | 
					// defined in the main executable.
 | 
				
			||||||
 | 
					extern "C" int __attribute__((weak)) main_global_default_serial() {
 | 
				
			||||||
 | 
					  return 2716057;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Even though this one is defined by the main
 | 
				
			||||||
 | 
					// executable it should not be preempted
 | 
				
			||||||
 | 
					// because of protected visibility
 | 
				
			||||||
 | 
					extern "C" int __attribute__((weak, visibility("protected"))) main_global_protected_serial() {
 | 
				
			||||||
 | 
					  return 3370318;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int main_global_default_get_serial() {
 | 
				
			||||||
 | 
					  return main_global_default_serial();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int main_global_protected_get_serial() {
 | 
				
			||||||
 | 
					  return main_global_protected_serial();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Trying to preempt functions from a DT_NEEDED .so
 | 
				
			||||||
 | 
					extern "C" int lib_global_default_serial() {
 | 
				
			||||||
 | 
					  return 3370318;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int lib_global_protected_serial() {
 | 
				
			||||||
 | 
					  return 2716057;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										37
									
								
								tests/libs/dl_preempt_library_2.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								tests/libs/dl_preempt_library_2.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 The Android Open Source Project
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This one should be preempted by the function
 | 
				
			||||||
 | 
					// defined in libdl_preempt_test_1.so
 | 
				
			||||||
 | 
					extern "C" int __attribute__((weak)) lib_global_default_serial() {
 | 
				
			||||||
 | 
					  return 2716057;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Even though this one is defined by
 | 
				
			||||||
 | 
					// libdl_preempt_test_1.so it should not be
 | 
				
			||||||
 | 
					// preempted because of protected visibility
 | 
				
			||||||
 | 
					extern "C" int __attribute__((weak,visibility("protected"))) lib_global_protected_serial() {
 | 
				
			||||||
 | 
					  return 3370318;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int lib_global_default_get_serial() {
 | 
				
			||||||
 | 
					  return lib_global_default_serial();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int lib_global_protected_get_serial() {
 | 
				
			||||||
 | 
					  return lib_global_protected_serial();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reference in New Issue
	
	Block a user