<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.

![Image](https://github.com/user-attachments/assets/93a7b1a5-cf02-4aa3-a0ba-ad2413e9ad6e)

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">