[lld] [LLD][COFF] Redirect __imp_ Symbols to __imp_aux_ on ARM64EC for x64 sections (PR #108608)
Jacek Caban via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 16 12:20:41 PDT 2024
https://github.com/cjacek updated https://github.com/llvm/llvm-project/pull/108608
>From a24afc797d897b429536bcf32798657a3ed48c77 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Mon, 2 Sep 2024 21:58:07 +0200
Subject: [PATCH] [LLD][COFF] Redirect __imp_ Symbols to __imp_aux_ on ARM64EC
for x64 Sections
On ARM64EC, __imp_ symbols reference the auxiliary IAT, while __imp_aux_ symbols
reference the regular IAT. However, x86_64 code expects both to reference the
regular IAT. This change adjusts the symbols accordingly, matching the behavior
observed in the MSVC linker.
---
lld/COFF/SymbolTable.cpp | 17 +++++++++++++++++
lld/test/COFF/arm64ec-import.test | 20 ++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 582a856213cbc8..7510c62572e2e2 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -20,6 +20,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Parallel.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
#include <utility>
@@ -562,6 +563,9 @@ void SymbolTable::addExitThunk(Symbol *from, Symbol *to) {
}
void SymbolTable::initializeECThunks() {
+ if (!isArm64EC(ctx.config.machine))
+ return;
+
for (auto it : entryThunks) {
auto *to = dyn_cast<Defined>(it.second);
if (!to)
@@ -587,6 +591,19 @@ void SymbolTable::initializeECThunks() {
sym = exitThunks.lookup(file->impECSym);
file->impchkThunk->exitThunk = dyn_cast_or_null<Defined>(sym);
}
+
+ // On ARM64EC, the __imp_ symbol references the auxiliary IAT, while the
+ // __imp_aux_ symbol references the regular IAT. However, x86_64 code expects
+ // both to reference the regular IAT, so adjust the symbol if necessary.
+ parallelForEach(ctx.objFileInstances, [&](ObjFile *file) {
+ if (file->getMachineType() != AMD64)
+ return;
+ for (auto &sym : file->getMutableSymbols()) {
+ auto impSym = dyn_cast_or_null<DefinedImportData>(sym);
+ if (impSym && impSym->file->impchkThunk && sym == impSym->file->impECSym)
+ sym = impSym->file->impSym;
+ }
+ });
}
Symbol *SymbolTable::addUndefined(StringRef name, InputFile *f,
diff --git a/lld/test/COFF/arm64ec-import.test b/lld/test/COFF/arm64ec-import.test
index e403daa41f368c..ac43114f7e7ebb 100644
--- a/lld/test/COFF/arm64ec-import.test
+++ b/lld/test/COFF/arm64ec-import.test
@@ -4,6 +4,7 @@ RUN: split-file %s %t.dir && cd %t.dir
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows test.s -o test.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows icall.s -o icall.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows hybmp.s -o hybmp.obj
+RUN: llvm-mc -filetype=obj -triple=x86_64-windows test.s -o test-x86_64.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
RUN: llvm-lib -machine:arm64ec -def:test.def -out:test-arm64ec.lib
RUN: llvm-lib -machine:arm64ec -def:test2.def -out:test2-arm64ec.lib
@@ -17,8 +18,13 @@ Link using x86_64 import library:
RUN: lld-link -machine:arm64ec -dll -noentry -out:out2.dll loadconfig-arm64ec.obj icall.obj hybmp.obj \
RUN: test.obj test-x86_64.lib test2-arm64ec.lib
+Link using x86_64 object file:
+RUN: lld-link -machine:arm64ec -dll -noentry -out:out3.dll loadconfig-arm64ec.obj icall.obj hybmp.obj \
+RUN: test-x86_64.obj test-arm64ec.lib test2-arm64ec.lib
+
RUN: llvm-readobj --coff-imports out.dll | FileCheck --check-prefix=IMPORTS %s
RUN: llvm-readobj --coff-imports out2.dll | FileCheck --check-prefix=IMPORTS %s
+RUN: llvm-readobj --coff-imports out3.dll | FileCheck -check-prefix=IMPORTS %s
IMPORTS: Import {
IMPORTS-NEXT: Name: test.dll
IMPORTS-NEXT: ImportLookupTableRVA:
@@ -36,6 +42,7 @@ IMPORTS-NEXT: }
RUN: llvm-objdump -d out.dll | FileCheck --check-prefix=DISASM %s
RUN: llvm-objdump -d out2.dll | FileCheck --check-prefix=DISASM %s
+RUN: llvm-objdump -d out3.dll | FileCheck -check-prefix=DISASM %s
DISASM: 180001000: 52800000 mov w0, #0x0 // =0
DISASM-NEXT: 180001004: d65f03c0 ret
@@ -74,20 +81,33 @@ TESTSEC-NEXT: 0x180007010 08300000 00500000 10300000 20300000
TESTSEC-NEXT: 0x180007020 14100000 28100000 00200000 08100000
TESTSEC-NEXT: 0x180007030 3c100000
+RUN: llvm-readobj --hex-dump=.test out3.dll | FileCheck -check-prefix=TESTSEC-X64 %s
+TESTSEC-X64: 0x180007000 08300000 00300000 10300000 20300000
+TESTSEC-X64-NEXT: 0x180007010 08300000 00500000 10300000 20300000
+TESTSEC-X64-NEXT: 0x180007020 14100000 28100000 00200000 08100000
+
RUN: llvm-readobj --headers out.dll | FileCheck -check-prefix=HEADERS %s
+RUN: llvm-readobj --headers out2.dll | FileCheck -check-prefix=HEADERS %s
+RUN: llvm-readobj --headers out3.dll | FileCheck -check-prefix=HEADERS %s
HEADERS: LoadConfigTableRVA: 0x4010
HEADERS: IATRVA: 0x3000
HEADERS: IATSize: 0x1000
RUN: llvm-readobj --coff-load-config out.dll | FileCheck -check-prefix=LOADCONFIG %s
+RUN: llvm-readobj --coff-load-config out2.dll | FileCheck -check-prefix=LOADCONFIG %s
+RUN: llvm-readobj --coff-load-config out3.dll | FileCheck -check-prefix=LOADCONFIG %s
LOADCONFIG: AuxiliaryIAT: 0x5000
RUN: llvm-readobj --hex-dump=.rdata out.dll | FileCheck -check-prefix=RDATA %s
+RUN: llvm-readobj --hex-dump=.rdata out2.dll | FileCheck -check-prefix=RDATA %s
+RUN: llvm-readobj --hex-dump=.rdata out3.dll | FileCheck -check-prefix=RDATA %s
RDATA: 0x180005000 00000000 00000000 14100080 01000000
RDATA-NEXT: 0x180005010 28100080 01000000 00000000 00000000
RDATA-NEXT: 0x180005020 48100080 01000000 00000000 00000000
RUN: llvm-readobj --coff-basereloc out.dll | FileCheck -check-prefix=BASERELOC %s
+RUN: llvm-readobj --coff-basereloc out2.dll | FileCheck -check-prefix=BASERELOC %s
+RUN: llvm-readobj --coff-basereloc out3.dll | FileCheck -check-prefix=BASERELOC %s
BASERELOC: BaseReloc [
BASERELOC-NOT: Address: 0x5000
BASERELOC: Address: 0x5008
More information about the llvm-commits
mailing list