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/StringRef.h" 25 #include "llvm/BinaryFormat/MachO.h" 26 #include "llvm/BinaryFormat/Magic.h" 27 #include "llvm/Option/ArgList.h" 28 #include "llvm/Option/Option.h" 29 #include "llvm/Support/MemoryBuffer.h" 30 31 using namespace llvm; 32 using namespace llvm::MachO; 33 using namespace llvm::sys; 34 using namespace lld; 35 using namespace lld::macho; 36 37 Configuration *lld::macho::config; 38 39 // Create prefix string literals used in Options.td 40 #define PREFIX(NAME, VALUE) const char *NAME[] = VALUE; 41 #include "Options.inc" 42 #undef PREFIX 43 44 // Create table mapping all options defined in Options.td 45 static const opt::OptTable::Info optInfo[] = { 46 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ 47 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ 48 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, 49 #include "Options.inc" 50 #undef OPTION 51 }; 52 53 MachOOptTable::MachOOptTable() : OptTable(optInfo) {} 54 55 opt::InputArgList MachOOptTable::parse(ArrayRef<const char *> argv) { 56 // Make InputArgList from string vectors. 57 unsigned missingIndex; 58 unsigned missingCount; 59 SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size()); 60 61 opt::InputArgList args = ParseArgs(vec, missingIndex, missingCount); 62 63 if (missingCount) 64 error(Twine(args.getArgString(missingIndex)) + ": missing argument"); 65 66 for (opt::Arg *arg : args.filtered(OPT_UNKNOWN)) 67 error("unknown argument: " + arg->getSpelling()); 68 return args; 69 } 70 71 static TargetInfo *createTargetInfo(opt::InputArgList &args) { 72 StringRef s = args.getLastArgValue(OPT_arch, "x86_64"); 73 if (s != "x86_64") 74 error("missing or unsupported -arch " + s); 75 return createX86_64TargetInfo(); 76 } 77 78 static void addFile(StringRef path) { 79 Optional<MemoryBufferRef> buffer = readFile(path); 80 if (!buffer) 81 return; 82 MemoryBufferRef mbref = *buffer; 83 84 switch (identify_magic(mbref.getBuffer())) { 85 case file_magic::macho_object: 86 inputFiles.push_back(make<ObjFile>(mbref)); 87 break; 88 default: 89 error(path + ": unhandled file type"); 90 } 91 } 92 93 bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly, 94 raw_ostream &stdoutOS, raw_ostream &stderrOS) { 95 lld::stdoutOS = &stdoutOS; 96 lld::stderrOS = &stderrOS; 97 98 MachOOptTable parser; 99 opt::InputArgList args = parser.parse(argsArr.slice(1)); 100 101 if (args.hasArg(OPT_v)) { 102 message(getLLDVersion()); 103 freeArena(); 104 return !errorCount(); 105 } 106 107 config = make<Configuration>(); 108 symtab = make<SymbolTable>(); 109 target = createTargetInfo(args); 110 111 config->entry = symtab->addUndefined(args.getLastArgValue(OPT_e, "_main")); 112 config->outputFile = args.getLastArgValue(OPT_o, "a.out"); 113 114 getOrCreateOutputSegment("__TEXT", VM_PROT_READ | VM_PROT_EXECUTE); 115 getOrCreateOutputSegment("__DATA", VM_PROT_READ | VM_PROT_WRITE); 116 117 for (opt::Arg *arg : args) { 118 switch (arg->getOption().getID()) { 119 case OPT_INPUT: 120 addFile(arg->getValue()); 121 break; 122 } 123 } 124 125 if (!isa<Defined>(config->entry)) { 126 error("undefined symbol: " + config->entry->getName()); 127 return false; 128 } 129 130 // Initialize InputSections. 131 for (InputFile *file : inputFiles) 132 for (InputSection *sec : file->sections) 133 inputSections.push_back(sec); 134 135 // Add input sections to output segments. 136 for (InputSection *isec : inputSections) { 137 OutputSegment *os = 138 getOrCreateOutputSegment(isec->segname, VM_PROT_READ | VM_PROT_WRITE); 139 os->sections[isec->name].push_back(isec); 140 } 141 142 // Write to an output file. 143 writeResult(); 144 145 if (canExitEarly) 146 exitLld(errorCount() ? 1 : 0); 147 148 freeArena(); 149 return !errorCount(); 150 } 151