Skip to content

[LLD][COFF] Add support for autoimports on ARM64X #129282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lld/COFF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2600,7 +2600,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
// If it ends up pulling in more object files from static libraries,
// (and maybe doing more stdcall fixups along the way), this would need
// to loop these two calls.
ctx.symtab.loadMinGWSymbols();
ctx.forEachSymtab([](SymbolTable &symtab) { symtab.loadMinGWSymbols(); });
run();
}

Expand Down
80 changes: 42 additions & 38 deletions lld/COFF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2288,49 +2288,53 @@ void Writer::createECChunks() {
// uses for fixing them up, and provide the synthetic symbols that the
// runtime uses for finding the table.
void Writer::createRuntimePseudoRelocs() {
std::vector<RuntimePseudoReloc> rels;
ctx.forEachSymtab([&](SymbolTable &symtab) {
std::vector<RuntimePseudoReloc> rels;

for (Chunk *c : ctx.driver.getChunks()) {
auto *sc = dyn_cast<SectionChunk>(c);
if (!sc || !sc->live)
continue;
// Don't create pseudo relocations for sections that won't be
// mapped at runtime.
if (sc->header->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
continue;
sc->getRuntimePseudoRelocs(rels);
}
for (Chunk *c : ctx.driver.getChunks()) {
auto *sc = dyn_cast<SectionChunk>(c);
if (!sc || !sc->live || &sc->file->symtab != &symtab)
continue;
// Don't create pseudo relocations for sections that won't be
// mapped at runtime.
if (sc->header->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
continue;
sc->getRuntimePseudoRelocs(rels);
}

if (!ctx.config.pseudoRelocs) {
// Not writing any pseudo relocs; if some were needed, error out and
// indicate what required them.
for (const RuntimePseudoReloc &rpr : rels)
Err(ctx) << "automatic dllimport of " << rpr.sym->getName() << " in "
<< toString(rpr.target->file) << " requires pseudo relocations";
return;
}
if (!ctx.config.pseudoRelocs) {
// Not writing any pseudo relocs; if some were needed, error out and
// indicate what required them.
for (const RuntimePseudoReloc &rpr : rels)
Err(ctx) << "automatic dllimport of " << rpr.sym->getName() << " in "
<< toString(rpr.target->file)
<< " requires pseudo relocations";
return;
}

if (!rels.empty()) {
Log(ctx) << "Writing " << rels.size() << " runtime pseudo relocations";
const char *symbolName = "_pei386_runtime_relocator";
Symbol *relocator = ctx.symtab.findUnderscore(symbolName);
if (!relocator)
Err(ctx)
<< "output image has runtime pseudo relocations, but the function "
<< symbolName
<< " is missing; it is needed for fixing the relocations at runtime";
}
if (!rels.empty()) {
Log(ctx) << "Writing " << Twine(rels.size())
<< " runtime pseudo relocations";
const char *symbolName = "_pei386_runtime_relocator";
Symbol *relocator = symtab.findUnderscore(symbolName);
if (!relocator)
Err(ctx)
<< "output image has runtime pseudo relocations, but the function "
<< symbolName
<< " is missing; it is needed for fixing the relocations at "
"runtime";
}

PseudoRelocTableChunk *table = make<PseudoRelocTableChunk>(rels);
rdataSec->addChunk(table);
EmptyChunk *endOfList = make<EmptyChunk>();
rdataSec->addChunk(endOfList);
PseudoRelocTableChunk *table = make<PseudoRelocTableChunk>(rels);
rdataSec->addChunk(table);
EmptyChunk *endOfList = make<EmptyChunk>();
rdataSec->addChunk(endOfList);

Symbol *headSym = ctx.symtab.findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST__");
Symbol *endSym =
ctx.symtab.findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST_END__");
replaceSymbol<DefinedSynthetic>(headSym, headSym->getName(), table);
replaceSymbol<DefinedSynthetic>(endSym, endSym->getName(), endOfList);
Symbol *headSym = symtab.findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST__");
Symbol *endSym = symtab.findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST_END__");
replaceSymbol<DefinedSynthetic>(headSym, headSym->getName(), table);
replaceSymbol<DefinedSynthetic>(endSym, endSym->getName(), endOfList);
});
}

// MinGW specific.
Expand Down
75 changes: 75 additions & 0 deletions lld/test/COFF/autoimport-arm64x-data.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# REQUIRES: aarch64
RUN: split-file %s %t.dir && cd %t.dir

RUN: llvm-lib -machine:arm64x -out:libtest.a -defArm64Native:test.def -def:test.def
RUN: llvm-mc -triple=arm64ec-windows-gnu arm64ec.s -filetype=obj -o arm64ec.obj
RUN: llvm-mc -triple=aarch64-windows-gnu aarch64.s -filetype=obj -o aarch64.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj

RUN: lld-link -machine:arm64x -out:out.dll -dll -noentry arm64ec.obj aarch64.obj libtest.a loadconfig-arm64.obj loadconfig-arm64ec.obj -lldmingw

RUN: llvm-readobj --coff-imports out.dll | FileCheck -check-prefix=IMPORTS %s
RUN: llvm-objdump -s out.dll | FileCheck --check-prefix=CONTENTS %s

IMPORTS: Import {
IMPORTS-NEXT: Name: test.dll
IMPORTS-NEXT: ImportLookupTableRVA: 0x5{{.*}}
IMPORTS-NEXT: ImportAddressTableRVA: 0x4000
IMPORTS-NEXT: Symbol: variable (0)
IMPORTS-NEXT: }
IMPORTS-NEXT: HybridObject {
IMPORTS: Import {
IMPORTS-NEXT: Name: test.dll
IMPORTS-NEXT: ImportLookupTableRVA: 0x5{{.*}}
IMPORTS-NEXT: ImportAddressTableRVA: 0x4000
IMPORTS-NEXT: Symbol: variable (0)
IMPORTS-NEXT: }
IMPORTS-NEXT: }

Native ARM64 runtime pseudo relocation list header at 0x5164, consisting of 0x0, 0x0, 0x1.
The runtime pseudo relocation is from an aarch64.obj object file, with import from 0x4000,
applied at 0x9018 with a size of 64 bits. ARM64EC runtime pseudo relocation list header at
0x517c, consisting of 0x0, 0x0, 0x1. The runtime pseudo relocation is from arm64ec.obj
object file, with import from 0x4000, applied at 0x9000 with a size of 64 bits.

CONTENTS: Contents of section .rdata:
CONTENTS: 180005160 00300000 00000000 00000000 01000000
CONTENTS: 180005170 00400000 18900000 40000000 00000000
CONTENTS: 180005180 00000000 01000000 00400000 00900000
CONTENTS: 180005190 40000000

CONTENTS: Contents of section .test:
CONTENTS-NEXT: 180009000 00400080 01000000 7c510080 01000000
CONTENTS-NEXT: 180009010 94510080 01000000 00400080 01000000
CONTENTS-NEXT: 180009020 64510080 01000000 7c510080 01000000

#--- arm64ec.s
.text
.global "#_pei386_runtime_relocator"
"#_pei386_runtime_relocator":
ret

.weak_anti_dep _pei386_runtime_relocator
.set _pei386_runtime_relocator,"#_pei386_runtime_relocator"

.section .test,"dr"
.quad variable
.quad __RUNTIME_PSEUDO_RELOC_LIST__
.quad __RUNTIME_PSEUDO_RELOC_LIST_END__

#--- aarch64.s
.text
.global _pei386_runtime_relocator
_pei386_runtime_relocator:
ret

.section .test,"dr"
.quad variable
.quad __RUNTIME_PSEUDO_RELOC_LIST__
.quad __RUNTIME_PSEUDO_RELOC_LIST_END__

#--- test.def
LIBRARY test.dll
EXPORTS
variable DATA