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

Conversation

cjacek
Copy link
Contributor

@cjacek cjacek commented Feb 28, 2025

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Feb 28, 2025

@llvm/pr-subscribers-platform-windows
@llvm/pr-subscribers-lld-coff

@llvm/pr-subscribers-lld

Author: Jacek Caban (cjacek)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/129282.diff

3 Files Affected:

  • (modified) lld/COFF/Driver.cpp (+1-1)
  • (modified) lld/COFF/Writer.cpp (+42-38)
  • (added) lld/test/COFF/autoimport-arm64x-data.test (+75)
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 1589323073c09..f7addc29d1a3a 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -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();
   }
 
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 0a84bce146483..a8148446a2657 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<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.
diff --git a/lld/test/COFF/autoimport-arm64x-data.test b/lld/test/COFF/autoimport-arm64x-data.test
new file mode 100644
index 0000000000000..c0636b900a264
--- /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 32 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 32 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

Copy link
Member

@mstorsjo mstorsjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks! Although there's a couple details in the test comments that I'm unsure about.


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 32 bits. ARM64EC runtime pseudo relocation list header at
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the size really 32 bit? 32 bit pseudo relocations in 64 bit images usually is a problem (and we warn about them nowadays too); as the reference is a .quad I presume that it is 64 bit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's 64 bit, good catch, thanks! I copied it from arm64ec test, which was based on aarch64 version, I will create a separate PR to fix those.

The runtime pseudo relocation is from an aarch64.obj object file, with import from 0x4000,
applied at 0x9018 with a size of 32 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 32 bits.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

@cjacek cjacek force-pushed the arm64x-autoimport branch from 1c3f58f to 5e3d412 Compare March 1, 2025 21:36
@cjacek cjacek merged commit c6598f6 into llvm:main Mar 2, 2025
11 checks passed
@cjacek cjacek deleted the arm64x-autoimport branch March 2, 2025 12:10
SquallATF pushed a commit to SquallATF/llvm-project that referenced this pull request Mar 10, 2025
SquallATF pushed a commit to SquallATF/llvm-project that referenced this pull request Mar 20, 2025
jph-13 pushed a commit to jph-13/llvm-project that referenced this pull request Mar 21, 2025
SquallATF pushed a commit to SquallATF/llvm-project that referenced this pull request Apr 2, 2025
SquallATF pushed a commit to SquallATF/llvm-project that referenced this pull request Apr 17, 2025
SquallATF pushed a commit to SquallATF/llvm-project that referenced this pull request Apr 30, 2025
SquallATF pushed a commit to SquallATF/llvm-project that referenced this pull request May 15, 2025
SquallATF pushed a commit to SquallATF/llvm-project that referenced this pull request May 29, 2025
SquallATF pushed a commit to SquallATF/llvm-project that referenced this pull request Jun 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants