diff options
| -rw-r--r-- | lld/include/lld/ReaderWriter/MachOLinkingContext.h | 11 | ||||
| -rw-r--r-- | lld/lib/Driver/DarwinInputGraph.cpp | 1 | ||||
| -rw-r--r-- | lld/lib/Driver/DarwinLdDriver.cpp | 12 | ||||
| -rw-r--r-- | lld/lib/Driver/DarwinLdOptions.td | 3 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp | 70 | ||||
| -rwxr-xr-x | lld/test/mach-o/Inputs/DependencyDump.py | 30 | ||||
| -rw-r--r-- | lld/test/mach-o/dependency_info.yaml | 21 |
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 + |

