diff options
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r-- | linker/linker.cpp | 603 |
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()); |