COFF: Fix export symbol names for x86.

I don't fully understand the rationale behind the name mangling
scheme used for the DLL export table and the import library.
Why only leading "_" is dropped for the import library while
both "_" and "@" are dropped from DLL symbol table? But this seems
to be what MSVC linker does.

llvm-svn: 243490
This commit is contained in:
Rui Ueyama 2015-07-28 22:34:24 +00:00
parent 7651dd8359
commit 9420dee328
5 changed files with 125 additions and 114 deletions

View File

@ -34,8 +34,10 @@ static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386;
// Represents an /export option.
struct Export {
StringRef Name;
StringRef ExtName;
StringRef Name; // N in /export:N or /export:E=N
StringRef ExtName; // E in /export:E=N
StringRef ExtDLLName; // Symbol name written to a DLL export table
StringRef ExtLibName; // Symbol name written to a import library
Undefined *Sym = nullptr;
uint16_t Ordinal = 0;
bool Noname = false;

View File

@ -535,7 +535,7 @@ EdataContents::EdataContents() {
std::vector<Chunk *> Names;
for (Export &E : Config->Exports)
if (!E.Noname)
Names.push_back(new StringChunk(E.ExtName));
Names.push_back(new StringChunk(E.ExtDLLName));
auto *NameTab = new NamePointersChunk(Names);
auto *OrdinalTab = new ExportOrdinalChunk(Names.size());
auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName,

View File

@ -425,12 +425,19 @@ std::error_code fixupExports() {
}
for (Export &E : Config->Exports) {
if (!E.ExtName.empty())
if (!E.ExtName.empty()) {
E.ExtDLLName = E.ExtName;
E.ExtLibName = E.ExtName;
continue;
}
StringRef S = E.Sym->repl()->getName();
if (Config->Machine == I386 && S.startswith("_"))
S = S.substr(1);
E.ExtName = S;
if (Config->Machine == I386 && S.startswith("_")) {
E.ExtDLLName = S.substr(1).split('@').first;
E.ExtLibName = S.substr(1);
continue;
}
E.ExtDLLName = S;
E.ExtLibName = S;
}
// Uniquefy by name.
@ -452,9 +459,10 @@ std::error_code fixupExports() {
Config->Exports = std::move(V);
// Sort by name.
std::sort(
Config->Exports.begin(), Config->Exports.end(),
[](const Export &A, const Export &B) { return A.ExtName < B.ExtName; });
std::sort(Config->Exports.begin(), Config->Exports.end(),
[](const Export &A, const Export &B) {
return A.ExtDLLName < B.ExtDLLName;
});
return std::error_code();
}
@ -528,7 +536,7 @@ static std::string createModuleDefinitionFile() {
OS << "LIBRARY \"" << llvm::sys::path::filename(Config->OutputFile) << "\"\n"
<< "EXPORTS\n";
for (Export &E : Config->Exports) {
OS << " " << E.ExtName;
OS << " " << E.ExtLibName;
if (E.Ordinal > 0)
OS << " @" << E.Ordinal;
if (E.Noname)

View File

@ -1,57 +0,0 @@
---
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@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
...

View File

@ -1,74 +1,132 @@
# RUN: yaml2obj < %p/Inputs/export32.yaml > %t.obj
# RUN: yaml2obj < %s > %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
# 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,@5 \
# RUN: /export:exportfn2 /export:mangled
# 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 ?mangled@@YAHXZ
CHECK2-NEXT: 7 0x1010 exportfn2
CHECK2-NEXT: 8 0x1010 exportfn3
# 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 ?mangled@@YAHXZ
# CHECK2-NEXT: 7 0x1010 exportfn2
# CHECK2-NEXT: 8 0x1010 exportfn3
# RUN: lld -flavor link2 /out:%t.dll /dll %t.obj /export:exportfn1,@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
# 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
# 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
# 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,@5 >& %t.log
# RUN: FileCheck -check-prefix=CHECK6 %s < %t.log
CHECK6: duplicate /export option: _exportfn2
CHECK6-NOT: duplicate /export option: _exportfn1
# CHECK6: duplicate /export option: _exportfn2
# CHECK6-NOT: duplicate /export option: _exportfn1
---
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@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@4
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
...