[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