summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter')
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler.h6
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp78
-rw-r--r--lld/lib/ReaderWriter/MachO/File.h10
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp6
5 files changed, 97 insertions, 7 deletions
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler.h b/lld/lib/ReaderWriter/MachO/ArchHandler.h
index b15462b4da6..6fb8211dcea 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler.h
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler.h
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "MachONormalizedFile.h"
+#include "Atoms.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Reference.h"
@@ -136,6 +137,11 @@ public:
FindAddressForAtom,
normalized::Relocations&) = 0;
+ /// Add arch-specific References.
+ virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
+
+ /// Only relevant for 32-bit arm archs.
+ virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
struct ReferenceInfo {
Reference::KindArch arch;
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
index 035313d3885..01d4343e9fa 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
@@ -69,6 +69,9 @@ public:
FindAddressForAtom,
normalized::Relocations &) override;
+ void addAdditionalReferences(MachODefinedAtom &atom) override;
+
+ bool isThumbFunction(const DefinedAtom &atom) override;
private:
static const Registry::KindStrings _sKindStrings[];
@@ -77,6 +80,9 @@ private:
enum : Reference::KindValue {
invalid, /// for error condition
+ modeThumbCode, /// Content starting at this offset is thumb.
+ modeArmCode, /// Content starting at this offset is arm.
+
// Kinds found in mach-o .o files:
thumb_b22, /// ex: bl _foo
thumb_movw, /// ex: movw r1, :lower16:_foo
@@ -115,12 +121,12 @@ private:
void applyFixupFinal(const Reference &ref, uint8_t *location,
uint64_t fixupAddress, uint64_t targetAddress,
- uint64_t inAtomAddress);
+ uint64_t inAtomAddress, bool &thumbMode);
void applyFixupRelocatable(const Reference &ref, uint8_t *location,
uint64_t fixupAddress,
uint64_t targetAddress,
- uint64_t inAtomAddress);
+ uint64_t inAtomAddress, bool &thumbMode);
const bool _swap;
};
@@ -135,6 +141,8 @@ ArchHandler_arm::ArchHandler_arm() :
ArchHandler_arm::~ArchHandler_arm() { }
const Registry::KindStrings ArchHandler_arm::_sKindStrings[] = {
+ LLD_KIND_STRING_ENTRY(modeThumbCode),
+ LLD_KIND_STRING_ENTRY(modeArmCode),
LLD_KIND_STRING_ENTRY(thumb_b22),
LLD_KIND_STRING_ENTRY(thumb_movw),
LLD_KIND_STRING_ENTRY(thumb_movt),
@@ -712,7 +720,8 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *location,
uint64_t fixupAddress,
uint64_t targetAddress,
- uint64_t inAtomAddress) {
+ uint64_t inAtomAddress,
+ bool &thumbMode) {
if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
return;
assert(ref.kindArch() == Reference::KindArch::ARM);
@@ -720,43 +729,59 @@ void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *location,
int32_t displacement;
uint16_t value16;
switch (ref.kindValue()) {
+ case modeThumbCode:
+ thumbMode = true;
+ break;
+ case modeArmCode:
+ thumbMode = false;
+ break;
case thumb_b22:
+ assert(thumbMode);
displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
write32(*loc32, _swap, setDisplacementInThumbBranch(*loc32, displacement));
break;
case thumb_movw:
+ assert(thumbMode);
value16 = (targetAddress + ref.addend()) & 0xFFFF;
write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
break;
case thumb_movt:
+ assert(thumbMode);
value16 = (targetAddress + ref.addend()) >> 16;
write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
break;
case thumb_movw_funcRel:
+ assert(thumbMode);
value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
break;
case thumb_movt_funcRel:
+ assert(thumbMode);
value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
break;
case arm_b24:
+ assert(!thumbMode);
displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
*loc32 = setDisplacementInArmBranch(*loc32, displacement);
break;
case arm_movw:
+ assert(!thumbMode);
value16 = (targetAddress + ref.addend()) & 0xFFFF;
write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
break;
case arm_movt:
+ assert(!thumbMode);
value16 = (targetAddress + ref.addend()) >> 16;
write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
break;
case arm_movw_funcRel:
+ assert(!thumbMode);
value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
break;
case arm_movt_funcRel:
+ assert(!thumbMode);
value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
break;
@@ -783,6 +808,7 @@ void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom,
// Copy raw bytes.
memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
// Apply fix-ups.
+ bool thumbMode = false;
for (const Reference *ref : atom) {
uint32_t offset = ref->offsetInAtom();
const Atom *target = ref->target();
@@ -794,11 +820,11 @@ void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom,
if (relocatable) {
applyFixupRelocatable(*ref, &atomContentBuffer[offset],
fixupAddress, targetAddress,
- atomAddress);
+ atomAddress, thumbMode);
} else {
applyFixupFinal(*ref, &atomContentBuffer[offset],
fixupAddress, targetAddress,
- atomAddress);
+ atomAddress, thumbMode);
}
}
}
@@ -829,13 +855,21 @@ void ArchHandler_arm::applyFixupRelocatable(const Reference &ref,
uint8_t *location,
uint64_t fixupAddress,
uint64_t targetAddress,
- uint64_t inAtomAddress) {
+ uint64_t inAtomAddress,
+ bool &thumbMode) {
bool useExternalReloc = useExternalRelocationTo(*ref.target());
int32_t *loc32 = reinterpret_cast<int32_t *>(location);
int32_t displacement;
uint16_t value16;
switch (ref.kindValue()) {
+ case modeThumbCode:
+ thumbMode = true;
+ break;
+ case modeArmCode:
+ thumbMode = false;
+ break;
case thumb_b22:
+ assert(thumbMode);
if (useExternalReloc)
displacement = (ref.addend() - (fixupAddress + 4));
else
@@ -843,6 +877,7 @@ void ArchHandler_arm::applyFixupRelocatable(const Reference &ref,
write32(*loc32, _swap, setDisplacementInThumbBranch(*loc32, displacement));
break;
case thumb_movw:
+ assert(thumbMode);
if (useExternalReloc)
value16 = ref.addend() & 0xFFFF;
else
@@ -850,6 +885,7 @@ void ArchHandler_arm::applyFixupRelocatable(const Reference &ref,
write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
break;
case thumb_movt:
+ assert(thumbMode);
if (useExternalReloc)
value16 = ref.addend() >> 16;
else
@@ -857,14 +893,17 @@ void ArchHandler_arm::applyFixupRelocatable(const Reference &ref,
write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
break;
case thumb_movw_funcRel:
+ assert(thumbMode);
value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
break;
case thumb_movt_funcRel:
+ assert(thumbMode);
value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
break;
case arm_b24:
+ assert(!thumbMode);
if (useExternalReloc)
displacement = (ref.addend() - (fixupAddress + 8));
else
@@ -872,6 +911,7 @@ void ArchHandler_arm::applyFixupRelocatable(const Reference &ref,
write32(*loc32, _swap, setDisplacementInArmBranch(*loc32, displacement));
break;
case arm_movw:
+ assert(!thumbMode);
if (useExternalReloc)
value16 = ref.addend() & 0xFFFF;
else
@@ -879,6 +919,7 @@ void ArchHandler_arm::applyFixupRelocatable(const Reference &ref,
write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
break;
case arm_movt:
+ assert(!thumbMode);
if (useExternalReloc)
value16 = ref.addend() >> 16;
else
@@ -886,10 +927,12 @@ void ArchHandler_arm::applyFixupRelocatable(const Reference &ref,
write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
break;
case arm_movw_funcRel:
+ assert(!thumbMode);
value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
break;
case arm_movt_funcRel:
+ assert(!thumbMode);
value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
break;
@@ -926,6 +969,10 @@ void ArchHandler_arm::appendSectionRelocations(
uint32_t fromAtomAddress;
uint16_t other16;
switch (ref.kindValue()) {
+ case modeThumbCode:
+ case modeArmCode:
+ // Do nothing.
+ break;
case thumb_b22:
if (useExternalReloc) {
appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
@@ -1115,6 +1162,25 @@ void ArchHandler_arm::appendSectionRelocations(
}
}
+void ArchHandler_arm::addAdditionalReferences(MachODefinedAtom &atom) {
+ if (atom.isThumb()) {
+ atom.addReference(0, modeThumbCode, &atom, 0, Reference::KindArch::ARM);
+ }
+}
+
+bool ArchHandler_arm::isThumbFunction(const DefinedAtom &atom) {
+ for (const Reference *ref : atom) {
+ if (ref->offsetInAtom() != 0)
+ return false;
+ if (ref->kindNamespace() != Reference::KindNamespace::mach_o)
+ continue;
+ assert(ref->kindArch() == Reference::KindArch::ARM);
+ if (ref->kindValue() == modeThumbCode)
+ return true;
+ }
+ return false;
+}
+
std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm() {
return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm());
}
diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h
index dffc14952b6..df9be71c18c 100644
--- a/lld/lib/ReaderWriter/MachO/File.h
+++ b/lld/lib/ReaderWriter/MachO/File.h
@@ -139,6 +139,16 @@ public:
return pos->second;
}
+ typedef std::function<void (MachODefinedAtom* atom)> DefinedAtomVisitor;
+
+ void eachDefinedAtom(DefinedAtomVisitor vistor) {
+ for (auto &sectAndAtoms : _sectionAtoms) {
+ for (auto &offAndAtom : sectAndAtoms.second) {
+ vistor(offAndAtom.atom);
+ }
+ }
+ }
+
llvm::BumpPtrAllocator &allocator() { return _allocator; }
private:
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index 9879e2d04ed..bedfe6d351c 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -617,6 +617,8 @@ uint16_t Util::descBits(const DefinedAtom* atom) {
}
if (atom->contentType() == lld::DefinedAtom::typeResolver)
desc |= N_SYMBOL_RESOLVER;
+ if (_archHandler.isThumbFunction(*atom))
+ desc |= N_ARM_THUMB_DEF;
return desc;
}
@@ -656,7 +658,7 @@ void Util::addSymbols(const lld::File &atomFile, NormalizedFile &file) {
sym.type = N_SECT;
sym.scope = scopeBits(atom);
sym.sect = sect->finalSectionIndex;
- sym.desc = 0;
+ sym.desc = descBits(atom);
sym.value = _atomToAddress[atom];
_atomToSymbolIndex[atom] = file.localSymbols.size();
file.localSymbols.push_back(sym);
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index ef6f49f7931..437c8d1281a 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -562,6 +562,7 @@ std::error_code convertRelocs(const Section &section,
handler.kindArch());
}
}
+
return std::error_code();
}
@@ -606,6 +607,11 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
return ec;
}
+ // Add additional arch-specific References
+ file->eachDefinedAtom([&](MachODefinedAtom* atom) -> void {
+ handler->addAdditionalReferences(*atom);
+ });
+
// Sort references in each atom to their canonical order.
for (const DefinedAtom* defAtom : file->defined()) {
reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();
OpenPOWER on IntegriCloud