1 //===- COFF/ModuleDef.cpp -------------------------------------------------===//
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 // A parser for the module-definition file (.def file).
12 // Parsed results are directly written to Config global variable.
14 // The format of module-definition files are described in this document:
15 // https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
17 //===----------------------------------------------------------------------===//
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/StringSwitch.h"
23 #include "llvm/Support/StringSaver.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include <system_error>
52 explicit Token(Kind T = Unknown, StringRef S = "") : K(T), Value(S) {}
57 static bool isDecorated(StringRef Sym) {
58 return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?");
63 explicit Lexer(StringRef S) : Buf(S) {}
74 size_t End = Buf.find('\n');
75 Buf = (End == Buf.npos) ? "" : Buf.drop_front(End);
79 Buf = Buf.drop_front();
80 return Token(Equal, "=");
82 Buf = Buf.drop_front();
83 return Token(Comma, ",");
86 std::tie(S, Buf) = Buf.substr(1).split('"');
87 return Token(Identifier, S);
90 size_t End = Buf.find_first_of("=,\r\n \t\v");
91 StringRef Word = Buf.substr(0, End);
92 Kind K = llvm::StringSwitch<Kind>(Word)
95 .Case("EXPORTS", KwExports)
96 .Case("HEAPSIZE", KwHeapsize)
97 .Case("LIBRARY", KwLibrary)
99 .Case("NONAME", KwNoname)
100 .Case("PRIVATE", KwPrivate)
101 .Case("STACKSIZE", KwStacksize)
102 .Case("VERSION", KwVersion)
103 .Default(Identifier);
104 Buf = (End == Buf.npos) ? "" : Buf.drop_front(End);
105 return Token(K, Word);
116 explicit Parser(StringRef S, StringSaver *A) : Lex(S), Alloc(A) {}
121 } while (Tok.K != Eof);
134 void readAsInt(uint64_t *I) {
136 if (Tok.K != Identifier || Tok.Value.getAsInteger(10, *I))
137 fatal("integer expected");
140 void expect(Kind Expected, StringRef Msg) {
142 if (Tok.K != Expected)
146 void unget() { Stack.push_back(Tok); }
156 if (Tok.K != Identifier) {
163 parseNumbers(&Config->HeapReserve, &Config->HeapCommit);
166 parseName(&Config->OutputFile, &Config->ImageBase);
167 if (!StringRef(Config->OutputFile).endswith_lower(".dll"))
168 Config->OutputFile += ".dll";
171 parseNumbers(&Config->StackReserve, &Config->StackCommit);
174 parseName(&Config->OutputFile, &Config->ImageBase);
177 parseVersion(&Config->MajorImageVersion, &Config->MinorImageVersion);
180 fatal("unknown directive: " + Tok.Value);
188 if (Tok.K == Equal) {
190 if (Tok.K != Identifier)
191 fatal("identifier expected, but got " + Tok.Value);
198 if (Config->Machine == I386) {
199 if (!isDecorated(E.Name))
200 E.Name = Alloc->save("_" + E.Name);
201 if (!E.ExtName.empty() && !isDecorated(E.ExtName))
202 E.ExtName = Alloc->save("_" + E.ExtName);
207 if (Tok.K == Identifier && Tok.Value[0] == '@') {
208 Tok.Value.drop_front().getAsInteger(10, E.Ordinal);
210 if (Tok.K == KwNoname) {
217 if (Tok.K == KwData) {
221 if (Tok.K == KwPrivate) {
226 Config->Exports.push_back(E);
231 // HEAPSIZE/STACKSIZE reserve[,commit]
232 void parseNumbers(uint64_t *Reserve, uint64_t *Commit) {
235 if (Tok.K != Comma) {
243 // NAME outputPath [BASE=address]
244 void parseName(std::string *Out, uint64_t *Baseaddr) {
246 if (Tok.K == Identifier) {
254 if (Tok.K == KwBase) {
255 expect(Equal, "'=' expected");
263 // VERSION major[.minor]
264 void parseVersion(uint32_t *Major, uint32_t *Minor) {
266 if (Tok.K != Identifier)
267 fatal("identifier expected, but got " + Tok.Value);
269 std::tie(V1, V2) = Tok.Value.split('.');
270 if (V1.getAsInteger(10, *Major))
271 fatal("integer expected, but got " + Tok.Value);
274 else if (V2.getAsInteger(10, *Minor))
275 fatal("integer expected, but got " + Tok.Value);
280 std::vector<Token> Stack;
284 } // anonymous namespace
286 void parseModuleDefs(MemoryBufferRef MB, StringSaver *Alloc) {
287 Parser(MB.getBuffer(), Alloc).parse();