[lld] r241872 - COFF: Fix dllexported symbol names on x86.

Rui Ueyama ruiu at google.com
Thu Jul 9 15:51:41 PDT 2015


Author: ruiu
Date: Thu Jul  9 17:51:41 2015
New Revision: 241872

URL: http://llvm.org/viewvc/llvm-project?rev=241872&view=rev
Log:
COFF: Fix dllexported symbol names on x86.

Symbol names are usually mangled by appending "_" prefix on x86.
But the mangled name is not used in DLL export table. The export
table contains unmangled names.

Added:
    lld/trunk/test/COFF/Inputs/export32.yaml
    lld/trunk/test/COFF/export32.test
Modified:
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/Driver.h
    lld/trunk/COFF/ModuleDef.cpp

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=241872&r1=241871&r2=241872&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Thu Jul  9 17:51:41 2015
@@ -108,6 +108,8 @@ LinkerDriver::parseDirectives(StringRef
       ErrorOr<Export> E = parseExport(Arg->getValue());
       if (auto EC = E.getError())
         return EC;
+      if (!Config->is64() && E->ExtName.startswith("_"))
+        E->ExtName = E->ExtName.substr(1);
       Config->Exports.push_back(E.get());
       break;
     }
@@ -293,11 +295,6 @@ bool LinkerDriver::link(llvm::ArrayRef<c
   if (Args.hasArg(OPT_force) || Args.hasArg(OPT_force_unresolved))
     Config->Force = true;
 
-  // Handle /entry
-  StringRef Entry;
-  if (auto *Arg = Args.getLastArg(OPT_entry))
-    Entry = Arg->getValue();
-
   // Handle /debug
   if (Args.hasArg(OPT_debug))
     Config->Debug = true;
@@ -316,8 +313,6 @@ bool LinkerDriver::link(llvm::ArrayRef<c
     Config->DLL = true;
     Config->ImageBase = 0x180000000U;
     Config->ManifestID = 2;
-    if (Entry.empty() && !Config->NoEntry)
-      Entry = "_DllMainCRTStartup";
   }
 
   // Handle /fixed
@@ -423,14 +418,6 @@ bool LinkerDriver::link(llvm::ArrayRef<c
     }
   }
 
-  // Handle /export
-  for (auto *Arg : Args.filtered(OPT_export)) {
-    ErrorOr<Export> E = parseExport(Arg->getValue());
-    if (E.getError())
-      return false;
-    Config->Exports.push_back(E.get());
-  }
-
   // Handle /delayload
   for (auto *Arg : Args.filtered(OPT_delayload)) {
     Config->DelayLoads.insert(StringRef(Arg->getValue()).lower());
@@ -442,18 +429,6 @@ bool LinkerDriver::link(llvm::ArrayRef<c
     if (checkFailIfMismatch(Arg->getValue()))
       return false;
 
-  // Handle /def
-  if (auto *Arg = Args.getLastArg(OPT_deffile)) {
-    ErrorOr<MemoryBufferRef> MBOrErr = openFile(Arg->getValue());
-    if (auto EC = MBOrErr.getError()) {
-      llvm::errs() << "/def: " << EC.message() << "\n";
-      return false;
-    }
-    // parseModuleDefs mutates Config object.
-    if (parseModuleDefs(MBOrErr.get()))
-      return false;
-  }
-
   // Handle /merge
   for (auto *Arg : Args.filtered(OPT_merge))
     if (parseMerge(Arg->getValue()))
@@ -581,13 +556,16 @@ bool LinkerDriver::link(llvm::ArrayRef<c
     OwningMBs.push_back(std::move(MB)); // take ownership
   }
 
-  if (!Entry.empty())
-    Config->Entry = addUndefined(mangle(Entry));
-  Symtab.addAbsolute(mangle("__ImageBase"), Config->ImageBase);
-
-  // Windows specific -- If entry point name is not given, we need to
-  // infer that from user-defined entry name.
-  if (Entry.empty() && !Config->NoEntry) {
+  // Handle /entry and /dll
+  if (auto *Arg = Args.getLastArg(OPT_entry)) {
+    Config->Entry = addUndefined(mangle(Arg->getValue()));
+  } else if (Args.hasArg(OPT_dll) && !Config->NoEntry) {
+    StringRef S =
+        Config->is64() ? "_DllMainCRTStartup" : "__DllMainCRTStartup at 12";
+    Config->Entry = addUndefined(S);
+  } else if (!Config->NoEntry) {
+    // Windows specific -- If entry point name is not given, we need to
+    // infer that from user-defined entry name.
     StringRef S = findDefaultEntry();
     if (S.empty()) {
       llvm::errs() << "entry point must be defined\n";
@@ -598,6 +576,30 @@ bool LinkerDriver::link(llvm::ArrayRef<c
       llvm::outs() << "Entry name inferred: " << S << "\n";
   }
 
+  // Handle /export
+  for (auto *Arg : Args.filtered(OPT_export)) {
+    ErrorOr<Export> E = parseExport(Arg->getValue());
+    if (E.getError())
+      return false;
+    if (!Config->is64() && !E->Name.startswith("_@?"))
+      E->Name = mangle(E->Name);
+    Config->Exports.push_back(E.get());
+  }
+
+  // Handle /def
+  if (auto *Arg = Args.getLastArg(OPT_deffile)) {
+    ErrorOr<MemoryBufferRef> MBOrErr = openFile(Arg->getValue());
+    if (auto EC = MBOrErr.getError()) {
+      llvm::errs() << "/def: " << EC.message() << "\n";
+      return false;
+    }
+    // parseModuleDefs mutates Config object.
+    if (parseModuleDefs(MBOrErr.get(), &Alloc))
+      return false;
+  }
+
+  Symtab.addAbsolute(mangle("__ImageBase"), Config->ImageBase);
+
   // Read as much files as we can from directives sections.
   if (auto EC = Symtab.run()) {
     llvm::errs() << EC.message() << "\n";

Modified: lld/trunk/COFF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.h?rev=241872&r1=241871&r2=241872&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.h (original)
+++ lld/trunk/COFF/Driver.h Thu Jul  9 17:51:41 2015
@@ -110,7 +110,8 @@ private:
   std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
 };
 
-std::error_code parseModuleDefs(MemoryBufferRef MB);
+std::error_code parseModuleDefs(MemoryBufferRef MB,
+                                llvm::BumpPtrStringSaver *Alloc);
 std::error_code writeImportLibrary();
 
 // Functions below this line are defined in DriverUtils.cpp.

Modified: lld/trunk/COFF/ModuleDef.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/ModuleDef.cpp?rev=241872&r1=241871&r2=241872&view=diff
==============================================================================
--- lld/trunk/COFF/ModuleDef.cpp (original)
+++ lld/trunk/COFF/ModuleDef.cpp Thu Jul  9 17:51:41 2015
@@ -20,6 +20,7 @@
 #include "Error.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/StringSaver.h"
 #include "llvm/Support/raw_ostream.h"
 #include <system_error>
 
@@ -108,7 +109,7 @@ private:
 
 class Parser {
 public:
-  explicit Parser(StringRef S) : Lex(S) {}
+  explicit Parser(StringRef S, BumpPtrStringSaver *A) : Lex(S), Alloc(A) {}
 
   std::error_code parse() {
     do {
@@ -208,6 +209,9 @@ private:
       E.Name = E.ExtName;
     }
 
+    if (!Config->is64() && !E.Name.startswith("_@?"))
+      E.Name = Alloc->save("_" + E.Name);
+
     for (;;) {
       read();
       if (Tok.K == Identifier && Tok.Value[0] == '@') {
@@ -297,12 +301,13 @@ private:
   Lexer Lex;
   Token Tok;
   std::vector<Token> Stack;
+  BumpPtrStringSaver *Alloc;
 };
 
 } // anonymous namespace
 
-std::error_code parseModuleDefs(MemoryBufferRef MB) {
-  return Parser(MB.getBuffer()).parse();
+std::error_code parseModuleDefs(MemoryBufferRef MB, BumpPtrStringSaver *Alloc) {
+  return Parser(MB.getBuffer(), Alloc).parse();
 }
 
 } // namespace coff

Added: lld/trunk/test/COFF/Inputs/export32.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/export32.yaml?rev=241872&view=auto
==============================================================================
--- lld/trunk/test/COFF/Inputs/export32.yaml (added)
+++ lld/trunk/test/COFF/Inputs/export32.yaml Thu Jul  9 17:51:41 2015
@@ -0,0 +1,57 @@
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_I386
+  Characteristics: []
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     B800000000506800000000680000000050E80000000050E800000000
+  - Name:            .drectve
+    Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+    Alignment:       2147483648
+    SectionData:     2f6578706f72743a5f6578706f7274666e3300  # /export:_exportfn3
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          28
+      NumberOfRelocations: 4
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          0
+  - Name:            __DllMainCRTStartup at 12
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            _exportfn1
+    Value:           8
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            _exportfn2
+    Value:           16
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            _exportfn3
+    Value:           16
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            '?mangled@@YAHXZ'
+    Value:           16
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...

Added: lld/trunk/test/COFF/export32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/export32.test?rev=241872&view=auto
==============================================================================
--- lld/trunk/test/COFF/export32.test (added)
+++ lld/trunk/test/COFF/export32.test Thu Jul  9 17:51:41 2015
@@ -0,0 +1,72 @@
+# RUN: yaml2obj < %p/Inputs/export32.yaml > %t.obj
+#
+# RUN: lld -flavor link2 /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK1 %s
+
+CHECK1:      Export Table:
+CHECK1:      DLL name: export32.test.tmp.dll
+CHECK1:      Ordinal      RVA  Name
+CHECK1-NEXT:       0        0
+CHECK1-NEXT:       1   0x1008  exportfn1
+CHECK1-NEXT:       2   0x1010  exportfn2
+
+# RUN: lld -flavor link2 /out:%t.dll /dll %t.obj /export:exportfn1, at 5 /export:exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK2 %s
+
+CHECK2:      Export Table:
+CHECK2:      DLL name: export32.test.tmp.dll
+CHECK2:      Ordinal      RVA  Name
+CHECK2-NEXT:       0        0
+CHECK2-NEXT:       1        0
+CHECK2-NEXT:       2        0
+CHECK2-NEXT:       3        0
+CHECK2-NEXT:       4        0
+CHECK2-NEXT:       5   0x1008  exportfn1
+CHECK2-NEXT:       6   0x1010  exportfn2
+CHECK2-NEXT:       7   0x1010  exportfn3
+
+# RUN: lld -flavor link2 /out:%t.dll /dll %t.obj /export:exportfn1, at 5,noname /export:exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK3 %s
+
+CHECK3:      Export Table:
+CHECK3:      DLL name: export32.test.tmp.dll
+CHECK3:      Ordinal      RVA  Name
+CHECK3-NEXT:       0        0
+CHECK3-NEXT:       1        0
+CHECK3-NEXT:       2        0
+CHECK3-NEXT:       3        0
+CHECK3-NEXT:       4        0
+CHECK3-NEXT:       5   0x1008
+CHECK3-NEXT:       6   0x1010  exportfn2
+
+# RUN: lld -flavor link2 /out:%t.dll /dll %t.obj /export:f1=exportfn1 /export:f2=exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK4 %s
+
+CHECK4:      Export Table:
+CHECK4:      DLL name: export32.test.tmp.dll
+CHECK4:      Ordinal      RVA  Name
+CHECK4-NEXT:       0        0
+CHECK4-NEXT:       1   0x1010  exportfn3
+CHECK4-NEXT:       2   0x1008  f1
+CHECK4-NEXT:       3   0x1010  f2
+
+# RUN: echo "EXPORTS exportfn1 @3" > %t.def
+# RUN: echo "fn2=exportfn2 @2" >> %t.def
+# RUN: lld -flavor link2 /out:%t.dll /dll %t.obj /def:%t.def
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK5 %s
+
+CHECK5:      Export Table:
+CHECK5:      DLL name: export32.test.tmp.dll
+CHECK5:      Ordinal      RVA  Name
+CHECK5-NEXT:       0        0
+CHECK5-NEXT:       1        0
+CHECK5-NEXT:       2   0x1010  fn2
+CHECK5-NEXT:       3   0x1008  exportfn1
+CHECK5-NEXT:       4   0x1010  exportfn3
+
+# RUN: lld -flavor link2 /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 \
+# RUN:   /export:exportfn1 /export:exportfn2, at 5 >& %t.log
+# RUN: FileCheck -check-prefix=CHECK6 %s < %t.log
+
+CHECK6:     duplicate /export option: _exportfn2
+CHECK6-NOT: duplicate /export option: _exportfn1





More information about the llvm-commits mailing list