blob: 516084c1a6ccbf7e88d2a42b4877a8124ae5b812 [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
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +000016#include "Config.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000017#include "Driver.h"
Rafael Espindola192e1fa2015-08-06 15:08:23 +000018#include "Error.h"
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +000019#include "SymbolTable.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000020#include "llvm/ADT/STLExtras.h"
Rui Ueyamaeeb22f82015-09-25 15:37:33 +000021#include "llvm/Support/CommandLine.h"
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +000022#include "llvm/Support/FileSystem.h"
23#include "llvm/Support/MemoryBuffer.h"
Rui Ueyamaeeb22f82015-09-25 15:37:33 +000024#include "llvm/Support/StringSaver.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000025
26using namespace llvm;
27
28using namespace lld;
29using namespace lld::elf2;
30
31// Create OptTable
32
33// Create prefix string literals used in Options.td
34#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
35#include "Options.inc"
36#undef PREFIX
37
38// Create table mapping all options defined in Options.td
39static const opt::OptTable::Info infoTable[] = {
40#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \
41 { \
42 X1, X2, X9, X10, OPT_##ID, opt::Option::KIND##Class, X8, X7, OPT_##GROUP, \
43 OPT_##ALIAS, X6 \
44 } \
45 ,
46#include "Options.inc"
47#undef OPTION
48};
49
50class ELFOptTable : public opt::OptTable {
51public:
52 ELFOptTable() : OptTable(infoTable, array_lengthof(infoTable)) {}
53};
54
55// Parses a given list of options.
56opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) {
57 // Make InputArgList from string vectors.
58 ELFOptTable Table;
59 unsigned MissingIndex;
60 unsigned MissingCount;
61
Rui Ueyamaeeb22f82015-09-25 15:37:33 +000062 // Expand response files. '@<filename>' is replaced by the file's contents.
63 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
64 StringSaver Saver(Alloc);
65 llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, Vec);
66
67 // Parse options and then do error checking.
68 opt::InputArgList Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
Michael J. Spencer84487f12015-07-24 21:03:07 +000069 if (MissingCount)
70 error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) +
71 "\", expected " + Twine(MissingCount) +
72 (MissingCount == 1 ? " argument.\n" : " arguments"));
Rui Ueyamad5b5ab72015-09-24 18:55:33 +000073
74 iterator_range<opt::arg_iterator> Unknowns = Args.filtered(OPT_UNKNOWN);
75 for (auto *Arg : Unknowns)
76 warning("warning: unknown argument: " + Arg->getSpelling());
77 if (Unknowns.begin() != Unknowns.end())
78 error("unknown argument(s) found");
79
Michael J. Spencer84487f12015-07-24 21:03:07 +000080 return Args;
81}
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +000082
83// Parser and evaluator of the linker script.
84// Results are directly written to the Config object.
85namespace {
86class LinkerScript {
87public:
88 LinkerScript(SymbolTable *T, StringRef S) : Symtab(T), Tokens(tokenize(S)) {}
89 void run();
90
91private:
92 static std::vector<StringRef> tokenize(StringRef S);
93 static StringRef skipSpace(StringRef S);
94 StringRef next();
95 bool atEOF() { return Tokens.size() == Pos; }
96 void expect(StringRef Expect);
97
98 void readAsNeeded();
99 void readGroup();
100 void readOutputFormat();
101
102 SymbolTable *Symtab;
103 std::vector<StringRef> Tokens;
104 size_t Pos = 0;
105};
106}
107
108void LinkerScript::run() {
109 while (!atEOF()) {
110 StringRef Tok = next();
111 if (Tok == "GROUP") {
112 readGroup();
113 } else if (Tok == "OUTPUT_FORMAT") {
114 readOutputFormat();
115 } else {
116 error("unknown directive: " + Tok);
117 }
118 }
119}
120
121// Split S into linker script tokens.
122std::vector<StringRef> LinkerScript::tokenize(StringRef S) {
123 std::vector<StringRef> Ret;
124 for (;;) {
125 S = skipSpace(S);
126 if (S.empty())
127 return Ret;
128 size_t Pos = S.find_first_not_of(
129 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
130 "0123456789_.$/\\~=+[]*?-:");
131 // A character that cannot start a word (which is usually a
132 // punctuation) forms a single character token.
133 if (Pos == 0)
134 Pos = 1;
135 Ret.push_back(S.substr(0, Pos));
136 S = S.substr(Pos);
137 }
138}
139
140// Skip leading whitespace characters or /**/-style comments.
141StringRef LinkerScript::skipSpace(StringRef S) {
142 for (;;) {
143 if (S.startswith("/*")) {
144 size_t E = S.find("*/", 2);
145 if (E == StringRef::npos)
146 error("unclosed comment in a linker script");
147 S = S.substr(E + 2);
148 continue;
149 }
150 size_t Size = S.size();
151 S = S.ltrim();
152 if (S.size() == Size)
153 return S;
154 }
155}
156
157StringRef LinkerScript::next() {
158 if (Pos == Tokens.size())
159 error("unexpected EOF");
160 return Tokens[Pos++];
161}
162
163void LinkerScript::expect(StringRef Expect) {
164 StringRef Tok = next();
165 if (Tok != Expect)
166 error(Expect + " expected, but got " + Tok);
167}
168
169void LinkerScript::readAsNeeded() {
170 expect("(");
171 for (;;) {
172 StringRef Tok = next();
173 if (Tok == ")")
174 return;
175 Symtab->addFile(createFile(openFile(Tok)));
176 }
177}
178
179void LinkerScript::readGroup() {
180 expect("(");
181 for (;;) {
182 StringRef Tok = next();
183 if (Tok == ")")
184 return;
185 if (Tok == "AS_NEEDED") {
186 readAsNeeded();
187 continue;
188 }
189 Symtab->addFile(createFile(openFile(Tok)));
190 }
191}
192
193void LinkerScript::readOutputFormat() {
194 // Error checking only for now.
195 expect("(");
196 next();
197 expect(")");
198}
199
200void lld::elf2::readLinkerScript(SymbolTable *Symtab, MemoryBufferRef MB) {
201 LinkerScript(Symtab, MB.getBuffer()).run();
202}