[lld] [mach-o] Support -l and -syslibroot options
Tim Northover
t.p.northover at gmail.com
Mon Jul 7 09:01:10 PDT 2014
Hi,
The attached patch implements the -l and -syslibroot options for the
Darwin lld driver. They're in the same patch because testing -l (looks
in /usr/lib and /usr/local/lib) without being able to override the
prefix is rather problematic.
I think the implementation itself is reasonably straightforward (the
one wrinkle is iterating through all arguments now, as opposed to just
OPT_INPUT and OPT_l. Not *strictly* necessary yet, but adding more
filter OPT_nnn arguments to the iterator doesn't scale and we do have
a lot more to support in the end).
The most controversial part is likely to be the testing: it adds
crafted binary MachO inputs, which isn't ideal if they ever need
updating (unlikely, they simply export a single, given symbol). This
isn't exactly unique though, so hopefully won't cause any problems.
OK to commit?
Cheers.
Tim.
-------------- next part --------------
commit ca1bf01d29014eee796172c9a89836fff1714bb0
Author: Tim Northover <tnorthover at apple.com>
Date: Mon Jul 7 16:30:49 2014 +0100
[mach-o]: support -syslibroot and -l options
diff --git a/include/lld/ReaderWriter/MachOLinkingContext.h b/include/lld/ReaderWriter/MachOLinkingContext.h
index 036fe8b..c79a091 100644
--- a/include/lld/ReaderWriter/MachOLinkingContext.h
+++ b/include/lld/ReaderWriter/MachOLinkingContext.h
@@ -79,6 +79,12 @@ public:
bool doNothing() const { return _doNothing; }
bool printAtoms() const { return _printAtoms; }
+ ErrorOr<StringRef> searchPathForLibrary(StringRef path,
+ StringRef libName) const;
+
+ /// Searches directories for a match on the input File
+ ErrorOr<StringRef> searchLibrary(StringRef libName) const;
+
/// \brief The dylib's binary compatibility version, in the raw uint32 format.
///
/// When building a dynamic library, this is the compatibility version that
@@ -125,6 +131,8 @@ public:
}
void setBundleLoader(StringRef loader) { _bundleLoader = loader; }
void setPrintAtoms(bool value=true) { _printAtoms = value; }
+ void setSyslibRoot(StringRef path) { _syslibRoot = path; }
+
StringRef dyldPath() const { return "/usr/lib/dyld"; }
static Arch archFromCpuType(uint32_t cputype, uint32_t cpusubtype);
@@ -153,6 +161,7 @@ private:
static ArchInfo _s_archInfos[];
+ StringRef _syslibRoot;
HeaderFileType _outputMachOType; // e.g MH_EXECUTE
bool _outputMachOTypeStatic; // Disambiguate static vs dynamic prog
bool _doNothing; // for -help and -v which just print info
diff --git a/lib/Driver/DarwinLdDriver.cpp b/lib/Driver/DarwinLdDriver.cpp
index 6686caf..aac89b8 100644
--- a/lib/Driver/DarwinLdDriver.cpp
+++ b/lib/Driver/DarwinLdDriver.cpp
@@ -268,12 +268,31 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
std::unique_ptr<InputGraph> inputGraph(new InputGraph());
+ if (llvm::opt::Arg *syslibRoot = parsedArgs->getLastArg(OPT_syslibroot)) {
+ ctx.setSyslibRoot(syslibRoot->getValue());
+ }
+
// Handle input files
- for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_INPUT),
- ie = parsedArgs->filtered_end();
- it != ie; ++it) {
+ for (auto &arg : *parsedArgs) {
+ StringRef inputPath;
+ switch (arg->getOption().getID()) {
+ default:
+ continue;
+ case OPT_INPUT:
+ inputPath = arg->getValue();
+ break;
+ case OPT_l: {
+ ErrorOr<StringRef> resolvedPath = ctx.searchLibrary(arg->getValue());
+ if (!resolvedPath) {
+ diagnostics << "Unable to find library -l" << arg->getValue() << "\n";
+ return false;
+ }
+ inputPath = resolvedPath.get();
+ break;
+ }
+ }
inputGraph->addInputElement(std::unique_ptr<InputElement>(
- new MachOFileNode(ctx, (*it)->getValue(), globalWholeArchive)));
+ new MachOFileNode(ctx, inputPath, globalWholeArchive)));
}
if (!inputGraph->size()) {
diff --git a/lib/Driver/DarwinLdOptions.td b/lib/Driver/DarwinLdOptions.td
index 61c151a..15af151 100644
--- a/lib/Driver/DarwinLdOptions.td
+++ b/lib/Driver/DarwinLdOptions.td
@@ -69,9 +69,16 @@ def L : Joined<["-"], "L">,
def all_load : Flag<["-"], "all_load">,
HelpText<"Forces all members of all static libraries to be loaded">,
Group<grp_libs>;
+def syslibroot : Separate<["-"], "syslibroot">,
+ HelpText<"Add prefix to all system library search paths">,
+ Group<grp_libs>;
+
+// Input options
+def l : Joined<["-"], "l">,
+ HelpText<"Root name of library to searchf for">;
// test case options
-def print_atoms : Flag<["-"], "print_atoms">,
+def print_atoms : Flag<["-"], "print_atoms">,
HelpText<"Emit output as yaml atoms">;
// general options
diff --git a/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
index b1e2929..36d267a 100644
--- a/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ b/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
@@ -20,8 +20,10 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Errc.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MachO.h"
+#include "llvm/Support/Path.h"
using lld::mach_o::KindHandler;
using namespace llvm::MachO;
@@ -262,6 +264,49 @@ bool MachOLinkingContext::addUnixThreadLoadCommand() const {
}
}
+ErrorOr<StringRef>
+MachOLinkingContext::searchPathForLibrary(StringRef path,
+ StringRef libName) const {
+ SmallString<128> fullPath;
+ if (libName.endswith(".o")) {
+ // A request ending in .o is special: just search for the file directly.
+ fullPath.assign(path);
+ llvm::sys::path::append(fullPath, libName);
+ if (llvm::sys::fs::exists(fullPath.str()))
+ return StringRef(*new (_allocator) std::string(fullPath.str()));
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+ }
+
+ // Search for dynamic library
+ fullPath.assign(path);
+ llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib");
+ if (llvm::sys::fs::exists(fullPath.str()))
+ return StringRef(*new (_allocator) std::string(fullPath.str()));
+
+ // If not, try for a static library
+ fullPath.assign(path);
+ llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a");
+ if (llvm::sys::fs::exists(fullPath.str()))
+ return StringRef(*new (_allocator) std::string(fullPath.str()));
+
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+ErrorOr<StringRef> MachOLinkingContext::searchLibrary(StringRef libName) const {
+ SmallString<128> path;
+ static const char *syslibPaths[] = {"/usr/lib", "/usr/local/lib"};
+ for (StringRef dir : syslibPaths) {
+ path.assign(_syslibRoot);
+ llvm::sys::path::append(path, dir);
+
+ ErrorOr<StringRef> ec = searchPathForLibrary(path, libName);
+ if (ec)
+ return ec;
+ }
+
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
// TODO: if -arch not specified, look at arch of first .o file.
diff --git a/test/mach-o/Inputs/lib-search-paths/usr/lib/libmyshared.dylib b/test/mach-o/Inputs/lib-search-paths/usr/lib/libmyshared.dylib
new file mode 100755
index 0000000000000000000000000000000000000000..839d00d1927993b520130aa099695ee24865c68b
GIT binary patch
literal 8360
zcmeI2y-or_5XT3>j{tsKU~DdGj7kDFMhgoukVrH}BQbU>cxNOLO^zdxj>f__Fm`sn
zft97TK7sKCd;tpMe~w%3f)eeSN&eZL+1=UM9~BI*&CjnvqEMKK2A~n>qmSr@#xNtA
zhVCGx3c2F~M>?#v%@2A$a#BAO@>Y~`tZT>L_9I`HJna(^YP9E=_;qD7g-l>Y=jk$X
zUHn$RF0<$q{qsuwo-d-eATRKAHLhzLQffE9x0B1}H8aCIqU-YfM=#8E>6$n+46Q&3
zC>Xyemn!w at dC|7alv#&|b+%ce2JipVj8;y51Lr=0&+`VxMT{|M9|{`ZuN92{XFh{X
zd{6S>;A!rD_2~9A_42k>o}5R_MG=h>LCf05$QFmzAwJ9X5k2E02vNFLwbOVu>#$yR
ztV(Jt2x0*{Id8%s8p62b`38KpB*g3NZ(<Y^0zyCt2mv7=1cZPP5CTF#2=oep)_1F3
zd9A!t2nYcoAOwVf5D)@FKnMr{As_^VK#vj#sWbbkqI6T4Cc<tnSkq{}$GMHa0dWhM
zZ3;0Sxn0aL{@Vcmj1UX7WZ}APc6VWvSKVeW(Kx0!q;ru$9rvTDZK|qME2&cX(zI;O
G1p5ZJR#I93
literal 0
HcmV?d00001
diff --git a/test/mach-o/Inputs/lib-search-paths/usr/lib/libmystatic.a b/test/mach-o/Inputs/lib-search-paths/usr/lib/libmystatic.a
new file mode 100644
index 0000000000000000000000000000000000000000..b12062941f376d739ba0bee9161c165f25c6a2a0
GIT binary patch
literal 556
zcmY$iNi0gvu;bEKKm~>-1}5evX6B}b3JL~bDP&SX!N>%rK7osYfq at Z-W8%|_@^j;J
zD~n4KOEQxg7+@^De2D2VGfgZN6if|(1}hkW4K*|{Ff##~2ecAuXad*yUvK}h1I=ZI
z8V;fZK(;6VF%U=s at e42uJHY}KE&%BP0vI1?CIbjFfdqjdKE5Qiq6ET*@Izc9LJ)j(
z7R)>(@dhL|(7cqyl0<|^e7uWeh$DgzW5L`5G7sh!m>e<<l9K at 95}-ODVrT&p0zjG@
Zhy#Ea8Gz(Lm>dAI2c(xD*)eDl3IOc4H2MGl
literal 0
HcmV?d00001
diff --git a/test/mach-o/Inputs/lib-search-paths/usr/local/lib/file.o b/test/mach-o/Inputs/lib-search-paths/usr/local/lib/file.o
new file mode 100644
index 0000000000000000000000000000000000000000..f9a923d37db381942611b306f0c87ed7266b2723
GIT binary patch
literal 404
zcmX^A>+L^w1_nlE1|R{%AUXiVPyk{ekOblvU>0_Q1u9$s(gOrAKF~}C5M}}i0zrIy
zNoqw2gbm?`xJHB^_~<N{c}U_7NNk{aDTyVC2$A at B7sn7s1RutNxd&t(%q=iEWEvzV
y0mLOhbwI?>0we^0G&c|j05LKE$%8OCKnth|q?aGrG4W|d`ML3FnK`NXATt4O85SG>
literal 0
HcmV?d00001
diff --git a/test/mach-o/lib-search-paths.yaml b/test/mach-o/lib-search-paths.yaml
new file mode 100644
index 0000000..88c4b51
--- /dev/null
+++ b/test/mach-o/lib-search-paths.yaml
@@ -0,0 +1,16 @@
+# RUN: lld -flavor darwin -arch x86_64 %s -syslibroot %p/Inputs/lib-search-paths -lmyshared -lmystatic -lfile.o -print_atoms 2>&1 -r | FileCheck %s
+
+--- !native
+undefined-atoms:
+ - name: _from_myshared
+ - name: _from_mystatic
+ - name: _from_fileo
+
+# CHECK: defined-atoms:
+# CHECK: - name: _from_mystatic
+# CHECK: content: [ 02, 00, 00, 00 ]
+# CHECK: - name: _from_fileo
+# CHECK: content: [ 2A, 00, 00, 00 ]
+# CHECK: shared-library-atoms:
+# CHECK: - name: _from_myshared
+# CHECK: load-name: libmyshared.dylib
More information about the llvm-commits
mailing list