diff options
Diffstat (limited to 'lld/MachO/Writer.cpp')
| -rw-r--r-- | lld/MachO/Writer.cpp | 122 |
1 files changed, 66 insertions, 56 deletions
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index 7fad9f5564ce..3c44a60f4be2 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -780,70 +780,80 @@ template <class LP> void Writer::createLoadCommands() { if (config->outputType == MH_EXECUTE) in.header->addLoadCommand(make<LCMain>()); + // See ld64's OutputFile::buildDylibOrdinalMapping for the corresponding + // library ordinal computation code in ld64. int64_t dylibOrdinal = 1; DenseMap<StringRef, int64_t> ordinalForInstallName; - for (InputFile *file : inputFiles) { - if (auto *dylibFile = dyn_cast<DylibFile>(file)) { - if (dylibFile->isBundleLoader) { - dylibFile->ordinal = BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE; - // Shortcut since bundle-loader does not re-export the symbols. - dylibFile->reexport = false; - continue; - } + std::vector<DylibFile *> dylibFiles; + for (InputFile *file : inputFiles) { + if (auto *dylibFile = dyn_cast<DylibFile>(file)) + dylibFiles.push_back(dylibFile); + } + for (size_t i = 0; i < dylibFiles.size(); ++i) + dylibFiles.insert(dylibFiles.end(), dylibFiles[i]->extraDylibs.begin(), + dylibFiles[i]->extraDylibs.end()); - // Don't emit load commands for a dylib that is not referenced if: - // - it was added implicitly (via a reexport, an LC_LOAD_DYLINKER -- - // if it's on the linker command line, it's explicit) - // - or it's marked MH_DEAD_STRIPPABLE_DYLIB - // - or the flag -dead_strip_dylibs is used - // FIXME: `isReferenced()` is currently computed before dead code - // stripping, so references from dead code keep a dylib alive. This - // matches ld64, but it's something we should do better. - if (!dylibFile->isReferenced() && !dylibFile->forceNeeded && - (!dylibFile->explicitlyLinked || dylibFile->deadStrippable || - config->deadStripDylibs)) - continue; + for (DylibFile *dylibFile : dylibFiles) { + if (dylibFile->isBundleLoader) { + dylibFile->ordinal = BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE; + // Shortcut since bundle-loader does not re-export the symbols. - // Several DylibFiles can have the same installName. Only emit a single - // load command for that installName and give all these DylibFiles the - // same ordinal. - // This can happen in several cases: - // - a new framework could change its installName to an older - // framework name via an $ld$ symbol depending on platform_version - // - symlinks (for example, libpthread.tbd is a symlink to libSystem.tbd; - // Foo.framework/Foo.tbd is usually a symlink to - // Foo.framework/Versions/Current/Foo.tbd, where - // Foo.framework/Versions/Current is usually a symlink to - // Foo.framework/Versions/A) - // - a framework can be linked both explicitly on the linker - // command line and implicitly as a reexport from a different - // framework. The re-export will usually point to the tbd file - // in Foo.framework/Versions/A/Foo.tbd, while the explicit link will - // usually find Foo.framework/Foo.tbd. These are usually symlinks, - // but in a --reproduce archive they will be identical but distinct - // files. - // In the first case, *semantically distinct* DylibFiles will have the - // same installName. - int64_t &ordinal = ordinalForInstallName[dylibFile->installName]; - if (ordinal) { - dylibFile->ordinal = ordinal; - continue; - } + dylibFile->reexport = false; + continue; + } - ordinal = dylibFile->ordinal = dylibOrdinal++; - LoadCommandType lcType = - dylibFile->forceWeakImport || dylibFile->refState == RefState::Weak - ? LC_LOAD_WEAK_DYLIB - : LC_LOAD_DYLIB; - in.header->addLoadCommand(make<LCDylib>(lcType, dylibFile->installName, - dylibFile->compatibilityVersion, - dylibFile->currentVersion)); + // Don't emit load commands for a dylib that is not referenced if: + // - it was added implicitly (via a reexport, an LC_LOAD_DYLINKER -- + // if it's on the linker command line, it's explicit) + // - or it's marked MH_DEAD_STRIPPABLE_DYLIB + // - or the flag -dead_strip_dylibs is used + // FIXME: `isReferenced()` is currently computed before dead code + // stripping, so references from dead code keep a dylib alive. This + // matches ld64, but it's something we should do better. + if (!dylibFile->isReferenced() && !dylibFile->forceNeeded && + (!dylibFile->isExplicitlyLinked() || dylibFile->deadStrippable || + config->deadStripDylibs)) + continue; - if (dylibFile->reexport) - in.header->addLoadCommand( - make<LCDylib>(LC_REEXPORT_DYLIB, dylibFile->installName)); + // Several DylibFiles can have the same installName. Only emit a single + // load command for that installName and give all these DylibFiles the + // same ordinal. + // This can happen in several cases: + // - a new framework could change its installName to an older + // framework name via an $ld$ symbol depending on platform_version + // - symlinks (for example, libpthread.tbd is a symlink to libSystem.tbd; + // Foo.framework/Foo.tbd is usually a symlink to + // Foo.framework/Versions/Current/Foo.tbd, where + // Foo.framework/Versions/Current is usually a symlink to + // Foo.framework/Versions/A) + // - a framework can be linked both explicitly on the linker + // command line and implicitly as a reexport from a different + // framework. The re-export will usually point to the tbd file + // in Foo.framework/Versions/A/Foo.tbd, while the explicit link will + // usually find Foo.framework/Foo.tbd. These are usually symlinks, + // but in a --reproduce archive they will be identical but distinct + // files. + // In the first case, *semantically distinct* DylibFiles will have the + // same installName. + int64_t &ordinal = ordinalForInstallName[dylibFile->installName]; + if (ordinal) { + dylibFile->ordinal = ordinal; + continue; } + + ordinal = dylibFile->ordinal = dylibOrdinal++; + LoadCommandType lcType = + dylibFile->forceWeakImport || dylibFile->refState == RefState::Weak + ? LC_LOAD_WEAK_DYLIB + : LC_LOAD_DYLIB; + in.header->addLoadCommand(make<LCDylib>(lcType, dylibFile->installName, + dylibFile->compatibilityVersion, + dylibFile->currentVersion)); + + if (dylibFile->reexport) + in.header->addLoadCommand( + make<LCDylib>(LC_REEXPORT_DYLIB, dylibFile->installName)); } if (functionStartsSection) |
