Skip to content

[LLD][COFF] Allow overriding EC alias symbols with alternate names #113456

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
Oct 25, 2024
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
16 changes: 13 additions & 3 deletions lld/COFF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2518,9 +2518,19 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
Symbol *sym = ctx.symtab.find(from);
if (!sym)
continue;
if (auto *u = dyn_cast<Undefined>(sym))
if (!u->weakAlias)
u->setWeakAlias(ctx.symtab.addUndefined(to));
if (auto *u = dyn_cast<Undefined>(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<Undefined>(u->weakAlias) &&
!isArm64ECMangledFunctionName(u->getName()))
continue;
}
u->setWeakAlias(ctx.symtab.addUndefined(to));
}
}

// If any inputs are bitcode files, the LTO code generator may create
Expand Down
109 changes: 109 additions & 0 deletions lld/test/COFF/arm64ec-altnames.s
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions llvm/include/llvm/IR/Mangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ std::optional<std::string> getArm64ECMangledFunctionName(StringRef Name);
/// mangled.
std::optional<std::string> 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
Loading