[lld] r198925 - [PECOFF] Support module-definition file.

Rui Ueyama ruiu at google.com
Fri Jan 10 02:19:48 PST 2014


Author: ruiu
Date: Fri Jan 10 04:19:47 2014
New Revision: 198925

URL: http://llvm.org/viewvc/llvm-project?rev=198925&view=rev
Log:
[PECOFF] Support module-definition file.

Module-definition (.def) files are the file containing linker directives,
such as export symbols. Because link.exe supports the same features as command
line options, just as some Linker Script commands overlaps with command line
options, use of module-definition file is not really necessary. It provides
an alternative way to specify some linker options.

This patch implements EXPORTS directive. Other directives will be implemented
in the future.

Added:
    lld/trunk/include/lld/Driver/WinLinkModuleDef.h
    lld/trunk/lib/Driver/WinLinkModuleDef.cpp
    lld/trunk/test/pecoff/Inputs/exports.def
Modified:
    lld/trunk/lib/Driver/CMakeLists.txt
    lld/trunk/lib/Driver/WinLinkDriver.cpp
    lld/trunk/lib/Driver/WinLinkOptions.td
    lld/trunk/test/pecoff/export.test

Added: lld/trunk/include/lld/Driver/WinLinkModuleDef.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/WinLinkModuleDef.h?rev=198925&view=auto
==============================================================================
--- lld/trunk/include/lld/Driver/WinLinkModuleDef.h (added)
+++ lld/trunk/include/lld/Driver/WinLinkModuleDef.h Fri Jan 10 04:19:47 2014
@@ -0,0 +1,76 @@
+//===- lld/Driver/WinLinkModuleDef.h --------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Windows module definition file parser.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_DRIVER_WIN_LINK_MODULE_DEF_H
+#define LLD_DRIVER_WIN_LINK_MODULE_DEF_H
+
+#include "lld/Core/LLVM.h"
+#include "lld/ReaderWriter/PECOFFLinkingContext.h"
+
+namespace lld {
+namespace moduledef {
+
+enum class Kind {
+  unknown,
+  eof,
+  identifier,
+  equal,
+  kw_data,
+  kw_exports,
+  kw_noname,
+};
+
+class Token {
+public:
+  Token() : _kind(Kind::unknown) {}
+  Token(Kind kind, StringRef range) : _kind(kind), _range(range) {}
+
+  Kind _kind;
+  StringRef _range;
+};
+
+class Lexer {
+public:
+  explicit Lexer(std::unique_ptr<MemoryBuffer> mb) : _buffer(mb->getBuffer()) {
+    _sourceManager.AddNewSourceBuffer(mb.release(), llvm::SMLoc());
+  }
+
+  Token lex();
+  const llvm::SourceMgr &getSourceMgr() const { return _sourceManager; }
+
+private:
+  StringRef _buffer;
+  llvm::SourceMgr _sourceManager;
+};
+
+class Parser {
+public:
+  explicit Parser(Lexer &lex) : _lex(lex) {}
+  bool parse(std::vector<PECOFFLinkingContext::ExportDesc> &result);
+
+private:
+  void consumeToken();
+  void ungetToken();
+  void error(const Token &tok, Twine msg);
+
+  bool parseExport(PECOFFLinkingContext::ExportDesc &result);
+
+  Lexer &_lex;
+  Token _tok;
+  std::vector<Token> _tokBuf;
+};
+}
+}
+
+#endif

Modified: lld/trunk/lib/Driver/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/CMakeLists.txt?rev=198925&r1=198924&r2=198925&view=diff
==============================================================================
--- lld/trunk/lib/Driver/CMakeLists.txt (original)
+++ lld/trunk/lib/Driver/CMakeLists.txt Fri Jan 10 04:19:47 2014
@@ -18,6 +18,7 @@ add_lld_library(lldDriver
   GnuLdInputGraph.cpp
   WinLinkDriver.cpp
   WinLinkInputGraph.cpp
+  WinLinkModuleDef.cpp
   UniversalDriver.cpp
   )
 

Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=198925&r1=198924&r2=198925&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Fri Jan 10 04:19:47 2014
@@ -20,6 +20,7 @@
 
 #include "lld/Driver/Driver.h"
 #include "lld/Driver/WinLinkInputGraph.h"
+#include "lld/Driver/WinLinkModuleDef.h"
 #include "lld/ReaderWriter/PECOFFLinkingContext.h"
 
 #include "llvm/ADT/ArrayRef.h"
@@ -28,6 +29,7 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/Option.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/Program.h"
@@ -337,8 +339,19 @@ bool parseExport(StringRef option, PECOF
   }
 }
 
-StringRef replaceExtension(PECOFFLinkingContext &ctx,
-                           StringRef path, StringRef extension) {
+// Read module-definition file.
+bool parseDef(StringRef option,
+              std::vector<PECOFFLinkingContext::ExportDesc> &ret) {
+  OwningPtr<MemoryBuffer> buf;
+  if (MemoryBuffer::getFile(option, buf))
+    return false;
+  moduledef::Lexer lexer(std::unique_ptr<MemoryBuffer>(buf.take()));
+  moduledef::Parser parser(lexer);
+  return parser.parse(ret);
+}
+
+StringRef replaceExtension(PECOFFLinkingContext &ctx, StringRef path,
+                           StringRef extension) {
   SmallString<128> val = path;
   llvm::sys::path::replace_extension(val, extension);
   return ctx.allocate(val.str());
@@ -905,6 +918,18 @@ WinLinkDriver::parse(int argc, const cha
       break;
     }
 
+    case OPT_deffile: {
+      std::vector<PECOFFLinkingContext::ExportDesc> exports;
+      if (!parseDef(inputArg->getValue(), exports)) {
+        diagnostics << "Error: invalid module-definition file\n";
+        return false;
+      }
+      for (PECOFFLinkingContext::ExportDesc desc : exports) {
+        desc.name = ctx.decorateSymbol(desc.name);
+        ctx.addDllExport(desc);
+      }
+    }
+
     case OPT_libpath:
       ctx.appendInputSearchPath(ctx.allocate(inputArg->getValue()));
       break;

Added: lld/trunk/lib/Driver/WinLinkModuleDef.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkModuleDef.cpp?rev=198925&view=auto
==============================================================================
--- lld/trunk/lib/Driver/WinLinkModuleDef.cpp (added)
+++ lld/trunk/lib/Driver/WinLinkModuleDef.cpp Fri Jan 10 04:19:47 2014
@@ -0,0 +1,119 @@
+//===- lib/Driver/WinLinkModuleDef.cpp ------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Windows module definition file parser.
+///
+//===----------------------------------------------------------------------===//
+
+#include "lld/Driver/WinLinkModuleDef.h"
+#include "llvm/ADT/StringSwitch.h"
+
+namespace lld {
+namespace moduledef {
+
+Token Lexer::lex() {
+  _buffer = _buffer.trim();
+  if (_buffer.empty() || _buffer[0] == '\0')
+    return Token(Kind::eof, _buffer);
+
+  switch (_buffer[0]) {
+  case '=':
+    _buffer = _buffer.drop_front();
+    return Token(Kind::equal, "=");
+  case '"': {
+    size_t end = _buffer.find('"', 1);
+    Token ret;
+    if (end == _buffer.npos) {
+      ret = Token(Kind::identifier, _buffer.substr(1, end));
+      _buffer = "";
+    } else {
+      ret = Token(Kind::identifier, _buffer.substr(1, end - 1));
+      _buffer = _buffer.drop_front(end);
+    }
+    return ret;
+  }
+  default: {
+    size_t end = _buffer.find_first_not_of(
+        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+        "0123456789_.*~+!@#$%^&*()");
+    StringRef word = _buffer.substr(0, end);
+    Kind kind = llvm::StringSwitch<Kind>(word)
+                    .Case("DATA", Kind::kw_data)
+                    .Case("EXPORTS", Kind::kw_exports)
+                    .Case("NONAME", Kind::kw_noname)
+                    .Default(Kind::identifier);
+    _buffer = (end == _buffer.npos) ? "" : _buffer.drop_front(end);
+    return Token(kind, word);
+  }
+  }
+}
+
+void Parser::consumeToken() {
+  if (_tokBuf.empty()) {
+    _tok = _lex.lex();
+    return;
+  }
+  _tok = _tokBuf.back();
+  _tokBuf.pop_back();
+}
+
+void Parser::ungetToken() { _tokBuf.push_back(_tok); }
+
+void Parser::error(const Token &tok, Twine msg) {
+  _lex.getSourceMgr().PrintMessage(
+      llvm::SMLoc::getFromPointer(tok._range.data()), llvm::SourceMgr::DK_Error,
+      msg);
+}
+
+bool Parser::parse(std::vector<PECOFFLinkingContext::ExportDesc> &result) {
+  consumeToken();
+  if (_tok._kind != Kind::kw_exports) {
+    error(_tok, "Expected EXPORTS");
+    return false;
+  }
+  for (;;) {
+    PECOFFLinkingContext::ExportDesc desc;
+    if (!parseExport(desc))
+      return true;
+    result.push_back(desc);
+  }
+}
+
+bool Parser::parseExport(PECOFFLinkingContext::ExportDesc &result) {
+  consumeToken();
+  if (_tok._kind != Kind::identifier) {
+    ungetToken();
+    return false;
+  }
+  result.name = _tok._range;
+
+  for (;;) {
+    consumeToken();
+    if (_tok._kind == Kind::identifier && _tok._range[0] == '@') {
+      _tok._range.drop_front().getAsInteger(10, result.ordinal);
+      consumeToken();
+      if (_tok._kind == Kind::kw_noname) {
+        result.noname = true;
+      } else {
+        ungetToken();
+      }
+      continue;
+    }
+    if (_tok._kind == Kind::kw_data) {
+      result.isData = true;
+      continue;
+    }
+    ungetToken();
+    return true;
+  }
+}
+
+} // moddef
+} // namespace lld

Modified: lld/trunk/lib/Driver/WinLinkOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkOptions.td?rev=198925&r1=198924&r2=198925&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkOptions.td (original)
+++ lld/trunk/lib/Driver/WinLinkOptions.td Fri Jan 10 04:19:47 2014
@@ -50,6 +50,10 @@ def manifestdependency : P<"manifestdepe
 def incl : Joined<["/", "-"], "include:">,
     HelpText<"Force symbol to be added to symbol table as undefined one">;
 
+// "def" is also a keyword.
+def deffile : Joined<["/", "-"], "def:">,
+    HelpText<"Use module-definition file">;
+
 def nodefaultlib_all : F<"nodefaultlib">;
 def noentry : F<"noentry">;
 def dll : F<"dll">;

Added: lld/trunk/test/pecoff/Inputs/exports.def
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/exports.def?rev=198925&view=auto
==============================================================================
--- lld/trunk/test/pecoff/Inputs/exports.def (added)
+++ lld/trunk/test/pecoff/Inputs/exports.def Fri Jan 10 04:19:47 2014
@@ -0,0 +1,3 @@
+EXPORTS
+  exportfn1 @5
+  exportfn2

Modified: lld/trunk/test/pecoff/export.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/export.test?rev=198925&r1=198924&r2=198925&view=diff
==============================================================================
--- lld/trunk/test/pecoff/export.test (original)
+++ lld/trunk/test/pecoff/export.test Fri Jan 10 04:19:47 2014
@@ -37,3 +37,16 @@ CHECK3-NEXT:  1020 30100000 34100000 082
 CHECK3-NEXT:  1030 4b100000 01006578 706f7274 2e746573
 CHECK3-NEXT:  1040 742e746d 70332e64 6c6c0065 78706f72
 CHECK3-NEXT:  1050 74666e32 00
+
+# RUN: lld -flavor link /out:%t4.dll /dll /entry:init \
+# RUN:   /def:%p/Inputs/exports.def -- %t.obj
+# RUN: llvm-objdump -s %t4.dll | FileCheck -check-prefix=CHECK4 %s
+
+CHECK4:      Contents of section .edata:
+CHECK4-NEXT:  1000 00000000 {{........}} 00000000 3c100000
+CHECK4-NEXT:  1010 05000000 02000000 02000000 28100000
+CHECK4-NEXT:  1020 30100000 38100000 08200000 10200000
+CHECK4-NEXT:  1030 51100000 5b100000 00000100 6578706f
+CHECK4-NEXT:  1040 72742e74 6573742e 746d7034 2e646c6c
+CHECK4-NEXT:  1050 00657870 6f727466 6e310065 78706f72
+CHECK4-NEXT:  1060 74666e32 00





More information about the llvm-commits mailing list