Skip to content

Commit 1c29793

Browse files
committed
[LLD][COFF] Add support for delay-load imports on ARM64X
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 97aa56a commit 1c29793

File tree

2 files changed

+441
-43
lines changed

2 files changed

+441
-43
lines changed

lld/COFF/DLL.cpp

Lines changed: 78 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -921,54 +921,89 @@ 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-
thunks.push_back(t);
931-
StringRef extName = s->getExternalName();
932-
if (extName.empty()) {
933-
names.push_back(make<OrdinalOnlyChunk>(ctx, s->getOrdinal()));
934-
} else {
935-
auto *c = make<HintNameChunk>(extName, 0);
936-
names.push_back(make<LookupChunk>(ctx, c));
937-
hintNames.push_back(c);
938-
// Add a synthetic symbol for this load thunk, using the "__imp___load"
939-
// prefix, in case this thunk needs to be added to the list of valid
940-
// call targets for Control Flow Guard.
941-
StringRef symName = saver().save("__imp___load_" + extName);
942-
s->loadThunkSym =
943-
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));
944940
}
945941

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

951-
chunk = make<AuxImportChunk>(s->file);
952-
auxIatCopy.push_back(chunk);
953-
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+
}
954989
}
955-
}
956-
thunks.push_back(tm);
957-
if (pdataChunk)
958-
pdata.push_back(pdataChunk);
959-
StringRef tmName =
960-
saver().save("__tailMerge_" + syms[0]->getDLLName().lower());
961-
ctx.symtab.addSynthetic(tmName, tm);
962-
// Terminate with null values.
963-
addresses.push_back(make<NullChunk>(ctx, 8));
964-
names.push_back(make<NullChunk>(ctx, 8));
965-
if (ctx.config.machine == ARM64EC) {
966-
auxIat.push_back(make<NullChunk>(ctx, 8));
967-
auxIatCopy.push_back(make<NullChunk>(ctx, 8));
968-
}
969990

970-
for (int i = 0, e = syms.size(); i < e; ++i)
971-
syms[i]->setLocation(addresses[base + i]);
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+
});
1006+
9721007
auto *mh = make<NullChunk>(8, 8);
9731008
moduleHandles.push_back(mh);
9741009

0 commit comments

Comments
 (0)