summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/include/lld/ReaderWriter/MachOLinkingContext.h11
-rw-r--r--lld/lib/Driver/DarwinInputGraph.cpp1
-rw-r--r--lld/lib/Driver/DarwinLdDriver.cpp12
-rw-r--r--lld/lib/Driver/DarwinLdOptions.td3
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp70
-rwxr-xr-xlld/test/mach-o/Inputs/DependencyDump.py30
-rw-r--r--lld/test/mach-o/dependency_info.yaml21
7 files changed, 143 insertions, 5 deletions
diff --git a/lld/include/lld/ReaderWriter/MachOLinkingContext.h b/lld/include/lld/ReaderWriter/MachOLinkingContext.h
index 0c495d8142d..4f9262a93b3 100644
--- a/lld/include/lld/ReaderWriter/MachOLinkingContext.h
+++ b/lld/include/lld/ReaderWriter/MachOLinkingContext.h
@@ -99,7 +99,12 @@ public:
void setKeepPrivateExterns(bool v) { _keepPrivateExterns = v; }
bool demangleSymbols() const { return _demangle; }
void setDemangleSymbols(bool d) { _demangle = d; }
-
+ /// Create file at specified path which will contain a binary encoding
+ /// of all input and output file paths.
+ std::error_code createDependencyFile(StringRef path);
+ void addInputFileDependency(StringRef path) const;
+ void addInputFileNotFound(StringRef path) const;
+ void addOutputFileDependency(StringRef path) const;
bool minOS(StringRef mac, StringRef iOS) const;
void setDoNothing(bool value) { _doNothing = value; }
@@ -123,6 +128,9 @@ public:
/// instead of the actual filesystem.
bool pathExists(StringRef path) const;
+ /// Like pathExists() but only used on files - not directories.
+ bool fileExists(StringRef path) const;
+
/// \brief Adds any library search paths derived from the given base, possibly
/// modified by -syslibroots.
///
@@ -304,6 +312,7 @@ private:
mutable std::vector<std::unique_ptr<class MachOFileNode>> _indirectDylibs;
ExportMode _exportMode;
llvm::StringSet<> _exportedSymbols;
+ std::unique_ptr<llvm::raw_fd_ostream> _dependencyInfo;
};
} // end namespace lld
diff --git a/lld/lib/Driver/DarwinInputGraph.cpp b/lld/lib/Driver/DarwinInputGraph.cpp
index 712cc79ab51..16dbdec7dbf 100644
--- a/lld/lib/Driver/DarwinInputGraph.cpp
+++ b/lld/lib/Driver/DarwinInputGraph.cpp
@@ -30,6 +30,7 @@ std::error_code MachOFileNode::parse(const LinkingContext &ctx,
if (std::error_code ec = getBuffer(*filePath))
return ec;
+ _context.addInputFileDependency(*filePath);
if (ctx.logInputFiles())
diagnostics << *filePath << "\n";
diff --git a/lld/lib/Driver/DarwinLdDriver.cpp b/lld/lib/Driver/DarwinLdDriver.cpp
index 7752cf3ea45..5aedd7b9774 100644
--- a/lld/lib/Driver/DarwinLdDriver.cpp
+++ b/lld/lib/Driver/DarwinLdDriver.cpp
@@ -100,6 +100,7 @@ static std::error_code parseExportsList(StringRef exportFilePath,
MemoryBuffer::getFileOrSTDIN(exportFilePath);
if (std::error_code ec = mb.getError())
return ec;
+ ctx.addInputFileDependency(exportFilePath);
StringRef buffer = mb->get()->getBuffer();
while (!buffer.empty()) {
// Split off each line in the file.
@@ -134,6 +135,7 @@ static std::error_code parseFileList(StringRef fileListPath,
std::pair<StringRef, StringRef> opt = fileListPath.split(',');
StringRef filePath = opt.first;
StringRef dirName = opt.second;
+ ctx.addInputFileDependency(filePath);
// Map in file list file.
ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
MemoryBuffer::getFileOrSTDIN(filePath);
@@ -436,6 +438,16 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
diagnostics << "warning: -keep_private_externs only used in -r mode\n";
}
+ // Handle -dependency_info <path> used by Xcode.
+ if (llvm::opt::Arg *depInfo = parsedArgs->getLastArg(OPT_dependency_info)) {
+ if (std::error_code ec = ctx.createDependencyFile(depInfo->getValue())) {
+ diagnostics << "warning: " << ec.message()
+ << ", processing '-dependency_info "
+ << depInfo->getValue()
+ << "'\n";
+ }
+ }
+
// In -test_file_usage mode, we'll be given an explicit list of paths that
// exist. We'll also be expected to print out information about how we located
// libraries and so on that the user specified, but not to actually do any
diff --git a/lld/lib/Driver/DarwinLdOptions.td b/lld/lib/Driver/DarwinLdOptions.td
index 73672fdad8b..d77163861e0 100644
--- a/lld/lib/Driver/DarwinLdOptions.td
+++ b/lld/lib/Driver/DarwinLdOptions.td
@@ -146,6 +146,9 @@ def image_base : Separate<["-"], "image_base">;
def seg1addr : Separate<["-"], "seg1addr">, Alias<image_base>;
def demangle : Flag<["-"], "demangle">,
HelpText<"Demangles symbol names in errors and warnings">;
+def dependency_info : Separate<["-"], "dependency_info">,
+ MetaVarName<"<file>">,
+ HelpText<"Write binary list of files used during link">;
def t : Flag<["-"], "t">,
HelpText<"Print the names of the input files as ld processes them">;
diff --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
index 7d72ffd5254..03555be0eb5 100644
--- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
@@ -357,6 +357,19 @@ bool MachOLinkingContext::pathExists(StringRef path) const {
return _existingPaths.find(key) != _existingPaths.end();
}
+bool MachOLinkingContext::fileExists(StringRef path) const {
+ bool found = pathExists(path);
+ // Log search misses.
+ if (!found)
+ addInputFileNotFound(path);
+
+ // When testing, file is never opened, so logging is done here.
+ if (_testingFileUsage && found)
+ addInputFileDependency(path);
+
+ return found;
+}
+
void MachOLinkingContext::setSysLibRoots(const StringRefVector &paths) {
_syslibRoots = paths;
}
@@ -426,7 +439,7 @@ MachOLinkingContext::searchDirForLibrary(StringRef path,
// A request ending in .o is special: just search for the file directly.
fullPath.assign(path);
llvm::sys::path::append(fullPath, libName);
- if (pathExists(fullPath))
+ if (fileExists(fullPath))
return fullPath.str().copy(_allocator);
return make_error_code(llvm::errc::no_such_file_or_directory);
}
@@ -434,13 +447,13 @@ MachOLinkingContext::searchDirForLibrary(StringRef path,
// Search for dynamic library
fullPath.assign(path);
llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib");
- if (pathExists(fullPath))
+ if (fileExists(fullPath))
return fullPath.str().copy(_allocator);
// If not, try for a static library
fullPath.assign(path);
llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a");
- if (pathExists(fullPath))
+ if (fileExists(fullPath))
return fullPath.str().copy(_allocator);
return make_error_code(llvm::errc::no_such_file_or_directory);
@@ -465,7 +478,7 @@ ErrorOr<StringRef> MachOLinkingContext::findPathForFramework(StringRef fwName) c
for (StringRef dir : frameworkDirs()) {
fullPath.assign(dir);
llvm::sys::path::append(fullPath, Twine(fwName) + ".framework", fwName);
- if (pathExists(fullPath))
+ if (fileExists(fullPath))
return fullPath.str().copy(_allocator);
}
@@ -520,6 +533,8 @@ bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
}
}
+ addOutputFileDependency(outputPath());
+
return true;
}
@@ -692,5 +707,52 @@ std::string MachOLinkingContext::demangle(StringRef symbolName) const {
return symbolName;
}
+std::error_code MachOLinkingContext::createDependencyFile(StringRef path) {
+ std::error_code ec;
+ _dependencyInfo = std::unique_ptr<llvm::raw_fd_ostream>(new
+ llvm::raw_fd_ostream(path, ec, llvm::sys::fs::F_None));
+ if (ec) {
+ _dependencyInfo.reset();
+ return ec;
+ }
+
+ char linkerVersionOpcode = 0x00;
+ *_dependencyInfo << linkerVersionOpcode;
+ *_dependencyInfo << "lld"; // FIXME
+ *_dependencyInfo << '\0';
+
+ return std::error_code();
+}
+
+void MachOLinkingContext::addInputFileDependency(StringRef path) const {
+ if (!_dependencyInfo)
+ return;
+
+ char inputFileOpcode = 0x10;
+ *_dependencyInfo << inputFileOpcode;
+ *_dependencyInfo << path;
+ *_dependencyInfo << '\0';
+}
+
+void MachOLinkingContext::addInputFileNotFound(StringRef path) const {
+ if (!_dependencyInfo)
+ return;
+
+ char inputFileOpcode = 0x11;
+ *_dependencyInfo << inputFileOpcode;
+ *_dependencyInfo << path;
+ *_dependencyInfo << '\0';
+}
+
+void MachOLinkingContext::addOutputFileDependency(StringRef path) const {
+ if (!_dependencyInfo)
+ return;
+
+ char outputFileOpcode = 0x40;
+ *_dependencyInfo << outputFileOpcode;
+ *_dependencyInfo << path;
+ *_dependencyInfo << '\0';
+}
+
} // end namespace lld
diff --git a/lld/test/mach-o/Inputs/DependencyDump.py b/lld/test/mach-o/Inputs/DependencyDump.py
new file mode 100755
index 00000000000..ba38f226046
--- /dev/null
+++ b/lld/test/mach-o/Inputs/DependencyDump.py
@@ -0,0 +1,30 @@
+# -*- Python -*-
+
+
+#
+# Dump out Xcode binary dependency file.
+#
+
+import sys
+
+f = open(sys.argv[1], "rb")
+byte = f.read(1)
+while byte != '':
+ if byte == '\000':
+ sys.stdout.write("linker-vers: ")
+ elif byte == '\020':
+ sys.stdout.write("input-file: ")
+ elif byte == '\021':
+ sys.stdout.write("not-found: ")
+ elif byte == '\100':
+ sys.stdout.write("output-file: ")
+ byte = f.read(1)
+ while byte != '\000':
+ if byte != '\012':
+ sys.stdout.write(byte)
+ byte = f.read(1)
+ sys.stdout.write("\n")
+ byte = f.read(1)
+
+f.close()
+
diff --git a/lld/test/mach-o/dependency_info.yaml b/lld/test/mach-o/dependency_info.yaml
new file mode 100644
index 00000000000..0bc4027f8ca
--- /dev/null
+++ b/lld/test/mach-o/dependency_info.yaml
@@ -0,0 +1,21 @@
+#
+# Test -dependency_info option
+#
+# RUN: lld -flavor darwin -arch x86_64 -test_file_usage \
+# RUN: -dependency_info %t.info \
+# RUN: -path_exists /System/Library/Frameworks \
+# RUN: -path_exists /System/Library/Frameworks/Foo.framework/Foo \
+# RUN: -path_exists /Custom/Frameworks \
+# RUN: -path_exists /Custom/Frameworks/Bar.framework/Bar \
+# RUN: -F/Custom/Frameworks \
+# RUN: -framework Bar \
+# RUN: -framework Foo
+# RUN: python %p/Inputs/DependencyDump.py %t.info | FileCheck %s
+
+
+# CHECK: linker-vers: lld
+# CHECK: input-file: /Custom/Frameworks/Bar.framework/Bar
+# CHECK: not-found: /Custom/Frameworks/Foo.framework/Foo
+# CHECK: input-file: /System/Library/Frameworks/Foo.framework/Foo
+# CHECK: output-file: a.out
+
OpenPOWER on IntegriCloud