Skip to content

Commit 455b3d6

Browse files
authored
[LLD][COFF] Separate EC and native exports for ARM64X (#123652)
Store exports in SymbolTable instead of Configuration.
1 parent ebc5020 commit 455b3d6

11 files changed

+324
-194
lines changed

lld/COFF/Config.h

-2
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,6 @@ struct Configuration {
162162
bool dll = false;
163163
StringRef implib;
164164
bool noimplib = false;
165-
std::vector<Export> exports;
166-
bool hadExplicitExports;
167165
std::set<std::string> delayLoads;
168166
std::map<std::string, int> dllOrder;
169167
Symbol *delayLoadHelper = nullptr;

lld/COFF/DLL.cpp

+18-16
Original file line numberDiff line numberDiff line change
@@ -639,22 +639,22 @@ class ExportDirectoryChunk : public NonSectionChunk {
639639

640640
class AddressTableChunk : public NonSectionChunk {
641641
public:
642-
explicit AddressTableChunk(COFFLinkerContext &ctx, size_t baseOrdinal,
642+
explicit AddressTableChunk(SymbolTable &symtab, size_t baseOrdinal,
643643
size_t maxOrdinal)
644644
: baseOrdinal(baseOrdinal), size((maxOrdinal - baseOrdinal) + 1),
645-
ctx(ctx) {}
645+
symtab(symtab) {}
646646
size_t getSize() const override { return size * 4; }
647647

648648
void writeTo(uint8_t *buf) const override {
649649
memset(buf, 0, getSize());
650650

651-
for (const Export &e : ctx.config.exports) {
651+
for (const Export &e : symtab.exports) {
652652
assert(e.ordinal >= baseOrdinal && "Export symbol has invalid ordinal");
653653
// Subtract the OrdinalBase to get the index.
654654
uint8_t *p = buf + (e.ordinal - baseOrdinal) * 4;
655655
uint32_t bit = 0;
656656
// Pointer to thumb code must have the LSB set, so adjust it.
657-
if (ctx.config.machine == ARMNT && !e.data)
657+
if (symtab.machine == ARMNT && !e.data)
658658
bit = 1;
659659
if (e.forwardChunk) {
660660
write32le(p, e.forwardChunk->getRVA() | bit);
@@ -669,7 +669,7 @@ class AddressTableChunk : public NonSectionChunk {
669669
private:
670670
size_t baseOrdinal;
671671
size_t size;
672-
const COFFLinkerContext &ctx;
672+
const SymbolTable &symtab;
673673
};
674674

675675
class NamePointersChunk : public NonSectionChunk {
@@ -690,13 +690,13 @@ class NamePointersChunk : public NonSectionChunk {
690690

691691
class ExportOrdinalChunk : public NonSectionChunk {
692692
public:
693-
explicit ExportOrdinalChunk(const COFFLinkerContext &ctx, size_t baseOrdinal,
693+
explicit ExportOrdinalChunk(const SymbolTable &symtab, size_t baseOrdinal,
694694
size_t tableSize)
695-
: baseOrdinal(baseOrdinal), size(tableSize), ctx(ctx) {}
695+
: baseOrdinal(baseOrdinal), size(tableSize), symtab(symtab) {}
696696
size_t getSize() const override { return size * 2; }
697697

698698
void writeTo(uint8_t *buf) const override {
699-
for (const Export &e : ctx.config.exports) {
699+
for (const Export &e : symtab.exports) {
700700
if (e.noname)
701701
continue;
702702
assert(e.ordinal >= baseOrdinal && "Export symbol has invalid ordinal");
@@ -709,7 +709,7 @@ class ExportOrdinalChunk : public NonSectionChunk {
709709
private:
710710
size_t baseOrdinal;
711711
size_t size;
712-
const COFFLinkerContext &ctx;
712+
const SymbolTable &symtab;
713713
};
714714

715715
} // anonymous namespace
@@ -920,33 +920,35 @@ Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *s,
920920
}
921921
}
922922

923-
void createEdataChunks(COFFLinkerContext &ctx, std::vector<Chunk *> &chunks) {
923+
void createEdataChunks(SymbolTable &symtab, std::vector<Chunk *> &chunks) {
924924
unsigned baseOrdinal = 1 << 16, maxOrdinal = 0;
925-
for (Export &e : ctx.config.exports) {
925+
for (Export &e : symtab.exports) {
926926
baseOrdinal = std::min(baseOrdinal, (unsigned)e.ordinal);
927927
maxOrdinal = std::max(maxOrdinal, (unsigned)e.ordinal);
928928
}
929929
// Ordinals must start at 1 as suggested in:
930930
// https://learn.microsoft.com/en-us/cpp/build/reference/export-exports-a-function?view=msvc-170
931931
assert(baseOrdinal >= 1);
932932

933-
auto *dllName = make<StringChunk>(sys::path::filename(ctx.config.outputFile));
934-
auto *addressTab = make<AddressTableChunk>(ctx, baseOrdinal, maxOrdinal);
933+
auto *dllName =
934+
make<StringChunk>(sys::path::filename(symtab.ctx.config.outputFile));
935+
auto *addressTab = make<AddressTableChunk>(symtab, baseOrdinal, maxOrdinal);
935936
std::vector<Chunk *> names;
936-
for (Export &e : ctx.config.exports)
937+
for (Export &e : symtab.exports)
937938
if (!e.noname)
938939
names.push_back(make<StringChunk>(e.exportName));
939940

940941
std::vector<Chunk *> forwards;
941-
for (Export &e : ctx.config.exports) {
942+
for (Export &e : symtab.exports) {
942943
if (e.forwardTo.empty())
943944
continue;
944945
e.forwardChunk = make<StringChunk>(e.forwardTo);
945946
forwards.push_back(e.forwardChunk);
946947
}
947948

948949
auto *nameTab = make<NamePointersChunk>(names);
949-
auto *ordinalTab = make<ExportOrdinalChunk>(ctx, baseOrdinal, names.size());
950+
auto *ordinalTab =
951+
make<ExportOrdinalChunk>(symtab, baseOrdinal, names.size());
950952
auto *dir =
951953
make<ExportDirectoryChunk>(baseOrdinal, maxOrdinal, names.size(), dllName,
952954
addressTab, nameTab, ordinalTab);

lld/COFF/DLL.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class DelayLoadContents {
7878
};
7979

8080
// Create all chunks for the DLL export table.
81-
void createEdataChunks(COFFLinkerContext &ctx, std::vector<Chunk *> &chunks);
81+
void createEdataChunks(SymbolTable &symtab, std::vector<Chunk *> &chunks);
8282

8383
} // namespace lld::coff
8484

lld/COFF/Driver.cpp

+32-27
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
458458
// declarations, many object files may end up with having the
459459
// same /EXPORT options. In order to save cost of parsing them,
460460
// we dedup them first.
461-
if (!directivesExports.insert(e).second)
461+
if (!file->symtab.directivesExports.insert(e).second)
462462
continue;
463463

464464
Export exp = parseExport(e);
@@ -469,7 +469,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
469469
exp.extName = saver().save("_" + exp.extName);
470470
}
471471
exp.source = ExportSource::Directives;
472-
ctx.config.exports.push_back(exp);
472+
file->symtab.exports.push_back(exp);
473473
}
474474

475475
// Handle /include: in bulk.
@@ -956,7 +956,7 @@ std::string LinkerDriver::getImportName(bool asLib) {
956956
void LinkerDriver::createImportLibrary(bool asLib) {
957957
llvm::TimeTraceScope timeScope("Create import library");
958958
std::vector<COFFShortExport> exports;
959-
for (Export &e1 : ctx.config.exports) {
959+
for (Export &e1 : ctx.symtab.exports) {
960960
COFFShortExport e2;
961961
e2.Name = std::string(e1.name);
962962
e2.SymbolName = std::string(e1.symbolName);
@@ -1069,7 +1069,7 @@ void LinkerDriver::parseModuleDefs(StringRef path) {
10691069
e2.isPrivate = e1.Private;
10701070
e2.constant = e1.Constant;
10711071
e2.source = ExportSource::ModuleDefinition;
1072-
ctx.config.exports.push_back(e2);
1072+
ctx.symtab.exports.push_back(e2);
10731073
}
10741074
}
10751075

@@ -1222,8 +1222,10 @@ static void findKeepUniqueSections(COFFLinkerContext &ctx) {
12221222

12231223
// Exported symbols could be address-significant in other executables or DSOs,
12241224
// so we conservatively mark them as address-significant.
1225-
for (Export &r : ctx.config.exports)
1226-
markAddrsig(r.sym);
1225+
ctx.forEachSymtab([](SymbolTable &symtab) {
1226+
for (Export &r : symtab.exports)
1227+
markAddrsig(r.sym);
1228+
});
12271229

12281230
// Visit the address-significance table in each object file and mark each
12291231
// referenced symbol as address-significant.
@@ -1376,13 +1378,13 @@ void LinkerDriver::maybeCreateECExportThunk(StringRef name, Symbol *&sym) {
13761378
void LinkerDriver::createECExportThunks() {
13771379
// Check if EXP+ symbols have corresponding $hp_target symbols and use them
13781380
// to create export thunks when available.
1379-
for (Symbol *s : ctx.symtab.expSymbols) {
1381+
for (Symbol *s : ctx.symtabEC->expSymbols) {
13801382
if (!s->isUsedInRegularObj)
13811383
continue;
13821384
assert(s->getName().starts_with("EXP+"));
13831385
std::string targetName =
13841386
(s->getName().substr(strlen("EXP+")) + "$hp_target").str();
1385-
Symbol *sym = ctx.symtab.find(targetName);
1387+
Symbol *sym = ctx.symtabEC->find(targetName);
13861388
if (!sym)
13871389
continue;
13881390
Defined *targetSym;
@@ -1407,7 +1409,7 @@ void LinkerDriver::createECExportThunks() {
14071409
if (ctx.symtabEC->entry)
14081410
maybeCreateECExportThunk(ctx.symtabEC->entry->getName(),
14091411
ctx.symtabEC->entry);
1410-
for (Export &e : ctx.config.exports) {
1412+
for (Export &e : ctx.symtabEC->exports) {
14111413
if (!e.data)
14121414
maybeCreateECExportThunk(e.extName.empty() ? e.name : e.extName, e.sym);
14131415
}
@@ -1430,7 +1432,7 @@ void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) {
14301432
if (!ctx.config.dll)
14311433
return;
14321434

1433-
if (!ctx.config.exports.empty())
1435+
if (!ctx.symtab.exports.empty())
14341436
return;
14351437
if (args.hasArg(OPT_exclude_all_symbols))
14361438
return;
@@ -1466,7 +1468,7 @@ void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) {
14661468
if (!(c->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
14671469
e.data = true;
14681470
s->isUsedInRegularObj = true;
1469-
ctx.config.exports.push_back(e);
1471+
ctx.symtab.exports.push_back(e);
14701472
});
14711473
}
14721474

@@ -2343,7 +2345,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
23432345
if (!e.extName.empty() && !isDecorated(e.extName))
23442346
e.extName = saver().save("_" + e.extName);
23452347
}
2346-
config->exports.push_back(e);
2348+
mainSymtab.exports.push_back(e);
23472349
}
23482350
}
23492351

@@ -2355,7 +2357,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
23552357

23562358
// Handle generation of import library from a def file.
23572359
if (!args.hasArg(OPT_INPUT, OPT_wholearchive_file)) {
2358-
fixupExports();
2360+
ctx.forEachSymtab([](SymbolTable &symtab) { symtab.fixupExports(); });
23592361
if (!config->noimplib)
23602362
createImportLibrary(/*asLib=*/true);
23612363
return;
@@ -2541,16 +2543,16 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
25412543
// search for its mangled names.
25422544
if (symtab.entry)
25432545
symtab.mangleMaybe(symtab.entry);
2544-
});
25452546

2546-
// Windows specific -- Make sure we resolve all dllexported symbols.
2547-
for (Export &e : config->exports) {
2548-
if (!e.forwardTo.empty())
2549-
continue;
2550-
e.sym = ctx.symtab.addGCRoot(e.name, !e.data);
2551-
if (e.source != ExportSource::Directives)
2552-
e.symbolName = ctx.symtab.mangleMaybe(e.sym);
2553-
}
2547+
// Windows specific -- Make sure we resolve all dllexported symbols.
2548+
for (Export &e : symtab.exports) {
2549+
if (!e.forwardTo.empty())
2550+
continue;
2551+
e.sym = symtab.addGCRoot(e.name, !e.data);
2552+
if (e.source != ExportSource::Directives)
2553+
e.symbolName = symtab.mangleMaybe(e.sym);
2554+
}
2555+
});
25542556

25552557
// Add weak aliases. Weak aliases is a mechanism to give remaining
25562558
// undefined symbols final chance to be resolved successfully.
@@ -2651,7 +2653,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
26512653
if (errorCount())
26522654
return;
26532655

2654-
config->hadExplicitExports = !config->exports.empty();
2656+
ctx.forEachSymtab([](SymbolTable &symtab) {
2657+
symtab.hadExplicitExports = !symtab.exports.empty();
2658+
});
26552659
if (config->mingw) {
26562660
// In MinGW, all symbols are automatically exported if no symbols
26572661
// are chosen to be exported.
@@ -2716,17 +2720,18 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
27162720
// Windows specific -- when we are creating a .dll file, we also
27172721
// need to create a .lib file. In MinGW mode, we only do that when the
27182722
// -implib option is given explicitly, for compatibility with GNU ld.
2719-
if (!config->exports.empty() || config->dll) {
2723+
if (!ctx.symtab.exports.empty() || config->dll) {
27202724
llvm::TimeTraceScope timeScope("Create .lib exports");
2721-
fixupExports();
2725+
ctx.forEachSymtab([](SymbolTable &symtab) { symtab.fixupExports(); });
27222726
if (!config->noimplib && (!config->mingw || !config->implib.empty()))
27232727
createImportLibrary(/*asLib=*/false);
2724-
assignExportOrdinals();
2728+
ctx.forEachSymtab(
2729+
[](SymbolTable &symtab) { symtab.assignExportOrdinals(); });
27252730
}
27262731

27272732
// Handle /output-def (MinGW specific).
27282733
if (auto *arg = args.getLastArg(OPT_output_def))
2729-
writeDefFile(ctx, arg->getValue(), config->exports);
2734+
writeDefFile(ctx, arg->getValue(), ctx.symtab.exports);
27302735

27312736
// Set extra alignment for .comm symbols
27322737
for (auto pair : config->alignComm) {

lld/COFF/Driver.h

-3
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ class LinkerDriver {
182182
std::list<std::function<void()>> taskQueue;
183183
std::vector<MemoryBufferRef> resources;
184184

185-
llvm::DenseSet<StringRef> directivesExports;
186185
llvm::DenseSet<StringRef> excludedSymbols;
187186

188187
COFFLinkerContext &ctx;
@@ -249,8 +248,6 @@ class LinkerDriver {
249248

250249
// Used for dllexported symbols.
251250
Export parseExport(StringRef arg);
252-
void fixupExports();
253-
void assignExportOrdinals();
254251

255252
// Parses a string in the form of "key=value" and check
256253
// if value matches previous values for the key.

0 commit comments

Comments
 (0)