xref: /llvm-project-15.0.7/lld/MachO/Driver.cpp (revision e80617df)
1 //===- Driver.cpp ---------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Driver.h"
10 #include "Config.h"
11 #include "InputFiles.h"
12 #include "OutputSection.h"
13 #include "OutputSegment.h"
14 #include "SymbolTable.h"
15 #include "Symbols.h"
16 #include "Target.h"
17 #include "Writer.h"
18 
19 #include "lld/Common/Args.h"
20 #include "lld/Common/Driver.h"
21 #include "lld/Common/ErrorHandler.h"
22 #include "lld/Common/LLVM.h"
23 #include "lld/Common/Memory.h"
24 #include "lld/Common/Version.h"
25 #include "llvm/ADT/DenseSet.h"
26 #include "llvm/ADT/StringExtras.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/BinaryFormat/MachO.h"
29 #include "llvm/BinaryFormat/Magic.h"
30 #include "llvm/Object/Archive.h"
31 #include "llvm/Option/ArgList.h"
32 #include "llvm/Option/Option.h"
33 #include "llvm/Support/MemoryBuffer.h"
34 #include "llvm/Support/Path.h"
35 
36 using namespace llvm;
37 using namespace llvm::MachO;
38 using namespace llvm::sys;
39 using namespace lld;
40 using namespace lld::macho;
41 
42 Configuration *lld::macho::config;
43 
44 // Create prefix string literals used in Options.td
45 #define PREFIX(NAME, VALUE) const char *NAME[] = VALUE;
46 #include "Options.inc"
47 #undef PREFIX
48 
49 // Create table mapping all options defined in Options.td
50 static const opt::OptTable::Info optInfo[] = {
51 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
52   {X1, X2, X10,         X11,         OPT_##ID, opt::Option::KIND##Class,       \
53    X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
54 #include "Options.inc"
55 #undef OPTION
56 };
57 
58 MachOOptTable::MachOOptTable() : OptTable(optInfo) {}
59 
60 opt::InputArgList MachOOptTable::parse(ArrayRef<const char *> argv) {
61   // Make InputArgList from string vectors.
62   unsigned missingIndex;
63   unsigned missingCount;
64   SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
65 
66   opt::InputArgList args = ParseArgs(vec, missingIndex, missingCount);
67 
68   if (missingCount)
69     error(Twine(args.getArgString(missingIndex)) + ": missing argument");
70 
71   for (opt::Arg *arg : args.filtered(OPT_UNKNOWN))
72     error("unknown argument: " + arg->getSpelling());
73   return args;
74 }
75 
76 static Optional<std::string> findLibrary(StringRef name) {
77   std::string shared = (llvm::Twine("lib") + name + ".dylib").str();
78   std::string archive = (llvm::Twine("lib") + name + ".a").str();
79   llvm::SmallString<260> location;
80 
81   for (StringRef dir : config->searchPaths) {
82     for (StringRef library : {shared, archive}) {
83       location = dir;
84       llvm::sys::path::append(location, library);
85       if (fs::exists(location))
86         return location.str().str();
87     }
88   }
89   return None;
90 }
91 
92 static TargetInfo *createTargetInfo(opt::InputArgList &args) {
93   StringRef s = args.getLastArgValue(OPT_arch, "x86_64");
94   if (s != "x86_64")
95     error("missing or unsupported -arch " + s);
96   return createX86_64TargetInfo();
97 }
98 
99 static std::vector<StringRef> getSearchPaths(opt::InputArgList &args) {
100   std::vector<StringRef> ret{args::getStrings(args, OPT_L)};
101   if (!args.hasArg(OPT_Z)) {
102     ret.push_back("/usr/lib");
103     ret.push_back("/usr/local/lib");
104   }
105   return ret;
106 }
107 
108 static void addFile(StringRef path) {
109   Optional<MemoryBufferRef> buffer = readFile(path);
110   if (!buffer)
111     return;
112   MemoryBufferRef mbref = *buffer;
113 
114   switch (identify_magic(mbref.getBuffer())) {
115   case file_magic::archive: {
116     std::unique_ptr<object::Archive> file = CHECK(
117         object::Archive::create(mbref), path + ": failed to parse archive");
118 
119     if (!file->isEmpty() && !file->hasSymbolTable())
120       error(path + ": archive has no index; run ranlib to add one");
121 
122     inputFiles.push_back(make<ArchiveFile>(std::move(file)));
123     break;
124   }
125   case file_magic::macho_object:
126     inputFiles.push_back(make<ObjFile>(mbref));
127     break;
128   case file_magic::macho_dynamically_linked_shared_lib:
129     inputFiles.push_back(make<DylibFile>(mbref));
130     break;
131   default:
132     error(path + ": unhandled file type");
133   }
134 }
135 
136 static std::array<StringRef, 6> archNames{"arm",    "arm64", "i386",
137                                           "x86_64", "ppc",   "ppc64"};
138 static bool isArchString(StringRef s) {
139   static DenseSet<StringRef> archNamesSet(archNames.begin(), archNames.end());
140   return archNamesSet.find(s) != archNamesSet.end();
141 }
142 
143 // An order file has one entry per line, in the following format:
144 //
145 //   <arch>:<object file>:<symbol name>
146 //
147 // <arch> and <object file> are optional. If not specified, then that entry
148 // matches any symbol of that name.
149 //
150 // If a symbol is matched by multiple entries, then it takes the lowest-ordered
151 // entry (the one nearest to the front of the list.)
152 //
153 // The file can also have line comments that start with '#'.
154 void parseOrderFile(StringRef path) {
155   Optional<MemoryBufferRef> buffer = readFile(path);
156   if (!buffer) {
157     error("Could not read order file at " + path);
158     return;
159   }
160 
161   MemoryBufferRef mbref = *buffer;
162   size_t priority = std::numeric_limits<size_t>::max();
163   for (StringRef rest : args::getLines(mbref)) {
164     StringRef arch, objectFile, symbol;
165 
166     std::array<StringRef, 3> fields;
167     uint8_t fieldCount = 0;
168     while (rest != "" && fieldCount < 3) {
169       std::pair<StringRef, StringRef> p = getToken(rest, ": \t\n\v\f\r");
170       StringRef tok = p.first;
171       rest = p.second;
172 
173       // Check if we have a comment
174       if (tok == "" || tok[0] == '#')
175         break;
176 
177       fields[fieldCount++] = tok;
178     }
179 
180     switch (fieldCount) {
181     case 3:
182       arch = fields[0];
183       objectFile = fields[1];
184       symbol = fields[2];
185       break;
186     case 2:
187       (isArchString(fields[0]) ? arch : objectFile) = fields[0];
188       symbol = fields[1];
189       break;
190     case 1:
191       symbol = fields[0];
192       break;
193     case 0:
194       break;
195     default:
196       llvm_unreachable("too many fields in order file");
197     }
198 
199     if (!arch.empty()) {
200       if (!isArchString(arch)) {
201         error("invalid arch \"" + arch + "\" in order file: expected one of " +
202               llvm::join(archNames, ", "));
203         continue;
204       }
205 
206       // TODO: Update when we extend support for other archs
207       if (arch != "x86_64")
208         continue;
209     }
210 
211     if (!objectFile.empty() && !objectFile.endswith(".o")) {
212       error("invalid object file name \"" + objectFile +
213             "\" in order file: should end with .o");
214       continue;
215     }
216 
217     if (!symbol.empty()) {
218       SymbolPriorityEntry &entry = config->priorities[symbol];
219       if (!objectFile.empty())
220         entry.objectFiles.insert(std::make_pair(objectFile, priority));
221       else
222         entry.anyObjectFile = std::max(entry.anyObjectFile, priority);
223     }
224 
225     --priority;
226   }
227 }
228 
229 // We expect sub-library names of the form "libfoo", which will match a dylib
230 // with a path of .*/libfoo.dylib.
231 static bool markSubLibrary(StringRef searchName) {
232   for (InputFile *file : inputFiles) {
233     if (auto *dylibFile = dyn_cast<DylibFile>(file)) {
234       StringRef filename = path::filename(dylibFile->getName());
235       if (filename.consume_front(searchName) && filename == ".dylib") {
236         dylibFile->reexport = true;
237         return true;
238       }
239     }
240   }
241   return false;
242 }
243 
244 static void handlePlatformVersion(opt::ArgList::iterator &it,
245                                   const opt::ArgList::iterator &end) {
246   // -platform_version takes 3 args, which LLVM's option library doesn't
247   // support directly.  So this explicitly handles that.
248   // FIXME: stash skipped args for later use.
249   for (int i = 0; i < 3; ++i) {
250     ++it;
251     if (it == end || (*it)->getOption().getID() != OPT_INPUT)
252       fatal("usage: -platform_version platform min_version sdk_version");
253   }
254 }
255 
256 bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
257                  raw_ostream &stdoutOS, raw_ostream &stderrOS) {
258   lld::stdoutOS = &stdoutOS;
259   lld::stderrOS = &stderrOS;
260 
261   stderrOS.enable_colors(stderrOS.has_colors());
262   // TODO: Set up error handler properly, e.g. the errorLimitExceededMsg
263 
264   MachOOptTable parser;
265   opt::InputArgList args = parser.parse(argsArr.slice(1));
266 
267   config = make<Configuration>();
268   symtab = make<SymbolTable>();
269   target = createTargetInfo(args);
270 
271   config->entry = symtab->addUndefined(args.getLastArgValue(OPT_e, "_main"));
272   config->outputFile = args.getLastArgValue(OPT_o, "a.out");
273   config->installName =
274       args.getLastArgValue(OPT_install_name, config->outputFile);
275   config->searchPaths = getSearchPaths(args);
276   config->outputType = args.hasArg(OPT_dylib) ? MH_DYLIB : MH_EXECUTE;
277 
278   if (args.hasArg(OPT_v)) {
279     message(getLLDVersion());
280     std::vector<StringRef> &searchPaths = config->searchPaths;
281     message("Library search paths:\n" +
282             llvm::join(searchPaths.begin(), searchPaths.end(), "\n"));
283     freeArena();
284     return !errorCount();
285   }
286 
287   for (opt::ArgList::iterator it = args.begin(), end = args.end(); it != end;
288        ++it) {
289     const opt::Arg *arg = *it;
290     switch (arg->getOption().getID()) {
291     case OPT_INPUT:
292       addFile(arg->getValue());
293       break;
294     case OPT_l: {
295       StringRef name = arg->getValue();
296       if (Optional<std::string> path = findLibrary(name)) {
297         addFile(*path);
298         break;
299       }
300       error("library not found for -l" + name);
301       break;
302     }
303     case OPT_platform_version: {
304       handlePlatformVersion(it, end); // Can advance "it".
305       break;
306     }
307     }
308   }
309 
310   // Now that all dylibs have been loaded, search for those that should be
311   // re-exported.
312   for (opt::Arg *arg : args.filtered(OPT_sub_library)) {
313     config->hasReexports = true;
314     StringRef searchName = arg->getValue();
315     if (!markSubLibrary(searchName))
316       error("-sub_library " + searchName + " does not match a supplied dylib");
317   }
318 
319   StringRef orderFile = args.getLastArgValue(OPT_order_file);
320   if (!orderFile.empty())
321     parseOrderFile(orderFile);
322 
323   // dyld requires us to load libSystem. Since we may run tests on non-OSX
324   // systems which do not have libSystem, we mock it out here.
325   // TODO: Replace this with a stub tbd file once we have TAPI support.
326   if (StringRef(getenv("LLD_IN_TEST")) == "1" &&
327       config->outputType == MH_EXECUTE) {
328     inputFiles.push_back(DylibFile::createLibSystemMock());
329   }
330 
331   if (config->outputType == MH_EXECUTE && !isa<Defined>(config->entry)) {
332     error("undefined symbol: " + config->entry->getName());
333     return false;
334   }
335 
336   createSyntheticSections();
337 
338   // Initialize InputSections.
339   for (InputFile *file : inputFiles) {
340     for (SubsectionMap &map : file->subsections) {
341       for (auto &p : map) {
342         InputSection *isec = p.second;
343         inputSections.push_back(isec);
344       }
345     }
346   }
347 
348   // Write to an output file.
349   writeResult();
350 
351   if (canExitEarly)
352     exitLld(errorCount() ? 1 : 0);
353 
354   freeArena();
355   return !errorCount();
356 }
357