From a063406afe04e43b9c7957b8e712dfd298dbaa14 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 18 Sep 2023 19:21:21 +0200 Subject: [PATCH] [LLD][COFF] Allow overriding EC alias symbols with alternate names --- lld/COFF/Driver.cpp | 16 ++++- lld/test/COFF/arm64ec-altnames.s | 109 +++++++++++++++++++++++++++++++ llvm/include/llvm/IR/Mangler.h | 6 ++ 3 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 lld/test/COFF/arm64ec-altnames.s diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index e7f768789271f..08c1476a595f6 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -2518,9 +2518,19 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { Symbol *sym = ctx.symtab.find(from); if (!sym) continue; - if (auto *u = dyn_cast(sym)) - if (!u->weakAlias) - u->setWeakAlias(ctx.symtab.addUndefined(to)); + if (auto *u = dyn_cast(sym)) { + if (u->weakAlias) { + // On ARM64EC, anti-dependency aliases are treated as undefined + // symbols unless a demangled symbol aliases a defined one, which is + // part of the implementation. + if (!isArm64EC(ctx.config.machine) || !u->isAntiDep) + continue; + if (!isa(u->weakAlias) && + !isArm64ECMangledFunctionName(u->getName())) + continue; + } + u->setWeakAlias(ctx.symtab.addUndefined(to)); + } } // If any inputs are bitcode files, the LTO code generator may create diff --git a/lld/test/COFF/arm64ec-altnames.s b/lld/test/COFF/arm64ec-altnames.s new file mode 100644 index 0000000000000..fb28ae15895f9 --- /dev/null +++ b/lld/test/COFF/arm64ec-altnames.s @@ -0,0 +1,109 @@ +REQUIRES: aarch64 +RUN: split-file %s %t.dir && cd %t.dir + +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows ext.s -o ext.obj +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows impl.s -o impl.obj +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows impl-cpp.s -o impl-cpp.obj +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig.obj + +# Ensure -alternatename can change a mangled function symbol aliasing a defined symbol (typically a guest exit thunk). + +RUN: lld-link -machine:arm64ec -dll -noentry -out:out1.dll ext.obj loadconfig.obj "-alternatename:#func=altsym" + +RUN: llvm-objdump -d out1.dll | FileCheck --check-prefix=DISASM %s +DISASM: 0000000180001000 <.text>: +DISASM-NEXT: 180001000: 52800020 mov w0, #0x1 // =1 +DISASM-NEXT: 180001004: d65f03c0 ret +DISASM-NOT: .thnk + +RUN: llvm-readobj --hex-dump=.test out1.dll | FileCheck --check-prefix=TESTSEC %s +TESTSEC: 0x180004000 00100000 00100000 + +# Ensure -alternatename can change a demangled function symbol aliasing an anti-dependency symbol. + +RUN: lld-link -machine:arm64ec -dll -noentry -out:out2.dll ext.obj loadconfig.obj -alternatename:func=altsym + +RUN: llvm-objdump -d out2.dll | FileCheck --check-prefix=DISASM2 %s +DISASM2: Disassembly of section .text: +DISASM2-EMPTY: +DISASM2-NEXT: 0000000180001000 <.text>: +DISASM2-NEXT: 180001000: 52800020 mov w0, #0x1 // =1 +DISASM2-NEXT: 180001004: d65f03c0 ret +DISASM2-EMPTY: +DISASM2-NEXT: Disassembly of section .thnk: +DISASM2-EMPTY: +DISASM2-NEXT: 0000000180005000 <.thnk>: +DISASM2-NEXT: 180005000: 52800040 mov w0, #0x2 // =2 +DISASM2-NEXT: 180005004: d65f03c0 ret + +RUN: llvm-readobj --hex-dump=.test out2.dll | FileCheck --check-prefix=TESTSEC2 %s +TESTSEC2: 0x180004000 00100000 00500000 + +# Ensure -alternatename cannot modify a demangled function symbol aliasing a defined symbol. + +RUN: lld-link -machine:arm64ec -dll -noentry -out:out3.dll impl.obj loadconfig.obj -alternatename:func=altsym +RUN: llvm-objdump -d out3.dll | FileCheck --check-prefix=DISASM %s +RUN: llvm-readobj --hex-dump=.test out3.dll | FileCheck --check-prefix=TESTSEC %s + +RUN: lld-link -machine:arm64ec -dll -noentry -out:out4.dll impl-cpp.obj loadconfig.obj -alternatename:func=altsym +RUN: llvm-objdump -d out4.dll | FileCheck --check-prefix=DISASM %s +RUN: llvm-readobj --hex-dump=.test out4.dll | FileCheck --check-prefix=TESTSEC %s + +#--- ext.s + .weak_anti_dep func +.set func, "#func" + .weak_anti_dep "#func" +.set "#func", thunksym + + .section .test, "r" + .rva func + .rva "#func" + + .section .thnk,"xr",discard,thunksym +thunksym: + mov w0, #2 + ret + + .section .text,"xr",discard,altsym + .globl altsym +altsym: + mov w0, #1 + ret + +#--- impl.s + .weak_anti_dep func +.set func, "#func" + + .section .test, "r" + .rva func + .rva "#func" + + .section .text,"xr",discard,"#func" +"#func": + mov w0, #1 + ret + + .section .text,"xr",discard,altsym + .globl altsym +altsym: + mov w0, #2 + ret + +#--- impl-cpp.s + .weak_anti_dep func +.set func, "?func@@$$hYAXXZ" + + .section .test, "r" + .rva func + .rva "?func@@$$hYAXXZ" + + .section .text,"xr",discard,"?func@@$$hYAXXZ" +"?func@@$$hYAXXZ": + mov w0, #1 + ret + + .section .text,"xr",discard,altsym + .globl altsym +altsym: + mov w0, #2 + ret diff --git a/llvm/include/llvm/IR/Mangler.h b/llvm/include/llvm/IR/Mangler.h index 349f9e6e75233..3c3f0c6dce80f 100644 --- a/llvm/include/llvm/IR/Mangler.h +++ b/llvm/include/llvm/IR/Mangler.h @@ -61,6 +61,12 @@ std::optional getArm64ECMangledFunctionName(StringRef Name); /// mangled. std::optional getArm64ECDemangledFunctionName(StringRef Name); +/// Check if an ARM64EC function name is mangled. +bool inline isArm64ECMangledFunctionName(StringRef Name) { + return Name[0] == '#' || + (Name[0] == '?' && Name.find("$$h") != StringRef::npos); +} + } // End llvm namespace #endif