1 //===- DriverUtils.cpp ----------------------------------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains utility functions for the driver. Because there 11 // are so many small functions, we created this separate file to make 12 // Driver.cpp less cluttered. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "Driver.h" 17 #include "Error.h" 18 #include "llvm/ADT/STLExtras.h" 19 #include "llvm/Support/CommandLine.h" 20 #include "llvm/Support/FileSystem.h" 21 #include "llvm/Support/Path.h" 22 #include "llvm/Support/StringSaver.h" 23 24 using namespace llvm; 25 26 using namespace lld; 27 using namespace lld::elf2; 28 29 // Create OptTable 30 31 // Create prefix string literals used in Options.td 32 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; 33 #include "Options.inc" 34 #undef PREFIX 35 36 // Create table mapping all options defined in Options.td 37 static const opt::OptTable::Info infoTable[] = { 38 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ 39 { \ 40 X1, X2, X9, X10, OPT_##ID, opt::Option::KIND##Class, X8, X7, OPT_##GROUP, \ 41 OPT_##ALIAS, X6 \ 42 } \ 43 , 44 #include "Options.inc" 45 #undef OPTION 46 }; 47 48 class ELFOptTable : public opt::OptTable { 49 public: 50 ELFOptTable() : OptTable(infoTable) {} 51 }; 52 53 // Parses a given list of options. 54 opt::InputArgList lld::elf2::parseArgs(llvm::BumpPtrAllocator *A, 55 ArrayRef<const char *> Argv) { 56 // Make InputArgList from string vectors. 57 ELFOptTable Table; 58 unsigned MissingIndex; 59 unsigned MissingCount; 60 61 // Expand response files. '@<filename>' is replaced by the file's contents. 62 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size()); 63 StringSaver Saver(*A); 64 llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, Vec); 65 66 // Parse options and then do error checking. 67 opt::InputArgList Args = Table.ParseArgs(Vec, MissingIndex, MissingCount); 68 if (MissingCount) 69 error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) + 70 "\", expected " + Twine(MissingCount) + 71 (MissingCount == 1 ? " argument.\n" : " arguments")); 72 73 iterator_range<opt::arg_iterator> Unknowns = Args.filtered(OPT_UNKNOWN); 74 for (auto *Arg : Unknowns) 75 warning("warning: unknown argument: " + Arg->getSpelling()); 76 if (Unknowns.begin() != Unknowns.end()) 77 error("unknown argument(s) found"); 78 79 return Args; 80 } 81 82 std::string lld::elf2::findFromSearchPaths(StringRef Path) { 83 for (StringRef Dir : Config->SearchPaths) { 84 std::string FullPath = buildSysrootedPath(Dir, Path); 85 if (sys::fs::exists(FullPath)) 86 return FullPath; 87 } 88 return ""; 89 } 90 91 // Searches a given library from input search paths, which are filled 92 // from -L command line switches. Returns a path to an existent library file. 93 std::string lld::elf2::searchLibrary(StringRef Path) { 94 std::vector<std::string> Names; 95 if (Path[0] == ':') { 96 Names.push_back(Path.drop_front()); 97 } else { 98 if (!Config->Static) 99 Names.push_back(("lib" + Path + ".so").str()); 100 Names.push_back(("lib" + Path + ".a").str()); 101 } 102 for (const std::string &Name : Names) { 103 std::string S = findFromSearchPaths(Name); 104 if (!S.empty()) 105 return S; 106 } 107 error("Unable to find library -l" + Path); 108 } 109 110 // Makes a path by concatenating Dir and File. 111 // If Dir starts with '=' the result will be preceded by Sysroot, 112 // which can be set with --sysroot command line switch. 113 std::string lld::elf2::buildSysrootedPath(StringRef Dir, StringRef File) { 114 SmallString<128> Path; 115 if (Dir.startswith("=")) 116 sys::path::append(Path, Config->Sysroot, Dir.substr(1), File); 117 else 118 sys::path::append(Path, Dir, File); 119 return Path.str(); 120 } 121