<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/141070>141070</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
The aarch64 trampoline of llvm-xray is unsound at tailcall
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
quininer
</td>
</tr>
</table>
<pre>
All trampolines in aarch64 do not backup the local variable register. https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/xray/xray_trampoline_AArch64.S#L4
this is unsound in tailcall functions that use function pointer.

Since tailcall trampoline (it's actually exit trampoline, because https://github.com/llvm/llvm-project/issues/141051) does not backup x9 register, it is possible to corrupt x9 during an xray rt call. the br instruction will then jump to corrupted address.
I can reproduce the crash using the following code
```c
#include <stdint.h>
typedef struct Func {
int(*ptr)(
unsigned long a0,
unsigned long a1,
unsigned long a2,
unsigned long a3,
unsigned long a4,
unsigned long a5,
unsigned long a6,
unsigned long a7
);
} func_t;
__attribute__ ((noinline))
int fx(
unsigned long a0,
unsigned long a1,
unsigned long a2,
unsigned long a3,
unsigned long a4,
unsigned long a5,
unsigned long a6,
unsigned long a7
) {
return a0
+ a1
- a2
* a3
/ a4
^ a5
& a6
<< a7
;
}
__attribute__ ((noinline))
int foo(
unsigned long a0,
unsigned long a1,
unsigned long a2,
unsigned long a3,
unsigned long a4,
unsigned long a5,
unsigned long a6,
unsigned long a7,
struct Func *f
) {
unsigned long n1 = a1 + a2;
unsigned long n2 = a3 - a4;
return ((*f).ptr)(
n1,
n2 ? a1 : a2,
a2,
a3,
a4,
a5,
a6,
a7
);
}
int main() {
struct Func func = { fx };
foo(
1,
2,
3,
4,
5,
6,
7,
8,
&func
);
}
```
and
```shell
$ clang foo.c -O2 -fxray-instrument -fxray-instruction-threshold=1 -fuse-ld=lld
$ env XRAY_OPTIONS="patch_premain=true verbosity=1 xray_mode=xray-basic" ./a.out
==15386==XRay: Log file in 'xray-log.a.out.JQTDQR'
fish: Job 1, 'env XRAY_OPTIONS="patch_premain…' terminated by signal SIGSEGV (Address boundary error)
```
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzUVk2P2zYQ_TX0ZSBBJmXLPvigXa-DDYKmyQZFejIoirKY0qTKj8363xdD2bvadF006KmAYZMcfrx5b8Yz3Ht1MFJuyOKGLLYzHkNv3ebPqIwy0s0a2542tdYQHD8OVisjPSgDnDvRL0toLRgboOHijzhA6CVoK7iGR-4Ub7QEJw_KB-ly6EMYPGE1oTtCdwcV-tjkwh4J3Wn9ePnJBme_SREI3TXaNoTujlwZQnfCHgelpcsc2rRC05Pjp_PP_gXgvq4TuPyBUPahJEUdeuVBeYjG22hadCBwpQXXGrpoRFDWeAg9DxC9fF6CwSqD2ElR44fOyeLm_sgPkiy2hK7-waPopct4CFz0R2mCJ3THvZdpsGa8auZ8kYmuoFnJOct40fCMt7ScM7nm7VISuh4ffVBGyBe0L14CoSsVCK08cBEi1_oE8kmFyRZCb6GRgqNPP82-8j5KhDsv58ViTugaWiv9VO6n9bO8-JQKyPFgvVeofLAgrHNxCLixjU6ZA3ADqBa4AOhPnkKmcaCMDy6OrH9X6GgvDXyLx2Fyj2yBt62T3p8VuQfBDTg5ONtGpKmXIBz3PUSPr-G8s1rb7zgTtpVnJZfF-BFJVqaM0LGVQNitD60yIe8Juxv3htMgW9nBiA920Qgg1Q0pagBlAqErQushOFSMrtIyYKBhWrWgLTpdEHr7tmV-1UKvWthVS3nVsrhqWV61VGkZ_WLoLqm2KTP24Twv6v2eh-BUE4Pc7yFRsTJWmTH41mMQKxOge7pwc42Za7xcY-UaJ9cYucbHNTbe4AJT4KK8kyE6g_hH6gi9QdDjJEOcl_UawV0mO0R0nizuEMbFssS3zxN2S9jtM_8X8n-Wcmv_95yf11-lHq27H7R4fczMgbAt8PmoCR35-9suOu5iKFZ52fPyddZ35De9Sdf5j1luJtmbLtylZ1n9KntfjSe5O83WaX5OM_KNHBzDABUeC-NqSsWUqS7RxbZohO4J8OzUz0mAAEw8mcCdoJ2AnWCdQK1ehquXIaFLxPGmF5c_4dEjbtof_px9L7VOWpcgNDcHhJwLyD5SyDosI9lYNrDCvl5JhSQLvZO-t7olbDuHrIteZmmidXu-V5pH-Pq5_n3_8dcv9x9_eSBsSygdeBD9fnAyUcy2wUUJj9I11qtwSrelnuOIFYVt08MN90oQSiHHWp_bGPAJtsXdC7ZajsOvn_kJA-SDPUCntMRWhNAq3aDtIU8H8_efvmw_fSYU1e-U7_HEe9sklXD7v0F9R8mqIPWS0AqCdEdlOBbQ5gSYB1zDw_27h7t3v2GM12NVhQa7I-5OIJ2z7tyDXOSYtRvWrtmaz-RmXpXVmrJVtZz1m6ITbFG2rWzEsuu6is-XHWd8TRvB5ZqzmdrQgi6KBaXzkpZskbOioQ2rpKQdLVm7ImWBoHWOPUhu3WGWuo8Nth5VMdO8kdqnFpVSI79DshJKsWN1m9S4NPHgSVlo5YN_uSaooOXmSy-fG9ZJA2U7SEdTQzLpDnl47rdm0enNf2udqmL2uKF_BQAA__9SD216">