1*146eb7a6SReid Kleckner //===--- COFFModuleDefinition.cpp - Simple DEF parser ---------------------===// 2*146eb7a6SReid Kleckner // 3*146eb7a6SReid Kleckner // The LLVM Compiler Infrastructure 4*146eb7a6SReid Kleckner // 5*146eb7a6SReid Kleckner // This file is distributed under the University of Illinois Open Source 6*146eb7a6SReid Kleckner // License. See LICENSE.TXT for details. 7*146eb7a6SReid Kleckner // 8*146eb7a6SReid Kleckner //===----------------------------------------------------------------------===// 9*146eb7a6SReid Kleckner // 10*146eb7a6SReid Kleckner // Windows-specific. 11*146eb7a6SReid Kleckner // A parser for the module-definition file (.def file). 12*146eb7a6SReid Kleckner // 13*146eb7a6SReid Kleckner // The format of module-definition files are described in this document: 14*146eb7a6SReid Kleckner // https://msdn.microsoft.com/en-us/library/28d6s79h.aspx 15*146eb7a6SReid Kleckner // 16*146eb7a6SReid Kleckner //===----------------------------------------------------------------------===// 17*146eb7a6SReid Kleckner 18*146eb7a6SReid Kleckner #include "llvm/Object/COFFModuleDefinition.h" 19*146eb7a6SReid Kleckner #include "llvm/ADT/StringRef.h" 20*146eb7a6SReid Kleckner #include "llvm/ADT/StringSwitch.h" 21*146eb7a6SReid Kleckner #include "llvm/Object/COFF.h" 22*146eb7a6SReid Kleckner #include "llvm/Object/COFFImportFile.h" 23*146eb7a6SReid Kleckner #include "llvm/Object/Error.h" 24*146eb7a6SReid Kleckner #include "llvm/Support/Error.h" 25*146eb7a6SReid Kleckner #include "llvm/Support/raw_ostream.h" 26*146eb7a6SReid Kleckner 27*146eb7a6SReid Kleckner using namespace llvm::COFF; 28*146eb7a6SReid Kleckner using namespace llvm; 29*146eb7a6SReid Kleckner 30*146eb7a6SReid Kleckner namespace llvm { 31*146eb7a6SReid Kleckner namespace object { 32*146eb7a6SReid Kleckner 33*146eb7a6SReid Kleckner enum Kind { 34*146eb7a6SReid Kleckner Unknown, 35*146eb7a6SReid Kleckner Eof, 36*146eb7a6SReid Kleckner Identifier, 37*146eb7a6SReid Kleckner Comma, 38*146eb7a6SReid Kleckner Equal, 39*146eb7a6SReid Kleckner KwBase, 40*146eb7a6SReid Kleckner KwConstant, 41*146eb7a6SReid Kleckner KwData, 42*146eb7a6SReid Kleckner KwExports, 43*146eb7a6SReid Kleckner KwHeapsize, 44*146eb7a6SReid Kleckner KwLibrary, 45*146eb7a6SReid Kleckner KwName, 46*146eb7a6SReid Kleckner KwNoname, 47*146eb7a6SReid Kleckner KwPrivate, 48*146eb7a6SReid Kleckner KwStacksize, 49*146eb7a6SReid Kleckner KwVersion, 50*146eb7a6SReid Kleckner }; 51*146eb7a6SReid Kleckner 52*146eb7a6SReid Kleckner struct Token { 53*146eb7a6SReid Kleckner explicit Token(Kind T = Unknown, StringRef S = "") : K(T), Value(S) {} 54*146eb7a6SReid Kleckner Kind K; 55*146eb7a6SReid Kleckner StringRef Value; 56*146eb7a6SReid Kleckner }; 57*146eb7a6SReid Kleckner 58*146eb7a6SReid Kleckner static bool isDecorated(StringRef Sym) { 59*146eb7a6SReid Kleckner return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?"); 60*146eb7a6SReid Kleckner } 61*146eb7a6SReid Kleckner 62*146eb7a6SReid Kleckner static Error createError(const Twine &Err) { 63*146eb7a6SReid Kleckner return make_error<StringError>(StringRef(Err.str()), 64*146eb7a6SReid Kleckner object_error::parse_failed); 65*146eb7a6SReid Kleckner } 66*146eb7a6SReid Kleckner 67*146eb7a6SReid Kleckner class Lexer { 68*146eb7a6SReid Kleckner public: 69*146eb7a6SReid Kleckner Lexer(StringRef S) : Buf(S) {} 70*146eb7a6SReid Kleckner 71*146eb7a6SReid Kleckner Token lex() { 72*146eb7a6SReid Kleckner Buf = Buf.trim(); 73*146eb7a6SReid Kleckner if (Buf.empty()) 74*146eb7a6SReid Kleckner return Token(Eof); 75*146eb7a6SReid Kleckner 76*146eb7a6SReid Kleckner switch (Buf[0]) { 77*146eb7a6SReid Kleckner case '\0': 78*146eb7a6SReid Kleckner return Token(Eof); 79*146eb7a6SReid Kleckner case ';': { 80*146eb7a6SReid Kleckner size_t End = Buf.find('\n'); 81*146eb7a6SReid Kleckner Buf = (End == Buf.npos) ? "" : Buf.drop_front(End); 82*146eb7a6SReid Kleckner return lex(); 83*146eb7a6SReid Kleckner } 84*146eb7a6SReid Kleckner case '=': 85*146eb7a6SReid Kleckner Buf = Buf.drop_front(); 86*146eb7a6SReid Kleckner return Token(Equal, "="); 87*146eb7a6SReid Kleckner case ',': 88*146eb7a6SReid Kleckner Buf = Buf.drop_front(); 89*146eb7a6SReid Kleckner return Token(Comma, ","); 90*146eb7a6SReid Kleckner case '"': { 91*146eb7a6SReid Kleckner StringRef S; 92*146eb7a6SReid Kleckner std::tie(S, Buf) = Buf.substr(1).split('"'); 93*146eb7a6SReid Kleckner return Token(Identifier, S); 94*146eb7a6SReid Kleckner } 95*146eb7a6SReid Kleckner default: { 96*146eb7a6SReid Kleckner size_t End = Buf.find_first_of("=,\r\n \t\v"); 97*146eb7a6SReid Kleckner StringRef Word = Buf.substr(0, End); 98*146eb7a6SReid Kleckner Kind K = llvm::StringSwitch<Kind>(Word) 99*146eb7a6SReid Kleckner .Case("BASE", KwBase) 100*146eb7a6SReid Kleckner .Case("CONSTANT", KwConstant) 101*146eb7a6SReid Kleckner .Case("DATA", KwData) 102*146eb7a6SReid Kleckner .Case("EXPORTS", KwExports) 103*146eb7a6SReid Kleckner .Case("HEAPSIZE", KwHeapsize) 104*146eb7a6SReid Kleckner .Case("LIBRARY", KwLibrary) 105*146eb7a6SReid Kleckner .Case("NAME", KwName) 106*146eb7a6SReid Kleckner .Case("NONAME", KwNoname) 107*146eb7a6SReid Kleckner .Case("PRIVATE", KwPrivate) 108*146eb7a6SReid Kleckner .Case("STACKSIZE", KwStacksize) 109*146eb7a6SReid Kleckner .Case("VERSION", KwVersion) 110*146eb7a6SReid Kleckner .Default(Identifier); 111*146eb7a6SReid Kleckner Buf = (End == Buf.npos) ? "" : Buf.drop_front(End); 112*146eb7a6SReid Kleckner return Token(K, Word); 113*146eb7a6SReid Kleckner } 114*146eb7a6SReid Kleckner } 115*146eb7a6SReid Kleckner } 116*146eb7a6SReid Kleckner 117*146eb7a6SReid Kleckner private: 118*146eb7a6SReid Kleckner StringRef Buf; 119*146eb7a6SReid Kleckner }; 120*146eb7a6SReid Kleckner 121*146eb7a6SReid Kleckner class Parser { 122*146eb7a6SReid Kleckner public: 123*146eb7a6SReid Kleckner explicit Parser(StringRef S, MachineTypes M) : Lex(S), Machine(M) {} 124*146eb7a6SReid Kleckner 125*146eb7a6SReid Kleckner Expected<COFFModuleDefinition> parse() { 126*146eb7a6SReid Kleckner do { 127*146eb7a6SReid Kleckner if (Error Err = parseOne()) 128*146eb7a6SReid Kleckner return std::move(Err); 129*146eb7a6SReid Kleckner } while (Tok.K != Eof); 130*146eb7a6SReid Kleckner return Info; 131*146eb7a6SReid Kleckner } 132*146eb7a6SReid Kleckner 133*146eb7a6SReid Kleckner private: 134*146eb7a6SReid Kleckner void read() { 135*146eb7a6SReid Kleckner if (Stack.empty()) { 136*146eb7a6SReid Kleckner Tok = Lex.lex(); 137*146eb7a6SReid Kleckner return; 138*146eb7a6SReid Kleckner } 139*146eb7a6SReid Kleckner Tok = Stack.back(); 140*146eb7a6SReid Kleckner Stack.pop_back(); 141*146eb7a6SReid Kleckner } 142*146eb7a6SReid Kleckner 143*146eb7a6SReid Kleckner Error readAsInt(uint64_t *I) { 144*146eb7a6SReid Kleckner read(); 145*146eb7a6SReid Kleckner if (Tok.K != Identifier || Tok.Value.getAsInteger(10, *I)) 146*146eb7a6SReid Kleckner return createError("integer expected"); 147*146eb7a6SReid Kleckner return Error::success(); 148*146eb7a6SReid Kleckner } 149*146eb7a6SReid Kleckner 150*146eb7a6SReid Kleckner Error expect(Kind Expected, StringRef Msg) { 151*146eb7a6SReid Kleckner read(); 152*146eb7a6SReid Kleckner if (Tok.K != Expected) 153*146eb7a6SReid Kleckner return createError(Msg); 154*146eb7a6SReid Kleckner return Error::success(); 155*146eb7a6SReid Kleckner } 156*146eb7a6SReid Kleckner 157*146eb7a6SReid Kleckner void unget() { Stack.push_back(Tok); } 158*146eb7a6SReid Kleckner 159*146eb7a6SReid Kleckner Error parseOne() { 160*146eb7a6SReid Kleckner read(); 161*146eb7a6SReid Kleckner switch (Tok.K) { 162*146eb7a6SReid Kleckner case Eof: 163*146eb7a6SReid Kleckner return Error::success(); 164*146eb7a6SReid Kleckner case KwExports: 165*146eb7a6SReid Kleckner for (;;) { 166*146eb7a6SReid Kleckner read(); 167*146eb7a6SReid Kleckner if (Tok.K != Identifier) { 168*146eb7a6SReid Kleckner unget(); 169*146eb7a6SReid Kleckner return Error::success(); 170*146eb7a6SReid Kleckner } 171*146eb7a6SReid Kleckner if (Error Err = parseExport()) 172*146eb7a6SReid Kleckner return Err; 173*146eb7a6SReid Kleckner } 174*146eb7a6SReid Kleckner case KwHeapsize: 175*146eb7a6SReid Kleckner return parseNumbers(&Info.HeapReserve, &Info.HeapCommit); 176*146eb7a6SReid Kleckner case KwStacksize: 177*146eb7a6SReid Kleckner return parseNumbers(&Info.StackReserve, &Info.StackCommit); 178*146eb7a6SReid Kleckner case KwLibrary: 179*146eb7a6SReid Kleckner case KwName: { 180*146eb7a6SReid Kleckner bool IsDll = Tok.K == KwLibrary; // Check before parseName. 181*146eb7a6SReid Kleckner std::string Name; 182*146eb7a6SReid Kleckner if (Error Err = parseName(&Name, &Info.ImageBase)) 183*146eb7a6SReid Kleckner return Err; 184*146eb7a6SReid Kleckner // Append the appropriate file extension if not already present. 185*146eb7a6SReid Kleckner StringRef Ext = IsDll ? ".dll" : ".exe"; 186*146eb7a6SReid Kleckner if (!StringRef(Name).endswith_lower(Ext)) 187*146eb7a6SReid Kleckner Name += Ext; 188*146eb7a6SReid Kleckner 189*146eb7a6SReid Kleckner // Set the output file, but don't override /out if it was already passed. 190*146eb7a6SReid Kleckner if (Info.OutputFile.empty()) 191*146eb7a6SReid Kleckner Info.OutputFile = Name; 192*146eb7a6SReid Kleckner return Error::success(); 193*146eb7a6SReid Kleckner } 194*146eb7a6SReid Kleckner case KwVersion: 195*146eb7a6SReid Kleckner return parseVersion(&Info.MajorImageVersion, &Info.MinorImageVersion); 196*146eb7a6SReid Kleckner default: 197*146eb7a6SReid Kleckner return createError("unknown directive: " + Tok.Value); 198*146eb7a6SReid Kleckner } 199*146eb7a6SReid Kleckner } 200*146eb7a6SReid Kleckner 201*146eb7a6SReid Kleckner Error parseExport() { 202*146eb7a6SReid Kleckner COFFShortExport E; 203*146eb7a6SReid Kleckner E.Name = Tok.Value; 204*146eb7a6SReid Kleckner read(); 205*146eb7a6SReid Kleckner if (Tok.K == Equal) { 206*146eb7a6SReid Kleckner read(); 207*146eb7a6SReid Kleckner if (Tok.K != Identifier) 208*146eb7a6SReid Kleckner return createError("identifier expected, but got " + Tok.Value); 209*146eb7a6SReid Kleckner E.ExtName = E.Name; 210*146eb7a6SReid Kleckner E.Name = Tok.Value; 211*146eb7a6SReid Kleckner } else { 212*146eb7a6SReid Kleckner unget(); 213*146eb7a6SReid Kleckner } 214*146eb7a6SReid Kleckner 215*146eb7a6SReid Kleckner if (Machine == IMAGE_FILE_MACHINE_I386) { 216*146eb7a6SReid Kleckner if (!isDecorated(E.Name)) 217*146eb7a6SReid Kleckner E.Name = (std::string("_").append(E.Name)); 218*146eb7a6SReid Kleckner if (!E.ExtName.empty() && !isDecorated(E.ExtName)) 219*146eb7a6SReid Kleckner E.ExtName = (std::string("_").append(E.ExtName)); 220*146eb7a6SReid Kleckner } 221*146eb7a6SReid Kleckner 222*146eb7a6SReid Kleckner for (;;) { 223*146eb7a6SReid Kleckner read(); 224*146eb7a6SReid Kleckner if (Tok.K == Identifier && Tok.Value[0] == '@') { 225*146eb7a6SReid Kleckner Tok.Value.drop_front().getAsInteger(10, E.Ordinal); 226*146eb7a6SReid Kleckner read(); 227*146eb7a6SReid Kleckner if (Tok.K == KwNoname) { 228*146eb7a6SReid Kleckner E.Noname = true; 229*146eb7a6SReid Kleckner } else { 230*146eb7a6SReid Kleckner unget(); 231*146eb7a6SReid Kleckner } 232*146eb7a6SReid Kleckner continue; 233*146eb7a6SReid Kleckner } 234*146eb7a6SReid Kleckner if (Tok.K == KwData) { 235*146eb7a6SReid Kleckner E.Data = true; 236*146eb7a6SReid Kleckner continue; 237*146eb7a6SReid Kleckner } 238*146eb7a6SReid Kleckner if (Tok.K == KwConstant) { 239*146eb7a6SReid Kleckner E.Constant = true; 240*146eb7a6SReid Kleckner continue; 241*146eb7a6SReid Kleckner } 242*146eb7a6SReid Kleckner if (Tok.K == KwPrivate) { 243*146eb7a6SReid Kleckner E.Private = true; 244*146eb7a6SReid Kleckner continue; 245*146eb7a6SReid Kleckner } 246*146eb7a6SReid Kleckner unget(); 247*146eb7a6SReid Kleckner Info.Exports.push_back(E); 248*146eb7a6SReid Kleckner return Error::success(); 249*146eb7a6SReid Kleckner } 250*146eb7a6SReid Kleckner } 251*146eb7a6SReid Kleckner 252*146eb7a6SReid Kleckner // HEAPSIZE/STACKSIZE reserve[,commit] 253*146eb7a6SReid Kleckner Error parseNumbers(uint64_t *Reserve, uint64_t *Commit) { 254*146eb7a6SReid Kleckner if (Error Err = readAsInt(Reserve)) 255*146eb7a6SReid Kleckner return Err; 256*146eb7a6SReid Kleckner read(); 257*146eb7a6SReid Kleckner if (Tok.K != Comma) { 258*146eb7a6SReid Kleckner unget(); 259*146eb7a6SReid Kleckner Commit = nullptr; 260*146eb7a6SReid Kleckner return Error::success(); 261*146eb7a6SReid Kleckner } 262*146eb7a6SReid Kleckner if (Error Err = readAsInt(Commit)) 263*146eb7a6SReid Kleckner return Err; 264*146eb7a6SReid Kleckner return Error::success(); 265*146eb7a6SReid Kleckner } 266*146eb7a6SReid Kleckner 267*146eb7a6SReid Kleckner // NAME outputPath [BASE=address] 268*146eb7a6SReid Kleckner Error parseName(std::string *Out, uint64_t *Baseaddr) { 269*146eb7a6SReid Kleckner read(); 270*146eb7a6SReid Kleckner if (Tok.K == Identifier) { 271*146eb7a6SReid Kleckner *Out = Tok.Value; 272*146eb7a6SReid Kleckner } else { 273*146eb7a6SReid Kleckner *Out = ""; 274*146eb7a6SReid Kleckner unget(); 275*146eb7a6SReid Kleckner return Error::success(); 276*146eb7a6SReid Kleckner } 277*146eb7a6SReid Kleckner read(); 278*146eb7a6SReid Kleckner if (Tok.K == KwBase) { 279*146eb7a6SReid Kleckner if (Error Err = expect(Equal, "'=' expected")) 280*146eb7a6SReid Kleckner return Err; 281*146eb7a6SReid Kleckner if (Error Err = readAsInt(Baseaddr)) 282*146eb7a6SReid Kleckner return Err; 283*146eb7a6SReid Kleckner } else { 284*146eb7a6SReid Kleckner unget(); 285*146eb7a6SReid Kleckner *Baseaddr = 0; 286*146eb7a6SReid Kleckner } 287*146eb7a6SReid Kleckner return Error::success(); 288*146eb7a6SReid Kleckner } 289*146eb7a6SReid Kleckner 290*146eb7a6SReid Kleckner // VERSION major[.minor] 291*146eb7a6SReid Kleckner Error parseVersion(uint32_t *Major, uint32_t *Minor) { 292*146eb7a6SReid Kleckner read(); 293*146eb7a6SReid Kleckner if (Tok.K != Identifier) 294*146eb7a6SReid Kleckner return createError("identifier expected, but got " + Tok.Value); 295*146eb7a6SReid Kleckner StringRef V1, V2; 296*146eb7a6SReid Kleckner std::tie(V1, V2) = Tok.Value.split('.'); 297*146eb7a6SReid Kleckner if (V1.getAsInteger(10, *Major)) 298*146eb7a6SReid Kleckner return createError("integer expected, but got " + Tok.Value); 299*146eb7a6SReid Kleckner if (V2.empty()) 300*146eb7a6SReid Kleckner *Minor = 0; 301*146eb7a6SReid Kleckner else if (V2.getAsInteger(10, *Minor)) 302*146eb7a6SReid Kleckner return createError("integer expected, but got " + Tok.Value); 303*146eb7a6SReid Kleckner return Error::success(); 304*146eb7a6SReid Kleckner } 305*146eb7a6SReid Kleckner 306*146eb7a6SReid Kleckner Lexer Lex; 307*146eb7a6SReid Kleckner Token Tok; 308*146eb7a6SReid Kleckner std::vector<Token> Stack; 309*146eb7a6SReid Kleckner MachineTypes Machine; 310*146eb7a6SReid Kleckner COFFModuleDefinition Info; 311*146eb7a6SReid Kleckner }; 312*146eb7a6SReid Kleckner 313*146eb7a6SReid Kleckner Expected<COFFModuleDefinition> parseCOFFModuleDefinition(MemoryBufferRef MB, 314*146eb7a6SReid Kleckner MachineTypes Machine) { 315*146eb7a6SReid Kleckner return Parser(MB.getBuffer(), Machine).parse(); 316*146eb7a6SReid Kleckner } 317*146eb7a6SReid Kleckner 318*146eb7a6SReid Kleckner } // namespace object 319*146eb7a6SReid Kleckner } // namespace llvm 320