diff options
| author | Leny Kholodov <lkholodov@accesssoftek.com> | 2015-04-22 11:47:53 +0000 |
|---|---|---|
| committer | Leny Kholodov <lkholodov@accesssoftek.com> | 2015-04-22 11:47:53 +0000 |
| commit | 9e4292c0ecb1235c47b8394203a70f8a9ca18458 (patch) | |
| tree | 94880c117f412b7f5f9c6b13f0b67ace71a13083 /lld/lib/ReaderWriter/ELF/ARM | |
| parent | 0d49cf2645289cfad9a99b7c2e19cf7645770428 (diff) | |
| download | bcm5719-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.cpp | 39 |
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(); |

