Skip to content

Commit 569b6bd

Browse files
cjacekSquallATF
authored andcommitted
[LLD][COFF] Write both native and EC export symbols to the import library on ARM64X (llvm#124833)
1 parent b856253 commit 569b6bd

File tree

2 files changed

+73
-19
lines changed

2 files changed

+73
-19
lines changed

lld/COFF/Driver.cpp

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -960,28 +960,39 @@ std::string LinkerDriver::getImportName(bool asLib) {
960960

961961
void LinkerDriver::createImportLibrary(bool asLib) {
962962
llvm::TimeTraceScope timeScope("Create import library");
963-
std::vector<COFFShortExport> exports;
964-
for (Export &e1 : ctx.symtab.exports) {
965-
COFFShortExport e2;
966-
e2.Name = std::string(e1.name);
967-
e2.SymbolName = std::string(e1.symbolName);
968-
e2.ExtName = std::string(e1.extName);
969-
e2.ExportAs = std::string(e1.exportAs);
970-
e2.ImportName = std::string(e1.importName);
971-
e2.Ordinal = e1.ordinal;
972-
e2.Noname = e1.noname;
973-
e2.Data = e1.data;
974-
e2.Private = e1.isPrivate;
975-
e2.Constant = e1.constant;
976-
exports.push_back(e2);
963+
std::vector<COFFShortExport> exports, nativeExports;
964+
965+
auto getExports = [](SymbolTable &symtab,
966+
std::vector<COFFShortExport> &exports) {
967+
for (Export &e1 : symtab.exports) {
968+
COFFShortExport e2;
969+
e2.Name = std::string(e1.name);
970+
e2.SymbolName = std::string(e1.symbolName);
971+
e2.ExtName = std::string(e1.extName);
972+
e2.ExportAs = std::string(e1.exportAs);
973+
e2.ImportName = std::string(e1.importName);
974+
e2.Ordinal = e1.ordinal;
975+
e2.Noname = e1.noname;
976+
e2.Data = e1.data;
977+
e2.Private = e1.isPrivate;
978+
e2.Constant = e1.constant;
979+
exports.push_back(e2);
980+
}
981+
};
982+
983+
if (ctx.hybridSymtab) {
984+
getExports(ctx.symtab, nativeExports);
985+
getExports(*ctx.hybridSymtab, exports);
986+
} else {
987+
getExports(ctx.symtab, exports);
977988
}
978989

979990
std::string libName = getImportName(asLib);
980991
std::string path = getImplibPath();
981992

982993
if (!ctx.config.incremental) {
983994
checkError(writeImportLibrary(libName, path, exports, ctx.config.machine,
984-
ctx.config.mingw));
995+
ctx.config.mingw, nativeExports));
985996
return;
986997
}
987998

@@ -991,7 +1002,7 @@ void LinkerDriver::createImportLibrary(bool asLib) {
9911002
path, /*IsText=*/false, /*RequiresNullTerminator=*/false);
9921003
if (!oldBuf) {
9931004
checkError(writeImportLibrary(libName, path, exports, ctx.config.machine,
994-
ctx.config.mingw));
1005+
ctx.config.mingw, nativeExports));
9951006
return;
9961007
}
9971008

@@ -1001,8 +1012,9 @@ void LinkerDriver::createImportLibrary(bool asLib) {
10011012
Fatal(ctx) << "cannot create temporary file for import library " << path
10021013
<< ": " << ec.message();
10031014

1004-
if (Error e = writeImportLibrary(libName, tmpName, exports,
1005-
ctx.config.machine, ctx.config.mingw)) {
1015+
if (Error e =
1016+
writeImportLibrary(libName, tmpName, exports, ctx.config.machine,
1017+
ctx.config.mingw, nativeExports)) {
10061018
checkError(std::move(e));
10071019
return;
10081020
}
@@ -2672,7 +2684,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
26722684
// Windows specific -- when we are creating a .dll file, we also
26732685
// need to create a .lib file. In MinGW mode, we only do that when the
26742686
// -implib option is given explicitly, for compatibility with GNU ld.
2675-
if (!ctx.symtab.exports.empty() || config->dll) {
2687+
if (config->dll || !ctx.symtab.exports.empty() ||
2688+
(ctx.hybridSymtab && !ctx.hybridSymtab->exports.empty())) {
26762689
llvm::TimeTraceScope timeScope("Create .lib exports");
26772690
ctx.forEachSymtab([](SymbolTable &symtab) { symtab.fixupExports(); });
26782691
if (!config->noimplib && (!config->mingw || !config->implib.empty()))

lld/test/COFF/arm64x-export.test

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,48 @@ EXPORTS-EC-NEXT: RVA: 0x2000
4848
EXPORTS-EC-NEXT: }
4949
EXPORTS-EC-NEXT: }
5050

51+
RUN: llvm-readobj out-cmd.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-EC %s
52+
IMPLIB-HEADER: File: out-{{.*}}.lib(out{{.*}}.dll)
53+
IMPLIB-HEADER-NEXT: Format: COFF-ARM64
54+
IMPLIB-HEADER-NEXT: Arch: aarch64
55+
IMPLIB-HEADER-NEXT: AddressSize: 64bit
56+
IMPLIB-HEADER-EMPTY:
57+
IMPLIB-HEADER-NEXT: File: out-{{.*}}.lib(out{{.*}}.dll)
58+
IMPLIB-HEADER-NEXT: Format: COFF-ARM64
59+
IMPLIB-HEADER-NEXT: Arch: aarch64
60+
IMPLIB-HEADER-NEXT: AddressSize: 64bit
61+
IMPLIB-HEADER-EMPTY:
62+
IMPLIB-HEADER-NEXT: File: out-{{.*}}.lib(out{{.*}}.dll)
63+
IMPLIB-HEADER-NEXT: Format: COFF-ARM64
64+
IMPLIB-HEADER-NEXT: Arch: aarch64
65+
IMPLIB-HEADER-NEXT: AddressSize: 64bit
66+
IMPLIB-HEADER-EMPTY:
67+
IMPLIB-EC: File: out{{.*}}.dll
68+
IMPLIB-EC-NEXT: Format: COFF-import-file-ARM64EC
69+
IMPLIB-EC-NEXT: Type: code
70+
IMPLIB-EC-NEXT: Name type: export as
71+
IMPLIB-EC-NEXT: Export name: func
72+
IMPLIB-EC-NEXT: Symbol: __imp_func
73+
IMPLIB-EC-NEXT: Symbol: func
74+
IMPLIB-EC-NEXT: Symbol: __imp_aux_func
75+
IMPLIB-EC-NEXT: Symbol: #func
76+
77+
5178
# Export using the EC .drectve section.
5279

5380
RUN: lld-link -machine:arm64x -dll -out:out-drectve-ec.dll arm64ec-func.obj arm64-func.obj \
5481
RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj arm64ec-drectve.obj -noentry
5582
RUN: llvm-objdump -d out-drectve-ec.dll | FileCheck --check-prefix=DISASM-EC %s
5683
RUN: llvm-readobj --headers --coff-exports out-drectve-ec.dll | FileCheck --check-prefix=EXPORTS-EC %s
84+
RUN: llvm-readobj out-drectve-ec.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-EC %s
5785

5886
# A command-line def file applies only to EC exports.
5987

6088
RUN: lld-link -machine:arm64x -dll -out:out-def-ec.dll arm64ec-func.obj arm64-func.obj \
6189
RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj -def:func.def -noentry
6290
RUN: llvm-objdump -d out-def-ec.dll | FileCheck --check-prefix=DISASM-EC %s
6391
RUN: llvm-readobj --headers --coff-exports out-def-ec.dll | FileCheck --check-prefix=EXPORTS-EC %s
92+
RUN: llvm-readobj out-def-ec.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-EC %s
6493

6594
# Export using the EC .edata section.
6695

@@ -111,6 +140,15 @@ EXPORTS-NATIVE: ExportTableRVA: 0x0
111140
EXPORTS-NATIVE-NEXT: ExportTableSize: 0x0
112141
EXPORTS-NATIVE-NOT: Name: func
113142

143+
RUN: llvm-readobj out-drectve-native.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-NATIVE %s
144+
IMPLIB-NATIVE: File: out{{.*}}.dll
145+
IMPLIB-NATIVE-NEXT: Format: COFF-import-file-ARM64
146+
IMPLIB-NATIVE-NEXT: Type: code
147+
IMPLIB-NATIVE-NEXT: Name type: name
148+
IMPLIB-NATIVE-NEXT: Export name: func
149+
IMPLIB-NATIVE-NEXT: Symbol: __imp_func
150+
IMPLIB-NATIVE-NEXT: Symbol: func
151+
114152
# Export using the native .edata section.
115153

116154
RUN: lld-link -machine:arm64x -dll -out:out-edata.dll arm64ec-func.obj arm64-func.obj \
@@ -162,12 +200,15 @@ EXPORTS-BOTH-NEXT: RVA: 0x3000
162200
EXPORTS-BOTH-NEXT: }
163201
EXPORTS-BOTH-NEXT: }
164202

203+
RUN: llvm-readobj out-both.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-EC,IMPLIB-NATIVE %s
204+
165205
# Export using both the -def and -defarm64native arguments.
166206

167207
RUN: lld-link -machine:arm64x -dll -out:out-def-both.dll arm64ec-func.obj arm64-func.obj \
168208
RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj -def:func.def -defarm64native:func.def -noentry
169209
RUN: llvm-objdump -d out-def-both.dll | FileCheck --check-prefix=DISASM-BOTH %s
170210
RUN: llvm-readobj --headers --coff-exports out-def-both.dll | FileCheck --check-prefix=EXPORTS-BOTH %s
211+
RUN: llvm-readobj out-def-both.lib | FileCheck --check-prefixes=IMPLIB-HEADER,IMPLIB-EC,IMPLIB-NATIVE %s
171212

172213
# -defarm64native is ignored if -def is not specified.
173214

0 commit comments

Comments
 (0)