From c6598f6ddf62e88af6c4c20b12264503ad11f234 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Sun, 2 Mar 2025 13:10:50 +0100 Subject: [PATCH] [LLD][COFF] Add support for autoimports on ARM64X (#129282) --- lld/COFF/Driver.cpp | 2 +- lld/COFF/Writer.cpp | 80 ++++++++++++----------- lld/test/COFF/autoimport-arm64x-data.test | 75 +++++++++++++++++++++ 3 files changed, 118 insertions(+), 39 deletions(-) create mode 100644 lld/test/COFF/autoimport-arm64x-data.test diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 1589323073c0..f7addc29d1a3 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -2600,7 +2600,7 @@ void LinkerDriver::linkerMain(ArrayRef 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(); } diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 0a84bce14648..a8148446a265 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -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 rels; + ctx.forEachSymtab([&](SymbolTable &symtab) { + std::vector rels; - for (Chunk *c : ctx.driver.getChunks()) { - auto *sc = dyn_cast(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(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(rels); - rdataSec->addChunk(table); - EmptyChunk *endOfList = make(); - rdataSec->addChunk(endOfList); + PseudoRelocTableChunk *table = make(rels); + rdataSec->addChunk(table); + EmptyChunk *endOfList = make(); + rdataSec->addChunk(endOfList); - Symbol *headSym = ctx.symtab.findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST__"); - Symbol *endSym = - ctx.symtab.findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST_END__"); - replaceSymbol(headSym, headSym->getName(), table); - replaceSymbol(endSym, endSym->getName(), endOfList); + Symbol *headSym = symtab.findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST__"); + Symbol *endSym = symtab.findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST_END__"); + replaceSymbol(headSym, headSym->getName(), table); + replaceSymbol(endSym, endSym->getName(), endOfList); + }); } // MinGW specific. diff --git a/lld/test/COFF/autoimport-arm64x-data.test b/lld/test/COFF/autoimport-arm64x-data.test new file mode 100644 index 000000000000..4cbb83610ede --- /dev/null +++ b/lld/test/COFF/autoimport-arm64x-data.test @@ -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