Skip to content

Commit e902cf2

Browse files
authored
[LLD][COFF] Write both native and EC export symbols to the import library on ARM64X (#124833)
1 parent 5a34e6f commit e902cf2

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
@@ -954,28 +954,39 @@ std::string LinkerDriver::getImportName(bool asLib) {
954954

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

973984
std::string libName = getImportName(asLib);
974985
std::string path = getImplibPath();
975986

976987
if (!ctx.config.incremental) {
977988
checkError(writeImportLibrary(libName, path, exports, ctx.config.machine,
978-
ctx.config.mingw));
989+
ctx.config.mingw, nativeExports));
979990
return;
980991
}
981992

@@ -985,7 +996,7 @@ void LinkerDriver::createImportLibrary(bool asLib) {
985996
path, /*IsText=*/false, /*RequiresNullTerminator=*/false);
986997
if (!oldBuf) {
987998
checkError(writeImportLibrary(libName, path, exports, ctx.config.machine,
988-
ctx.config.mingw));
999+
ctx.config.mingw, nativeExports));
9891000
return;
9901001
}
9911002

@@ -995,8 +1006,9 @@ void LinkerDriver::createImportLibrary(bool asLib) {
9951006
Fatal(ctx) << "cannot create temporary file for import library " << path
9961007
<< ": " << ec.message();
9971008

998-
if (Error e = writeImportLibrary(libName, tmpName, exports,
999-
ctx.config.machine, ctx.config.mingw)) {
1009+
if (Error e =
1010+
writeImportLibrary(libName, tmpName, exports, ctx.config.machine,
1011+
ctx.config.mingw, nativeExports)) {
10001012
checkError(std::move(e));
10011013
return;
10021014
}
@@ -2668,7 +2680,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
26682680
// Windows specific -- when we are creating a .dll file, we also
26692681
// need to create a .lib file. In MinGW mode, we only do that when the
26702682
// -implib option is given explicitly, for compatibility with GNU ld.
2671-
if (!ctx.symtab.exports.empty() || config->dll) {
2683+
if (config->dll || !ctx.symtab.exports.empty() ||
2684+
(ctx.hybridSymtab && !ctx.hybridSymtab->exports.empty())) {
26722685
llvm::TimeTraceScope timeScope("Create .lib exports");
26732686
ctx.forEachSymtab([](SymbolTable &symtab) { symtab.fixupExports(); });
26742687
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)