Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[llvm-dlltool] Fix renamed imports without a separate regular import entry #98229

Merged
merged 1 commit into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions lld/test/COFF/lib.test
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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

9 changes: 4 additions & 5 deletions llvm/include/llvm/Object/COFFImportFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<COFFShortExport> Exports,
COFF::MachineTypes Machine, bool MinGW,
ArrayRef<COFFShortExport> NativeExports = std::nullopt,
bool AddUnderscores = true);
Error writeImportLibrary(
StringRef ImportName, StringRef Path, ArrayRef<COFFShortExport> Exports,
COFF::MachineTypes Machine, bool MinGW,
ArrayRef<COFFShortExport> NativeExports = std::nullopt);

} // namespace object
} // namespace llvm
Expand Down
42 changes: 31 additions & 11 deletions llvm/lib/Object/COFFImportFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -657,8 +659,7 @@ NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
Error writeImportLibrary(StringRef ImportName, StringRef Path,
ArrayRef<COFFShortExport> Exports,
MachineTypes Machine, bool MinGW,
ArrayRef<COFFShortExport> NativeExports,
bool AddUnderscores) {
ArrayRef<COFFShortExport> NativeExports) {

MachineTypes NativeMachine = Machine;
if (isArm64EC(Machine)) {
Expand All @@ -680,6 +681,13 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path,

auto addExports = [&](ArrayRef<COFFShortExport> Exp,
MachineTypes M) -> Error {
StringMap<std::string> RegularImports;
struct Deferred {
std::string Name;
ImportType ImpType;
const COFFShortExport *Export;
};
SmallVector<Deferred, 0> Renames;
for (const COFFShortExport &E : Exp) {
if (E.Private)
continue;
Expand Down Expand Up @@ -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 {
Expand All @@ -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();
};

Expand Down
5 changes: 2 additions & 3 deletions llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,8 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> 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;
}
2 changes: 1 addition & 1 deletion llvm/test/tools/llvm-dlltool/coff-decorated.def
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 11 additions & 4 deletions llvm/test/tools/llvm-dlltool/coff-weak-exports.def
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -17,21 +20,25 @@ 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
; CHECK-NEXT: W __imp_TestFunction
; 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

Expand Down
39 changes: 39 additions & 0 deletions llvm/test/tools/llvm-dlltool/renaming.def
Original file line number Diff line number Diff line change
@@ -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
Loading