summaryrefslogtreecommitdiff
path: root/linker/linker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r--linker/linker.cpp193
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())) {