blob: 8673fe004f63408ad1ff80c56136b838017b54ce [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 Ueyama411c63602015-05-28 19:09:30 +000038
39static std::string getOutputPath(llvm::opt::InputArgList *Args) {
40 if (auto *Arg = Args->getLastArg(OPT_out))
41 return Arg->getValue();
42 for (auto *Arg : Args->filtered(OPT_INPUT)) {
43 if (!StringRef(Arg->getValue()).endswith_lower(".obj"))
44 continue;
45 SmallString<128> Val = StringRef(Arg->getValue());
46 llvm::sys::path::replace_extension(Val, ".exe");
47 return Val.str();
48 }
49 llvm_unreachable("internal error");
50}
51
Rui Ueyama411c63602015-05-28 19:09:30 +000052std::unique_ptr<InputFile> createFile(StringRef Path) {
53 if (StringRef(Path).endswith_lower(".lib"))
54 return llvm::make_unique<ArchiveFile>(Path);
55 return llvm::make_unique<ObjectFile>(Path);
56}
57
Rui Ueyama3500f662015-05-28 20:30:06 +000058namespace {
59class BumpPtrStringSaver : public llvm::cl::StringSaver {
60public:
61 BumpPtrStringSaver(lld::coff::StringAllocator *A) : Alloc(A) {}
62 const char *SaveString(const char *S) override {
63 return Alloc->save(S).data();
64 }
65 lld::coff::StringAllocator *Alloc;
66};
67}
68
Rui Ueyama411c63602015-05-28 19:09:30 +000069// Parses .drectve section contents and returns a list of files
70// specified by /defaultlib.
71std::error_code parseDirectives(StringRef S,
72 std::vector<std::unique_ptr<InputFile>> *Res,
73 StringAllocator *Alloc) {
74 SmallVector<const char *, 16> Tokens;
75 Tokens.push_back("link"); // argv[0] value. Will be ignored.
76 BumpPtrStringSaver Saver(Alloc);
77 llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);
78 Tokens.push_back(nullptr);
79 int Argc = Tokens.size() - 1;
80 const char **Argv = &Tokens[0];
81
82 auto ArgsOrErr = parseArgs(Argc, Argv);
83 if (auto EC = ArgsOrErr.getError())
84 return EC;
85 std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
86
87 for (auto *Arg : Args->filtered(OPT_defaultlib)) {
88 std::string Path = findLib(Arg->getValue());
89 if (!Config->insertFile(Path))
90 continue;
91 Res->push_back(llvm::make_unique<ArchiveFile>(Path));
92 }
93 return std::error_code();
94}
95
96bool link(int Argc, const char *Argv[]) {
97 // Parse command line options.
98 Config = new Configuration();
99 auto ArgsOrErr = parseArgs(Argc, Argv);
100 if (auto EC = ArgsOrErr.getError()) {
101 llvm::errs() << EC.message() << "\n";
102 return false;
103 }
104 std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
105
Rui Ueyama5c726432015-05-29 16:11:52 +0000106 // Handle /help
107 if (Args->hasArg(OPT_help)) {
108 printHelp(Argv[0]);
109 return true;
110 }
111
Rui Ueyama411c63602015-05-28 19:09:30 +0000112 if (Args->filtered_begin(OPT_INPUT) == Args->filtered_end()) {
113 llvm::errs() << "no input files.\n";
114 return false;
115 }
Rui Ueyama3d3e6fb2015-05-29 16:06:00 +0000116
117 // Handle /verbose
Rui Ueyama411c63602015-05-28 19:09:30 +0000118 if (Args->hasArg(OPT_verbose))
119 Config->Verbose = true;
Rui Ueyama3d3e6fb2015-05-29 16:06:00 +0000120
121 // Handle /entry
Rui Ueyama411c63602015-05-28 19:09:30 +0000122 if (auto *Arg = Args->getLastArg(OPT_entry))
123 Config->EntryName = Arg->getValue();
124
Rui Ueyama3d3e6fb2015-05-29 16:06:00 +0000125 // Handle /machine
126 auto MTOrErr = getMachineType(Args.get());
127 if (auto EC = MTOrErr.getError()) {
128 llvm::errs() << EC.message() << "\n";
129 return false;
130 }
131 Config->MachineType = MTOrErr.get();
132
Rui Ueyama804a8b62015-05-29 16:18:15 +0000133 // Handle /base
134 if (auto *Arg = Args->getLastArg(OPT_base)) {
135 if (auto EC = parseNumbers(Arg->getValue(), &Config->ImageBase)) {
Rui Ueyamab41b7e52015-05-29 16:21:11 +0000136 llvm::errs() << "/base: " << EC.message() << "\n";
137 return false;
138 }
139 }
140
141 // Handle /stack
142 if (auto *Arg = Args->getLastArg(OPT_stack)) {
143 if (auto EC = parseNumbers(Arg->getValue(), &Config->StackReserve,
144 &Config->StackCommit)) {
145 llvm::errs() << "/stack: " << EC.message() << "\n";
Rui Ueyama804a8b62015-05-29 16:18:15 +0000146 return false;
147 }
148 }
149
Rui Ueyamac377e9a2015-05-29 16:23:40 +0000150 // Handle /heap
151 if (auto *Arg = Args->getLastArg(OPT_heap)) {
152 if (auto EC = parseNumbers(Arg->getValue(), &Config->HeapReserve,
153 &Config->HeapCommit)) {
154 llvm::errs() << "/heap: " << EC.message() << "\n";
155 return false;
156 }
157 }
158
Rui Ueyamab9dcdb52015-05-29 16:28:29 +0000159 // Handle /version
160 if (auto *Arg = Args->getLastArg(OPT_version)) {
161 if (auto EC = parseVersion(Arg->getValue(), &Config->MajorImageVersion,
162 &Config->MinorImageVersion)) {
163 llvm::errs() << "/version: " << EC.message() << "\n";
164 return false;
165 }
166 }
167
Rui Ueyama15cc47e2015-05-29 16:34:31 +0000168 // Handle /subsystem
169 if (auto *Arg = Args->getLastArg(OPT_subsystem)) {
170 if (auto EC = parseSubsystem(Arg->getValue(), &Config->Subsystem,
171 &Config->MajorOSVersion,
172 &Config->MinorOSVersion)) {
173 llvm::errs() << "/subsystem: " << EC.message() << "\n";
174 return false;
175 }
176 }
177
Rui Ueyama411c63602015-05-28 19:09:30 +0000178 // Parse all input files and put all symbols to the symbol table.
179 // The symbol table will take care of name resolution.
180 SymbolTable Symtab;
181 for (auto *Arg : Args->filtered(OPT_INPUT)) {
182 std::string Path = findFile(Arg->getValue());
183 if (!Config->insertFile(Path))
184 continue;
185 if (auto EC = Symtab.addFile(createFile(Path))) {
186 llvm::errs() << Path << ": " << EC.message() << "\n";
187 return false;
188 }
189 }
Rui Ueyama5cff6852015-05-31 03:34:08 +0000190
191 // Windows specific -- If entry point name is not given, we need to
192 // infer that from user-defined entry name. The symbol table takes
193 // care of details.
194 if (Config->EntryName.empty()) {
195 auto EntryOrErr = Symtab.findDefaultEntry();
196 if (auto EC = EntryOrErr.getError()) {
197 llvm::errs() << EC.message() << "\n";
198 return false;
199 }
200 Config->EntryName = EntryOrErr.get();
201 }
202
203 // Make sure we have resolved all symbols.
Rui Ueyama411c63602015-05-28 19:09:30 +0000204 if (Symtab.reportRemainingUndefines())
205 return false;
206
Rui Ueyama3ee0fe42015-05-31 03:55:46 +0000207 // Windows specific -- if no /subsystem is given, we need to infer
208 // that from entry point name.
209 if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
210 Config->Subsystem =
211 StringSwitch<WindowsSubsystem>(Config->EntryName)
212 .Case("mainCRTStartup", IMAGE_SUBSYSTEM_WINDOWS_CUI)
213 .Case("wmainCRTStartup", IMAGE_SUBSYSTEM_WINDOWS_CUI)
214 .Case("WinMainCRTStartup", IMAGE_SUBSYSTEM_WINDOWS_GUI)
215 .Case("wWinMainCRTStartup", IMAGE_SUBSYSTEM_WINDOWS_GUI)
216 .Default(IMAGE_SUBSYSTEM_UNKNOWN);
217 if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
218 llvm::errs() << "subsystem must be defined\n";
219 return false;
220 }
221 }
222
Rui Ueyama411c63602015-05-28 19:09:30 +0000223 // Write the result.
224 Writer Out(&Symtab);
225 if (auto EC = Out.write(getOutputPath(Args.get()))) {
226 llvm::errs() << EC.message() << "\n";
227 return false;
228 }
229 return true;
230}
231
232} // namespace coff
233} // namespace lld