summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/include/lld/Driver/DarwinInputGraph.h17
-rw-r--r--lld/include/lld/ReaderWriter/MachOLinkingContext.h25
-rw-r--r--lld/include/lld/ReaderWriter/Reader.h2
-rw-r--r--lld/lib/Driver/DarwinLdDriver.cpp13
-rw-r--r--lld/lib/Driver/DarwinLdOptions.td2
-rw-r--r--lld/lib/ReaderWriter/MachO/Atoms.h2
-rw-r--r--lld/lib/ReaderWriter/MachO/File.h90
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp93
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp45
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp14
-rw-r--r--lld/test/mach-o/re-exported-dylib-ordinal.yaml105
11 files changed, 351 insertions, 57 deletions
diff --git a/lld/include/lld/Driver/DarwinInputGraph.h b/lld/include/lld/Driver/DarwinInputGraph.h
index 9b097bd47b7..be4635b01c5 100644
--- a/lld/include/lld/Driver/DarwinInputGraph.h
+++ b/lld/include/lld/Driver/DarwinInputGraph.h
@@ -19,6 +19,7 @@
#include "lld/Core/InputGraph.h"
#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/SharedLibraryFile.h"
#include "lld/ReaderWriter/MachOLinkingContext.h"
#include <map>
@@ -28,7 +29,7 @@ namespace lld {
/// \brief Represents a MachO File
class MachOFileNode : public FileNode {
public:
- MachOFileNode(MachOLinkingContext &, StringRef path, bool isWholeArchive)
+ MachOFileNode(StringRef path, bool isWholeArchive)
: FileNode(path), _isWholeArchive(isWholeArchive) {}
/// \brief Parse the input file to lld::File.
@@ -44,8 +45,8 @@ public:
if (ctx.logInputFiles())
diagnostics << *filePath << "\n";
+ std::vector<std::unique_ptr<File>> parsedFiles;
if (_isWholeArchive) {
- std::vector<std::unique_ptr<File>> parsedFiles;
std::error_code ec = ctx.registry().parseFile(_buffer, parsedFiles);
if (ec)
return ec;
@@ -62,7 +63,17 @@ public:
return std::error_code();
}
}
- return ctx.registry().parseFile(_buffer, _files);
+ if (std::error_code ec = ctx.registry().parseFile(_buffer, parsedFiles))
+ return ec;
+ for (std::unique_ptr<File> &pf : parsedFiles) {
+ // If a dylib was parsed, inform LinkingContext about it.
+ if (SharedLibraryFile *shl = dyn_cast<SharedLibraryFile>(pf.get())) {
+ MachOLinkingContext *mctx = (MachOLinkingContext*)(&ctx);
+ mctx->registerDylib(reinterpret_cast<mach_o::MachODylibFile*>(shl));
+ }
+ _files.push_back(std::move(pf));
+ }
+ return std::error_code();
}
/// \brief Return the file that has to be processed by the resolver
diff --git a/lld/include/lld/ReaderWriter/MachOLinkingContext.h b/lld/include/lld/ReaderWriter/MachOLinkingContext.h
index fe13aab7dbc..65cfc9eff06 100644
--- a/lld/include/lld/ReaderWriter/MachOLinkingContext.h
+++ b/lld/include/lld/ReaderWriter/MachOLinkingContext.h
@@ -14,6 +14,7 @@
#include "lld/ReaderWriter/Reader.h"
#include "lld/ReaderWriter/Writer.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MachO.h"
@@ -25,6 +26,7 @@ namespace lld {
namespace mach_o {
class ArchHandler;
+class MachODylibFile;
}
class MachOLinkingContext : public LinkingContext {
@@ -56,6 +58,7 @@ public:
void addPasses(PassManager &pm) override;
bool validateImpl(raw_ostream &diagnostics) override;
+ bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) const override;
uint32_t getCPUType() const;
uint32_t getCPUSubType() const;
@@ -82,6 +85,8 @@ public:
bool printAtoms() const { return _printAtoms; }
bool testingLibResolution() const { return _testingLibResolution; }
const StringRefVector &searchDirs() const { return _searchDirs; }
+ void addSysLibRoot(StringRef sysPath) { _syslibRoots.push_back(sysPath); }
+ const StringRefVector &sysLibRoots() const { return _syslibRoots; }
/// \brief Checks whether a given path on the filesystem exists.
///
@@ -96,9 +101,7 @@ public:
/// The set of paths added consists of approximately all syslibroot-prepended
/// versions of libPath that exist, or the original libPath if there are none
/// for whatever reason. With various edge-cases for compatibility.
- void addModifiedSearchDir(StringRef libPath,
- const StringRefVector &syslibRoots,
- bool isSystemPath = false);
+ void addModifiedSearchDir(StringRef libPath, bool isSystemPath = false);
/// \brief Determine whether -lFoo can be resolve within the given path, and
/// return the filename if so.
@@ -177,12 +180,20 @@ public:
/// Stub creation Pass should be run.
bool needsStubsPass() const;
- // GOT createion Pass should be run.
+ // GOT creation Pass should be run.
bool needsGOTPass() const;
/// Magic symbol name stubs will need to help lazy bind.
StringRef binderSymbolName() const;
+ /// Used to keep track of direct and indirect dylibs.
+ void registerDylib(mach_o::MachODylibFile *dylib);
+
+ /// Used to find indirect dylibs. Instantiates a MachODylibFile if one
+ /// has not already been made for the requested dylib. Uses -L and -F
+ /// search paths to allow indirect dylibs to be overridden.
+ mach_o::MachODylibFile* findIndirectDylib(StringRef path) const;
+
static Arch archFromCpuType(uint32_t cputype, uint32_t cpusubtype);
static Arch archFromName(StringRef archName);
static StringRef nameFromArch(Arch arch);
@@ -198,6 +209,8 @@ public:
private:
Writer &writer() const override;
+ mach_o::MachODylibFile* loadIndirectDylib(StringRef path) const;
+
struct ArchInfo {
StringRef archName;
@@ -217,6 +230,7 @@ private:
std::set<StringRef> _existingPaths; // For testing only.
StringRefVector _searchDirs;
+ StringRefVector _syslibRoots;
HeaderFileType _outputMachOType; // e.g MH_EXECUTE
bool _outputMachOTypeStatic; // Disambiguate static vs dynamic prog
bool _doNothing; // for -help and -v which just print info
@@ -235,6 +249,9 @@ private:
mutable std::unique_ptr<mach_o::ArchHandler> _archHandler;
mutable std::unique_ptr<Writer> _writer;
std::vector<SectionAlign> _sectAligns;
+ llvm::StringMap<mach_o::MachODylibFile*> _pathToDylibMap;
+ std::set<mach_o::MachODylibFile*> _allDylibs;
+ mutable std::vector<std::unique_ptr<class MachOFileNode>> _indirectDylibs;
};
} // end namespace lld
diff --git a/lld/include/lld/ReaderWriter/Reader.h b/lld/include/lld/ReaderWriter/Reader.h
index 694b302788e..97c89627ec6 100644
--- a/lld/include/lld/ReaderWriter/Reader.h
+++ b/lld/include/lld/ReaderWriter/Reader.h
@@ -123,7 +123,7 @@ public:
void addSupportNativeObjects();
void addSupportCOFFObjects(PECOFFLinkingContext &);
void addSupportCOFFImportLibraries();
- void addSupportMachOObjects(const MachOLinkingContext &);
+ void addSupportMachOObjects(MachOLinkingContext &);
void addSupportELFObjects(bool atomizeStrings, TargetHandlerBase *handler);
void addSupportELFDynamicSharedObjects(bool useShlibUndefines,
TargetHandlerBase *handler);
diff --git a/lld/lib/Driver/DarwinLdDriver.cpp b/lld/lib/Driver/DarwinLdDriver.cpp
index 64d77a971a1..fe255fbc0df 100644
--- a/lld/lib/Driver/DarwinLdDriver.cpp
+++ b/lld/lib/Driver/DarwinLdDriver.cpp
@@ -321,26 +321,25 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
// skipped.
// 3. If the last -syslibroot is "/", all of them are ignored entirely.
// 4. If { syslibroots } x path == {}, the original path is kept.
- std::vector<StringRef> syslibRoots;
for (auto syslibRoot : parsedArgs->filtered(OPT_syslibroot)) {
- syslibRoots.push_back(syslibRoot->getValue());
+ ctx.addSysLibRoot(syslibRoot->getValue());
}
// Paths specified with -L come first, and are not considered system paths for
// the case where there is precisely 1 -syslibroot.
for (auto libPath : parsedArgs->filtered(OPT_L)) {
- ctx.addModifiedSearchDir(libPath->getValue(), syslibRoots, false);
+ ctx.addModifiedSearchDir(libPath->getValue());
}
// -Z suppresses the standard search paths.
if (!parsedArgs->hasArg(OPT_Z)) {
- ctx.addModifiedSearchDir("/usr/lib", syslibRoots, true);
- ctx.addModifiedSearchDir("/usr/local/lib", syslibRoots, true);
+ ctx.addModifiedSearchDir("/usr/lib", true);
+ ctx.addModifiedSearchDir("/usr/local/lib", true);
}
// Now that we've constructed the final set of search paths, print out what
// we'll be using for testing purposes.
- if (ctx.testingLibResolution()) {
+ if (ctx.testingLibResolution() || parsedArgs->getLastArg(OPT_v)) {
diagnostics << "Library search paths:\n";
for (auto path : ctx.searchDirs()) {
diagnostics << " " << path << '\n';
@@ -373,7 +372,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
}
inputGraph->addInputElement(std::unique_ptr<InputElement>(
- new MachOFileNode(ctx, inputPath, globalWholeArchive)));
+ new MachOFileNode(inputPath, globalWholeArchive)));
}
if (!inputGraph->size()) {
diff --git a/lld/lib/Driver/DarwinLdOptions.td b/lld/lib/Driver/DarwinLdOptions.td
index cf5fcf129d8..b9f7b1baed2 100644
--- a/lld/lib/Driver/DarwinLdOptions.td
+++ b/lld/lib/Driver/DarwinLdOptions.td
@@ -96,6 +96,8 @@ def sectalign : MultiArg<["-"], "sectalign", 3>,
HelpText<"alignment for segment/section">;
def t : Flag<["-"], "t">,
HelpText<"Print the names of the input files as ld processes them">;
+def v : Flag<["-"], "v">,
+ HelpText<"Print linker information">;
// extras
diff --git a/lld/lib/ReaderWriter/MachO/Atoms.h b/lld/lib/ReaderWriter/MachO/Atoms.h
index 13d546f0264..3107ee384d6 100644
--- a/lld/lib/ReaderWriter/MachO/Atoms.h
+++ b/lld/lib/ReaderWriter/MachO/Atoms.h
@@ -123,7 +123,7 @@ private:
class MachOSharedLibraryAtom : public SharedLibraryAtom {
public:
MachOSharedLibraryAtom(const File &file, StringRef name,
- StringRef dylibInstallName)
+ StringRef dylibInstallName, bool weakDef)
: SharedLibraryAtom(), _file(file), _name(name),
_dylibInstallName(dylibInstallName) {}
virtual ~MachOSharedLibraryAtom() {}
diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h
index df9be71c18c..bc6a75a39f5 100644
--- a/lld/lib/ReaderWriter/MachO/File.h
+++ b/lld/lib/ReaderWriter/MachO/File.h
@@ -175,22 +175,16 @@ private:
class MachODylibFile : public SharedLibraryFile {
public:
- MachODylibFile(StringRef path) : SharedLibraryFile(path), _dylib_name(path) {}
-
- virtual const SharedLibraryAtom *exports(StringRef name,
- bool dataSymbolOnly) const {
- // FIXME: we obviously need to record code/data if we're going to make
- // proper use of dataSymbolOnly.
- auto sym = _nameToAtom.find(name);
-
- if (sym == _nameToAtom.end())
- return nullptr;
-
- if (!sym->second)
- sym->second =
- new (_allocator) MachOSharedLibraryAtom(*this, name, _dylib_name);
+ MachODylibFile(StringRef path, StringRef installName)
+ : SharedLibraryFile(path), _installName(installName) {
+ }
- return sym->second;
+ virtual const SharedLibraryAtom *exports(StringRef name, bool isData) const {
+ // Pass down _installName and _allocator so that if this requested symbol
+ // is re-exported through this dylib, the SharedLibraryAtom's loadName()
+ // is this dylib installName and not the implementation dylib's.
+ // NOTE: isData is not needed for dylibs (it matters for static libs).
+ return exports(name, _installName, _allocator);
}
const atom_collection<DefinedAtom> &defined() const override {
@@ -209,22 +203,78 @@ public:
return _absoluteAtoms;
}
- void addSharedLibraryAtom(StringRef name, bool copyRefs) {
+ /// Adds symbol name that this dylib exports. The corresponding
+ /// SharedLibraryAtom is created lazily (since most symbols are not used).
+ void addExportedSymbol(StringRef name, bool weakDef, bool copyRefs) {
if (copyRefs) {
name = name.copy(_allocator);
}
+ AtomAndFlags info(weakDef);
+ _nameToAtom[name] = info;
+ }
- _nameToAtom[name] = nullptr;
+ void addReExportedDylib(StringRef dylibPath) {
+ _reExportedDylibs.emplace_back(dylibPath);
+ }
+
+ StringRef installName() { return _installName; }
+
+ typedef std::function<MachODylibFile *(StringRef)> FindDylib;
+
+ void loadReExportedDylibs(FindDylib find) {
+ for (ReExportedDylib &entry : _reExportedDylibs) {
+ entry.file = find(entry.path);
+ }
}
private:
- StringRef _dylib_name;
+ const SharedLibraryAtom *exports(StringRef name, StringRef installName,
+ llvm::BumpPtrAllocator &allocator) const {
+ // First, check if requested symbol is directly implemented by this dylib.
+ auto entry = _nameToAtom.find(name);
+ if (entry != _nameToAtom.end()) {
+ if (!entry->second.atom) {
+ // Lazily create SharedLibraryAtom.
+ entry->second.atom =
+ new (allocator) MachOSharedLibraryAtom(*this, name, installName,
+ entry->second.weakDef);
+ }
+ return entry->second.atom;
+ }
+
+ // Next, check if symbol is implemented in some re-exported dylib.
+ for (const ReExportedDylib &dylib : _reExportedDylibs) {
+ assert(dylib.file);
+ auto atom = dylib.file->exports(name, installName, allocator);
+ if (atom)
+ return atom;
+ }
+
+ // Symbol not exported or re-exported by this dylib.
+ return nullptr;
+ }
+
+
+ struct ReExportedDylib {
+ ReExportedDylib(StringRef p) : path(p), file(nullptr) { }
+ StringRef path;
+ MachODylibFile *file;
+ };
+
+ struct AtomAndFlags {
+ AtomAndFlags() : atom(nullptr), weakDef(false) { }
+ AtomAndFlags(bool weak) : atom(nullptr), weakDef(weak) { }
+ const SharedLibraryAtom *atom;
+ bool weakDef;
+ };
+
+ StringRef _installName;
atom_collection_vector<DefinedAtom> _definedAtoms;
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
-
- mutable std::unordered_map<StringRef, SharedLibraryAtom *> _nameToAtom;
+ std::vector<ReExportedDylib> _reExportedDylibs;
+ mutable std::unordered_map<StringRef, AtomAndFlags> _nameToAtom;
mutable llvm::BumpPtrAllocator _allocator;
};
diff --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
index a5bca11cb5f..427b59a8b70 100644
--- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
@@ -10,9 +10,11 @@
#include "lld/ReaderWriter/MachOLinkingContext.h"
#include "ArchHandler.h"
+#include "File.h"
#include "MachOPasses.h"
#include "lld/Core/PassManager.h"
+#include "lld/Driver/DarwinInputGraph.h"
#include "lld/ReaderWriter/Reader.h"
#include "lld/ReaderWriter/Writer.h"
#include "lld/Passes/LayoutPass.h"
@@ -28,6 +30,7 @@
#include <algorithm>
using lld::mach_o::ArchHandler;
+using lld::mach_o::MachODylibFile;
using namespace llvm::MachO;
namespace lld {
@@ -304,16 +307,16 @@ bool MachOLinkingContext::pathExists(StringRef path) const {
return _existingPaths.find(key) != _existingPaths.end();
}
-void MachOLinkingContext::addModifiedSearchDir(
- StringRef libPath, const StringRefVector &syslibRoots, bool isSystemPath) {
+void MachOLinkingContext::addModifiedSearchDir(StringRef libPath,
+ bool isSystemPath) {
bool addedModifiedPath = false;
// Two cases to consider here:
// + If the last -syslibroot is "/", all of them are ignored (don't ask).
// + -syslibroot only applies to absolute paths.
- if (!syslibRoots.empty() && syslibRoots.back() != "/" &&
+ if (!_syslibRoots.empty() && _syslibRoots.back() != "/" &&
libPath.startswith("/")) {
- for (auto syslibRoot : syslibRoots) {
+ for (auto syslibRoot : _syslibRoots) {
SmallString<256> path(syslibRoot);
llvm::sys::path::append(path, libPath);
if (pathExists(path)) {
@@ -328,7 +331,7 @@ void MachOLinkingContext::addModifiedSearchDir(
// Finally, if only one -syslibroot is given, system paths which aren't in it
// get suppressed.
- if (syslibRoots.size() != 1 || !isSystemPath) {
+ if (_syslibRoots.size() != 1 || !isSystemPath) {
if (pathExists(libPath)) {
_searchDirs.push_back(libPath);
}
@@ -419,6 +422,86 @@ Writer &MachOLinkingContext::writer() const {
return *_writer;
}
+MachODylibFile* MachOLinkingContext::loadIndirectDylib(StringRef path) const {
+ std::unique_ptr<MachOFileNode> node(new MachOFileNode(path, false));
+ std::error_code ec = node->parse(*this, llvm::errs());
+ if (ec)
+ return nullptr;
+
+ assert(node->files().size() == 1 && "expected one file in dylib");
+ // lld::File object is owned by MachOFileNode object. This method returns
+ // an unowned pointer to the lld::File object.
+ MachODylibFile* result = reinterpret_cast<MachODylibFile*>(
+ node->files().front().get());
+
+ // Node object now owned by _indirectDylibs vector.
+ _indirectDylibs.push_back(std::move(node));
+
+ return result;
+}
+
+
+MachODylibFile* MachOLinkingContext::findIndirectDylib(StringRef path) const {
+ // See if already loaded.
+ auto pos = _pathToDylibMap.find(path);
+ if (pos != _pathToDylibMap.end())
+ return pos->second;
+
+ // Search -L paths if of the form "libXXX.dylib"
+ std::pair<StringRef, StringRef> split = path.rsplit('/');
+ StringRef leafName = split.second;
+ if (leafName.startswith("lib") && leafName.endswith(".dylib")) {
+ // FIXME: Need to enhance searchLibrary() to only look for .dylib
+ auto libPath = searchLibrary(leafName);
+ if (!libPath.getError()) {
+ return loadIndirectDylib(libPath.get());
+ }
+ }
+
+ // Try full path with sysroot.
+ for (StringRef sysPath : _syslibRoots) {
+ SmallString<256> fullPath;
+ fullPath.assign(sysPath);
+ llvm::sys::path::append(fullPath, path);
+ if (pathExists(fullPath))
+ return loadIndirectDylib(fullPath);
+ }
+
+ // Try full path.
+ if (pathExists(path)) {
+ return loadIndirectDylib(path);
+ }
+
+ return nullptr;
+}
+
+bool MachOLinkingContext::createImplicitFiles(
+ std::vector<std::unique_ptr<File> > &result) const {
+ // Add indirect dylibs by asking each linked dylib to add its indirects.
+ // Iterate until no more dylibs get loaded.
+ size_t dylibCount = 0;
+ while (dylibCount != _allDylibs.size()) {
+ dylibCount = _allDylibs.size();
+ for (MachODylibFile *dylib : _allDylibs) {
+ dylib->loadReExportedDylibs([this] (StringRef path) -> MachODylibFile* {
+ return findIndirectDylib(path); });
+ }
+ }
+
+ // Let writer add output type specific extras.
+ return writer().createImplicitFiles(result);
+}
+
+
+void MachOLinkingContext::registerDylib(MachODylibFile *dylib) {
+ _allDylibs.insert(dylib);
+ _pathToDylibMap[dylib->installName()] = dylib;
+ // If path is different than install name, register path too.
+ if (!dylib->path().equals(dylib->installName()))
+ _pathToDylibMap[dylib->path()] = dylib;
+}
+
+
ArchHandler &MachOLinkingContext::archHandler() const {
if (!_archHandler)
_archHandler = ArchHandler::create(_arch);
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
index 27162450d64..fc43141ca24 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
@@ -28,6 +28,7 @@
#include "lld/Core/Error.h"
#include "lld/Core/LLVM.h"
+#include "lld/Core/SharedLibraryFile.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
@@ -233,8 +234,9 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
uint32_t dataInCodeSize = 0;
ec = forEachLoadCommand(lcRange, lcCount, swap, is64,
[&] (uint32_t cmd, uint32_t size, const char* lc) -> bool {
- if (is64) {
- if (cmd == LC_SEGMENT_64) {
+ switch(cmd) {
+ case LC_SEGMENT_64:
+ if (is64) {
const segment_command_64 *seg =
reinterpret_cast<const segment_command_64*>(lc);
const unsigned sectionCount = (swap
@@ -276,8 +278,9 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
f->sections.push_back(section);
}
}
- } else {
- if (cmd == LC_SEGMENT) {
+ break;
+ case LC_SEGMENT:
+ if (!is64) {
const segment_command *seg =
reinterpret_cast<const segment_command*>(lc);
const unsigned sectionCount = (swap
@@ -319,8 +322,8 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
f->sections.push_back(section);
}
}
- }
- if (cmd == LC_SYMTAB) {
+ break;
+ case LC_SYMTAB: {
const symtab_command *st = reinterpret_cast<const symtab_command*>(lc);
const char *strings = start + read32(swap, st->stroff);
const uint32_t strSize = read32(swap, st->strsize);
@@ -389,15 +392,31 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
f->localSymbols.push_back(sout);
}
}
- } else if (cmd == LC_ID_DYLIB) {
+ }
+ break;
+ case LC_ID_DYLIB: {
const dylib_command *dl = reinterpret_cast<const dylib_command*>(lc);
f->installName = lc + read32(swap, dl->dylib.name);
- } else if (cmd == LC_DATA_IN_CODE) {
+ }
+ break;
+ case LC_DATA_IN_CODE: {
const linkedit_data_command *ldc =
reinterpret_cast<const linkedit_data_command*>(lc);
dataInCode = reinterpret_cast<const data_in_code_entry*>(
start + read32(swap, ldc->dataoff));
dataInCodeSize = read32(swap, ldc->datasize);
+ }
+ case LC_LOAD_DYLIB:
+ case LC_LOAD_WEAK_DYLIB:
+ case LC_REEXPORT_DYLIB:
+ case LC_LOAD_UPWARD_DYLIB: {
+ const dylib_command *dl = reinterpret_cast<const dylib_command*>(lc);
+ DependentDylib entry;
+ entry.path = lc + read32(swap, dl->dylib.name);
+ entry.kind = LoadCommandType(cmd);
+ f->dependentDylibs.push_back(entry);
+ }
+ break;
}
return false;
});
@@ -422,7 +441,7 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
class MachOReader : public Reader {
public:
- MachOReader(MachOLinkingContext::Arch arch) : _arch(arch) {}
+ MachOReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
bool canParse(file_magic magic, StringRef ext,
const MemoryBuffer &mb) const override {
@@ -437,7 +456,7 @@ public:
parseFile(std::unique_ptr<MemoryBuffer> &mb, const Registry &registry,
std::vector<std::unique_ptr<File>> &result) const override {
// Convert binary file to normalized mach-o.
- auto normFile = readBinary(mb, _arch);
+ auto normFile = readBinary(mb, _ctx.arch());
if (std::error_code ec = normFile.getError())
return ec;
// Convert normalized mach-o to atoms.
@@ -450,16 +469,16 @@ public:
return std::error_code();
}
private:
- MachOLinkingContext::Arch _arch;
+ MachOLinkingContext &_ctx;
};
} // namespace normalized
} // namespace mach_o
-void Registry::addSupportMachOObjects(const MachOLinkingContext &ctx) {
+void Registry::addSupportMachOObjects(MachOLinkingContext &ctx) {
MachOLinkingContext::Arch arch = ctx.arch();
- add(std::unique_ptr<Reader>(new mach_o::normalized::MachOReader(arch)));
+ add(std::unique_ptr<Reader>(new mach_o::normalized::MachOReader(ctx)));
addKindTable(Reference::KindNamespace::mach_o, ctx.archHandler().kindArch(),
ctx.archHandler().kindStrings());
add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index 900c9eb9680..9b9c625ab76 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -671,12 +671,19 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
ErrorOr<std::unique_ptr<lld::File>>
normalizedDylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
bool copyRefs) {
+ // Instantiate SharedLibraryFile object.
std::unique_ptr<MachODylibFile> file(
- new MachODylibFile(normalizedFile.installName));
-
+ new MachODylibFile(path, normalizedFile.installName));
+ // Tell MachODylibFile object about all symbols it exports.
for (auto &sym : normalizedFile.globalSymbols) {
assert((sym.scope & N_EXT) && "only expect external symbols here");
- file->addSharedLibraryAtom(sym.name, copyRefs);
+ bool weakDef = (sym.desc & N_WEAK_DEF);
+ file->addExportedSymbol(sym.name, weakDef, copyRefs);
+ }
+ // Tell MachODylibFile object about all dylibs it re-exports.
+ for (const DependentDylib &dep : normalizedFile.dependentDylibs) {
+ if (dep.kind == llvm::MachO::LC_REEXPORT_DYLIB)
+ file->addReExportedDylib(dep.path);
}
return std::unique_ptr<File>(std::move(file));
@@ -715,6 +722,7 @@ normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
bool copyRefs) {
switch (normalizedFile.fileType) {
case MH_DYLIB:
+ case MH_DYLIB_STUB:
return normalizedDylibToAtoms(normalizedFile, path, copyRefs);
case MH_OBJECT:
return normalizedObjectToAtoms(normalizedFile, path, copyRefs);
diff --git a/lld/test/mach-o/re-exported-dylib-ordinal.yaml b/lld/test/mach-o/re-exported-dylib-ordinal.yaml
new file mode 100644
index 00000000000..9d628e9af15
--- /dev/null
+++ b/lld/test/mach-o/re-exported-dylib-ordinal.yaml
@@ -0,0 +1,105 @@
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -dylib -o %t \
+# RUN: && llvm-nm -m %t | FileCheck %s
+#
+# Test that when one dylib A re-exports dylib B that using a symbol from B
+# gets recorded as coming from A.
+#
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xE9,
+ 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000008
+ type: X86_64_RELOC_BRANCH
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 1
+global-symbols:
+ - name: _test
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+undefined-symbols:
+ - name: _bar
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+flags: [ MH_TWOLEVEL ]
+install-name: /junk/libfoo.dylib
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000F9A
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3 ]
+global-symbols:
+ - name: _foo
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000F9A
+dependents:
+ - path: /junk/libbar.dylib
+ kind: LC_REEXPORT_DYLIB
+
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+flags: [ MH_TWOLEVEL ]
+install-name: /junk/libbar.dylib
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000F9A
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3 ]
+global-symbols:
+ - name: _bar
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000F9A
+
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+flags: [ MH_TWOLEVEL ]
+install-name: /usr/lib/libSystem.B.dylib
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x55 ]
+
+global-symbols:
+ - name: dyld_stub_binder
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+
+...
+
+# CHECK: (undefined) external _bar (from libfoo)
+# CHECK: (undefined) external dyld_stub_binder (from libSystem)
OpenPOWER on IntegriCloud