Skip to content

Commit 3a51466

Browse files
authored
[LLD][COFF] Add support for delay-load imports on ARM64X (llvm#124600)
For each imported module, emit null-terminated native import entries, followed by null-terminated EC entries. If a view lacks imports for a given module, only terminators are emitted. Use ARM64X relocations to skip native entries in the EC view. Move `delayLoadHelper` and `tailMergeUnwindInfoChunk` to `SymbolTable` since they are different for each symbol table.
1 parent c5840cc commit 3a51466

File tree

2 files changed

+441
-42
lines changed

2 files changed

+441
-42
lines changed

lld/COFF/DLL.cpp

+78-42
Original file line numberDiff line numberDiff line change
@@ -921,52 +921,88 @@ void DelayLoadContents::create() {
921921
auto *dir = make<DelayDirectoryChunk>(dllNames.back());
922922

923923
size_t base = addresses.size();
924-
Chunk *tm = newTailMergeChunk(ctx.symtab, dir);
925-
Chunk *pdataChunk = newTailMergePDataChunk(ctx.symtab, tm);
926-
for (DefinedImportData *s : syms) {
927-
Chunk *t = newThunkChunk(s, tm);
928-
auto *a = make<DelayAddressChunk>(ctx, t);
929-
addresses.push_back(a);
930-
s->setLocation(a);
931-
thunks.push_back(t);
932-
StringRef extName = s->getExternalName();
933-
if (extName.empty()) {
934-
names.push_back(make<OrdinalOnlyChunk>(ctx, s->getOrdinal()));
935-
} else {
936-
auto *c = make<HintNameChunk>(extName, 0);
937-
names.push_back(make<LookupChunk>(ctx, c));
938-
hintNames.push_back(c);
939-
// Add a synthetic symbol for this load thunk, using the "__imp___load"
940-
// prefix, in case this thunk needs to be added to the list of valid
941-
// call targets for Control Flow Guard.
942-
StringRef symName = saver().save("__imp___load_" + extName);
943-
s->loadThunkSym =
944-
cast<DefinedSynthetic>(ctx.symtab.addSynthetic(symName, t));
924+
ctx.forEachSymtab([&](SymbolTable &symtab) {
925+
if (ctx.hybridSymtab && symtab.isEC()) {
926+
// For hybrid images, emit null-terminated native import entries
927+
// followed by null-terminated EC entries. If a view is missing imports
928+
// for a given module, only terminators are emitted. Emit ARM64X
929+
// relocations to skip native entries in the EC view.
930+
ctx.dynamicRelocs->add(
931+
IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0,
932+
Arm64XRelocVal(dir, offsetof(delay_import_directory_table_entry,
933+
DelayImportAddressTable)),
934+
(addresses.size() - base) * sizeof(uint64_t));
935+
ctx.dynamicRelocs->add(
936+
IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA, 0,
937+
Arm64XRelocVal(dir, offsetof(delay_import_directory_table_entry,
938+
DelayImportNameTable)),
939+
(addresses.size() - base) * sizeof(uint64_t));
945940
}
946941

947-
if (s->file->impECSym) {
948-
auto chunk = make<AuxImportChunk>(s->file);
949-
auxIat.push_back(chunk);
950-
s->file->impECSym->setLocation(chunk);
942+
Chunk *tm = nullptr;
951943

952-
chunk = make<AuxImportChunk>(s->file);
953-
auxIatCopy.push_back(chunk);
954-
s->file->auxImpCopySym->setLocation(chunk);
944+
for (DefinedImportData *s : syms) {
945+
// Process only the symbols belonging to the current symtab.
946+
if (symtab.isEC() != s->file->isEC())
947+
continue;
948+
949+
if (!tm) {
950+
tm = newTailMergeChunk(symtab, dir);
951+
Chunk *pdataChunk = newTailMergePDataChunk(symtab, tm);
952+
if (pdataChunk)
953+
pdata.push_back(pdataChunk);
954+
}
955+
956+
Chunk *t = newThunkChunk(s, tm);
957+
auto *a = make<DelayAddressChunk>(ctx, t);
958+
addresses.push_back(a);
959+
s->setLocation(a);
960+
thunks.push_back(t);
961+
StringRef extName = s->getExternalName();
962+
if (extName.empty()) {
963+
names.push_back(make<OrdinalOnlyChunk>(ctx, s->getOrdinal()));
964+
} else {
965+
auto *c = make<HintNameChunk>(extName, 0);
966+
names.push_back(make<LookupChunk>(ctx, c));
967+
hintNames.push_back(c);
968+
// Add a synthetic symbol for this load thunk, using the
969+
// "__imp___load" prefix, in case this thunk needs to be added to the
970+
// list of valid call targets for Control Flow Guard.
971+
StringRef symName = saver().save("__imp___load_" + extName);
972+
s->loadThunkSym =
973+
cast<DefinedSynthetic>(symtab.addSynthetic(symName, t));
974+
}
975+
976+
if (symtab.isEC()) {
977+
auto chunk = make<AuxImportChunk>(s->file);
978+
auxIat.push_back(chunk);
979+
s->file->impECSym->setLocation(chunk);
980+
981+
chunk = make<AuxImportChunk>(s->file);
982+
auxIatCopy.push_back(chunk);
983+
s->file->auxImpCopySym->setLocation(chunk);
984+
} else if (ctx.hybridSymtab) {
985+
// Fill the auxiliary IAT with null chunks for native imports.
986+
auxIat.push_back(make<NullChunk>(ctx));
987+
auxIatCopy.push_back(make<NullChunk>(ctx));
988+
}
955989
}
956-
}
957-
thunks.push_back(tm);
958-
if (pdataChunk)
959-
pdata.push_back(pdataChunk);
960-
StringRef tmName =
961-
saver().save("__tailMerge_" + syms[0]->getDLLName().lower());
962-
ctx.symtab.addSynthetic(tmName, tm);
963-
// Terminate with null values.
964-
addresses.push_back(make<NullChunk>(ctx, 8));
965-
names.push_back(make<NullChunk>(ctx, 8));
966-
if (ctx.config.machine == ARM64EC) {
967-
auxIat.push_back(make<NullChunk>(ctx, 8));
968-
auxIatCopy.push_back(make<NullChunk>(ctx, 8));
969-
}
990+
991+
if (tm) {
992+
thunks.push_back(tm);
993+
StringRef tmName =
994+
saver().save("__tailMerge_" + syms[0]->getDLLName().lower());
995+
symtab.addSynthetic(tmName, tm);
996+
}
997+
998+
// Terminate with null values.
999+
addresses.push_back(make<NullChunk>(ctx, 8));
1000+
names.push_back(make<NullChunk>(ctx, 8));
1001+
if (ctx.symtabEC) {
1002+
auxIat.push_back(make<NullChunk>(ctx, 8));
1003+
auxIatCopy.push_back(make<NullChunk>(ctx, 8));
1004+
}
1005+
});
9701006

9711007
auto *mh = make<NullChunk>(8, 8);
9721008
moduleHandles.push_back(mh);

0 commit comments

Comments
 (0)