blob: 739494e1df4064479bdd14d39505c27087696bf9 [file] [log] [blame]
Rui Ueyama411c63602015-05-28 19:09:30 +00001//===- Driver.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#include "Config.h"
11#include "Driver.h"
12#include "InputFiles.h"
13#include "Memory.h"
14#include "SymbolTable.h"
15#include "Writer.h"
16#include "lld/Core/Error.h"
17#include "llvm/ADT/Optional.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/Object/COFF.h"
20#include "llvm/Option/Arg.h"
21#include "llvm/Option/ArgList.h"
22#include "llvm/Option/Option.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/Debug.h"
25#include "llvm/Support/Format.h"
26#include "llvm/Support/Path.h"
27#include "llvm/Support/Process.h"
28#include "llvm/Support/raw_ostream.h"
29#include <memory>
30
31using namespace llvm;
32
33// Create enum with OPT_xxx values for each option in Options.td
34enum {
35 OPT_INVALID = 0,
36#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
37 HELP, META) \
38 OPT_##ID,
39#include "Options.inc"
40#undef OPTION
41};
42
43// Create prefix string literals used in Options.td
44#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
45#include "Options.inc"
46#undef PREFIX
47
48// Create table mapping all options defined in Options.td
49static const llvm::opt::OptTable::Info infoTable[] = {
50#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
51 HELPTEXT, METAVAR) \
52 { \
53 PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
54 PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS \
55 } \
56 ,
57#include "Options.inc"
58#undef OPTION
59};
60
61namespace {
62
63class COFFOptTable : public llvm::opt::OptTable {
64public:
65 COFFOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable), true) {}
66};
67
68class BumpPtrStringSaver : public llvm::cl::StringSaver {
69public:
70 BumpPtrStringSaver(lld::coff::StringAllocator *A) : Alloc(A) {}
71
72 const char *SaveString(const char *S) override {
73 return Alloc->save(S).data();
74 }
75
76private:
77 lld::coff::StringAllocator *Alloc;
78};
79}
80
81static std::string getOutputPath(llvm::opt::InputArgList *Args) {
82 if (auto *Arg = Args->getLastArg(OPT_out))
83 return Arg->getValue();
84 for (auto *Arg : Args->filtered(OPT_INPUT)) {
85 if (!StringRef(Arg->getValue()).endswith_lower(".obj"))
86 continue;
87 SmallString<128> Val = StringRef(Arg->getValue());
88 llvm::sys::path::replace_extension(Val, ".exe");
89 return Val.str();
90 }
91 llvm_unreachable("internal error");
92}
93
94// Split the given string with the path separator.
95static std::vector<StringRef> splitPathList(StringRef str) {
96 std::vector<StringRef> ret;
97 while (!str.empty()) {
98 StringRef path;
99 std::tie(path, str) = str.split(';');
100 ret.push_back(path);
101 }
102 return ret;
103}
104
105namespace lld {
106namespace coff {
107
108Configuration *Config;
109
110ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
111parseArgs(int Argc, const char *Argv[]) {
112 COFFOptTable Table;
113 unsigned MissingIndex;
114 unsigned MissingCount;
115 std::unique_ptr<llvm::opt::InputArgList> Args(
116 Table.ParseArgs(&Argv[1], &Argv[Argc], MissingIndex, MissingCount));
117 if (MissingCount) {
118 std::string S;
119 llvm::raw_string_ostream OS(S);
120 OS << llvm::format("missing arg value for \"%s\", expected %d argument%s.",
121 Args->getArgString(MissingIndex), MissingCount,
122 (MissingCount == 1 ? "" : "s"));
123 OS.flush();
124 return make_dynamic_error_code(StringRef(S));
125 }
126 for (auto *Arg : Args->filtered(OPT_UNKNOWN))
127 llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n";
128 return std::move(Args);
129}
130
131std::string findLib(StringRef Filename) {
132 if (llvm::sys::fs::exists(Filename))
133 return Filename;
134 std::string Name;
135 if (Filename.endswith_lower(".lib")) {
136 Name = Filename;
137 } else {
138 Name = (Filename + ".lib").str();
139 }
140
141 llvm::Optional<std::string> Env = llvm::sys::Process::GetEnv("LIB");
142 if (!Env.hasValue())
143 return Filename;
144 for (StringRef Dir : splitPathList(*Env)) {
145 SmallString<128> Path = Dir;
146 llvm::sys::path::append(Path, Name);
147 if (llvm::sys::fs::exists(Path.str()))
148 return Path.str();
149 }
150 return Filename;
151}
152
153std::string findFile(StringRef Filename) {
154 if (llvm::sys::fs::exists(Filename))
155 return Filename;
156 llvm::Optional<std::string> Env = llvm::sys::Process::GetEnv("LIB");
157 if (!Env.hasValue())
158 return Filename;
159 for (StringRef Dir : splitPathList(*Env)) {
160 SmallString<128> Path = Dir;
161 llvm::sys::path::append(Path, Filename);
162 if (llvm::sys::fs::exists(Path.str()))
163 return Path.str();
164 }
165 return Filename;
166}
167
168std::unique_ptr<InputFile> createFile(StringRef Path) {
169 if (StringRef(Path).endswith_lower(".lib"))
170 return llvm::make_unique<ArchiveFile>(Path);
171 return llvm::make_unique<ObjectFile>(Path);
172}
173
174// Parses .drectve section contents and returns a list of files
175// specified by /defaultlib.
176std::error_code parseDirectives(StringRef S,
177 std::vector<std::unique_ptr<InputFile>> *Res,
178 StringAllocator *Alloc) {
179 SmallVector<const char *, 16> Tokens;
180 Tokens.push_back("link"); // argv[0] value. Will be ignored.
181 BumpPtrStringSaver Saver(Alloc);
182 llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);
183 Tokens.push_back(nullptr);
184 int Argc = Tokens.size() - 1;
185 const char **Argv = &Tokens[0];
186
187 auto ArgsOrErr = parseArgs(Argc, Argv);
188 if (auto EC = ArgsOrErr.getError())
189 return EC;
190 std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
191
192 for (auto *Arg : Args->filtered(OPT_defaultlib)) {
193 std::string Path = findLib(Arg->getValue());
194 if (!Config->insertFile(Path))
195 continue;
196 Res->push_back(llvm::make_unique<ArchiveFile>(Path));
197 }
198 return std::error_code();
199}
200
201bool link(int Argc, const char *Argv[]) {
202 // Parse command line options.
203 Config = new Configuration();
204 auto ArgsOrErr = parseArgs(Argc, Argv);
205 if (auto EC = ArgsOrErr.getError()) {
206 llvm::errs() << EC.message() << "\n";
207 return false;
208 }
209 std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
210
211 if (Args->filtered_begin(OPT_INPUT) == Args->filtered_end()) {
212 llvm::errs() << "no input files.\n";
213 return false;
214 }
215 if (Args->hasArg(OPT_verbose))
216 Config->Verbose = true;
217 if (auto *Arg = Args->getLastArg(OPT_entry))
218 Config->EntryName = Arg->getValue();
219
220 // Parse all input files and put all symbols to the symbol table.
221 // The symbol table will take care of name resolution.
222 SymbolTable Symtab;
223 for (auto *Arg : Args->filtered(OPT_INPUT)) {
224 std::string Path = findFile(Arg->getValue());
225 if (!Config->insertFile(Path))
226 continue;
227 if (auto EC = Symtab.addFile(createFile(Path))) {
228 llvm::errs() << Path << ": " << EC.message() << "\n";
229 return false;
230 }
231 }
232 if (Symtab.reportRemainingUndefines())
233 return false;
234
235 // Write the result.
236 Writer Out(&Symtab);
237 if (auto EC = Out.write(getOutputPath(Args.get()))) {
238 llvm::errs() << EC.message() << "\n";
239 return false;
240 }
241 return true;
242}
243
244} // namespace coff
245} // namespace lld