[lld] r218355 - [PECOFF] Exported name should match C++ mangled name

Rui Ueyama ruiu at google.com
Tue Sep 23 19:01:11 PDT 2014


Author: ruiu
Date: Tue Sep 23 21:01:10 2014
New Revision: 218355

URL: http://llvm.org/viewvc/llvm-project?rev=218355&view=rev
Log:
[PECOFF] Exported name should match C++ mangled name

Currently you can omit the leading underscore from exported
symbol name. LLD will look for mangled name for you. But it won't
look for C++ mangled name.

This patch is to support that.

If "sym" is specified to be exported, the linker looks for not
only "sym", but also "_sym" and "?sym@@<whatever>", so that you
can export a C++ function without decorating it.

Modified:
    lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
    lld/trunk/test/pecoff/Inputs/export.obj.yaml
    lld/trunk/test/pecoff/export.test

Modified: lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h?rev=218355&r1=218354&r2=218355&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h Tue Sep 23 21:01:10 2014
@@ -217,12 +217,12 @@ private:
 //
 // DLLExported symbols can be specified using a module definition file. In a
 // file, one can write an EXPORT directive followed by symbol names. Such
-// symbols may not be fully decorated -- one can omit "@" and the following
-// number suffix for the stdcall function.
+// symbols may not be fully decorated.
 //
 // If a symbol FOO is specified to be dllexported by a module definition file,
-// linker has to search not only for FOO but also for FOO@[0-9]+. This ambiguous
-// matching semantics does not fit well with Resolver.
+// linker has to search not only for /FOO/ but also for /FOO@[0-9]+/ for stdcall
+// and for /\?FOO@@.+/ for C++. This ambiguous matching semantics does not fit
+// well with Resolver.
 //
 // We could probably modify Resolver to resolve ambiguous symbols, but I think
 // we don't want to do that because it'd be rarely used, and only this Windows
@@ -255,7 +255,7 @@ public:
     if (it == _exportedSyms.end())
       return nullptr;
     std::string replace;
-    if (!findSymbolWithAtsignSuffix(sym.str(), replace))
+    if (!findDecoratedSymbol(sym.str(), replace))
       return nullptr;
     it->second->name = replace;
     if (_ctx->deadStrip())
@@ -264,23 +264,33 @@ public:
   }
 
 private:
-
-  // Find a symbol that starts with a given symbol name followed
-  // by @number suffix.
-  bool findSymbolWithAtsignSuffix(std::string sym, std::string &res) const {
-    sym.append("@");
+  // Find decorated symbol, namely /sym@[0-9]+/ or /\?sym@@.+/.
+  bool findDecoratedSymbol(std::string sym, std::string &res) const {
     const std::set<std::string> &defined = _syms->defined();
-    auto it = defined.lower_bound(sym);
-    for (auto e = defined.end(); it != e; ++it) {
-      if (!StringRef(*it).startswith(sym))
-        return false;
-      if (it->size() == sym.size())
-        continue;
-      StringRef suffix = StringRef(*it).substr(sym.size());
-      if (suffix.find_first_not_of("0123456789") != StringRef::npos)
-        continue;
-      res = *it;
-      return true;
+    // Search for /sym@[0-9]+/
+    {
+      std::string s = sym + '@';
+      auto it = defined.lower_bound(s);
+      for (auto e = defined.end(); it != e; ++it) {
+        if (!StringRef(*it).startswith(s))
+          break;
+        if (it->size() == s.size())
+          continue;
+        StringRef suffix = StringRef(*it).substr(s.size());
+        if (suffix.find_first_not_of("0123456789") != StringRef::npos)
+          continue;
+        res = *it;
+        return true;
+      }
+    }
+    // Search for /\?sym@@.+/
+    {
+      std::string s = "?" + _ctx->undecorateSymbol(sym).str() + "@@";
+      auto it = defined.lower_bound(s);
+      if (it != defined.end() && StringRef(*it).startswith(s)) {
+        res = *it;
+        return true;
+      }
     }
     return false;
   }

Modified: lld/trunk/test/pecoff/Inputs/export.obj.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/export.obj.yaml?rev=218355&r1=218354&r2=218355&view=diff
==============================================================================
--- lld/trunk/test/pecoff/Inputs/export.obj.yaml (original)
+++ lld/trunk/test/pecoff/Inputs/export.obj.yaml Tue Sep 23 21:01:10 2014
@@ -60,4 +60,10 @@ symbols:
     SimpleType:      IMAGE_SYM_TYPE_NULL
     ComplexType:     IMAGE_SYM_DTYPE_NULL
     StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            "?exportfn8@@YAXXZ"
+    Value:           16
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
 ...

Modified: lld/trunk/test/pecoff/export.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/export.test?rev=218355&r1=218354&r2=218355&view=diff
==============================================================================
--- lld/trunk/test/pecoff/export.test (original)
+++ lld/trunk/test/pecoff/export.test Tue Sep 23 21:01:10 2014
@@ -50,3 +50,12 @@ CHECK5:      Export Table:
 CHECK5:      DLL name: export.test.tmp5.dll
 CHECK5:       Ordinal      RVA  Name
 CHECK5-NEXT:        1   0x2010  exportfn7
+
+# RUN: lld -flavor link /out:%t6.dll /dll /entry:init \
+# RUN:   /export:exportfn8 -- %t.obj
+# RUN: llvm-objdump -p %t6.dll | FileCheck -check-prefix=CHECK6 %s
+
+CHECK6:      Export Table:
+CHECK6:      DLL name: export.test.tmp6.dll
+CHECK6:       Ordinal      RVA  Name
+CHECK6-NEXT:        1   0x2010  exportfn8





More information about the llvm-commits mailing list