blob: 635ad39004d21583d4e9dc021fc20dff7ec9a2d6 [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 Ueyama411c63602015-05-28 19:09:30 +000019#include "llvm/Option/Arg.h"
20#include "llvm/Option/ArgList.h"
21#include "llvm/Option/Option.h"
22#include "llvm/Support/CommandLine.h"
23#include "llvm/Support/Debug.h"
Rui Ueyama411c63602015-05-28 19:09:30 +000024#include "llvm/Support/Path.h"
Rui Ueyama411c63602015-05-28 19:09:30 +000025#include "llvm/Support/raw_ostream.h"
26#include <memory>
27
28using namespace llvm;
29
Rui Ueyama3500f662015-05-28 20:30:06 +000030namespace lld {
31namespace coff {
Rui Ueyama411c63602015-05-28 19:09:30 +000032
Rui Ueyama3500f662015-05-28 20:30:06 +000033Configuration *Config;
Rui Ueyama411c63602015-05-28 19:09:30 +000034
35static std::string getOutputPath(llvm::opt::InputArgList *Args) {
36 if (auto *Arg = Args->getLastArg(OPT_out))
37 return Arg->getValue();
38 for (auto *Arg : Args->filtered(OPT_INPUT)) {
39 if (!StringRef(Arg->getValue()).endswith_lower(".obj"))
40 continue;
41 SmallString<128> Val = StringRef(Arg->getValue());
42 llvm::sys::path::replace_extension(Val, ".exe");
43 return Val.str();
44 }
45 llvm_unreachable("internal error");
46}
47
Rui Ueyama411c63602015-05-28 19:09:30 +000048std::unique_ptr<InputFile> createFile(StringRef Path) {
49 if (StringRef(Path).endswith_lower(".lib"))
50 return llvm::make_unique<ArchiveFile>(Path);
51 return llvm::make_unique<ObjectFile>(Path);
52}
53
Rui Ueyama3500f662015-05-28 20:30:06 +000054namespace {
55class BumpPtrStringSaver : public llvm::cl::StringSaver {
56public:
57 BumpPtrStringSaver(lld::coff::StringAllocator *A) : Alloc(A) {}
58 const char *SaveString(const char *S) override {
59 return Alloc->save(S).data();
60 }
61 lld::coff::StringAllocator *Alloc;
62};
63}
64
Rui Ueyama411c63602015-05-28 19:09:30 +000065// Parses .drectve section contents and returns a list of files
66// specified by /defaultlib.
67std::error_code parseDirectives(StringRef S,
68 std::vector<std::unique_ptr<InputFile>> *Res,
69 StringAllocator *Alloc) {
70 SmallVector<const char *, 16> Tokens;
71 Tokens.push_back("link"); // argv[0] value. Will be ignored.
72 BumpPtrStringSaver Saver(Alloc);
73 llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);
74 Tokens.push_back(nullptr);
75 int Argc = Tokens.size() - 1;
76 const char **Argv = &Tokens[0];
77
78 auto ArgsOrErr = parseArgs(Argc, Argv);
79 if (auto EC = ArgsOrErr.getError())
80 return EC;
81 std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
82
83 for (auto *Arg : Args->filtered(OPT_defaultlib)) {
84 std::string Path = findLib(Arg->getValue());
85 if (!Config->insertFile(Path))
86 continue;
87 Res->push_back(llvm::make_unique<ArchiveFile>(Path));
88 }
89 return std::error_code();
90}
91
92bool link(int Argc, const char *Argv[]) {
93 // Parse command line options.
94 Config = new Configuration();
95 auto ArgsOrErr = parseArgs(Argc, Argv);
96 if (auto EC = ArgsOrErr.getError()) {
97 llvm::errs() << EC.message() << "\n";
98 return false;
99 }
100 std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
101
Rui Ueyama5c726432015-05-29 16:11:52 +0000102 // Handle /help
103 if (Args->hasArg(OPT_help)) {
104 printHelp(Argv[0]);
105 return true;
106 }
107
Rui Ueyama411c63602015-05-28 19:09:30 +0000108 if (Args->filtered_begin(OPT_INPUT) == Args->filtered_end()) {
109 llvm::errs() << "no input files.\n";
110 return false;
111 }
Rui Ueyama3d3e6fb2015-05-29 16:06:00 +0000112
113 // Handle /verbose
Rui Ueyama411c63602015-05-28 19:09:30 +0000114 if (Args->hasArg(OPT_verbose))
115 Config->Verbose = true;
Rui Ueyama3d3e6fb2015-05-29 16:06:00 +0000116
117 // Handle /entry
Rui Ueyama411c63602015-05-28 19:09:30 +0000118 if (auto *Arg = Args->getLastArg(OPT_entry))
119 Config->EntryName = Arg->getValue();
120
Rui Ueyama3d3e6fb2015-05-29 16:06:00 +0000121 // Handle /machine
122 auto MTOrErr = getMachineType(Args.get());
123 if (auto EC = MTOrErr.getError()) {
124 llvm::errs() << EC.message() << "\n";
125 return false;
126 }
127 Config->MachineType = MTOrErr.get();
128
Rui Ueyama804a8b62015-05-29 16:18:15 +0000129 // Handle /base
130 if (auto *Arg = Args->getLastArg(OPT_base)) {
131 if (auto EC = parseNumbers(Arg->getValue(), &Config->ImageBase)) {
Rui Ueyamab41b7e52015-05-29 16:21:11 +0000132 llvm::errs() << "/base: " << EC.message() << "\n";
133 return false;
134 }
135 }
136
137 // Handle /stack
138 if (auto *Arg = Args->getLastArg(OPT_stack)) {
139 if (auto EC = parseNumbers(Arg->getValue(), &Config->StackReserve,
140 &Config->StackCommit)) {
141 llvm::errs() << "/stack: " << EC.message() << "\n";
Rui Ueyama804a8b62015-05-29 16:18:15 +0000142 return false;
143 }
144 }
145
Rui Ueyamac377e9a2015-05-29 16:23:40 +0000146 // Handle /heap
147 if (auto *Arg = Args->getLastArg(OPT_heap)) {
148 if (auto EC = parseNumbers(Arg->getValue(), &Config->HeapReserve,
149 &Config->HeapCommit)) {
150 llvm::errs() << "/heap: " << EC.message() << "\n";
151 return false;
152 }
153 }
154
Rui Ueyamab9dcdb52015-05-29 16:28:29 +0000155 // Handle /version
156 if (auto *Arg = Args->getLastArg(OPT_version)) {
157 if (auto EC = parseVersion(Arg->getValue(), &Config->MajorImageVersion,
158 &Config->MinorImageVersion)) {
159 llvm::errs() << "/version: " << EC.message() << "\n";
160 return false;
161 }
162 }
163
Rui Ueyama15cc47e2015-05-29 16:34:31 +0000164 // Handle /subsystem
165 if (auto *Arg = Args->getLastArg(OPT_subsystem)) {
166 if (auto EC = parseSubsystem(Arg->getValue(), &Config->Subsystem,
167 &Config->MajorOSVersion,
168 &Config->MinorOSVersion)) {
169 llvm::errs() << "/subsystem: " << EC.message() << "\n";
170 return false;
171 }
172 }
173
Rui Ueyama411c63602015-05-28 19:09:30 +0000174 // Parse all input files and put all symbols to the symbol table.
175 // The symbol table will take care of name resolution.
176 SymbolTable Symtab;
177 for (auto *Arg : Args->filtered(OPT_INPUT)) {
178 std::string Path = findFile(Arg->getValue());
179 if (!Config->insertFile(Path))
180 continue;
181 if (auto EC = Symtab.addFile(createFile(Path))) {
182 llvm::errs() << Path << ": " << EC.message() << "\n";
183 return false;
184 }
185 }
186 if (Symtab.reportRemainingUndefines())
187 return false;
188
189 // Write the result.
190 Writer Out(&Symtab);
191 if (auto EC = Out.write(getOutputPath(Args.get()))) {
192 llvm::errs() << EC.message() << "\n";
193 return false;
194 }
195 return true;
196}
197
198} // namespace coff
199} // namespace lld