From 8765fbae15bb2974bb7689f8f4d8042d1e64469e Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Wed, 15 Jul 2015 22:21:08 +0000 Subject: [PATCH] COFF: Fix mangled dllexported names. If a symbol is exported as /export:foo, and foo is resolved as a mangled name (_foo@ or ?foo@@Y...), that mangled name should be written to the export table. Previously, we wrote the original name to the export table. llvm-svn: 242342 --- lld/COFF/Driver.cpp | 9 ++++----- lld/COFF/Driver.h | 1 + lld/COFF/DriverUtils.cpp | 16 +++++++++++++--- lld/COFF/ModuleDef.cpp | 4 ++-- lld/test/COFF/dll.test | 16 ++++++---------- lld/test/COFF/export32.test | 6 +++--- 6 files changed, 29 insertions(+), 23 deletions(-) diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index f553cb1..0719c80 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -670,13 +670,12 @@ bool LinkerDriver::link(llvm::ArrayRef ArgsArr) { // Windows specific -- when we are creating a .dll file, we also // need to create a .lib file. - if (!Config->Exports.empty()) - writeImportLibrary(); - - // Windows specific -- fix up dllexported symbols. - if (!Config->Exports.empty()) + if (!Config->Exports.empty()) { if (fixupExports()) return false; + writeImportLibrary(); + assignExportOrdinals(); + } // Windows specific -- Create a side-by-side manifest file. if (Config->Manifest == Configuration::SideBySide) diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index 8f4b4f2..b7b40b6 100644 --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -150,6 +150,7 @@ std::error_code createSideBySideManifest(); // Used for dllexported symbols. ErrorOr parseExport(StringRef Arg); std::error_code fixupExports(); +void assignExportOrdinals(); // Parses a string in the form of "key=value" and check // if value matches previous values for the key. diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index cb83842..560f9e2 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -16,6 +16,7 @@ #include "Config.h" #include "Driver.h" #include "Error.h" +#include "Symbols.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" @@ -372,8 +373,6 @@ ErrorOr parseExport(StringRef Arg) { std::tie(E.ExtName, E.Name) = E.Name.split("="); if (E.Name.empty()) goto err; - } else { - E.ExtName = E.Name; } while (!Rest.empty()) { @@ -425,6 +424,15 @@ std::error_code fixupExports() { } } + for (Export &E : Config->Exports) { + if (!E.ExtName.empty()) + continue; + StringRef S = E.Sym->repl()->getName(); + if (!Config->is64() && S.startswith("_")) + S = S.substr(1); + E.ExtName = S; + } + // Uniquefy by name. std::map Map; std::vector V; @@ -447,7 +455,10 @@ std::error_code fixupExports() { std::sort( Config->Exports.begin(), Config->Exports.end(), [](const Export &A, const Export &B) { return A.ExtName < B.ExtName; }); + return std::error_code(); +} +void assignExportOrdinals() { // Assign unique ordinals if default (= 0). uint16_t Max = 0; for (Export &E : Config->Exports) @@ -455,7 +466,6 @@ std::error_code fixupExports() { for (Export &E : Config->Exports) if (E.Ordinal == 0) E.Ordinal = ++Max; - return std::error_code(); } // Parses a string in the form of "key=value" and check diff --git a/lld/COFF/ModuleDef.cpp b/lld/COFF/ModuleDef.cpp index eeffa22..fc93dcc 100644 --- a/lld/COFF/ModuleDef.cpp +++ b/lld/COFF/ModuleDef.cpp @@ -195,7 +195,7 @@ private: std::error_code parseExport() { Export E; - E.ExtName = Tok.Value; + E.Name = Tok.Value; read(); if (Tok.K == Equal) { read(); @@ -203,10 +203,10 @@ private: llvm::errs() << "identifier expected, but got " << Tok.Value << "\n"; return make_error_code(LLDError::InvalidOption); } + E.ExtName = E.Name; E.Name = Tok.Value; } else { unget(); - E.Name = E.ExtName; } if (!Config->is64() && !E.Name.startswith("_@?")) diff --git a/lld/test/COFF/dll.test b/lld/test/COFF/dll.test index 9bfb68d..8c897b2 100644 --- a/lld/test/COFF/dll.test +++ b/lld/test/COFF/dll.test @@ -9,10 +9,10 @@ EXPORT: Export Table: EXPORT: DLL name: dll.test.tmp.dll EXPORT: Ordinal RVA Name EXPORT-NEXT: 0 0 -EXPORT-NEXT: 1 0x1008 exportfn1 -EXPORT-NEXT: 2 0x1010 exportfn2 -EXPORT-NEXT: 3 0x1010 exportfn3 -EXPORT-NEXT: 4 0x1010 mangled +EXPORT-NEXT: 1 0x1010 ?mangled@@YAHXZ +EXPORT-NEXT: 2 0x1008 exportfn1 +EXPORT-NEXT: 3 0x1010 exportfn2 +EXPORT-NEXT: 4 0x1010 exportfn3 # RUN: yaml2obj < %p/Inputs/export2.yaml > %t5.obj # RUN: rm -f %t5.lib @@ -24,8 +24,8 @@ EXPORT2: Export Table: EXPORT2: DLL name: dll.test.tmp5.dll EXPORT2: Ordinal RVA Name EXPORT2-NEXT: 0 0 -EXPORT2-NEXT: 1 0x1010 exportfn3 -EXPORT2-NEXT: 2 0x101c mangled2 +EXPORT2-NEXT: 1 0x101c ?mangled2@@YAHXZ +EXPORT2-NEXT: 2 0x1010 exportfn3 # RUN: llvm-as -o %t.lto.obj %p/Inputs/export.ll # RUN: lld -flavor link2 /out:%t.lto.dll /dll %t.lto.obj /export:exportfn1 /export:exportfn2 @@ -39,10 +39,6 @@ EXPORT-LTO-NEXT: 1 0x1010 exportfn1 EXPORT-LTO-NEXT: 2 0x1020 exportfn2 EXPORT-LTO-NEXT: 3 0x1030 exportfn3 -# RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj -# RUN: lld -flavor link2 /out:%t2.exe /entry:main %t2.obj %t.lib -# RUN: llvm-readobj -coff-imports %t2.exe | FileCheck -check-prefix=IMPORT %s - # RUN: lld -flavor link2 /out:%t.dll /dll %t.obj /implib:%t2.lib \ # RUN: /export:exportfn1 /export:exportfn2 # RUN: lld -flavor link2 /out:%t2.exe /entry:main %t2.obj %t2.lib diff --git a/lld/test/COFF/export32.test b/lld/test/COFF/export32.test index a9e49e0..dc01484 100644 --- a/lld/test/COFF/export32.test +++ b/lld/test/COFF/export32.test @@ -23,9 +23,9 @@ 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 -CHECK2-NEXT: 8 0x1010 mangled +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 -- 2.7.4