diff --git a/lld/test/COFF/lib.test b/lld/test/COFF/lib.test index 7525ef4226cda5..82abca6ec9307b 100644 --- a/lld/test/COFF/lib.test +++ b/lld/test/COFF/lib.test @@ -1,6 +1,14 @@ # RUN: lld-link /machine:x64 /def:%S/Inputs/library.def /out:%t.lib # RUN: llvm-nm %t.lib | FileCheck %s +CHECK: 00000000 R __imp_constant +CHECK: 00000000 R constant + +CHECK: 00000000 D __imp_data + +CHECK: 00000000 T __imp_function +CHECK: 00000000 T function + CHECK: 00000000 a @comp.id CHECK: 00000000 a @feat.00 CHECK: 00000000 W alias @@ -11,11 +19,3 @@ CHECK: 00000000 a @feat.00 CHECK: 00000000 W __imp_alias CHECK: U __imp_function -CHECK: 00000000 R __imp_constant -CHECK: 00000000 R constant - -CHECK: 00000000 D __imp_data - -CHECK: 00000000 T __imp_function -CHECK: 00000000 T function - diff --git a/llvm/include/llvm/Object/COFFImportFile.h b/llvm/include/llvm/Object/COFFImportFile.h index e91d5a9b3198af..649fb4930934d3 100644 --- a/llvm/include/llvm/Object/COFFImportFile.h +++ b/llvm/include/llvm/Object/COFFImportFile.h @@ -135,11 +135,10 @@ struct COFFShortExport { /// linking both ARM64EC and pure ARM64 objects, and the linker will pick only /// the exports relevant to the target platform. For non-hybrid targets, /// the NativeExports parameter should not be used. -Error writeImportLibrary(StringRef ImportName, StringRef Path, - ArrayRef Exports, - COFF::MachineTypes Machine, bool MinGW, - ArrayRef NativeExports = std::nullopt, - bool AddUnderscores = true); +Error writeImportLibrary( + StringRef ImportName, StringRef Path, ArrayRef Exports, + COFF::MachineTypes Machine, bool MinGW, + ArrayRef NativeExports = std::nullopt); } // namespace object } // namespace llvm diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp index 1ddc5d954de685..2458a53cb6d548 100644 --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -12,6 +12,8 @@ #include "llvm/Object/COFFImportFile.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ArchiveWriter.h" @@ -657,8 +659,7 @@ NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym, Error writeImportLibrary(StringRef ImportName, StringRef Path, ArrayRef Exports, MachineTypes Machine, bool MinGW, - ArrayRef NativeExports, - bool AddUnderscores) { + ArrayRef NativeExports) { MachineTypes NativeMachine = Machine; if (isArm64EC(Machine)) { @@ -680,6 +681,13 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path, auto addExports = [&](ArrayRef Exp, MachineTypes M) -> Error { + StringMap RegularImports; + struct Deferred { + std::string Name; + ImportType ImpType; + const COFFShortExport *Export; + }; + SmallVector Renames; for (const COFFShortExport &E : Exp) { if (E.Private) continue; @@ -724,15 +732,11 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path, else if (Name == E.ImportName) NameType = IMPORT_NAME; else { - StringRef Prefix = ""; - if (Machine == IMAGE_FILE_MACHINE_I386 && AddUnderscores) - Prefix = "_"; - - if (ImportType == IMPORT_CODE) - Members.push_back(OF.createWeakExternal( - (Prefix + E.ImportName).str(), Name, false, M)); - Members.push_back(OF.createWeakExternal((Prefix + E.ImportName).str(), - Name, true, M)); + Deferred D; + D.Name = Name; + D.ImpType = ImportType; + D.Export = &E; + Renames.push_back(D); continue; } } else { @@ -754,9 +758,25 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path, } } + RegularImports[applyNameType(NameType, Name)] = Name; Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType, NameType, ExportName, M)); } + for (const auto &D : Renames) { + auto It = RegularImports.find(D.Export->ImportName); + if (It != RegularImports.end()) { + // We have a regular import entry for a symbol with the name we + // want to reference; produce an alias pointing at that. + StringRef Symbol = It->second; + if (D.ImpType == IMPORT_CODE) + Members.push_back(OF.createWeakExternal(Symbol, D.Name, false, M)); + Members.push_back(OF.createWeakExternal(Symbol, D.Name, true, M)); + } else { + Members.push_back(OF.createShortImport(D.Name, D.Export->Ordinal, + D.ImpType, IMPORT_NAME_EXPORTAS, + D.Export->ImportName, M)); + } + } return Error::success(); }; diff --git a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp index 012ad246888f97..15e4cac08cd4ed 100644 --- a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp +++ b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp @@ -243,9 +243,8 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef ArgsArr) { } std::string Path = std::string(Args.getLastArgValue(OPT_l)); - if (!Path.empty() && - writeImportLibrary(OutputFile, Path, Exports, Machine, - /*MinGW=*/true, NativeExports, AddUnderscores)) + if (!Path.empty() && writeImportLibrary(OutputFile, Path, Exports, Machine, + /*MinGW=*/true, NativeExports)) return 1; return 0; } diff --git a/llvm/test/tools/llvm-dlltool/coff-decorated.def b/llvm/test/tools/llvm-dlltool/coff-decorated.def index 773e3762cc3d73..f5685fb1cf0c6a 100644 --- a/llvm/test/tools/llvm-dlltool/coff-decorated.def +++ b/llvm/test/tools/llvm-dlltool/coff-decorated.def @@ -7,7 +7,7 @@ EXPORTS CdeclFunction StdcallFunction@4 @FastcallFunction@4 -StdcallAlias@4==StdcallFunction@4 +StdcallAlias@4==StdcallFunction ??_7exception@@6B@ StdcallExportName@4=StdcallInternalFunction@4 OtherStdcallExportName@4=CdeclInternalFunction diff --git a/llvm/test/tools/llvm-dlltool/coff-weak-exports.def b/llvm/test/tools/llvm-dlltool/coff-weak-exports.def index 67f0013bf170f8..b08040e29fa42e 100644 --- a/llvm/test/tools/llvm-dlltool/coff-weak-exports.def +++ b/llvm/test/tools/llvm-dlltool/coff-weak-exports.def @@ -5,6 +5,9 @@ LIBRARY test.dll EXPORTS +AltTestFunction +AltTestFunction2 +AltTestData TestFunction==AltTestFunction TestData DATA == AltTestData ; When creating an import library, the DLL internal function name of @@ -17,6 +20,14 @@ ImpLibName2 = Implementation2 == AltTestFunction2 ; matter for the import library ImpLibName3 = kernel32.Sleep +; CHECK: T AltTestFunction +; CHECK-NEXT: T __imp_AltTestFunction +; CHECK: T AltTestFunction2 +; CHECK-NEXT: T __imp_AltTestFunction2 +; CHECK: T ImpLibName +; CHECK-NEXT: T __imp_ImpLibName +; CHECK: T ImpLibName3 +; CHECK-NEXT: T __imp_ImpLibName3 ; CHECK: U AltTestFunction ; CHECK-NEXT: W TestFunction ; CHECK: U __imp_AltTestFunction @@ -24,14 +35,10 @@ ImpLibName3 = kernel32.Sleep ; CHECK-NOT: W TestData ; CHECK: U __imp_AltTestData ; CHECK-NEXT: W __imp_TestData -; CHECK: T ImpLibName -; CHECK-NEXT: T __imp_ImpLibName ; CHECK: U AltTestFunction2 ; CHECK-NEXT: W ImpLibName2 ; CHECK: U __imp_AltTestFunction2 ; CHECK-NEXT: W __imp_ImpLibName2 -; CHECK: T ImpLibName3 -; CHECK-NEXT: T __imp_ImpLibName3 ; ARCH-NOT: unknown arch diff --git a/llvm/test/tools/llvm-dlltool/renaming.def b/llvm/test/tools/llvm-dlltool/renaming.def new file mode 100644 index 00000000000000..57fd472aa37cf7 --- /dev/null +++ b/llvm/test/tools/llvm-dlltool/renaming.def @@ -0,0 +1,39 @@ +; RUN: llvm-dlltool -k -m i386 --input-def %s --output-lib %t.a +; RUN: llvm-readobj %t.a | FileCheck %s +; RUN: llvm-nm %t.a | FileCheck %s -check-prefix=CHECK-NM + +LIBRARY test.dll +EXPORTS + +symbolname == actualimport + +dataname DATA == actualdata + +_wcstok == wcstok +wcstok == wcstok_s + +; CHECK-NM-NOT: actualimport +; CHECK-NM-NOT: actualdata + +; CHECK: Type: code +; CHECK-NEXT: Name type: export as +; CHECK-NEXT: Export name: actualimport +; CHECK-NEXT: Symbol: __imp__symbolname +; CHECK-NEXT: Symbol: _symbolname + +; CHECK: Type: data +; CHECK-NEXT: Name type: export as +; CHECK-NEXT: Export name: actualdata +; CHECK-NEXT: Symbol: __imp__dataname + +; CHECK: Type: code +; CHECK-NEXT: Name type: export as +; CHECK-NEXT: Export name: wcstok +; CHECK-NEXT: Symbol: __imp___wcstok +; CHECK-NEXT: Symbol: __wcstok + +; CHECK: Type: code +; CHECK-NEXT: Name type: export as +; CHECK-NEXT: Export name: wcstok_s +; CHECK-NEXT: Symbol: __imp__wcstok +; CHECK-NEXT: Symbol: _wcstok