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 "OutputSegment.h" 13 #include "SymbolTable.h" 14 #include "Symbols.h" 15 #include "Target.h" 16 #include "Writer.h" 17 18 #include "lld/Common/Args.h" 19 #include "lld/Common/Driver.h" 20 #include "lld/Common/ErrorHandler.h" 21 #include "lld/Common/LLVM.h" 22 #include "lld/Common/Memory.h" 23 #include "lld/Common/Version.h" 24 #include "llvm/ADT/StringExtras.h" 25 #include "llvm/ADT/StringRef.h" 26 #include "llvm/BinaryFormat/MachO.h" 27 #include "llvm/BinaryFormat/Magic.h" 28 #include "llvm/Option/ArgList.h" 29 #include "llvm/Option/Option.h" 30 #include "llvm/Support/MemoryBuffer.h" 31 32 using namespace llvm; 33 using namespace llvm::MachO; 34 using namespace llvm::sys; 35 using namespace lld; 36 using namespace lld::macho; 37 38 Configuration *lld::macho::config; 39 40 // Create prefix string literals used in Options.td 41 #define PREFIX(NAME, VALUE) const char *NAME[] = VALUE; 42 #include "Options.inc" 43 #undef PREFIX 44 45 // Create table mapping all options defined in Options.td 46 static const opt::OptTable::Info optInfo[] = { 47 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ 48 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ 49 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, 50 #include "Options.inc" 51 #undef OPTION 52 }; 53 54 MachOOptTable::MachOOptTable() : OptTable(optInfo) {} 55 56 opt::InputArgList MachOOptTable::parse(ArrayRef<const char *> argv) { 57 // Make InputArgList from string vectors. 58 unsigned missingIndex; 59 unsigned missingCount; 60 SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size()); 61 62 opt::InputArgList args = ParseArgs(vec, missingIndex, missingCount); 63 64 if (missingCount) 65 error(Twine(args.getArgString(missingIndex)) + ": missing argument"); 66 67 for (opt::Arg *arg : args.filtered(OPT_UNKNOWN)) 68 error("unknown argument: " + arg->getSpelling()); 69 return args; 70 } 71 72 // This is for -lfoo. We'll look for libfoo.dylib from search paths. 73 static Optional<std::string> findDylib(StringRef name) { 74 for (StringRef dir : config->searchPaths) { 75 std::string path = (dir + "/lib" + name + ".dylib").str(); 76 if (fs::exists(path)) 77 return path; 78 } 79 error("library not found for -l" + name); 80 return None; 81 } 82 83 static TargetInfo *createTargetInfo(opt::InputArgList &args) { 84 StringRef s = args.getLastArgValue(OPT_arch, "x86_64"); 85 if (s != "x86_64") 86 error("missing or unsupported -arch " + s); 87 return createX86_64TargetInfo(); 88 } 89 90 static std::vector<StringRef> getSearchPaths(opt::InputArgList &args) { 91 std::vector<StringRef> ret{args::getStrings(args, OPT_L)}; 92 if (!args.hasArg(OPT_Z)) { 93 ret.push_back("/usr/lib"); 94 ret.push_back("/usr/local/lib"); 95 } 96 return ret; 97 } 98 99 static void addFile(StringRef path) { 100 Optional<MemoryBufferRef> buffer = readFile(path); 101 if (!buffer) 102 return; 103 MemoryBufferRef mbref = *buffer; 104 105 switch (identify_magic(mbref.getBuffer())) { 106 case file_magic::macho_object: 107 inputFiles.push_back(make<ObjFile>(mbref)); 108 break; 109 case file_magic::macho_dynamically_linked_shared_lib: 110 inputFiles.push_back(make<DylibFile>(mbref)); 111 break; 112 default: 113 error(path + ": unhandled file type"); 114 } 115 } 116 117 bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly, 118 raw_ostream &stdoutOS, raw_ostream &stderrOS) { 119 lld::stdoutOS = &stdoutOS; 120 lld::stderrOS = &stderrOS; 121 122 MachOOptTable parser; 123 opt::InputArgList args = parser.parse(argsArr.slice(1)); 124 125 config = make<Configuration>(); 126 symtab = make<SymbolTable>(); 127 target = createTargetInfo(args); 128 129 config->entry = symtab->addUndefined(args.getLastArgValue(OPT_e, "_main")); 130 config->outputFile = args.getLastArgValue(OPT_o, "a.out"); 131 config->searchPaths = getSearchPaths(args); 132 133 if (args.hasArg(OPT_v)) { 134 message(getLLDVersion()); 135 std::vector<StringRef> &searchPaths = config->searchPaths; 136 message("Library search paths:\n" + 137 llvm::join(searchPaths.begin(), searchPaths.end(), "\n")); 138 freeArena(); 139 return !errorCount(); 140 } 141 142 for (opt::Arg *arg : args) { 143 switch (arg->getOption().getID()) { 144 case OPT_INPUT: 145 addFile(arg->getValue()); 146 break; 147 case OPT_l: 148 if (Optional<std::string> path = findDylib(arg->getValue())) 149 addFile(*path); 150 break; 151 } 152 } 153 154 if (!isa<Defined>(config->entry)) { 155 error("undefined symbol: " + config->entry->getName()); 156 return false; 157 } 158 159 createSyntheticSections(); 160 161 // Initialize InputSections. 162 for (InputFile *file : inputFiles) 163 for (InputSection *sec : file->sections) 164 inputSections.push_back(sec); 165 166 // Write to an output file. 167 writeResult(); 168 169 if (canExitEarly) 170 exitLld(errorCount() ? 1 : 0); 171 172 freeArena(); 173 return !errorCount(); 174 } 175