summaryrefslogtreecommitdiff
path: root/linker/linker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r--linker/linker.cpp603
1 files changed, 9 insertions, 594 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 10833be9d..57554fb92 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -63,8 +63,7 @@
#include "linker_namespaces.h"
#include "linker_sleb128.h"
#include "linker_phdr.h"
-#include "linker_relocs.h"
-#include "linker_reloc_iterators.h"
+#include "linker_relocate.h"
#include "linker_tls.h"
#include "linker_utils.h"
@@ -276,31 +275,6 @@ static bool translateSystemPathToApexPath(const char* name, std::string* out_nam
static std::vector<std::string> g_ld_preload_names;
-#if STATS
-struct linker_stats_t {
- int count[kRelocMax];
-};
-
-static linker_stats_t linker_stats;
-
-void count_relocation(RelocationKind kind) {
- ++linker_stats.count[kind];
-}
-
-void print_linker_stats() {
- PRINT("RELO STATS: %s: %d abs, %d rel, %d copy, %d symbol (%d cached)",
- g_argv[0],
- linker_stats.count[kRelocAbsolute],
- linker_stats.count[kRelocRelative],
- linker_stats.count[kRelocCopy],
- linker_stats.count[kRelocSymbol],
- linker_stats.count[kRelocSymbolCached]);
-}
-#else
-void count_relocation(RelocationKind) {
-}
-#endif
-
static void notify_gdb_of_load(soinfo* info) {
if (info->is_linker() || info->is_main_executable()) {
// gdb already knows about the linker and the main executable.
@@ -488,79 +462,6 @@ int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), v
return rv;
}
-
-bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi,
- soinfo** si_found_in, const soinfo_list_t& global_group,
- const soinfo_list_t& local_group, const ElfW(Sym)** symbol) {
- SymbolName symbol_name(name);
- const ElfW(Sym)* s = nullptr;
-
- /* "This element's presence in a shared object library alters the dynamic linker's
- * symbol resolution algorithm for references within the library. Instead of starting
- * a symbol search with the executable file, the dynamic linker starts from the shared
- * object itself. If the shared object fails to supply the referenced symbol, the
- * dynamic linker then searches the executable file and other shared objects as usual."
- *
- * http://www.sco.com/developers/gabi/2012-12-31/ch5.dynamic.html
- *
- * Note that this is unlikely since static linker avoids generating
- * relocations for -Bsymbolic linked dynamic executables.
- */
- if (si_from->has_DT_SYMBOLIC) {
- DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si_from->get_realpath(), name);
- s = si_from->find_symbol_by_name(symbol_name, vi);
- if (s != nullptr) {
- *si_found_in = si_from;
- }
- }
-
- // 1. Look for it in global_group
- if (s == nullptr) {
- global_group.visit([&](soinfo* global_si) {
- DEBUG("%s: looking up %s in %s (from global group)",
- si_from->get_realpath(), name, global_si->get_realpath());
- s = global_si->find_symbol_by_name(symbol_name, vi);
- if (s != nullptr) {
- *si_found_in = global_si;
- return false;
- }
-
- return true;
- });
- }
-
- // 2. Look for it in the local group
- if (s == nullptr) {
- local_group.visit([&](soinfo* local_si) {
- if (local_si == si_from && si_from->has_DT_SYMBOLIC) {
- // we already did this - skip
- return true;
- }
-
- DEBUG("%s: looking up %s in %s (from local group)",
- si_from->get_realpath(), name, local_si->get_realpath());
- s = local_si->find_symbol_by_name(symbol_name, vi);
- if (s != nullptr) {
- *si_found_in = local_si;
- return false;
- }
-
- return true;
- });
- }
-
- if (s != nullptr) {
- TRACE_TYPE(LOOKUP, "si %s sym %s s->st_value = %p, "
- "found in %s, base = %p, load bias = %p",
- si_from->get_realpath(), name, reinterpret_cast<void*>(s->st_value),
- (*si_found_in)->get_realpath(), reinterpret_cast<void*>((*si_found_in)->base),
- reinterpret_cast<void*>((*si_found_in)->load_bias));
- }
-
- *symbol = s;
- return true;
-}
-
ProtectedDataGuard::ProtectedDataGuard() {
if (ref_count_++ == 0) {
protect_data(PROT_READ | PROT_WRITE);
@@ -1906,6 +1807,9 @@ bool find_libraries(android_namespace_t* ns,
});
soinfo_list_t global_group = local_group_ns->get_global_group();
+ SymbolLookupList lookup_list(global_group, local_group);
+ soinfo* local_group_root = local_group.front();
+
bool linked = local_group.visit([&](soinfo* si) {
// Even though local group may contain accessible soinfos from other namespaces
// we should avoid linking them (because if they are not linked -> they
@@ -1920,7 +1824,8 @@ bool find_libraries(android_namespace_t* ns,
if (__libc_shared_globals()->load_hook) {
__libc_shared_globals()->load_hook(si->load_bias, si->phdr, si->phnum);
}
- if (!si->link_image(global_group, local_group, link_extinfo, &relro_fd_offset) ||
+ lookup_list.set_dt_symbolic_lib(si->has_DT_SYMBOLIC ? si : nullptr);
+ if (!si->link_image(lookup_list, local_group_root, link_extinfo, &relro_fd_offset) ||
!get_cfi_shadow()->AfterLoad(si, solist_get_head())) {
return false;
}
@@ -2912,421 +2817,6 @@ bool soinfo::relocate_relr() {
return true;
}
-#if !defined(__mips__)
-#if defined(USE_RELA)
-static ElfW(Addr) get_addend(ElfW(Rela)* rela, ElfW(Addr) reloc_addr __unused) {
- return rela->r_addend;
-}
-#else
-static ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) {
- // The i386 psABI specifies that R_386_GLOB_DAT doesn't have an addend. The ARM ELF ABI document
- // (IHI0044F) specifies that R_ARM_GLOB_DAT has an addend, but Bionic isn't adding it.
- if (ELFW(R_TYPE)(rel->r_info) == R_GENERIC_RELATIVE ||
- ELFW(R_TYPE)(rel->r_info) == R_GENERIC_IRELATIVE ||
- ELFW(R_TYPE)(rel->r_info) == R_GENERIC_ABSOLUTE ||
- ELFW(R_TYPE)(rel->r_info) == R_GENERIC_TLS_DTPREL ||
- ELFW(R_TYPE)(rel->r_info) == R_GENERIC_TLS_TPREL) {
- return *reinterpret_cast<ElfW(Addr)*>(reloc_addr);
- }
- return 0;
-}
-#endif
-
-static bool is_tls_reloc(ElfW(Word) type) {
- switch (type) {
- case R_GENERIC_TLS_DTPMOD:
- case R_GENERIC_TLS_DTPREL:
- case R_GENERIC_TLS_TPREL:
- case R_GENERIC_TLSDESC:
- return true;
- default:
- return false;
- }
-}
-
-template<typename ElfRelIteratorT>
-bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
- const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
- const size_t tls_tp_base = __libc_shared_globals()->static_tls_layout.offset_thread_pointer();
- std::vector<std::pair<TlsDescriptor*, size_t>> deferred_tlsdesc_relocs;
-
- struct {
- // Cache key
- ElfW(Word) sym;
-
- // Cache value
- const ElfW(Sym)* s;
- soinfo* lsi;
- } symbol_lookup_cache;
-
- symbol_lookup_cache.sym = 0;
-
- for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
- const auto rel = rel_iterator.next();
- if (rel == nullptr) {
- return false;
- }
-
- ElfW(Word) type = ELFW(R_TYPE)(rel->r_info);
- ElfW(Word) sym = ELFW(R_SYM)(rel->r_info);
-
- ElfW(Addr) reloc = static_cast<ElfW(Addr)>(rel->r_offset + load_bias);
- ElfW(Addr) sym_addr = 0;
- const char* sym_name = nullptr;
- ElfW(Addr) addend = get_addend(rel, reloc);
-
- DEBUG("Processing \"%s\" relocation at index %zd", get_realpath(), idx);
- if (type == R_GENERIC_NONE) {
- continue;
- }
-
- const ElfW(Sym)* s = nullptr;
- soinfo* lsi = nullptr;
-
- if (sym == 0) {
- // By convention in ld.bfd and lld, an omitted symbol on a TLS relocation
- // is a reference to the current module.
- if (is_tls_reloc(type)) {
- lsi = this;
- }
- } else if (ELF_ST_BIND(symtab_[sym].st_info) == STB_LOCAL && is_tls_reloc(type)) {
- // In certain situations, the Gold linker accesses a TLS symbol using a
- // relocation to an STB_LOCAL symbol in .dynsym of either STT_SECTION or
- // STT_TLS type. Bionic doesn't support these relocations, so issue an
- // error. References:
- // - https://groups.google.com/d/topic/generic-abi/dJ4_Y78aQ2M/discussion
- // - https://sourceware.org/bugzilla/show_bug.cgi?id=17699
- s = &symtab_[sym];
- sym_name = get_string(s->st_name);
- DL_ERR("unexpected TLS reference to local symbol \"%s\": "
- "sym type %d, rel type %u (idx %zu of \"%s\")",
- sym_name, ELF_ST_TYPE(s->st_info), type, idx, get_realpath());
- return false;
- } else {
- sym_name = get_string(symtab_[sym].st_name);
-
- if (sym == symbol_lookup_cache.sym) {
- s = symbol_lookup_cache.s;
- lsi = symbol_lookup_cache.lsi;
- count_relocation(kRelocSymbolCached);
- } else {
- const version_info* vi = nullptr;
-
- if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
- return false;
- }
-
- if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
- return false;
- }
-
- symbol_lookup_cache.sym = sym;
- symbol_lookup_cache.s = s;
- symbol_lookup_cache.lsi = lsi;
- }
-
- if (s == nullptr) {
- // We only allow an undefined symbol if this is a weak reference...
- s = &symtab_[sym];
- if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
- DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, get_realpath());
- return false;
- }
-
- /* IHI0044C AAELF 4.5.1.1:
-
- Libraries are not searched to resolve weak references.
- It is not an error for a weak reference to remain unsatisfied.
-
- During linking, the value of an undefined weak reference is:
- - Zero if the relocation type is absolute
- - The address of the place if the relocation is pc-relative
- - The address of nominal base address if the relocation
- type is base-relative.
- */
-
- switch (type) {
- case R_GENERIC_JUMP_SLOT:
- case R_GENERIC_ABSOLUTE:
- case R_GENERIC_GLOB_DAT:
- case R_GENERIC_RELATIVE:
- case R_GENERIC_IRELATIVE:
- case R_GENERIC_TLS_DTPMOD:
- case R_GENERIC_TLS_DTPREL:
- case R_GENERIC_TLS_TPREL:
- case R_GENERIC_TLSDESC:
-#if defined(__x86_64__)
- case R_X86_64_32:
-#endif
- /*
- * The sym_addr was initialized to be zero above, or the relocation
- * code below does not care about value of sym_addr.
- * No need to do anything.
- */
- break;
-#if defined(__x86_64__)
- case R_X86_64_PC32:
- sym_addr = reloc;
- break;
-#elif defined(__i386__)
- case R_386_PC32:
- sym_addr = reloc;
- break;
-#endif
- default:
- DL_ERR("unknown weak reloc type %d @ %p (%zu)", type, rel, idx);
- return false;
- }
- } else { // We got a definition.
-#if !defined(__LP64__)
- // When relocating dso with text_relocation .text segment is
- // not executable. We need to restore elf flags before resolving
- // STT_GNU_IFUNC symbol.
- bool protect_segments = has_text_relocations &&
- lsi == this &&
- ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC;
- if (protect_segments) {
- if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
- DL_ERR("can't protect segments for \"%s\": %s",
- get_realpath(), strerror(errno));
- return false;
- }
- }
-#endif
- if (is_tls_reloc(type)) {
- if (ELF_ST_TYPE(s->st_info) != STT_TLS) {
- DL_ERR("reference to non-TLS symbol \"%s\" from TLS relocation in \"%s\"",
- sym_name, get_realpath());
- return false;
- }
- if (lsi->get_tls() == nullptr) {
- DL_ERR("TLS relocation refers to symbol \"%s\" in solib \"%s\" with no TLS segment",
- sym_name, lsi->get_realpath());
- return false;
- }
- sym_addr = s->st_value;
- } else {
- if (ELF_ST_TYPE(s->st_info) == STT_TLS) {
- DL_ERR("reference to TLS symbol \"%s\" from non-TLS relocation in \"%s\"",
- sym_name, get_realpath());
- return false;
- }
- sym_addr = lsi->resolve_symbol_address(s);
- }
-#if !defined(__LP64__)
- if (protect_segments) {
- if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
- DL_ERR("can't unprotect loadable segments for \"%s\": %s",
- get_realpath(), strerror(errno));
- return false;
- }
- }
-#endif
- }
- count_relocation(kRelocSymbol);
- }
-
- switch (type) {
- case R_GENERIC_JUMP_SLOT:
- count_relocation(kRelocAbsolute);
- TRACE_TYPE(RELO, "RELO JMP_SLOT %16p <- %16p %s\n",
- reinterpret_cast<void*>(reloc),
- reinterpret_cast<void*>(sym_addr + addend), sym_name);
-
- *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
- break;
- case R_GENERIC_ABSOLUTE:
- case R_GENERIC_GLOB_DAT:
- count_relocation(kRelocAbsolute);
- TRACE_TYPE(RELO, "RELO ABSOLUTE/GLOB_DAT %16p <- %16p %s\n",
- reinterpret_cast<void*>(reloc),
- reinterpret_cast<void*>(sym_addr + addend), sym_name);
- *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
- break;
- case R_GENERIC_RELATIVE:
- count_relocation(kRelocRelative);
- TRACE_TYPE(RELO, "RELO RELATIVE %16p <- %16p\n",
- reinterpret_cast<void*>(reloc),
- reinterpret_cast<void*>(load_bias + addend));
- *reinterpret_cast<ElfW(Addr)*>(reloc) = (load_bias + addend);
- break;
- case R_GENERIC_IRELATIVE:
- count_relocation(kRelocRelative);
- TRACE_TYPE(RELO, "RELO IRELATIVE %16p <- %16p\n",
- reinterpret_cast<void*>(reloc),
- reinterpret_cast<void*>(load_bias + addend));
- // In the linker, ifuncs are called as soon as possible so that string functions work.
- // We must not call them again. (e.g. On arm32, resolving an ifunc changes the meaning of
- // the addend from a resolver function to the implementation.)
- if (!is_linker()) {
-#if !defined(__LP64__)
- // When relocating dso with text_relocation .text segment is
- // not executable. We need to restore elf flags for this
- // particular call.
- if (has_text_relocations) {
- if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
- DL_ERR("can't protect segments for \"%s\": %s",
- get_realpath(), strerror(errno));
- return false;
- }
- }
-#endif
- ElfW(Addr) ifunc_addr = call_ifunc_resolver(load_bias + addend);
-#if !defined(__LP64__)
- // Unprotect it afterwards...
- if (has_text_relocations) {
- if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
- DL_ERR("can't unprotect loadable segments for \"%s\": %s",
- get_realpath(), strerror(errno));
- return false;
- }
- }
-#endif
- *reinterpret_cast<ElfW(Addr)*>(reloc) = ifunc_addr;
- }
- break;
- case R_GENERIC_COPY:
- // Copy relocations allow read-only data or code in a non-PIE executable to access a
- // variable from a DSO. The executable reserves extra space in its .bss section, and the
- // linker copies the variable into the extra space. The executable then exports its copy
- // to interpose the copy in the DSO.
- //
- // Bionic only supports PIE executables, so copy relocations aren't supported. The ARM and
- // AArch64 ABI documents only allow them for ET_EXEC (non-PIE) objects. See IHI0056B and
- // IHI0044F.
- DL_ERR("%s COPY relocations are not supported", get_realpath());
- return false;
- case R_GENERIC_TLS_TPREL:
- count_relocation(kRelocRelative);
- {
- ElfW(Addr) tpoff = 0;
- if (lsi == nullptr) {
- // Unresolved weak relocation. Leave tpoff at 0 to resolve
- // &weak_tls_symbol to __get_tls().
- } else {
- CHECK(lsi->get_tls() != nullptr); // We rejected a missing TLS segment above.
- const TlsModule& mod = get_tls_module(lsi->get_tls()->module_id);
- if (mod.static_offset != SIZE_MAX) {
- tpoff += mod.static_offset - tls_tp_base;
- } else {
- DL_ERR("TLS symbol \"%s\" in dlopened \"%s\" referenced from \"%s\" using IE access model",
- sym_name, lsi->get_realpath(), get_realpath());
- return false;
- }
- }
- tpoff += sym_addr + addend;
- TRACE_TYPE(RELO, "RELO TLS_TPREL %16p <- %16p %s\n",
- reinterpret_cast<void*>(reloc),
- reinterpret_cast<void*>(tpoff), sym_name);
- *reinterpret_cast<ElfW(Addr)*>(reloc) = tpoff;
- }
- break;
- case R_GENERIC_TLS_DTPMOD:
- count_relocation(kRelocRelative);
- {
- size_t module_id = 0;
- if (lsi == nullptr) {
- // Unresolved weak relocation. Evaluate the module ID to 0.
- } else {
- CHECK(lsi->get_tls() != nullptr); // We rejected a missing TLS segment above.
- module_id = lsi->get_tls()->module_id;
- }
- TRACE_TYPE(RELO, "RELO TLS_DTPMOD %16p <- %zu %s\n",
- reinterpret_cast<void*>(reloc), module_id, sym_name);
- *reinterpret_cast<ElfW(Addr)*>(reloc) = module_id;
- }
- break;
- case R_GENERIC_TLS_DTPREL:
- count_relocation(kRelocRelative);
- TRACE_TYPE(RELO, "RELO TLS_DTPREL %16p <- %16p %s\n",
- reinterpret_cast<void*>(reloc),
- reinterpret_cast<void*>(sym_addr + addend), sym_name);
- *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
- break;
-
-#if defined(__aarch64__)
- // Bionic currently only implements TLSDESC for arm64. This implementation should work with
- // other architectures, as long as the resolver functions are implemented.
- case R_GENERIC_TLSDESC:
- count_relocation(kRelocRelative);
- {
- TlsDescriptor* desc = reinterpret_cast<TlsDescriptor*>(reloc);
- if (lsi == nullptr) {
- // Unresolved weak relocation.
- desc->func = tlsdesc_resolver_unresolved_weak;
- desc->arg = addend;
- TRACE_TYPE(RELO, "RELO TLSDESC %16p <- unresolved weak 0x%zx %s\n",
- reinterpret_cast<void*>(reloc), static_cast<size_t>(addend), sym_name);
- } else {
- CHECK(lsi->get_tls() != nullptr); // We rejected a missing TLS segment above.
- size_t module_id = lsi->get_tls()->module_id;
- const TlsModule& mod = get_tls_module(module_id);
- if (mod.static_offset != SIZE_MAX) {
- desc->func = tlsdesc_resolver_static;
- desc->arg = mod.static_offset - tls_tp_base + sym_addr + addend;
- TRACE_TYPE(RELO, "RELO TLSDESC %16p <- static (0x%zx - 0x%zx + 0x%zx + 0x%zx) %s\n",
- reinterpret_cast<void*>(reloc), mod.static_offset, tls_tp_base,
- static_cast<size_t>(sym_addr), static_cast<size_t>(addend), sym_name);
- } else {
- tlsdesc_args_.push_back({
- .generation = mod.first_generation,
- .index.module_id = module_id,
- .index.offset = sym_addr + addend,
- });
- // Defer the TLSDESC relocation until the address of the TlsDynamicResolverArg object
- // is finalized.
- deferred_tlsdesc_relocs.push_back({ desc, tlsdesc_args_.size() - 1 });
- const TlsDynamicResolverArg& desc_arg = tlsdesc_args_.back();
- TRACE_TYPE(RELO, "RELO TLSDESC %16p <- dynamic (gen %zu, mod %zu, off %zu) %s",
- reinterpret_cast<void*>(reloc), desc_arg.generation,
- desc_arg.index.module_id, desc_arg.index.offset, sym_name);
- }
- }
- }
- break;
-#endif // defined(__aarch64__)
-
-#if defined(__x86_64__)
- case R_X86_64_32:
- count_relocation(kRelocAbsolute);
- TRACE_TYPE(RELO, "RELO R_X86_64_32 %08zx <- +%08zx %s", static_cast<size_t>(reloc),
- static_cast<size_t>(sym_addr), sym_name);
- *reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr + addend;
- break;
- case R_X86_64_PC32:
- count_relocation(kRelocRelative);
- TRACE_TYPE(RELO, "RELO R_X86_64_PC32 %08zx <- +%08zx (%08zx - %08zx) %s",
- static_cast<size_t>(reloc), static_cast<size_t>(sym_addr - reloc),
- static_cast<size_t>(sym_addr), static_cast<size_t>(reloc), sym_name);
- *reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr + addend - reloc;
- break;
-#elif defined(__i386__)
- case R_386_PC32:
- count_relocation(kRelocRelative);
- TRACE_TYPE(RELO, "RELO R_386_PC32 %08x <- +%08x (%08x - %08x) %s",
- reloc, (sym_addr - reloc), sym_addr, reloc, sym_name);
- *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr - reloc);
- break;
-#endif
- default:
- DL_ERR("unknown reloc type %d @ %p (%zu)", type, rel, idx);
- return false;
- }
- }
-
-#if defined(__aarch64__)
- // Bionic currently only implements TLSDESC for arm64.
- for (const std::pair<TlsDescriptor*, size_t>& pair : deferred_tlsdesc_relocs) {
- TlsDescriptor* desc = pair.first;
- desc->func = tlsdesc_resolver_dynamic;
- desc->arg = reinterpret_cast<size_t>(&tlsdesc_args_[pair.second]);
- }
-#endif
-
- return true;
-}
-#endif // !defined(__mips__)
-
// An empty list of soinfos
static soinfo_list_t g_empty_list;
@@ -3835,7 +3325,7 @@ bool soinfo::prelink_image() {
return true;
}
-bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,
+bool soinfo::link_image(const SymbolLookupList& lookup_list, soinfo* local_group_root,
const android_dlextinfo* extinfo, size_t* relro_fd_offset) {
if (is_image_linked()) {
// already linked.
@@ -3847,7 +3337,7 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
get_realpath(), reinterpret_cast<void*>(base));
}
- local_group_root_ = local_group.front();
+ local_group_root_ = local_group_root;
if (local_group_root_ == nullptr) {
local_group_root_ = this;
}
@@ -3856,12 +3346,6 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
target_sdk_version_ = get_application_target_sdk_version();
}
- VersionTracker version_tracker;
-
- if (!version_tracker.init(this)) {
- return false;
- }
-
#if !defined(__LP64__)
if (has_text_relocations) {
// Fail if app is targeting M or above.
@@ -3886,78 +3370,9 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
}
#endif
- if (android_relocs_ != nullptr) {
- // check signature
- if (android_relocs_size_ > 3 &&
- android_relocs_[0] == 'A' &&
- android_relocs_[1] == 'P' &&
- android_relocs_[2] == 'S' &&
- android_relocs_[3] == '2') {
- DEBUG("[ android relocating %s ]", get_realpath());
-
- bool relocated = false;
- const uint8_t* packed_relocs = android_relocs_ + 4;
- const size_t packed_relocs_size = android_relocs_size_ - 4;
-
- relocated = relocate(
- version_tracker,
- packed_reloc_iterator<sleb128_decoder>(
- sleb128_decoder(packed_relocs, packed_relocs_size)),
- global_group, local_group);
-
- if (!relocated) {
- return false;
- }
- } else {
- DL_ERR("bad android relocation header.");
- return false;
- }
- }
-
- if (relr_ != nullptr) {
- DEBUG("[ relocating %s relr ]", get_realpath());
- if (!relocate_relr()) {
- return false;
- }
- }
-
-#if defined(USE_RELA)
- if (rela_ != nullptr) {
- DEBUG("[ relocating %s rela ]", get_realpath());
- if (!relocate(version_tracker,
- plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) {
- return false;
- }
- }
- if (plt_rela_ != nullptr) {
- DEBUG("[ relocating %s plt rela ]", get_realpath());
- if (!relocate(version_tracker,
- plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) {
- return false;
- }
- }
-#else
- if (rel_ != nullptr) {
- DEBUG("[ relocating %s rel ]", get_realpath());
- if (!relocate(version_tracker,
- plain_reloc_iterator(rel_, rel_count_), global_group, local_group)) {
- return false;
- }
- }
- if (plt_rel_ != nullptr) {
- DEBUG("[ relocating %s plt rel ]", get_realpath());
- if (!relocate(version_tracker,
- plain_reloc_iterator(plt_rel_, plt_rel_count_), global_group, local_group)) {
- return false;
- }
- }
-#endif
-
-#if defined(__mips__)
- if (!mips_relocate_got(version_tracker, global_group, local_group)) {
+ if (!relocate(lookup_list)) {
return false;
}
-#endif
DEBUG("[ finished linking %s ]", get_realpath());