Skip to content

Commit f729477

Browse files
authored
[LLD][COFF] Add support for MinGW auto-export on ARM64X (#125862)
Export all symbols from both EC and native symbol tables. If an explicit export is present in either symbol table, auto-export is disabled for both.
1 parent f0e1857 commit f729477

File tree

4 files changed

+129
-34
lines changed

4 files changed

+129
-34
lines changed

lld/COFF/Driver.cpp

+30-27
Original file line numberDiff line numberDiff line change
@@ -1382,43 +1382,46 @@ void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) {
13821382
if (!ctx.config.dll)
13831383
return;
13841384

1385-
if (!ctx.symtab.exports.empty())
1385+
if (ctx.symtab.hadExplicitExports ||
1386+
(ctx.hybridSymtab && ctx.hybridSymtab->hadExplicitExports))
13861387
return;
13871388
if (args.hasArg(OPT_exclude_all_symbols))
13881389
return;
13891390
}
13901391

1391-
AutoExporter exporter(ctx, excludedSymbols);
1392+
ctx.forEachSymtab([&](SymbolTable &symtab) {
1393+
AutoExporter exporter(symtab, excludedSymbols);
13921394

1393-
for (auto *arg : args.filtered(OPT_wholearchive_file))
1394-
if (std::optional<StringRef> path = findFile(arg->getValue()))
1395-
exporter.addWholeArchive(*path);
1395+
for (auto *arg : args.filtered(OPT_wholearchive_file))
1396+
if (std::optional<StringRef> path = findFile(arg->getValue()))
1397+
exporter.addWholeArchive(*path);
13961398

1397-
for (auto *arg : args.filtered(OPT_exclude_symbols)) {
1398-
SmallVector<StringRef, 2> vec;
1399-
StringRef(arg->getValue()).split(vec, ',');
1400-
for (StringRef sym : vec)
1401-
exporter.addExcludedSymbol(ctx.symtab.mangle(sym));
1402-
}
1399+
for (auto *arg : args.filtered(OPT_exclude_symbols)) {
1400+
SmallVector<StringRef, 2> vec;
1401+
StringRef(arg->getValue()).split(vec, ',');
1402+
for (StringRef sym : vec)
1403+
exporter.addExcludedSymbol(symtab.mangle(sym));
1404+
}
14031405

1404-
ctx.symtab.forEachSymbol([&](Symbol *s) {
1405-
auto *def = dyn_cast<Defined>(s);
1406-
if (!exporter.shouldExport(def))
1407-
return;
1406+
symtab.forEachSymbol([&](Symbol *s) {
1407+
auto *def = dyn_cast<Defined>(s);
1408+
if (!exporter.shouldExport(def))
1409+
return;
14081410

1409-
if (!def->isGCRoot) {
1410-
def->isGCRoot = true;
1411-
ctx.config.gcroot.push_back(def);
1412-
}
1411+
if (!def->isGCRoot) {
1412+
def->isGCRoot = true;
1413+
ctx.config.gcroot.push_back(def);
1414+
}
14131415

1414-
Export e;
1415-
e.name = def->getName();
1416-
e.sym = def;
1417-
if (Chunk *c = def->getChunk())
1418-
if (!(c->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
1419-
e.data = true;
1420-
s->isUsedInRegularObj = true;
1421-
ctx.symtab.exports.push_back(e);
1416+
Export e;
1417+
e.name = def->getName();
1418+
e.sym = def;
1419+
if (Chunk *c = def->getChunk())
1420+
if (!(c->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
1421+
e.data = true;
1422+
s->isUsedInRegularObj = true;
1423+
symtab.exports.push_back(e);
1424+
});
14221425
});
14231426
}
14241427

lld/COFF/MinGW.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ using namespace lld;
2525
using namespace lld::coff;
2626

2727
AutoExporter::AutoExporter(
28-
COFFLinkerContext &ctx,
29-
const llvm::DenseSet<StringRef> &manualExcludeSymbols)
30-
: manualExcludeSymbols(manualExcludeSymbols), ctx(ctx) {
28+
SymbolTable &symtab, const llvm::DenseSet<StringRef> &manualExcludeSymbols)
29+
: manualExcludeSymbols(manualExcludeSymbols), symtab(symtab) {
3130
excludeLibs = {
3231
"libgcc",
3332
"libgcc_s",
@@ -84,7 +83,7 @@ AutoExporter::AutoExporter(
8483
"_NULL_THUNK_DATA",
8584
};
8685

87-
if (ctx.config.machine == I386) {
86+
if (symtab.machine == I386) {
8887
excludeSymbols = {
8988
"__NULL_IMPORT_DESCRIPTOR",
9089
"__pei386_runtime_relocator",
@@ -151,7 +150,7 @@ bool AutoExporter::shouldExport(Defined *sym) const {
151150
return false;
152151

153152
// If a corresponding __imp_ symbol exists and is defined, don't export it.
154-
if (ctx.symtab.find(("__imp_" + sym->getName()).str()))
153+
if (symtab.find(("__imp_" + sym->getName()).str()))
155154
return false;
156155

157156
// Check that file is non-null before dereferencing it, symbols not

lld/COFF/MinGW.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class COFFLinkerContext;
2525
// symbols for MinGW.
2626
class AutoExporter {
2727
public:
28-
AutoExporter(COFFLinkerContext &ctx,
28+
AutoExporter(SymbolTable &symtab,
2929
const llvm::DenseSet<StringRef> &manualExcludeSymbols);
3030

3131
void addWholeArchive(StringRef path);
@@ -42,7 +42,7 @@ class AutoExporter {
4242
bool shouldExport(Defined *sym) const;
4343

4444
private:
45-
COFFLinkerContext &ctx;
45+
SymbolTable &symtab;
4646
};
4747

4848
void writeDefFile(COFFLinkerContext &, StringRef name,

lld/test/COFF/arm64x-export-all.s

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// REQUIRES: aarch64
2+
3+
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %s -o %t.arm64.obj
4+
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %s -o %t.arm64ec.obj
5+
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o %t-loadconfig-arm64ec.obj
6+
// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o %t-loadconfig-arm64.obj
7+
8+
// Check that all symbols are exported in both EC and native views.
9+
10+
// RUN: lld-link -machine:arm64x -lldmingw -dll -noentry -out:%t.dll %t.arm64.obj %t.arm64ec.obj %t-loadconfig-arm64.obj %t-loadconfig-arm64ec.obj
11+
12+
// RUN: llvm-readobj --coff-exports %t.dll | FileCheck --check-prefix=EXP %s
13+
// EXP: Format: COFF-ARM64X
14+
// EXP-NEXT: Arch: aarch64
15+
// EXP-NEXT: AddressSize: 64bit
16+
// EXP-NEXT: Export {
17+
// EXP-NEXT: Ordinal: 1
18+
// EXP-NEXT: Name: _load_config_used
19+
// EXP-NEXT: RVA:
20+
// EXP-NEXT: }
21+
// EXP-NEXT: Export {
22+
// EXP-NEXT: Ordinal: 2
23+
// EXP-NEXT: Name: sym
24+
// EXP-NEXT: RVA: 0x2000
25+
// EXP-NEXT: }
26+
// EXP-NEXT: Export {
27+
// EXP-NEXT: Ordinal: 3
28+
// EXP-NEXT: Name: sym2
29+
// EXP-NEXT: RVA: 0x2004
30+
// EXP-NEXT: }
31+
// EXP-NEXT: HybridObject {
32+
// EXP-NEXT: Format: COFF-ARM64EC
33+
// EXP-NEXT: Arch: aarch64
34+
// EXP-NEXT: AddressSize: 64bit
35+
// EXP-NEXT: Export {
36+
// EXP-NEXT: Ordinal: 1
37+
// EXP-NEXT: Name: __chpe_metadata
38+
// EXP-NEXT: RVA:
39+
// EXP-NEXT: }
40+
// EXP-NEXT: Export {
41+
// EXP-NEXT: Ordinal: 2
42+
// EXP-NEXT: Name: __os_arm64x_dispatch_icall
43+
// EXP-NEXT: RVA: 0x12B0
44+
// EXP-NEXT: }
45+
// EXP-NEXT: Export {
46+
// EXP-NEXT: Ordinal: 3
47+
// EXP-NEXT: Name: __os_arm64x_dispatch_ret
48+
// EXP-NEXT: RVA:
49+
// EXP-NEXT: }
50+
// EXP-NEXT: Export {
51+
// EXP-NEXT: Ordinal: 4
52+
// EXP-NEXT: Name: _load_config_used
53+
// EXP-NEXT: RVA:
54+
// EXP-NEXT: }
55+
// EXP-NEXT: Export {
56+
// EXP-NEXT: Ordinal: 5
57+
// EXP-NEXT: Name: sym
58+
// EXP-NEXT: RVA: 0x2008
59+
// EXP-NEXT: }
60+
// EXP-NEXT: Export {
61+
// EXP-NEXT: Ordinal: 6
62+
// EXP-NEXT: Name: sym2
63+
// EXP-NEXT: RVA: 0x200C
64+
// EXP-NEXT: }
65+
// EXP-NEXT: }
66+
67+
// Check that an explicit export in the EC view is respected, preventing symbols from being auto-exported in both EC and native views.
68+
69+
// RUN: lld-link -machine:arm64x -lldmingw -dll -noentry -out:%t2.dll %t.arm64.obj %t.arm64ec.obj -export:sym \
70+
// RUN: %t-loadconfig-arm64.obj %t-loadconfig-arm64ec.obj
71+
72+
// RUN: llvm-readobj --coff-exports %t2.dll | FileCheck --check-prefix=EXP2 %s
73+
// EXP2: Format: COFF-ARM64X
74+
// EXP2-NEXT: Arch: aarch64
75+
// EXP2-NEXT: AddressSize: 64bit
76+
// EXP2-NEXT: HybridObject {
77+
// EXP2-NEXT: Format: COFF-ARM64EC
78+
// EXP2-NEXT: Arch: aarch64
79+
// EXP2-NEXT: AddressSize: 64bit
80+
// EXP2-NEXT: Export {
81+
// EXP2-NEXT: Ordinal: 1
82+
// EXP2-NEXT: Name: sym
83+
// EXP2-NEXT: RVA: 0x2008
84+
// EXP2-NEXT: }
85+
// EXP2-NEXT: }
86+
87+
.data
88+
.globl sym
89+
sym:
90+
.word 0
91+
.globl sym2
92+
sym2:
93+
.word 0

0 commit comments

Comments
 (0)