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_arm.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp13
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp1
-rw-r--r--lld/lib/ReaderWriter/MachO/StubsPass.cpp207
7 files changed, 114 insertions, 123 deletions
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
index e30dd4dede0..65a40802c54 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
@@ -998,9 +998,11 @@ void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *loc,
*loc32 = targetAddress - fixupAddress + ref.addend();
break;
case lazyPointer:
- case lazyImmediateLocation:
// do nothing
break;
+ case lazyImmediateLocation:
+ *loc32 = ref.addend();
+ break;
case invalid:
llvm_unreachable("invalid ARM Reference Kind");
break;
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
index c39e4c1cdaf..c4456a896aa 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
@@ -573,9 +573,11 @@ void ArchHandler_arm64::applyFixupFinal(const Reference &ref, uint8_t *loc,
*loc32 = (targetAddress - fixupAddress) + ref.addend();
return;
case lazyPointer:
- case lazyImmediateLocation:
// Do nothing
return;
+ case lazyImmediateLocation:
+ *loc32 = ref.addend();
+ return;
case invalid:
// Fall into llvm_unreachable().
break;
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
index c278042cf8d..a2b6067efa6 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
@@ -461,9 +461,11 @@ void ArchHandler_x86::applyFixupFinal(const Reference &ref, uint8_t *loc,
case modeCode:
case modeData:
case lazyPointer:
- case lazyImmediateLocation:
// do nothing
break;
+ case lazyImmediateLocation:
+ *loc32 = ref.addend();
+ break;
default:
llvm_unreachable("invalid x86 Reference Kind");
break;
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
index b0c47af8259..ccab82419f7 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
@@ -521,8 +521,10 @@ void ArchHandler_x86_64::applyFixupFinal(
*loc32 = fixupAddress - targetAddress + ref.addend();
return;
case lazyPointer:
+ // Do nothing
+ return;
case lazyImmediateLocation:
- // do nothing
+ *loc32 = ref.addend();
return;
case imageOffset:
case imageOffsetGot:
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
index 543b60fe8bc..102b185df52 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
@@ -125,6 +125,12 @@ private:
void append_uleb128(uint64_t value) {
llvm::encodeULEB128(value, _ostream);
}
+ void append_uleb128Fixed(uint64_t value, unsigned byteCount) {
+ unsigned min = llvm::getULEB128Size(value);
+ assert(min <= byteCount);
+ unsigned pad = byteCount - min;
+ llvm::encodeULEB128(value, _ostream, pad);
+ }
void append_sleb128(int64_t value) {
llvm::encodeSLEB128(value, _ostream);
}
@@ -999,6 +1005,7 @@ void MachOFileLayout::buildRebaseInfo() {
void MachOFileLayout::buildBindInfo() {
// TODO: compress bind info.
+ uint64_t lastAddend = 0;
for (const BindLocation& entry : _file.bindingInfo) {
_bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
_bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
@@ -1007,9 +1014,10 @@ void MachOFileLayout::buildBindInfo() {
_bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
_bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
_bindingInfo.append_string(entry.symbolName);
- if (entry.addend != 0) {
+ if (entry.addend != lastAddend) {
_bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
_bindingInfo.append_sleb128(entry.addend);
+ lastAddend = entry.addend;
}
_bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
}
@@ -1022,11 +1030,12 @@ void MachOFileLayout::buildLazyBindInfo() {
_lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
_lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
| entry.segIndex);
- _lazyBindingInfo.append_uleb128(entry.segOffset);
+ _lazyBindingInfo.append_uleb128Fixed(entry.segOffset, 5);
_lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
_lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
_lazyBindingInfo.append_string(entry.symbolName);
_lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
+ _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
}
_lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
_lazyBindingInfo.align(_is64 ? 8 : 4);
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index 6d0236bcc91..8333d099ccc 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -244,6 +244,7 @@ SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
switch (atomType) {
case DefinedAtom::typeCode:
case DefinedAtom::typeStub:
+ case DefinedAtom::typeStubHelper:
sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
break;
default:
diff --git a/lld/lib/ReaderWriter/MachO/StubsPass.cpp b/lld/lib/ReaderWriter/MachO/StubsPass.cpp
index 6f58b9954f9..38af5597618 100644
--- a/lld/lib/ReaderWriter/MachO/StubsPass.cpp
+++ b/lld/lib/ReaderWriter/MachO/StubsPass.cpp
@@ -24,6 +24,7 @@
#include "lld/Core/Simple.h"
#include "lld/ReaderWriter/MachOLinkingContext.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
namespace lld {
@@ -107,7 +108,7 @@ private:
class StubAtom : public SimpleDefinedAtom {
public:
StubAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
- : SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
+ : SimpleDefinedAtom(file), _stubInfo(stubInfo){ }
ContentType contentType() const override {
return DefinedAtom::typeStub;
@@ -205,14 +206,8 @@ private:
class StubsPass : public Pass {
public:
StubsPass(const MachOLinkingContext &context)
- : _context(context)
- , _archHandler(_context.archHandler())
- , _stubInfo(_archHandler.stubInfo())
- , _file("<mach-o Stubs pass>")
- , _helperCommonAtom(nullptr)
- , _helperCacheNLPAtom(nullptr)
- , _helperBinderNLPAtom(nullptr) {
- }
+ : _context(context), _archHandler(_context.archHandler()),
+ _stubInfo(_archHandler.stubInfo()), _file("<mach-o Stubs pass>") { }
void perform(std::unique_ptr<MutableFile> &mergedFile) override {
@@ -230,7 +225,7 @@ public:
assert(target != nullptr);
if (isa<SharedLibraryAtom>(target)) {
// Calls to shared libraries go through stubs.
- replaceCalleeWithStub(target, ref);
+ _targetToUses[target].push_back(ref);
continue;
}
const DefinedAtom *defTarget = dyn_cast<DefinedAtom>(target);
@@ -238,47 +233,93 @@ public:
// Calls to interposable functions in same linkage unit must also go
// through a stub.
assert(defTarget->scope() != DefinedAtom::scopeTranslationUnit);
- replaceCalleeWithStub(target, ref);
+ _targetToUses[target].push_back(ref);
}
}
}
+
// Exit early if no stubs needed.
- if (_targetToStub.empty())
+ if (_targetToUses.empty())
return;
-
+
+ // First add help-common and GOT slots used by lazy binding.
+ SimpleDefinedAtom *helperCommonAtom =
+ new (_file.allocator()) StubHelperCommonAtom(_file, _stubInfo);
+ SimpleDefinedAtom *helperCacheNLPAtom =
+ new (_file.allocator()) NonLazyPointerAtom(_file, _context.is64Bit());
+ SimpleDefinedAtom *helperBinderNLPAtom =
+ new (_file.allocator()) NonLazyPointerAtom(_file, _context.is64Bit());
+ addReference(helperCommonAtom, _stubInfo.stubHelperCommonReferenceToCache,
+ helperCacheNLPAtom);
+ addOptReference(
+ helperCommonAtom, _stubInfo.stubHelperCommonReferenceToCache,
+ _stubInfo.optStubHelperCommonReferenceToCache, helperCacheNLPAtom);
+ addReference(helperCommonAtom, _stubInfo.stubHelperCommonReferenceToBinder,
+ helperBinderNLPAtom);
+ addOptReference(
+ helperCommonAtom, _stubInfo.stubHelperCommonReferenceToBinder,
+ _stubInfo.optStubHelperCommonReferenceToBinder, helperBinderNLPAtom);
+ mergedFile->addAtom(*helperCommonAtom);
+ mergedFile->addAtom(*helperBinderNLPAtom);
+ mergedFile->addAtom(*helperCacheNLPAtom);
+
// Add reference to dyld_stub_binder in libSystem.dylib
- if (_helperBinderNLPAtom) {
- bool found = false;
- for (const SharedLibraryAtom *atom : mergedFile->sharedLibrary()) {
- if (atom->name().equals(_stubInfo.binderSymbolName)) {
- addReference(_helperBinderNLPAtom,
- _stubInfo.nonLazyPointerReferenceToBinder, atom);
- found = true;
- break;
- }
+ bool binderFound = false;
+ for (const SharedLibraryAtom *atom : mergedFile->sharedLibrary()) {
+ if (atom->name().equals(_stubInfo.binderSymbolName)) {
+ addReference(helperBinderNLPAtom,
+ _stubInfo.nonLazyPointerReferenceToBinder, atom);
+ binderFound = true;
+ break;
}
- assert(found && "dyld_stub_binder not found");
}
-
- // Add all stubs to master file.
- for (auto it : _targetToStub) {
- mergedFile->addAtom(*it.second);
- }
- // Add helper code atoms.
- mergedFile->addAtom(*_helperCommonAtom);
- for (const DefinedAtom *lp : _stubHelperAtoms) {
- mergedFile->addAtom(*lp);
- }
- // Add GOT slots used for lazy binding.
- mergedFile->addAtom(*_helperBinderNLPAtom);
- mergedFile->addAtom(*_helperCacheNLPAtom);
- // Add all lazy pointers to master file.
- for (const DefinedAtom *lp : _lazyPointers) {
+ assert(binderFound && "dyld_stub_binder not found");
+
+ // Sort targets by name, so stubs and lazy pointers are consistent
+ std::vector<const Atom *> targetsNeedingStubs;
+ for (auto it : _targetToUses)
+ targetsNeedingStubs.push_back(it.first);
+ std::sort(targetsNeedingStubs.begin(), targetsNeedingStubs.end(),
+ [](const Atom * left, const Atom * right) {
+ return (left->name().compare(right->name()) < 0);
+ });
+
+ // Make and append stubs, lazy pointers, and helpers in alphabetical order.
+ unsigned lazyOffset = 0;
+ for (const Atom *target : targetsNeedingStubs) {
+ StubAtom *stub = new (_file.allocator()) StubAtom(_file, _stubInfo);
+ LazyPointerAtom *lp =
+ new (_file.allocator()) LazyPointerAtom(_file, _context.is64Bit());
+ StubHelperAtom *helper =
+ new (_file.allocator()) StubHelperAtom(_file, _stubInfo);
+
+ addReference(stub, _stubInfo.stubReferenceToLP, lp);
+ addOptReference(stub, _stubInfo.stubReferenceToLP,
+ _stubInfo.optStubReferenceToLP, lp);
+ addReference(lp, _stubInfo.lazyPointerReferenceToHelper, helper);
+ addReference(lp, _stubInfo.lazyPointerReferenceToFinal, target);
+ addReference(helper, _stubInfo.stubHelperReferenceToImm, helper);
+ addReferenceAddend(helper, _stubInfo.stubHelperReferenceToImm, helper,
+ lazyOffset);
+ addReference(helper, _stubInfo.stubHelperReferenceToHelperCommon,
+ helperCommonAtom);
+
+ mergedFile->addAtom(*stub);
mergedFile->addAtom(*lp);
+ mergedFile->addAtom(*helper);
+
+ // Update each reference to use stub.
+ for (const Reference *ref : _targetToUses[target]) {
+ assert(ref->target() == target);
+ // Switch call site to reference stub atom instead.
+ const_cast<Reference *>(ref)->setTarget(stub);
+ }
+
+ // Calculate new offset
+ lazyOffset += target->name().size() + 12;
}
}
-
private:
bool noTextRelocs() {
@@ -288,51 +329,6 @@ private:
bool isCallSite(const Reference &ref) {
return _archHandler.isCallSite(ref);
}
-
- void replaceCalleeWithStub(const Atom *target, const Reference *ref) {
- // Make file-format specific stub and other support atoms.
- const DefinedAtom *stub = this->getStub(*target);
- assert(stub != nullptr);
- // Switch call site to reference stub atom instead.
- const_cast<Reference *>(ref)->setTarget(stub);
- }
-
- const DefinedAtom* getStub(const Atom& target) {
- auto pos = _targetToStub.find(&target);
- if ( pos != _targetToStub.end() ) {
- // Reuse an existing stub.
- assert(pos->second != nullptr);
- return pos->second;
- }
- else {
- // There is no existing stub, so create a new one.
- return this->makeStub(target);
- }
- }
-
- const DefinedAtom* makeStub(const Atom &target) {
- SimpleDefinedAtom* stub = new (_file.allocator())
- StubAtom(_file, _stubInfo);
- SimpleDefinedAtom* lp = new (_file.allocator())
- LazyPointerAtom(_file, _context.is64Bit());
- SimpleDefinedAtom* helper = new (_file.allocator())
- StubHelperAtom(_file, _stubInfo);
-
- addReference(stub, _stubInfo.stubReferenceToLP, lp);
- addOptReference(stub, _stubInfo.stubReferenceToLP,
- _stubInfo.optStubReferenceToLP, lp);
- addReference(lp, _stubInfo.lazyPointerReferenceToHelper, helper);
- addReference(lp, _stubInfo.lazyPointerReferenceToFinal, &target);
- addReference(helper, _stubInfo.stubHelperReferenceToImm, helper);
- addReference(helper, _stubInfo.stubHelperReferenceToHelperCommon,
- helperCommon());
-
- _stubHelperAtoms.push_back(helper);
- _targetToStub[&target] = stub;
- _lazyPointers.push_back(lp);
-
- return stub;
- }
void addReference(SimpleDefinedAtom* atom,
const ArchHandler::ReferenceInfo &refInfo,
@@ -342,6 +338,13 @@ private:
target, refInfo.addend);
}
+ void addReferenceAddend(SimpleDefinedAtom *atom,
+ const ArchHandler::ReferenceInfo &refInfo,
+ const lld::Atom *target, uint64_t addend) {
+ atom->addReference(Reference::KindNamespace::mach_o, refInfo.arch,
+ refInfo.kind, refInfo.offset, target, addend);
+ }
+
void addOptReference(SimpleDefinedAtom* atom,
const ArchHandler::ReferenceInfo &refInfo,
const ArchHandler::OptionalRefInfo &optRef,
@@ -353,44 +356,14 @@ private:
target, optRef.addend);
}
- const DefinedAtom* helperCommon() {
- if ( !_helperCommonAtom ) {
- // Lazily create common helper code and data.
- _helperCommonAtom = new (_file.allocator())
- StubHelperCommonAtom(_file, _stubInfo);
- _helperCacheNLPAtom = new (_file.allocator())
- NonLazyPointerAtom(_file, _context.is64Bit());
- _helperBinderNLPAtom = new (_file.allocator())
- NonLazyPointerAtom(_file, _context.is64Bit());
- addReference(_helperCommonAtom,
- _stubInfo.stubHelperCommonReferenceToCache,
- _helperCacheNLPAtom);
- addOptReference(_helperCommonAtom,
- _stubInfo.stubHelperCommonReferenceToCache,
- _stubInfo.optStubHelperCommonReferenceToCache,
- _helperCacheNLPAtom);
- addReference(_helperCommonAtom,
- _stubInfo.stubHelperCommonReferenceToBinder,
- _helperBinderNLPAtom);
- addOptReference(_helperCommonAtom,
- _stubInfo.stubHelperCommonReferenceToBinder,
- _stubInfo.optStubHelperCommonReferenceToBinder,
- _helperBinderNLPAtom);
- }
- return _helperCommonAtom;
- }
-
+ typedef llvm::DenseMap<const Atom*,
+ llvm::SmallVector<const Reference *, 8>> TargetToUses;
const MachOLinkingContext &_context;
mach_o::ArchHandler &_archHandler;
const ArchHandler::StubInfo &_stubInfo;
MachOFile _file;
- llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub;
- std::vector<const DefinedAtom*> _lazyPointers;
- std::vector<const DefinedAtom*> _stubHelperAtoms;
- SimpleDefinedAtom *_helperCommonAtom;
- SimpleDefinedAtom *_helperCacheNLPAtom;
- SimpleDefinedAtom *_helperBinderNLPAtom;
+ TargetToUses _targetToUses;
};
OpenPOWER on IntegriCloud