summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp')
-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