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 // This is for -lfoo. We'll look for libfoo.dylib from search paths. 77 static Optional<std::string> findDylib(StringRef name) { 78 for (StringRef dir : config->searchPaths) { 79 std::string path = (dir + "/lib" + name + ".dylib").str(); 80 if (fs::exists(path)) 81 return path; 82 } 83 error("library not found for -l" + name); 84 return None; 85 } 86 87 static TargetInfo *createTargetInfo(opt::InputArgList &args) { 88 StringRef s = args.getLastArgValue(OPT_arch, "x86_64"); 89 if (s != "x86_64") 90 error("missing or unsupported -arch " + s); 91 return createX86_64TargetInfo(); 92 } 93 94 static std::vector<StringRef> getSearchPaths(opt::InputArgList &args) { 95 std::vector<StringRef> ret{args::getStrings(args, OPT_L)}; 96 if (!args.hasArg(OPT_Z)) { 97 ret.push_back("/usr/lib"); 98 ret.push_back("/usr/local/lib"); 99 } 100 return ret; 101 } 102 103 static void addFile(StringRef path) { 104 Optional<MemoryBufferRef> buffer = readFile(path); 105 if (!buffer) 106 return; 107 MemoryBufferRef mbref = *buffer; 108 109 switch (identify_magic(mbref.getBuffer())) { 110 case file_magic::archive: { 111 std::unique_ptr<object::Archive> file = CHECK( 112 object::Archive::create(mbref), path + ": failed to parse archive"); 113 114 if (!file->isEmpty() && !file->hasSymbolTable()) 115 error(path + ": archive has no index; run ranlib to add one"); 116 117 inputFiles.push_back(make<ArchiveFile>(std::move(file))); 118 break; 119 } 120 case file_magic::macho_object: 121 inputFiles.push_back(make<ObjFile>(mbref)); 122 break; 123 case file_magic::macho_dynamically_linked_shared_lib: 124 inputFiles.push_back(make<DylibFile>(mbref)); 125 break; 126 default: 127 error(path + ": unhandled file type"); 128 } 129 } 130 131 static std::array<StringRef, 6> archNames{"arm", "arm64", "i386", 132 "x86_64", "ppc", "ppc64"}; 133 static bool isArchString(StringRef s) { 134 static DenseSet<StringRef> archNamesSet(archNames.begin(), archNames.end()); 135 return archNamesSet.find(s) != archNamesSet.end(); 136 } 137 138 // An order file has one entry per line, in the following format: 139 // 140 // <arch>:<object file>:<symbol name> 141 // 142 // <arch> and <object file> are optional. If not specified, then that entry 143 // matches any symbol of that name. 144 // 145 // If a symbol is matched by multiple entries, then it takes the lowest-ordered 146 // entry (the one nearest to the front of the list.) 147 // 148 // The file can also have line comments that start with '#'. 149 void parseOrderFile(StringRef path) { 150 Optional<MemoryBufferRef> buffer = readFile(path); 151 if (!buffer) { 152 error("Could not read order file at " + path); 153 return; 154 } 155 156 MemoryBufferRef mbref = *buffer; 157 size_t priority = std::numeric_limits<size_t>::max(); 158 for (StringRef rest : args::getLines(mbref)) { 159 StringRef arch, objectFile, symbol; 160 161 std::array<StringRef, 3> fields; 162 uint8_t fieldCount = 0; 163 while (rest != "" && fieldCount < 3) { 164 std::pair<StringRef, StringRef> p = getToken(rest, ": \t\n\v\f\r"); 165 StringRef tok = p.first; 166 rest = p.second; 167 168 // Check if we have a comment 169 if (tok == "" || tok[0] == '#') 170 break; 171 172 fields[fieldCount++] = tok; 173 } 174 175 switch (fieldCount) { 176 case 3: 177 arch = fields[0]; 178 objectFile = fields[1]; 179 symbol = fields[2]; 180 break; 181 case 2: 182 (isArchString(fields[0]) ? arch : objectFile) = fields[0]; 183 symbol = fields[1]; 184 break; 185 case 1: 186 symbol = fields[0]; 187 break; 188 case 0: 189 break; 190 default: 191 llvm_unreachable("too many fields in order file"); 192 } 193 194 if (!arch.empty()) { 195 if (!isArchString(arch)) { 196 error("invalid arch \"" + arch + "\" in order file: expected one of " + 197 llvm::join(archNames, ", ")); 198 continue; 199 } 200 201 // TODO: Update when we extend support for other archs 202 if (arch != "x86_64") 203 continue; 204 } 205 206 if (!objectFile.empty() && !objectFile.endswith(".o")) { 207 error("invalid object file name \"" + objectFile + 208 "\" in order file: should end with .o"); 209 continue; 210 } 211 212 if (!symbol.empty()) { 213 SymbolPriorityEntry &entry = config->priorities[symbol]; 214 if (!objectFile.empty()) 215 entry.objectFiles.insert(std::make_pair(objectFile, priority)); 216 else 217 entry.anyObjectFile = std::max(entry.anyObjectFile, priority); 218 } 219 220 --priority; 221 } 222 } 223 224 // We expect sub-library names of the form "libfoo", which will match a dylib 225 // with a path of .*/libfoo.dylib. 226 static bool markSubLibrary(StringRef searchName) { 227 for (InputFile *file : inputFiles) { 228 if (auto *dylibFile = dyn_cast<DylibFile>(file)) { 229 StringRef filename = path::filename(dylibFile->getName()); 230 if (filename.consume_front(searchName) && filename == ".dylib") { 231 dylibFile->reexport = true; 232 return true; 233 } 234 } 235 } 236 return false; 237 } 238 239 static void handlePlatformVersion(opt::ArgList::iterator &it, 240 const opt::ArgList::iterator &end) { 241 // -platform_version takes 3 args, which LLVM's option library doesn't 242 // support directly. So this explicitly handles that. 243 // FIXME: stash skipped args for later use. 244 for (int i = 0; i < 3; ++i) { 245 ++it; 246 if (it == end || (*it)->getOption().getID() != OPT_INPUT) 247 fatal("usage: -platform_version platform min_version sdk_version"); 248 } 249 } 250 251 bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly, 252 raw_ostream &stdoutOS, raw_ostream &stderrOS) { 253 lld::stdoutOS = &stdoutOS; 254 lld::stderrOS = &stderrOS; 255 256 stderrOS.enable_colors(stderrOS.has_colors()); 257 // TODO: Set up error handler properly, e.g. the errorLimitExceededMsg 258 259 MachOOptTable parser; 260 opt::InputArgList args = parser.parse(argsArr.slice(1)); 261 262 config = make<Configuration>(); 263 symtab = make<SymbolTable>(); 264 target = createTargetInfo(args); 265 266 config->entry = symtab->addUndefined(args.getLastArgValue(OPT_e, "_main")); 267 config->outputFile = args.getLastArgValue(OPT_o, "a.out"); 268 config->installName = 269 args.getLastArgValue(OPT_install_name, config->outputFile); 270 config->searchPaths = getSearchPaths(args); 271 config->outputType = args.hasArg(OPT_dylib) ? MH_DYLIB : MH_EXECUTE; 272 273 if (args.hasArg(OPT_v)) { 274 message(getLLDVersion()); 275 std::vector<StringRef> &searchPaths = config->searchPaths; 276 message("Library search paths:\n" + 277 llvm::join(searchPaths.begin(), searchPaths.end(), "\n")); 278 freeArena(); 279 return !errorCount(); 280 } 281 282 for (opt::ArgList::iterator it = args.begin(), end = args.end(); it != end; 283 ++it) { 284 const opt::Arg *arg = *it; 285 switch (arg->getOption().getID()) { 286 case OPT_INPUT: 287 addFile(arg->getValue()); 288 break; 289 case OPT_l: 290 if (Optional<std::string> path = findDylib(arg->getValue())) 291 addFile(*path); 292 break; 293 case OPT_platform_version: { 294 handlePlatformVersion(it, end); // Can advance "it". 295 break; 296 } 297 } 298 } 299 300 // Now that all dylibs have been loaded, search for those that should be 301 // re-exported. 302 for (opt::Arg *arg : args.filtered(OPT_sub_library)) { 303 config->hasReexports = true; 304 StringRef searchName = arg->getValue(); 305 if (!markSubLibrary(searchName)) 306 error("-sub_library " + searchName + " does not match a supplied dylib"); 307 } 308 309 StringRef orderFile = args.getLastArgValue(OPT_order_file); 310 if (!orderFile.empty()) 311 parseOrderFile(orderFile); 312 313 // dyld requires us to load libSystem. Since we may run tests on non-OSX 314 // systems which do not have libSystem, we mock it out here. 315 // TODO: Replace this with a stub tbd file once we have TAPI support. 316 if (StringRef(getenv("LLD_IN_TEST")) == "1" && 317 config->outputType == MH_EXECUTE) { 318 inputFiles.push_back(DylibFile::createLibSystemMock()); 319 } 320 321 if (config->outputType == MH_EXECUTE && !isa<Defined>(config->entry)) { 322 error("undefined symbol: " + config->entry->getName()); 323 return false; 324 } 325 326 createSyntheticSections(); 327 328 // Initialize InputSections. 329 for (InputFile *file : inputFiles) { 330 for (SubsectionMap &map : file->subsections) { 331 for (auto &p : map) { 332 InputSection *isec = p.second; 333 inputSections.push_back(isec); 334 } 335 } 336 } 337 338 // Write to an output file. 339 writeResult(); 340 341 if (canExitEarly) 342 exitLld(errorCount() ? 1 : 0); 343 344 freeArena(); 345 return !errorCount(); 346 } 347