diff options
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r-- | linker/linker.cpp | 193 |
1 files changed, 33 insertions, 160 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp index 9aa648016..dec575baf 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -204,7 +204,6 @@ static bool is_greylisted(android_namespace_t* ns, const char* name, const soinf "libsqlite.so", "libui.so", "libutils.so", - "libvorbisidec.so", nullptr }; @@ -2932,8 +2931,11 @@ static ElfW(Addr) get_addend(ElfW(Rela)* rela, ElfW(Addr) reloc_addr __unused) { } #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); @@ -3057,6 +3059,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r switch (type) { case R_GENERIC_JUMP_SLOT: + case R_GENERIC_ABSOLUTE: case R_GENERIC_GLOB_DAT: case R_GENERIC_RELATIVE: case R_GENERIC_IRELATIVE: @@ -3064,17 +3067,8 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r case R_GENERIC_TLS_DTPREL: case R_GENERIC_TLS_TPREL: case R_GENERIC_TLSDESC: -#if defined(__aarch64__) - case R_AARCH64_ABS64: - case R_AARCH64_ABS32: - case R_AARCH64_ABS16: -#elif defined(__x86_64__) +#if defined(__x86_64__) case R_X86_64_32: - case R_X86_64_64: -#elif defined(__arm__) - case R_ARM_ABS32: -#elif defined(__i386__) - case R_386_32: #endif /* * The sym_addr was initialized to be zero above, or the relocation @@ -3154,10 +3148,11 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend); break; + case R_GENERIC_ABSOLUTE: case R_GENERIC_GLOB_DAT: count_relocation(kRelocAbsolute); MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO GLOB_DAT %16p <- %16p %s\n", + 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); @@ -3203,6 +3198,17 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r *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); MARK(rel->r_offset); @@ -3297,121 +3303,14 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r break; #endif // defined(__aarch64__) -#if defined(__aarch64__) - case R_AARCH64_ABS64: - count_relocation(kRelocAbsolute); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO ABS64 %16llx <- %16llx %s\n", - reloc, sym_addr + addend, sym_name); - *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend; - break; - case R_AARCH64_ABS32: - count_relocation(kRelocAbsolute); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO ABS32 %16llx <- %16llx %s\n", - reloc, sym_addr + addend, sym_name); - { - const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN); - const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX); - if ((min_value <= (sym_addr + addend)) && - ((sym_addr + addend) <= max_value)) { - *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend; - } else { - DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", - sym_addr + addend, min_value, max_value); - return false; - } - } - break; - case R_AARCH64_ABS16: - count_relocation(kRelocAbsolute); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO ABS16 %16llx <- %16llx %s\n", - reloc, sym_addr + addend, sym_name); - { - const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN); - const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX); - if ((min_value <= (sym_addr + addend)) && - ((sym_addr + addend) <= max_value)) { - *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend); - } else { - DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", - sym_addr + addend, min_value, max_value); - return false; - } - } - break; - case R_AARCH64_PREL64: - count_relocation(kRelocRelative); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO REL64 %16llx <- %16llx - %16llx %s\n", - reloc, sym_addr + addend, rel->r_offset, sym_name); - *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset; - break; - case R_AARCH64_PREL32: - count_relocation(kRelocRelative); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO REL32 %16llx <- %16llx - %16llx %s\n", - reloc, sym_addr + addend, rel->r_offset, sym_name); - { - const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN); - const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX); - if ((min_value <= (sym_addr + addend - rel->r_offset)) && - ((sym_addr + addend - rel->r_offset) <= max_value)) { - *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset; - } else { - DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", - sym_addr + addend - rel->r_offset, min_value, max_value); - return false; - } - } - break; - case R_AARCH64_PREL16: - count_relocation(kRelocRelative); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO REL16 %16llx <- %16llx - %16llx %s\n", - reloc, sym_addr + addend, rel->r_offset, sym_name); - { - const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN); - const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX); - if ((min_value <= (sym_addr + addend - rel->r_offset)) && - ((sym_addr + addend - rel->r_offset) <= max_value)) { - *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset; - } else { - DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", - sym_addr + addend - rel->r_offset, min_value, max_value); - return false; - } - } - break; - - case R_AARCH64_COPY: - /* - * ET_EXEC is not supported so this should not happen. - * - * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf - * - * Section 4.6.11 "Dynamic relocations" - * R_AARCH64_COPY may only appear in executable objects where e_type is - * set to ET_EXEC. - */ - DL_ERR("%s R_AARCH64_COPY relocations are not supported", get_realpath()); - return false; -#elif defined(__x86_64__) +#if defined(__x86_64__) case R_X86_64_32: - count_relocation(kRelocRelative); + count_relocation(kRelocAbsolute); MARK(rel->r_offset); 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_64: - count_relocation(kRelocRelative); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO R_X86_64_64 %08zx <- +%08zx %s", static_cast<size_t>(reloc), - static_cast<size_t>(sym_addr), sym_name); - *reinterpret_cast<Elf64_Addr*>(reloc) = sym_addr + addend; - break; case R_X86_64_PC32: count_relocation(kRelocRelative); MARK(rel->r_offset); @@ -3420,39 +3319,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r 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(__arm__) - case R_ARM_ABS32: - count_relocation(kRelocAbsolute); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO ABS %08x <- %08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr; - break; - case R_ARM_REL32: - count_relocation(kRelocRelative); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO REL32 %08x <- %08x - %08x %s", - reloc, sym_addr, rel->r_offset, sym_name); - *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset; - break; - case R_ARM_COPY: - /* - * ET_EXEC is not supported so this should not happen. - * - * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf - * - * Section 4.6.1.10 "Dynamic relocations" - * R_ARM_COPY may only appear in executable objects where e_type is - * set to ET_EXEC. - */ - DL_ERR("%s R_ARM_COPY relocations are not supported", get_realpath()); - return false; #elif defined(__i386__) - case R_386_32: - count_relocation(kRelocRelative); - MARK(rel->r_offset); - TRACE_TYPE(RELO, "RELO R_386_32 %08x <- +%08x %s", reloc, sym_addr, sym_name); - *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr; - break; case R_386_PC32: count_relocation(kRelocRelative); MARK(rel->r_offset); @@ -4191,6 +4058,19 @@ static std::string get_ld_config_file_vndk_path() { return kLdConfigVndkLiteFilePath; } + // Use generated linker config if flag is set + // TODO(b/138920271) Do not check property once it is confirmed as stable + // TODO(b/139638519) This file should also cover legacy or vndk-lite config + if (android::base::GetProperty("ro.vndk.version", "") != "" && + android::base::GetBoolProperty("sys.linker.use_generated_config", true)) { + if (file_exists(kLdGeneratedConfigFilePath)) { + return kLdGeneratedConfigFilePath; + } else { + DL_WARN("Warning: failed to find generated linker configuration from \"%s\"", + kLdGeneratedConfigFilePath); + } + } + std::string ld_config_file_vndk = kLdConfigFilePath; size_t insert_pos = ld_config_file_vndk.find_last_of('.'); if (insert_pos == std::string::npos) { @@ -4210,13 +4090,6 @@ static std::string get_ld_config_file_path(const char* executable_path) { } #endif - // Use generated linker config if flag is set - // TODO(b/138920271) Do not check property once it is confirmed as stable - if (android::base::GetBoolProperty("sys.linker.use_generated_config", false) && - file_exists(kLdGeneratedConfigFilePath)) { - return kLdGeneratedConfigFilePath; - } - std::string path = get_ld_config_file_apex_path(executable_path); if (!path.empty()) { if (file_exists(path.c_str())) { |