blob: d178baca435ad485381adaafad86c060896ff5c2 [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"
Rui Ueyama3ee0fe42015-05-31 03:55:46 +000019#include "llvm/ADT/StringSwitch.h"
Rui Ueyama411c63602015-05-28 19:09:30 +000020#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"
Rui Ueyama411c63602015-05-28 19:09:30 +000025#include "llvm/Support/Path.h"
Rui Ueyama411c63602015-05-28 19:09:30 +000026#include "llvm/Support/raw_ostream.h"
27#include <memory>
28
29using namespace llvm;
Rui Ueyama3ee0fe42015-05-31 03:55:46 +000030using llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
31using llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI;
32using llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI;
Rui Ueyama411c63602015-05-28 19:09:30 +000033
Rui Ueyama3500f662015-05-28 20:30:06 +000034namespace lld {
35namespace coff {
Rui Ueyama411c63602015-05-28 19:09:30 +000036
Rui Ueyama3500f662015-05-28 20:30:06 +000037Configuration *Config;
Rui Ueyamaa9cbbf82015-05-31 19:17:09 +000038LinkerDriver *Driver;
39
40bool link(int Argc, const char *Argv[]) {
41 auto C = make_unique<Configuration>();
42 Config = C.get();
43 auto D = make_unique<LinkerDriver>();
44 Driver = D.get();
45 return Driver->link(Argc, Argv);
46}
Rui Ueyama411c63602015-05-28 19:09:30 +000047
48static std::string getOutputPath(llvm::opt::InputArgList *Args) {
49 if (auto *Arg = Args->getLastArg(OPT_out))
50 return Arg->getValue();
51 for (auto *Arg : Args->filtered(OPT_INPUT)) {
52 if (!StringRef(Arg->getValue()).endswith_lower(".obj"))
53 continue;
54 SmallString<128> Val = StringRef(Arg->getValue());
55 llvm::sys::path::replace_extension(Val, ".exe");
56 return Val.str();
57 }
58 llvm_unreachable("internal error");
59}
60
Rui Ueyama411c63602015-05-28 19:09:30 +000061std::unique_ptr<InputFile> createFile(StringRef Path) {
62 if (StringRef(Path).endswith_lower(".lib"))
63 return llvm::make_unique<ArchiveFile>(Path);
64 return llvm::make_unique<ObjectFile>(Path);
65}
66
Rui Ueyama3500f662015-05-28 20:30:06 +000067namespace {
68class BumpPtrStringSaver : public llvm::cl::StringSaver {
69public:
70 BumpPtrStringSaver(lld::coff::StringAllocator *A) : Alloc(A) {}
71 const char *SaveString(const char *S) override {
72 return Alloc->save(S).data();
73 }
74 lld::coff::StringAllocator *Alloc;
75};
76}
77
Rui Ueyama411c63602015-05-28 19:09:30 +000078// Parses .drectve section contents and returns a list of files
79// specified by /defaultlib.
Rui Ueyamaa9cbbf82015-05-31 19:17:09 +000080std::error_code
81LinkerDriver::parseDirectives(StringRef S,
82 std::vector<std::unique_ptr<InputFile>> *Res) {
Rui Ueyama411c63602015-05-28 19:09:30 +000083 SmallVector<const char *, 16> Tokens;
84 Tokens.push_back("link"); // argv[0] value. Will be ignored.
Rui Ueyamaa9cbbf82015-05-31 19:17:09 +000085 BumpPtrStringSaver Saver(&Alloc);
Rui Ueyama411c63602015-05-28 19:09:30 +000086 llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);
87 Tokens.push_back(nullptr);
88 int Argc = Tokens.size() - 1;
89 const char **Argv = &Tokens[0];
90
91 auto ArgsOrErr = parseArgs(Argc, Argv);
92 if (auto EC = ArgsOrErr.getError())
93 return EC;
94 std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
95
96 for (auto *Arg : Args->filtered(OPT_defaultlib)) {
97 std::string Path = findLib(Arg->getValue());
Rui Ueyamaa9cbbf82015-05-31 19:17:09 +000098 if (!insertFile(Path))
Rui Ueyama411c63602015-05-28 19:09:30 +000099 continue;
100 Res->push_back(llvm::make_unique<ArchiveFile>(Path));
101 }
102 return std::error_code();
103}
104
Rui Ueyamaa9cbbf82015-05-31 19:17:09 +0000105bool LinkerDriver::link(int Argc, const char *Argv[]) {
Rui Ueyama411c63602015-05-28 19:09:30 +0000106 // Parse command line options.
Rui Ueyama411c63602015-05-28 19:09:30 +0000107 auto ArgsOrErr = parseArgs(Argc, Argv);
108 if (auto EC = ArgsOrErr.getError()) {
109 llvm::errs() << EC.message() << "\n";
110 return false;
111 }
112 std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
113
Rui Ueyama5c726432015-05-29 16:11:52 +0000114 // Handle /help
115 if (Args->hasArg(OPT_help)) {
116 printHelp(Argv[0]);
117 return true;
118 }
119
Rui Ueyama411c63602015-05-28 19:09:30 +0000120 if (Args->filtered_begin(OPT_INPUT) == Args->filtered_end()) {
121 llvm::errs() << "no input files.\n";
122 return false;
123 }
Rui Ueyama3d3e6fb2015-05-29 16:06:00 +0000124
125 // Handle /verbose
Rui Ueyama411c63602015-05-28 19:09:30 +0000126 if (Args->hasArg(OPT_verbose))
127 Config->Verbose = true;
Rui Ueyama3d3e6fb2015-05-29 16:06:00 +0000128
129 // Handle /entry
Rui Ueyama411c63602015-05-28 19:09:30 +0000130 if (auto *Arg = Args->getLastArg(OPT_entry))
131 Config->EntryName = Arg->getValue();
132
Rui Ueyama3d3e6fb2015-05-29 16:06:00 +0000133 // Handle /machine
134 auto MTOrErr = getMachineType(Args.get());
135 if (auto EC = MTOrErr.getError()) {
136 llvm::errs() << EC.message() << "\n";
137 return false;
138 }
139 Config->MachineType = MTOrErr.get();
140
Rui Ueyama804a8b62015-05-29 16:18:15 +0000141 // Handle /base
142 if (auto *Arg = Args->getLastArg(OPT_base)) {
143 if (auto EC = parseNumbers(Arg->getValue(), &Config->ImageBase)) {
Rui Ueyamab41b7e52015-05-29 16:21:11 +0000144 llvm::errs() << "/base: " << EC.message() << "\n";
145 return false;
146 }
147 }
148
149 // Handle /stack
150 if (auto *Arg = Args->getLastArg(OPT_stack)) {
151 if (auto EC = parseNumbers(Arg->getValue(), &Config->StackReserve,
152 &Config->StackCommit)) {
153 llvm::errs() << "/stack: " << EC.message() << "\n";
Rui Ueyama804a8b62015-05-29 16:18:15 +0000154 return false;
155 }
156 }
157
Rui Ueyamac377e9a2015-05-29 16:23:40 +0000158 // Handle /heap
159 if (auto *Arg = Args->getLastArg(OPT_heap)) {
160 if (auto EC = parseNumbers(Arg->getValue(), &Config->HeapReserve,
161 &Config->HeapCommit)) {
162 llvm::errs() << "/heap: " << EC.message() << "\n";
163 return false;
164 }
165 }
166
Rui Ueyamab9dcdb52015-05-29 16:28:29 +0000167 // Handle /version
168 if (auto *Arg = Args->getLastArg(OPT_version)) {
169 if (auto EC = parseVersion(Arg->getValue(), &Config->MajorImageVersion,
170 &Config->MinorImageVersion)) {
171 llvm::errs() << "/version: " << EC.message() << "\n";
172 return false;
173 }
174 }
175
Rui Ueyama15cc47e2015-05-29 16:34:31 +0000176 // Handle /subsystem
177 if (auto *Arg = Args->getLastArg(OPT_subsystem)) {
178 if (auto EC = parseSubsystem(Arg->getValue(), &Config->Subsystem,
179 &Config->MajorOSVersion,
180 &Config->MinorOSVersion)) {
181 llvm::errs() << "/subsystem: " << EC.message() << "\n";
182 return false;
183 }
184 }
185
Rui Ueyama411c63602015-05-28 19:09:30 +0000186 // Parse all input files and put all symbols to the symbol table.
187 // The symbol table will take care of name resolution.
188 SymbolTable Symtab;
189 for (auto *Arg : Args->filtered(OPT_INPUT)) {
190 std::string Path = findFile(Arg->getValue());
Rui Ueyamaa9cbbf82015-05-31 19:17:09 +0000191 if (!insertFile(Path))
Rui Ueyama411c63602015-05-28 19:09:30 +0000192 continue;
193 if (auto EC = Symtab.addFile(createFile(Path))) {
194 llvm::errs() << Path << ": " << EC.message() << "\n";
195 return false;
196 }
197 }
Rui Ueyama5cff6852015-05-31 03:34:08 +0000198
199 // Windows specific -- If entry point name is not given, we need to
200 // infer that from user-defined entry name. The symbol table takes
201 // care of details.
202 if (Config->EntryName.empty()) {
203 auto EntryOrErr = Symtab.findDefaultEntry();
204 if (auto EC = EntryOrErr.getError()) {
205 llvm::errs() << EC.message() << "\n";
206 return false;
207 }
208 Config->EntryName = EntryOrErr.get();
209 }
210
211 // Make sure we have resolved all symbols.
Rui Ueyama411c63602015-05-28 19:09:30 +0000212 if (Symtab.reportRemainingUndefines())
213 return false;
214
Rui Ueyama3ee0fe42015-05-31 03:55:46 +0000215 // Windows specific -- if no /subsystem is given, we need to infer
216 // that from entry point name.
217 if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
218 Config->Subsystem =
219 StringSwitch<WindowsSubsystem>(Config->EntryName)
220 .Case("mainCRTStartup", IMAGE_SUBSYSTEM_WINDOWS_CUI)
221 .Case("wmainCRTStartup", IMAGE_SUBSYSTEM_WINDOWS_CUI)
222 .Case("WinMainCRTStartup", IMAGE_SUBSYSTEM_WINDOWS_GUI)
223 .Case("wWinMainCRTStartup", IMAGE_SUBSYSTEM_WINDOWS_GUI)
224 .Default(IMAGE_SUBSYSTEM_UNKNOWN);
225 if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
226 llvm::errs() << "subsystem must be defined\n";
227 return false;
228 }
229 }
230
Rui Ueyama411c63602015-05-28 19:09:30 +0000231 // Write the result.
232 Writer Out(&Symtab);
233 if (auto EC = Out.write(getOutputPath(Args.get()))) {
234 llvm::errs() << EC.message() << "\n";
235 return false;
236 }
237 return true;
238}
239
Rui Ueyamaa9cbbf82015-05-31 19:17:09 +0000240bool LinkerDriver::insertFile(StringRef Path) {
241 return VisitedFiles.insert(Path.lower()).second;
242}
243
Rui Ueyama411c63602015-05-28 19:09:30 +0000244} // namespace coff
245} // namespace lld