summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/ARM
diff options
context:
space:
mode:
authorLeny Kholodov <lkholodov@accesssoftek.com>2015-04-22 11:47:53 +0000
committerLeny Kholodov <lkholodov@accesssoftek.com>2015-04-22 11:47:53 +0000
commit9e4292c0ecb1235c47b8394203a70f8a9ca18458 (patch)
tree94880c117f412b7f5f9c6b13f0b67ace71a13083 /lld/lib/ReaderWriter/ELF/ARM
parent0d49cf2645289cfad9a99b7c2e19cf7645770428 (diff)
downloadbcm5719-llvm-9e4292c0ecb1235c47b8394203a70f8a9ca18458.tar.gz
bcm5719-llvm-9e4292c0ecb1235c47b8394203a70f8a9ca18458.zip
[ARM] Replace branches to undefined weak functions with NOP
According to the code model (ARM, Thumb, Thumb2) this patch updates the b/bl/blx 0 instructions with NOP. test/elf/ARM/weak-branch.test has been added with tests for all available NOP (A1, T1, T2 encodings). Differential Revision: http://reviews.llvm.org/D8807 llvm-svn: 235498
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/ARM')
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
index b0dfac20776..74aed57ecf6 100644
--- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
+++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
@@ -510,6 +510,32 @@ static void relocR_ARM_LDR_PC_G2(uint8_t *location, uint64_t P, uint64_t S,
applyArmReloc(location, (uint32_t)result & mask, mask);
}
+/// \brief Fixup unresolved weak reference with NOP instruction
+static bool fixupUnresolvedWeakCall(uint8_t *location,
+ Reference::KindValue kindValue) {
+ //TODO: workaround for archs without NOP instruction
+ switch (kindValue) {
+ case R_ARM_THM_CALL:
+ case R_ARM_THM_JUMP24:
+ // Thumb32 NOP.W
+ write32le(location, 0x8000F3AF);
+ break;
+ case R_ARM_THM_JUMP11:
+ // Thumb16 NOP
+ write16le(location, 0xBF00);
+ break;
+ case R_ARM_CALL:
+ case R_ARM_JUMP24:
+ // A1 NOP<c>, save condition bits
+ applyArmReloc(location, 0x320F000, 0xFFFFFFF);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
std::error_code ARMTargetRelocationHandler::applyRelocation(
ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
const Reference &ref) const {
@@ -522,6 +548,19 @@ std::error_code ARMTargetRelocationHandler::applyRelocation(
return std::error_code();
assert(ref.kindArch() == Reference::KindArch::ARM);
+ // Fixup unresolved weak references
+ if (!target) {
+ bool isCallFixed = fixupUnresolvedWeakCall(loc, ref.kindValue());
+
+ if (isCallFixed) {
+ DEBUG(llvm::dbgs() << "\t\tFixup unresolved weak reference '";
+ llvm::dbgs() << ref.target()->name() << "'";
+ llvm::dbgs() << " at address: 0x" << Twine::utohexstr(reloc);
+ llvm::dbgs() << (isCallFixed ? "\n" : " isn't possible\n"));
+ return std::error_code();
+ }
+ }
+
// Calculate proper initial addend for the relocation
const Reference::Addend addend =
readAddend(loc, ref.kindValue()) + ref.addend();
OpenPOWER on IntegriCloud