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
This commit is contained in:
parent
2ab4e0f999
commit
9ef61a287a
1 changed files with 0 additions and 82 deletions
|
@ -3065,8 +3065,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
|||
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 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
|||
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.
|
||||
|
|
Loading…
Reference in a new issue