Remove broken arm64 PREL/ABS relocations
Specifically, remove:
- R_AARCH64_ABS32
- R_AARCH64_ABS16
- R_AARCH64_PREL64
- R_AARCH64_PREL32
- R_AARCH64_PREL16
These relocations never currently appear in dynamic ELF files, and the
linker didn't handle them correctly. The AArch64 ELF ABI document
classifies them as "static relocations", which dynamic linkers don't need
to handle. (The document also classifies R_AARCH64_ABS64 as static,
though, and that relocation is common in DSOs. Perhaps static linkers
can't use R_AARCH64_GLOB_DAT to relocate data outside the GOT.)
Previously, for {ABS,PREL}{32,16}, Bionic always failed with an
out-of-range error. e.g. For {ABS,PREL}16, the value had to satisfy two
conditions:
- be at least (Elf64_Addr)INT16_MIN, i.e. 0xffff_ffff_ffff_8000
- be at most (Elf64_Addr)UINT16_MAX, i.e. 0xffff
The PREL relocations should have used sym_addr + addend - reloc, not
sym_addr + addend - rel->r_offset.
Bug: http://b/19197129
Test: bionic unit tests
Change-Id: I791da8ac471b3fb108cf77405c222f6e4bd34ae4
diff --git a/linker/linker.cpp b/linker/linker.cpp
index cee9c3b..2ea2665 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -3065,8 +3065,6 @@
case R_GENERIC_TLSDESC:
#if defined(__aarch64__)
case R_AARCH64_ABS64:
- case R_AARCH64_ABS32:
- case R_AARCH64_ABS16:
#elif defined(__x86_64__)
case R_X86_64_32:
case R_X86_64_64:
@@ -3304,86 +3302,6 @@
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.