diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -243,13 +243,6 @@ SmallVector contents; }; -// Whether a given symbol's address can only be resolved at runtime. -bool needsBinding(const Symbol *); - -// Add bindings for symbols that need weak or non-lazy bindings. -void addNonLazyBindingEntries(const Symbol *, const InputSection *, - uint64_t offset, int64_t addend = 0); - // The following sections implement lazy symbol binding -- very similar to the // PLT mechanism in ELF. // @@ -349,10 +342,6 @@ llvm::raw_svector_ostream os{contents}; }; -// Adds stubs and bindings where necessary (e.g. if the symbol is a -// DylibSymbol.) -void prepareBranchTarget(Symbol *); - // Stores a trie that describes the set of exported symbols. class ExportSection : public LinkEditSection { public: diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -207,6 +207,24 @@ flags = S_NON_LAZY_SYMBOL_POINTERS; } +void macho::addNonLazyBindingEntries(const Symbol *sym, + const InputSection *isec, uint64_t offset, + int64_t addend) { + if (const auto *dysym = dyn_cast(sym)) { + in.binding->addEntry(dysym, isec, offset, addend); + if (dysym->isWeakDef()) + in.weakBinding->addEntry(sym, isec, offset, addend); + } else if (const auto *defined = dyn_cast(sym)) { + in.rebase->addEntry(isec, offset); + if (defined->isExternalWeakDef()) + in.weakBinding->addEntry(sym, isec, offset, addend); + } else { + // Undefined symbols are filtered out in scanRelocations(); we should never + // get here + llvm_unreachable("cannot bind to an undefined symbol"); + } +} + void NonLazyPointerSectionBase::addEntry(Symbol *sym) { if (entries.insert(sym)) { assert(!sym->isInGot()); @@ -370,32 +388,6 @@ memcpy(buf, contents.data(), contents.size()); } -bool macho::needsBinding(const Symbol *sym) { - if (isa(sym)) - return true; - if (const auto *defined = dyn_cast(sym)) - return defined->isExternalWeakDef(); - return false; -} - -void macho::addNonLazyBindingEntries(const Symbol *sym, - const InputSection *isec, uint64_t offset, - int64_t addend) { - if (auto *dysym = dyn_cast(sym)) { - in.binding->addEntry(dysym, isec, offset, addend); - if (dysym->isWeakDef()) - in.weakBinding->addEntry(sym, isec, offset, addend); - } else if (auto *defined = dyn_cast(sym)) { - in.rebase->addEntry(isec, offset); - if (defined->isExternalWeakDef()) - in.weakBinding->addEntry(sym, isec, offset, addend); - } else { - // Undefined symbols are filtered out in scanRelocations(); we should never - // get here - llvm_unreachable("cannot bind to an undefined symbol"); - } -} - StubsSection::StubsSection() : SyntheticSection(segment_names::text, "__stubs") { flags = S_SYMBOL_STUBS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS; @@ -549,29 +541,6 @@ return opstreamOffset; } -void macho::prepareBranchTarget(Symbol *sym) { - if (auto *dysym = dyn_cast(sym)) { - if (in.stubs->addEntry(dysym)) { - if (sym->isWeakDef()) { - in.binding->addEntry(dysym, in.lazyPointers->isec, - sym->stubsIndex * WordSize); - in.weakBinding->addEntry(sym, in.lazyPointers->isec, - sym->stubsIndex * WordSize); - } else { - in.lazyBinding->addEntry(dysym); - } - } - } else if (auto *defined = dyn_cast(sym)) { - if (defined->isExternalWeakDef()) { - if (in.stubs->addEntry(sym)) { - in.rebase->addEntry(in.lazyPointers->isec, sym->stubsIndex * WordSize); - in.weakBinding->addEntry(sym, in.lazyPointers->isec, - sym->stubsIndex * WordSize); - } - } - } -} - ExportSection::ExportSection() : LinkEditSection(segment_names::linkEdit, section_names::export_) {} diff --git a/lld/MachO/Target.h b/lld/MachO/Target.h --- a/lld/MachO/Target.h +++ b/lld/MachO/Target.h @@ -67,11 +67,6 @@ return getRelocAttrs(type).hasAttr(bit); } - bool validateRelocationInfo(llvm::MemoryBufferRef, - const llvm::MachO::section_64 &sec, - llvm::MachO::relocation_info); - void prepareSymbolRelocation(Symbol *, const InputSection *, const Reloc &); - uint32_t cpuType; uint32_t cpuSubtype; diff --git a/lld/MachO/Writer.h b/lld/MachO/Writer.h --- a/lld/MachO/Writer.h +++ b/lld/MachO/Writer.h @@ -15,6 +15,8 @@ namespace macho { class OutputSection; +class InputSection; +class Symbol; class LoadCommand { public: @@ -27,6 +29,10 @@ void createSyntheticSections(); +// Add bindings for symbols that need weak or non-lazy bindings. +void addNonLazyBindingEntries(const Symbol *, const InputSection *, + uint64_t offset, int64_t addend = 0); + extern OutputSection *firstTLVDataSection; } // namespace macho diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -47,6 +47,8 @@ void scanSymbols(); void createOutputSections(); void createLoadCommands(); + void finalizeAddressses(); + void finalizeLinkEditSegment(); void assignAddresses(OutputSegment *); void openFile(); @@ -66,6 +68,7 @@ CodeSignatureSection *codeSignatureSection = nullptr; UnwindInfoSection *unwindInfoSection = nullptr; LCUuid *uuidCommand = nullptr; + OutputSegment *linkEditSegment = nullptr; }; // LC_DYLD_INFO_ONLY stores the offsets of symbol import/export information. @@ -442,6 +445,40 @@ } // namespace +// Adds stubs and bindings where necessary (e.g. if the symbol is a +// DylibSymbol.) +static void prepareBranchTarget(Symbol *sym) { + if (auto *dysym = dyn_cast(sym)) { + if (in.stubs->addEntry(dysym)) { + if (sym->isWeakDef()) { + in.binding->addEntry(dysym, in.lazyPointers->isec, + sym->stubsIndex * WordSize); + in.weakBinding->addEntry(sym, in.lazyPointers->isec, + sym->stubsIndex * WordSize); + } else { + in.lazyBinding->addEntry(dysym); + } + } + } else if (auto *defined = dyn_cast(sym)) { + if (defined->isExternalWeakDef()) { + if (in.stubs->addEntry(sym)) { + in.rebase->addEntry(in.lazyPointers->isec, sym->stubsIndex * WordSize); + in.weakBinding->addEntry(sym, in.lazyPointers->isec, + sym->stubsIndex * WordSize); + } + } + } +} + +// Can a symbol's address can only be resolved at runtime? +static bool needsBinding(const Symbol *sym) { + if (isa(sym)) + return true; + if (const auto *defined = dyn_cast(sym)) + return defined->isExternalWeakDef(); + return false; +} + static void prepareSymbolRelocation(lld::macho::Symbol *sym, const InputSection *isec, const Reloc &r) { const RelocAttrs &relocAttrs = target->getRelocAttrs(r.type); @@ -791,6 +828,39 @@ ssec->name); } } + + // dyld requires __LINKEDIT segment to always exist (even if empty). + linkEditSegment = getOrCreateOutputSegment(segment_names::linkEdit); +} + +void Writer::finalizeAddressses() { + // Ensure that segments (and the sections they contain) are allocated + // addresses in ascending order, which dyld requires. + // + // Note that at this point, __LINKEDIT sections are empty, but we need to + // determine addresses of other segments/sections before generating its + // contents. + for (OutputSegment *seg : outputSegments) + if (seg != linkEditSegment) + assignAddresses(seg); + + // FIXME(gkm): create branch-extension thunks here, then adjust addresses +} + +void Writer::finalizeLinkEditSegment() { + // Fill __LINKEDIT contents. + in.rebase->finalizeContents(); + in.binding->finalizeContents(); + in.weakBinding->finalizeContents(); + in.lazyBinding->finalizeContents(); + in.exports->finalizeContents(); + in.functionStarts->finalizeContents(); + symtabSection->finalizeContents(); + indirectSymtabSection->finalizeContents(); + + // Now that __LINKEDIT is filled out, do a proper calculation of its + // addresses and offsets. + assignAddresses(linkEditSegment); } void Writer::assignAddresses(OutputSegment *seg) { @@ -845,51 +915,20 @@ } void Writer::run() { - // dyld requires __LINKEDIT segment to always exist (even if empty). - OutputSegment *linkEditSegment = - getOrCreateOutputSegment(segment_names::linkEdit); - prepareBranchTarget(config->entry); scanRelocations(); if (in.stubHelper->isNeeded()) in.stubHelper->setup(); scanSymbols(); - - // Sort and assign sections to their respective segments. No more sections nor - // segments may be created after these methods run. createOutputSections(); + // No more sections nor segments are created beyond this point. sortSegmentsAndSections(); - createLoadCommands(); - - // Ensure that segments (and the sections they contain) are allocated - // addresses in ascending order, which dyld requires. - // - // Note that at this point, __LINKEDIT sections are empty, but we need to - // determine addresses of other segments/sections before generating its - // contents. - for (OutputSegment *seg : outputSegments) - if (seg != linkEditSegment) - assignAddresses(seg); - - // Fill __LINKEDIT contents. - in.rebase->finalizeContents(); - in.binding->finalizeContents(); - in.weakBinding->finalizeContents(); - in.lazyBinding->finalizeContents(); - in.exports->finalizeContents(); - in.functionStarts->finalizeContents(); - symtabSection->finalizeContents(); - indirectSymtabSection->finalizeContents(); - - // Now that __LINKEDIT is filled out, do a proper calculation of its - // addresses and offsets. - assignAddresses(linkEditSegment); - + finalizeAddressses(); + finalizeLinkEditSegment(); openFile(); if (errorCount()) return; - writeSections(); writeUuid(); writeCodeSignature();