aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Ivanov <dimitry@google.com>2015-10-15 13:26:03 -0700
committerDmitriy Ivanov <dimitry@google.com>2015-10-16 10:42:16 -0700
commit77f91c6d99c25fce4fbf9704aa6f7232fb624ff4 (patch)
treed10dc214af563d8081bcf72af4ef9e5bdbeb614a
parent198d13e8c25e69f7dbda3f5e1a3258b13fe8db5d (diff)
downloadbionic-77f91c6d99c25fce4fbf9704aa6f7232fb624ff4.tar.gz
Fix R_AARCH64_ABS/PREL relocations
According to specification arm64 relocations should not use *reloc value. See http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf section 4.6.5 Bug: http://b/24977219 Bug: http://b/24527155 Change-Id: I3813255771f408ba957963c6ad56ed08e5110d83
-rw-r--r--linker/linker.cpp52
1 files changed, 24 insertions, 28 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 406cdee1a..50fbb0b79 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -2165,24 +2165,23 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
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);
+ 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);
+ reloc, sym_addr + addend, sym_name);
{
- const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
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 <= (reloc_value + (sym_addr + addend))) &&
- ((reloc_value + (sym_addr + addend)) <= max_value)) {
- *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr + addend);
+ 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",
- (reloc_value + (sym_addr + addend)), min_value, max_value);
+ sym_addr + addend, min_value, max_value);
return false;
}
}
@@ -2191,17 +2190,16 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
count_relocation(kRelocAbsolute);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "RELO ABS16 %16llx <- %16llx %s\n",
- reloc, (sym_addr + addend), sym_name);
+ reloc, sym_addr + addend, sym_name);
{
- const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
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 <= (reloc_value + (sym_addr + addend))) &&
- ((reloc_value + (sym_addr + addend)) <= max_value)) {
- *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr + addend);
+ 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",
- reloc_value + (sym_addr + addend), min_value, max_value);
+ sym_addr + addend, min_value, max_value);
return false;
}
}
@@ -2210,24 +2208,23 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
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;
+ 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);
+ reloc, sym_addr + addend, rel->r_offset, sym_name);
{
- const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
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 <= (reloc_value + ((sym_addr + addend) - rel->r_offset))) &&
- ((reloc_value + ((sym_addr + addend) - rel->r_offset)) <= max_value)) {
- *reinterpret_cast<ElfW(Addr)*>(reloc) += ((sym_addr + addend) - rel->r_offset);
+ 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",
- reloc_value + ((sym_addr + addend) - rel->r_offset), min_value, max_value);
+ sym_addr + addend - rel->r_offset, min_value, max_value);
return false;
}
}
@@ -2236,17 +2233,16 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
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);
+ reloc, sym_addr + addend, rel->r_offset, sym_name);
{
- const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
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 <= (reloc_value + ((sym_addr + addend) - rel->r_offset))) &&
- ((reloc_value + ((sym_addr + addend) - rel->r_offset)) <= max_value)) {
- *reinterpret_cast<ElfW(Addr)*>(reloc) += ((sym_addr + addend) - rel->r_offset);
+ 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",
- reloc_value + ((sym_addr + addend) - rel->r_offset), min_value, max_value);
+ sym_addr + addend - rel->r_offset, min_value, max_value);
return false;
}
}