blob: 06b0b651de8b368a27054d31e6ec09b1ff139fbe [file] [log] [blame]
Michael J. Spencer84487f12015-07-24 21:03:07 +00001//===- 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"
Rafael Espindola192e1fa2015-08-06 15:08:23 +000017#include "Error.h"
Rui Ueyama1abcf372016-02-28 03:18:07 +000018#include "lld/Config/Version.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000019#include "llvm/ADT/STLExtras.h"
Rui Ueyamaaf2312f2016-05-04 23:12:55 +000020#include "llvm/Option/Option.h"
Rui Ueyamaeeb22f82015-09-25 15:37:33 +000021#include "llvm/Support/CommandLine.h"
Rui Ueyama4b02ca92015-10-11 03:28:39 +000022#include "llvm/Support/FileSystem.h"
23#include "llvm/Support/Path.h"
Rui Ueyamac6e1b972015-10-11 18:19:01 +000024#include "llvm/Support/StringSaver.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000025
26using namespace llvm;
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +000027using namespace llvm::sys;
Michael J. Spencer84487f12015-07-24 21:03:07 +000028
29using namespace lld;
Rafael Espindolae0df00b2016-02-28 00:25:54 +000030using namespace lld::elf;
Michael J. Spencer84487f12015-07-24 21:03:07 +000031
32// Create OptTable
33
34// Create prefix string literals used in Options.td
35#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
36#include "Options.inc"
37#undef PREFIX
38
39// Create table mapping all options defined in Options.td
Rui Ueyama8fe7ce52016-04-02 19:15:26 +000040static const opt::OptTable::Info OptInfo[] = {
Michael J. Spencer84487f12015-07-24 21:03:07 +000041#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \
42 { \
43 X1, X2, X9, X10, OPT_##ID, opt::Option::KIND##Class, X8, X7, OPT_##GROUP, \
44 OPT_##ALIAS, X6 \
Rui Ueyama8fe7ce52016-04-02 19:15:26 +000045 },
Michael J. Spencer84487f12015-07-24 21:03:07 +000046#include "Options.inc"
47#undef OPTION
48};
49
Rui Ueyama8fe7ce52016-04-02 19:15:26 +000050ELFOptTable::ELFOptTable() : OptTable(OptInfo) {}
Michael J. Spencer84487f12015-07-24 21:03:07 +000051
52// Parses a given list of options.
Rui Ueyama15fa0352016-03-15 18:20:50 +000053opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) {
Michael J. Spencer84487f12015-07-24 21:03:07 +000054 // Make InputArgList from string vectors.
Michael J. Spencer84487f12015-07-24 21:03:07 +000055 unsigned MissingIndex;
56 unsigned MissingCount;
57
Rui Ueyamaeeb22f82015-09-25 15:37:33 +000058 // Expand response files. '@<filename>' is replaced by the file's contents.
59 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
Rui Ueyama15fa0352016-03-15 18:20:50 +000060 StringSaver Saver(Alloc);
Rui Ueyama5002a672016-05-02 19:59:56 +000061 cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Vec);
Rui Ueyamaeeb22f82015-09-25 15:37:33 +000062
63 // Parse options and then do error checking.
Rui Ueyama15fa0352016-03-15 18:20:50 +000064 opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
Michael J. Spencer84487f12015-07-24 21:03:07 +000065 if (MissingCount)
George Rimar57610422016-03-11 14:43:02 +000066 error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) +
Michael J. Spencer84487f12015-07-24 21:03:07 +000067 "\", expected " + Twine(MissingCount) +
68 (MissingCount == 1 ? " argument.\n" : " arguments"));
Rui Ueyamad5b5ab72015-09-24 18:55:33 +000069
70 iterator_range<opt::arg_iterator> Unknowns = Args.filtered(OPT_UNKNOWN);
71 for (auto *Arg : Unknowns)
George Rimar57610422016-03-11 14:43:02 +000072 warning("warning: unknown argument: " + Arg->getSpelling());
Rui Ueyamad5b5ab72015-09-24 18:55:33 +000073 if (Unknowns.begin() != Unknowns.end())
George Rimar57610422016-03-11 14:43:02 +000074 error("unknown argument(s) found");
Michael J. Spencer84487f12015-07-24 21:03:07 +000075 return Args;
76}
Rui Ueyama4b02ca92015-10-11 03:28:39 +000077
Rui Ueyama1eb9f442016-02-28 03:18:09 +000078void elf::printHelp(const char *Argv0) {
79 ELFOptTable Table;
80 Table.PrintHelp(outs(), Argv0, "lld", false);
81}
82
Rui Ueyama1abcf372016-02-28 03:18:07 +000083void elf::printVersion() {
84 outs() << "LLD " << getLLDVersion();
85 std::string S = getLLDRepositoryVersion();
86 if (!S.empty())
Rui Ueyama5bc2acd2016-03-13 23:07:42 +000087 outs() << " " << S;
88 outs() << "\n";
Rui Ueyama1abcf372016-02-28 03:18:07 +000089}
90
Rui Ueyamaaa00e962016-04-30 21:40:04 +000091// Makes a given pathname an absolute path first, and then remove
92// beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
93// assuming that the current directory is "/home/john/bar".
Rui Ueyama9aea9572016-04-30 22:23:29 +000094static std::string relativeToRoot(StringRef Path) {
Rui Ueyamaaa00e962016-04-30 21:40:04 +000095 SmallString<128> Abs = Path;
96 if (std::error_code EC = fs::make_absolute(Abs))
97 fatal("make_absolute failed: " + EC.message());
98 path::remove_dots(Abs, /*remove_dot_dot=*/true);
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +000099
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000100 // This is Windows specific. root_name() returns a drive letter
101 // (e.g. "c:") or a UNC name (//net). We want to keep it as part
102 // of the result.
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000103 SmallString<128> Res;
Rui Ueyamaff12f232016-05-02 18:16:14 +0000104 StringRef Root = path::root_name(Abs);
Rui Ueyama38aa57d2016-04-30 22:20:27 +0000105 if (Root.endswith(":"))
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000106 Res = Root.drop_back();
Rui Ueyama38aa57d2016-04-30 22:20:27 +0000107 else if (Root.startswith("//"))
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000108 Res = Root.substr(2);
109
110 path::append(Res, path::relative_path(Abs));
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000111 return Res.str();
112}
113
Rui Ueyama9aea9572016-04-30 22:23:29 +0000114static std::string getDestPath(StringRef Path) {
115 std::string Relpath = relativeToRoot(Path);
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000116 SmallString<128> Dest;
Rafael Espindola1dd2b3d2016-05-03 17:30:44 +0000117 path::append(Dest, path::filename(Config->Reproduce), Relpath);
Rui Ueyama9aea9572016-04-30 22:23:29 +0000118 return Dest.str();
119}
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000120
Rafael Espindola2c51e612016-05-04 12:47:56 +0000121static void maybePrintCpioMemberAux(raw_fd_ostream &OS, StringRef Path,
122 StringRef Data) {
Rafael Espindola1dd2b3d2016-05-03 17:30:44 +0000123 OS << "070707"; // c_magic
124
125 // The c_dev/c_ino pair should be unique according to the spec, but no one
126 // seems to care.
127 OS << "000000"; // c_dev
128 OS << "000000"; // c_ino
129
130 OS << "100664"; // c_mode: C_ISREG | rw-rw-r--
131 OS << "000000"; // c_uid
132 OS << "000000"; // c_gid
133 OS << "000001"; // c_nlink
134 OS << "000000"; // c_rdev
135 OS << "00000000000"; // c_mtime
136 OS << format("%06o", Path.size() + 1); // c_namesize
137 OS << format("%011o", Data.size()); // c_filesize
138 OS << Path << '\0'; // c_name
139 OS << Data; // c_filedata
140}
141
Rafael Espindola2c51e612016-05-04 12:47:56 +0000142static void maybePrintCpioMember(StringRef Path, StringRef Data) {
143 if (Config->Reproduce.empty())
144 return;
145
146 if (!Driver->IncludedFiles.insert(Path).second)
147 return;
148 raw_fd_ostream &OS = *Driver->ReproduceArchive;
149 maybePrintCpioMemberAux(OS, Path, Data);
150
151 // Print the trailer and seek back. This way we have a valid archive if we
152 // crash.
Rafael Espindolaf72914f2016-05-10 19:26:55 +0000153 // See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_11
154 // for the format details.
Rafael Espindola2c51e612016-05-04 12:47:56 +0000155 uint64_t Pos = OS.tell();
156 maybePrintCpioMemberAux(OS, "TRAILER!!!", "");
157 OS.seek(Pos);
158}
159
Rafael Espindola1dd2b3d2016-05-03 17:30:44 +0000160// Write file Src with content Data to the archive.
161void elf::maybeCopyInputFile(StringRef Src, StringRef Data) {
162 std::string Dest = getDestPath(Src);
163 maybePrintCpioMember(Dest, Data);
164}
165
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000166// Quote a given string if it contains a space character.
167static std::string quote(StringRef S) {
168 if (S.find(' ') == StringRef::npos)
169 return S;
170 return ("\"" + S + "\"").str();
171}
172
Rui Ueyama2796ae32016-04-30 22:46:47 +0000173static std::string rewritePath(StringRef S) {
174 if (fs::exists(S))
Rafael Espindolae85bcbd2016-05-02 14:12:35 +0000175 return relativeToRoot(S);
Rui Ueyama2796ae32016-04-30 22:46:47 +0000176 return S;
177}
178
Rui Ueyamaaf2312f2016-05-04 23:12:55 +0000179static std::string stringize(opt::Arg *Arg) {
180 std::string K = Arg->getSpelling();
181 if (Arg->getNumValues() == 0)
182 return K;
183 std::string V = quote(Arg->getValue());
184 if (Arg->getOption().getRenderStyle() == opt::Option::RenderJoinedStyle)
185 return K + V;
186 return K + " " + V;
187}
188
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000189// Copies all input files to Config->Reproduce directory and
190// create a response file as "response.txt", so that you can re-run
191// the same command with the same inputs just by executing
192// "ld.lld @response.txt". Used by --reproduce. This feature is
193// supposed to be used by users to report an issue to LLD developers.
Rui Ueyama5002a672016-05-02 19:59:56 +0000194void elf::createResponseFile(const opt::InputArgList &Args) {
Rafael Espindola1dd2b3d2016-05-03 17:30:44 +0000195 SmallString<0> Data;
196 raw_svector_ostream OS(Data);
Rui Ueyama2796ae32016-04-30 22:46:47 +0000197 // Copy the command line to response.txt while rewriting paths.
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000198 for (auto *Arg : Args) {
199 switch (Arg->getOption().getID()) {
200 case OPT_reproduce:
201 break;
Rui Ueyama2796ae32016-04-30 22:46:47 +0000202 case OPT_INPUT:
203 OS << quote(rewritePath(Arg->getValue())) << "\n";
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000204 break;
Rui Ueyama2796ae32016-04-30 22:46:47 +0000205 case OPT_L:
206 case OPT_dynamic_list:
Rui Ueyama2796ae32016-04-30 22:46:47 +0000207 case OPT_rpath:
208 case OPT_script:
209 case OPT_version_script:
210 OS << Arg->getSpelling() << " "
211 << quote(rewritePath(Arg->getValue())) << "\n";
212 break;
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000213 default:
Rui Ueyamaaf2312f2016-05-04 23:12:55 +0000214 OS << stringize(Arg) << "\n";
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000215 }
216 }
Rafael Espindola1dd2b3d2016-05-03 17:30:44 +0000217
218 SmallString<128> Dest;
219 path::append(Dest, path::filename(Config->Reproduce), "response.txt");
220 maybePrintCpioMember(Dest, Data);
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000221}
222
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000223std::string elf::findFromSearchPaths(StringRef Path) {
Rui Ueyama52a15092015-10-11 03:28:42 +0000224 for (StringRef Dir : Config->SearchPaths) {
225 std::string FullPath = buildSysrootedPath(Dir, Path);
Rui Ueyamafc288272016-05-02 18:51:08 +0000226 if (fs::exists(FullPath))
Rui Ueyama52a15092015-10-11 03:28:42 +0000227 return FullPath;
228 }
229 return "";
230}
231
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000232// Searches a given library from input search paths, which are filled
233// from -L command line switches. Returns a path to an existent library file.
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000234std::string elf::searchLibrary(StringRef Path) {
Rui Ueyama319d7302016-03-29 20:53:21 +0000235 if (Path.startswith(":"))
236 return findFromSearchPaths(Path.substr(1));
237 if (!Config->Static) {
238 std::string S = findFromSearchPaths(("lib" + Path + ".so").str());
Rui Ueyama52a15092015-10-11 03:28:42 +0000239 if (!S.empty())
240 return S;
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000241 }
Rui Ueyama319d7302016-03-29 20:53:21 +0000242 return findFromSearchPaths(("lib" + Path + ".a").str());
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000243}
244
245// Makes a path by concatenating Dir and File.
246// If Dir starts with '=' the result will be preceded by Sysroot,
247// which can be set with --sysroot command line switch.
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000248std::string elf::buildSysrootedPath(StringRef Dir, StringRef File) {
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000249 SmallString<128> Path;
250 if (Dir.startswith("="))
Rui Ueyamafc288272016-05-02 18:51:08 +0000251 path::append(Path, Config->Sysroot, Dir.substr(1), File);
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000252 else
Rui Ueyamafc288272016-05-02 18:51:08 +0000253 path::append(Path, Dir, File);
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000254 return Path.str();
255}