xref: /llvm-project-15.0.7/lld/MachO/Driver.cpp (revision 2c861e8a)
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/StringExtras.h"
26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/BinaryFormat/MachO.h"
28 #include "llvm/BinaryFormat/Magic.h"
29 #include "llvm/Option/ArgList.h"
30 #include "llvm/Option/Option.h"
31 #include "llvm/Support/MemoryBuffer.h"
32 #include "llvm/Support/Path.h"
33 
34 using namespace llvm;
35 using namespace llvm::MachO;
36 using namespace llvm::sys;
37 using namespace lld;
38 using namespace lld::macho;
39 
40 Configuration *lld::macho::config;
41 
42 // Create prefix string literals used in Options.td
43 #define PREFIX(NAME, VALUE) const char *NAME[] = VALUE;
44 #include "Options.inc"
45 #undef PREFIX
46 
47 // Create table mapping all options defined in Options.td
48 static const opt::OptTable::Info optInfo[] = {
49 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
50   {X1, X2, X10,         X11,         OPT_##ID, opt::Option::KIND##Class,       \
51    X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
52 #include "Options.inc"
53 #undef OPTION
54 };
55 
56 MachOOptTable::MachOOptTable() : OptTable(optInfo) {}
57 
58 opt::InputArgList MachOOptTable::parse(ArrayRef<const char *> argv) {
59   // Make InputArgList from string vectors.
60   unsigned missingIndex;
61   unsigned missingCount;
62   SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
63 
64   opt::InputArgList args = ParseArgs(vec, missingIndex, missingCount);
65 
66   if (missingCount)
67     error(Twine(args.getArgString(missingIndex)) + ": missing argument");
68 
69   for (opt::Arg *arg : args.filtered(OPT_UNKNOWN))
70     error("unknown argument: " + arg->getSpelling());
71   return args;
72 }
73 
74 // This is for -lfoo. We'll look for libfoo.dylib from search paths.
75 static Optional<std::string> findDylib(StringRef name) {
76   for (StringRef dir : config->searchPaths) {
77     std::string path = (dir + "/lib" + name + ".dylib").str();
78     if (fs::exists(path))
79       return path;
80   }
81   error("library not found for -l" + name);
82   return None;
83 }
84 
85 static TargetInfo *createTargetInfo(opt::InputArgList &args) {
86   StringRef s = args.getLastArgValue(OPT_arch, "x86_64");
87   if (s != "x86_64")
88     error("missing or unsupported -arch " + s);
89   return createX86_64TargetInfo();
90 }
91 
92 static std::vector<StringRef> getSearchPaths(opt::InputArgList &args) {
93   std::vector<StringRef> ret{args::getStrings(args, OPT_L)};
94   if (!args.hasArg(OPT_Z)) {
95     ret.push_back("/usr/lib");
96     ret.push_back("/usr/local/lib");
97   }
98   return ret;
99 }
100 
101 static void addFile(StringRef path) {
102   Optional<MemoryBufferRef> buffer = readFile(path);
103   if (!buffer)
104     return;
105   MemoryBufferRef mbref = *buffer;
106 
107   switch (identify_magic(mbref.getBuffer())) {
108   case file_magic::macho_object:
109     inputFiles.push_back(make<ObjFile>(mbref));
110     break;
111   case file_magic::macho_dynamically_linked_shared_lib:
112     inputFiles.push_back(make<DylibFile>(mbref));
113     break;
114   default:
115     error(path + ": unhandled file type");
116   }
117 }
118 
119 // We expect sub-library names of the form "libfoo", which will match a dylib
120 // with a path of .*/libfoo.dylib.
121 static bool markSubLibrary(StringRef searchName) {
122   for (InputFile *file : inputFiles) {
123     if (auto *dylibFile = dyn_cast<DylibFile>(file)) {
124       StringRef filename = path::filename(dylibFile->getName());
125       if (filename.consume_front(searchName) && filename == ".dylib") {
126         dylibFile->reexport = true;
127         return true;
128       }
129     }
130   }
131   return false;
132 }
133 
134 bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
135                  raw_ostream &stdoutOS, raw_ostream &stderrOS) {
136   lld::stdoutOS = &stdoutOS;
137   lld::stderrOS = &stderrOS;
138 
139   stderrOS.enable_colors(stderrOS.has_colors());
140   // TODO: Set up error handler properly, e.g. the errorLimitExceededMsg
141 
142   MachOOptTable parser;
143   opt::InputArgList args = parser.parse(argsArr.slice(1));
144 
145   config = make<Configuration>();
146   symtab = make<SymbolTable>();
147   target = createTargetInfo(args);
148 
149   config->entry = symtab->addUndefined(args.getLastArgValue(OPT_e, "_main"));
150   config->outputFile = args.getLastArgValue(OPT_o, "a.out");
151   config->installName =
152       args.getLastArgValue(OPT_install_name, config->outputFile);
153   config->searchPaths = getSearchPaths(args);
154   config->outputType = args.hasArg(OPT_dylib) ? MH_DYLIB : MH_EXECUTE;
155 
156   if (args.hasArg(OPT_v)) {
157     message(getLLDVersion());
158     std::vector<StringRef> &searchPaths = config->searchPaths;
159     message("Library search paths:\n" +
160             llvm::join(searchPaths.begin(), searchPaths.end(), "\n"));
161     freeArena();
162     return !errorCount();
163   }
164 
165   for (opt::Arg *arg : args) {
166     switch (arg->getOption().getID()) {
167     case OPT_INPUT:
168       addFile(arg->getValue());
169       break;
170     case OPT_l:
171       if (Optional<std::string> path = findDylib(arg->getValue()))
172         addFile(*path);
173       break;
174     }
175   }
176 
177   // Now that all dylibs have been loaded, search for those that should be
178   // re-exported.
179   for (opt::Arg *arg : args.filtered(OPT_sub_library)) {
180     config->hasReexports = true;
181     StringRef searchName = arg->getValue();
182     if (!markSubLibrary(searchName))
183       error("-sub_library " + searchName + " does not match a supplied dylib");
184   }
185 
186   // dyld requires us to load libSystem. Since we may run tests on non-OSX
187   // systems which do not have libSystem, we mock it out here.
188   // TODO: Replace this with a stub tbd file once we have TAPI support.
189   if (StringRef(getenv("LLD_IN_TEST")) == "1" &&
190       config->outputType == MH_EXECUTE) {
191     inputFiles.push_back(DylibFile::createLibSystemMock());
192   }
193 
194   if (config->outputType == MH_EXECUTE && !isa<Defined>(config->entry)) {
195     error("undefined symbol: " + config->entry->getName());
196     return false;
197   }
198 
199   createSyntheticSections();
200 
201   // Initialize InputSections.
202   for (InputFile *file : inputFiles)
203     for (InputSection *sec : file->sections)
204       inputSections.push_back(sec);
205 
206   // Write to an output file.
207   writeResult();
208 
209   if (canExitEarly)
210     exitLld(errorCount() ? 1 : 0);
211 
212   freeArena();
213   return !errorCount();
214 }
215