Skip to content

Commit a35398d

Browse files
authored
[LLD][COFF] Generate redirection metadata for custom ARM64EC export thunks. (#105901)
This allows using custom export thunks instead of default generated ones. This is useful for performance in cases where transferring between JIT and ARM64EC code is more expensive than just emulating the whole function (but it's still useful to have ARM64EC version so that ARM64EC callers don't call into the emulator). It's also useful for compatibility, where applications have specific expectations about function contents (like syscall functions).
1 parent 2d37e48 commit a35398d

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

lld/COFF/Writer.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,6 +2062,24 @@ void Writer::createECChunks() {
20622062
if (auto thunk = dyn_cast<ECExportThunkChunk>(sym->getChunk())) {
20632063
hexpthkSec->addChunk(thunk);
20642064
exportThunks.push_back({thunk, thunk->target});
2065+
} else if (auto def = dyn_cast<DefinedRegular>(sym)) {
2066+
// Allow section chunk to be treated as an export thunk if it looks like
2067+
// one.
2068+
SectionChunk *chunk = def->getChunk();
2069+
if (!chunk->live || chunk->getMachine() != AMD64)
2070+
continue;
2071+
assert(sym->getName().starts_with("EXP+"));
2072+
StringRef targetName = sym->getName().substr(strlen("EXP+"));
2073+
// If EXP+#foo is an export thunk of a hybrid patchable function,
2074+
// we should use the #foo$hp_target symbol as the redirection target.
2075+
// First, try to look up the $hp_target symbol. If it can't be found,
2076+
// assume it's a regular function and look for #foo instead.
2077+
Symbol *targetSym = ctx.symtab.find((targetName + "$hp_target").str());
2078+
if (!targetSym)
2079+
targetSym = ctx.symtab.find(targetName);
2080+
Defined *t = dyn_cast_or_null<Defined>(targetSym);
2081+
if (t && isArm64EC(t->getChunk()->getMachine()))
2082+
exportThunks.push_back({chunk, t});
20652083
}
20662084
}
20672085

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# REQUIRES: aarch64, x86
2+
# RUN: split-file %s %t.dir && cd %t.dir
3+
4+
# Test that metadata is generated when a custom export thunk is supplied.
5+
6+
# RUN: llvm-mc -filetype=obj -triple=arm64ec-windows func.s -o func.obj
7+
# RUN: llvm-mc -filetype=obj -triple=arm64ec-windows hp-func.s -o hp-func.obj
8+
# RUN: llvm-mc -filetype=obj -triple=x86_64-windows thunk.s -o thunk.obj
9+
# RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
10+
11+
# RUN: lld-link -out:out.dll -machine:arm64ec func.obj thunk.obj loadconfig-arm64ec.obj -dll -noentry "-export:#func,EXPORTAS,func"
12+
13+
# RUN: llvm-objdump -d out.dll | FileCheck --check-prefixes=DISASM,DISASM-EXP %s
14+
# DISASM: Disassembly of section .text:
15+
# DISASM-EMPTY:
16+
# DISASM-NEXT: 0000000180001000 <.text>:
17+
# DISASM-NEXT: 180001000: 52800040 mov w0, #0x2 // =2
18+
# DISASM-NEXT: 180001004: d65f03c0 ret
19+
# DISASM-NEXT: ...
20+
# DISASM-EXP-EMPTY:
21+
# DISASM-EXP-NEXT: 0000000180002000 <func>:
22+
# DISASM-NEXT: 180002000: b8 03 00 00 00 movl $0x3, %eax
23+
# DISASM-NEXT: 180002005: c3 retq
24+
25+
# RUN: llvm-objdump -p out.dll | FileCheck --check-prefix=EXPORT %s
26+
# EXPORT: Ordinal RVA Name
27+
# EXPORT-NEXT: 1 0x2000 func
28+
29+
# RUN: llvm-readobj --coff-load-config out.dll | FileCheck --check-prefix=CHPE %s
30+
# CHPE: CodeMap [
31+
# CHPE-NEXT: 0x1000 - 0x1008 ARM64EC
32+
# CHPE-NEXT: 0x2000 - 0x2006 X64
33+
# CHPE-NEXT: ]
34+
# CHPE-NEXT: CodeRangesToEntryPoints [
35+
# CHPE-NEXT: 0x2000 - 0x2006 -> 0x2000
36+
# CHPE-NEXT: ]
37+
# CHPE-NEXT: RedirectionMetadata [
38+
# CHPE-NEXT: 0x2000 -> 0x1000
39+
# CHPE-NEXT: ]
40+
41+
# RUN: lld-link -out:out2.dll -machine:arm64ec hp-func.obj thunk.obj loadconfig-arm64ec.obj -dll -noentry
42+
# RUN: llvm-objdump -d out2.dll | FileCheck --check-prefix=DISASM %s
43+
# RUN: llvm-readobj --coff-load-config out2.dll | FileCheck --check-prefix=CHPE %s
44+
45+
#--- func.s
46+
.globl "#func"
47+
.p2align 2, 0x0
48+
"#func":
49+
mov w0, #2
50+
ret
51+
52+
#--- hp-func.s
53+
.section .text,"xr",discard,"#func$hp_target"
54+
.globl "#func$hp_target"
55+
.p2align 2, 0x0
56+
"#func$hp_target":
57+
mov w0, #2
58+
ret
59+
60+
.def "EXP+#func"
61+
.scl 2
62+
.type 32
63+
.endef
64+
.weak func
65+
.set func, "EXP+#func"
66+
.weak "#func"
67+
.set "#func", "#func$hp_target"
68+
69+
.data
70+
.rva func
71+
72+
#--- thunk.s
73+
.def "EXP+#func"
74+
.scl 2
75+
.type 32
76+
.endef
77+
.section .wowthk$aa,"xr",discard,"EXP+#func"
78+
.globl "EXP+#func"
79+
.p2align 2, 0x0
80+
"EXP+#func":
81+
movl $3, %eax
82+
retq

0 commit comments

Comments
 (0)