diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -243,9 +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); @@ -349,10 +346,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 (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"); + } +} + 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.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -47,6 +47,7 @@ void scanSymbols(); void createOutputSections(); void createLoadCommands(); + void assignAddresses(); void assignAddresses(OutputSegment *); void openFile(); @@ -442,6 +443,42 @@ } // 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); @@ -793,6 +830,38 @@ } } +void Writer::assignAddresses() { + // dyld requires __LINKEDIT segment to always exist (even if empty). + OutputSegment *linkEditSegment = + getOrCreateOutputSegment(segment_names::linkEdit); + + // 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 + + // 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) { uint64_t pageSize = target->getPageSize(); addr = alignTo(addr, pageSize); @@ -845,47 +914,16 @@ } 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(); 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); - + assignAddresses(); openFile(); if (errorCount()) return;