[lld] r197217 - [PECOFF] Parse /export optional arguments.

Rui Ueyama ruiu at google.com
Fri Dec 13 00:42:52 PST 2013


Author: ruiu
Date: Fri Dec 13 02:42:52 2013
New Revision: 197217

URL: http://llvm.org/viewvc/llvm-project?rev=197217&view=rev
Log:
[PECOFF] Parse /export optional arguments.

/EXPORT command line option can take an ordinal, NONAME flag, and DATA flag.
This patch is to parse these optional arguments.

Modified:
    lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
    lld/trunk/lib/Driver/WinLinkDriver.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp
    lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp

Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=197217&r1=197216&r2=197217&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Fri Dec 13 02:42:52 2013
@@ -57,6 +57,14 @@ public:
     int minorVersion;
   };
 
+  struct ExportDesc {
+    ExportDesc() : ordinal(-1), noname(false), isData(false) {}
+    std::string name;
+    int ordinal;
+    bool noname;
+    bool isData;
+  };
+
   /// \brief Casting support
   static inline bool classof(const LinkingContext *info) { return true; }
 
@@ -219,8 +227,8 @@ public:
   void setDosStub(ArrayRef<uint8_t> data) { _dosStub = data; }
   ArrayRef<uint8_t> getDosStub() const { return _dosStub; }
 
-  void addDllExport(StringRef sym) { _dllExports.insert(sym); }
-  const std::set<std::string> &getDllExports() const { return _dllExports; }
+  void addDllExport(ExportDesc &desc) { _dllExports.push_back(desc); }
+  const std::vector<ExportDesc> &getDllExports() const { return _dllExports; }
 
   StringRef allocate(StringRef ref) const {
     char *x = _allocator.Allocate<char>(ref.size() + 1);
@@ -301,7 +309,7 @@ private:
   std::map<std::string, uint32_t> _sectionClearMask;
 
   // DLLExport'ed symbols.
-  std::set<std::string> _dllExports;
+  std::vector<ExportDesc> _dllExports;
 
   // List of files that will be removed on destruction.
   std::vector<std::unique_ptr<llvm::FileRemover> > _tempFiles;

Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=197217&r1=197216&r2=197217&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Fri Dec 13 02:42:52 2013
@@ -300,6 +300,41 @@ bool parseManifestUac(StringRef option,
   }
 }
 
+// Parse /export:name[, at ordinal[,NONAME]][,DATA].
+bool parseExport(StringRef option, PECOFFLinkingContext::ExportDesc &ret) {
+  StringRef name;
+  StringRef rest;
+  llvm::tie(name, rest) = option.split(",");
+  if (name.empty())
+    return false;
+  ret.name = name;
+
+  for (;;) {
+    if (rest.empty())
+      return true;
+    StringRef arg;
+    llvm::tie(arg, rest) = rest.split(",");
+    if (arg.equals_lower("noname")) {
+      if (ret.ordinal < 0)
+        return false;
+      ret.noname = true;
+      continue;
+    }
+    if (arg.equals_lower("data")) {
+      ret.isData = true;
+      continue;
+    }
+    if (arg.startswith("@")) {
+      int ordinal;
+      if (arg.substr(1).getAsInteger(0, ordinal))
+        return false;
+      ret.ordinal = ordinal;
+      continue;
+    }
+    return false;
+  }
+}
+
 StringRef replaceExtension(PECOFFLinkingContext &ctx,
                            StringRef path, StringRef extension) {
   SmallString<128> val = path;
@@ -840,9 +875,15 @@ WinLinkDriver::parse(int argc, const cha
       ctx.setEntrySymbolName(ctx.allocate(inputArg->getValue()));
       break;
 
-    case OPT_export:
-      ctx.addDllExport(inputArg->getValue());
+    case OPT_export: {
+      PECOFFLinkingContext::ExportDesc desc;
+      if (!parseExport(inputArg->getValue(), desc)) {
+        diagnostics << "Error: malformed /export option\n";
+        return false;
+      }
+      ctx.addDllExport(desc);
       break;
+    }
 
     case OPT_libpath:
       ctx.appendInputSearchPath(ctx.allocate(inputArg->getValue()));

Modified: lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp?rev=197217&r1=197216&r2=197217&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp Fri Dec 13 02:42:52 2013
@@ -30,10 +30,10 @@ static bool getExportedAtoms(const PECOF
   for (const DefinedAtom *atom : file->defined())
     definedAtoms[atom->name()] = atom;
 
-  for (StringRef dllExport : ctx.getDllExports()) {
-    auto it = definedAtoms.find(ctx.decorateSymbol(dllExport));
+  for (const PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports()) {
+    auto it = definedAtoms.find(ctx.decorateSymbol(desc.name));
     if (it == definedAtoms.end()) {
-      llvm::errs() << "Symbol <" << dllExport
+      llvm::errs() << "Symbol <" << desc.name
                    << "> is exported but not defined.\n";
       return false;
     }

Modified: lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=197217&r1=197216&r2=197217&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp Fri Dec 13 02:42:52 2013
@@ -157,10 +157,30 @@ TEST_F(WinLinkParserTest, AlternateName)
 }
 
 TEST_F(WinLinkParserTest, Export) {
-  EXPECT_TRUE(parse("link.exe", "/export:_foo", "a.out", nullptr));
-  const std::set<std::string> &exports = _context.getDllExports();
-  EXPECT_TRUE(exports.count("_foo") == 1);
-  EXPECT_TRUE(exports.count("nosuchsym") == 0);
+  EXPECT_TRUE(parse("link.exe", "/export:foo", "a.out", nullptr));
+  const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
+      _context.getDllExports();
+  EXPECT_TRUE(exports.size() == 1);
+  EXPECT_EQ("foo", exports[0].name);
+  EXPECT_EQ(-1, exports[0].ordinal);
+  EXPECT_FALSE(exports[0].noname);
+  EXPECT_FALSE(exports[0].isData);
+}
+
+TEST_F(WinLinkParserTest, ExportWithOptions) {
+  EXPECT_TRUE(parse("link.exe", "/export:foo, at 8,noname,data",
+                    "/export:bar, at 10,data", "a.out", nullptr));
+  const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
+      _context.getDllExports();
+  EXPECT_TRUE(exports.size() == 2);
+  EXPECT_EQ("foo", exports[0].name);
+  EXPECT_EQ(8, exports[0].ordinal);
+  EXPECT_TRUE(exports[0].noname);
+  EXPECT_TRUE(exports[0].isData);
+  EXPECT_EQ("bar", exports[1].name);
+  EXPECT_EQ(10, exports[1].ordinal);
+  EXPECT_FALSE(exports[1].noname);
+  EXPECT_TRUE(exports[1].isData);
 }
 
 TEST_F(WinLinkParserTest, MachineX86) {





More information about the llvm-commits mailing list