<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/112943>112943</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Landing pad accesses corrupted register
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          purplesyringa
      </td>
    </tr>
</table>

<pre>
    LLVM currently assumes that if a function preserves the value of a register, this register can be safely accessed from a landing pad even if the function unwinds.

For example (x86_64):

```cpp
#include <stdio.h>

__attribute__((ms_abi, noinline)) void f() { throw 1; }

struct Dropper {
  int x;
  ~Dropper() { printf("Dropper{%d}\n", x); }
};

__attribute__((noinline)) void test(int arg) {
  Dropper dropper{arg};
  f();
}

int main() try { test(1); } catch (...) {
}
```

`f()` is marked as `ms_abi`, where `rdi` is callee-saved, so the value of `arg` can be read out from `rdi` after invoking `f()`. That's what LLVM does both if `f()` returns and in `test`'s cleanup pad.

Unfortunately, that's incorrect behavior. According to [the Itanium C++ ABI](https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#landing), the landing pad can only rely on the registers that are *callee-saved by the base ABI*. For Linux, "base ABI" is the SysV ABI, where `rdi` is caller-saved, so the unwinding library is not required to restore `rdi`.

While LLVM's libunwind goes beyond the EH ABI requirements and restores `rdi`, libgcc indeed doesn't (which I'd argue is compliant with the standard). When compiled against libgcc, the above code produces `Dropper{random garbage}` instead of `Dropper{1}`.

---

I've tested this on clang 18.1.8 from the Arch repos, built against libgcc. It compiles the `test` function from above to

```
       │ test(int)
  1200 │     53                      push   rbx
  1201 │     48 83 ec 20             sub    rsp, 0x20
  1205 │     89 fe                   mov    esi, edi
  1207 │     e8 84 ff ff ff          call   f()
  120c │     48 89 c3                mov    rbx, rax
  120f │     48 8d 3d ee 0d 00 00    lea    rdi, [rel _IO_stdin_used+0x4]        
  1216 │     31 c0                   xor    eax, eax
  1218 │     e8 13 fe ff ff          call   printf@plt
  121d │     48 89 df                mov    rdi, rbx
  1220 │     e8 5b fe ff ff          call   _Unwind_Resume@plt
  1225 │     66 66 2e 0f 1f 84 00    data16 cs nop word [rax+rax]
       │     00 00 00 00
```

which erroneously assumes `rsi` is retained rather than `rdi`, but it's the same bug anyway.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJx8Vl2Ps7oR_jXOzSgITAjkIhebzbvqSm9Vqe055zIyeAjuAZvaJh83_e3VGLIhebMHoaDY45lnnvmycE4dNeKWZTuW7Rdi8I2x236wfYvuapU-ikVp5HX78-fvf4dqsBa1b68gnBs6dOAb4UHVIKAedOWV0dBbdGhPYRPhJNoBwZCExaNyHi3j7-Ab5b4WoBIaSgQnaiTdVYXOoYTamg4EtEJLpY_QCwl4Qk32SPWXxUGflZYuYvGexW_j74exgBfR9S0C48WlWB_WK8Y3LH2bi7F1PL5V308rPFW6ageJwNJ356UyUcPSH_NTh4Pw3qpy8Hg4MF4wXnTuIEpFrmmjdKs0kjG-gZNREuogtAGW78A31pwhYekOWL6fq3XeDpWHvTV9j5aEx3UApT1cWPr1_3-TzExtb5X2ox1-2813jGeSrGTvmnFO8C6BhLntfP-l-Vv3Xjnl0XnGC8Im7HHCcUN4c0J-QSGZmSm4kXI3_sgG6e2E0pOP3l5H-karyd0NqISvGopyFEUPMO4ab2F-iv0NwjoG5aAT9k-UIBywdTwFdB0TaecGLdKqlWoSrkTbIi6dOKEkEWce852tY_J4Hd-y26KQYAY_pvVdl6ipBJQ-mT8pyx9QRfDvRnjGcwdnqrRQhdKgg9L4hgrh0QmLfrDagdASlKbNQBc5kTuoWhR66KmQHmrlN10b6wctPLbXsTono0pXxlqsPJTYiJMyNoK3qjI2FKQ3wLIdef3phVZDB--M7xjfwdvuk2V7xovG-95RzfEPxj_UKLasLpelKFV0VL4ZykgZxj-mNcY_RKmW2ESN71rG06n6Q-K9B4rn_YC4Nbq9gqXOYXQQuPWVqT0JCh1_mwcMymuQLIXDAJa_RUAt46fSw4UMMc7vm5wCTvL_urrfx6Xvc8L-khNjfyLIrSqtsFeS1caDxf8OyqIkJi06b-YKH0L0R6NaDOEPcWlVOSqFY0gGvBotg60ffyN8N80daj9mw6Te3fUTwFaVx6oCpSWiDImlGc891dK5UVUDn4znksp7wOCg6fpWCe3hrHwTDDovtBRWMr6J4I8GdRBSLRXSUSjt_GTlFj5RmhNCZSRCb40cqhHUvWdZoaXp4ChsKY5INUzsaudDAdWPwsm4_0DWcrmc_yUfThgaB1FNk8doqFqhj5AUURIVY0kSuDdbNWCxN47gloNq_ZMbEXz6m4tjUtyr7D6SxtEVPPXm5cC5dcHwsB-cbVas4LOmShk_ySQ8jmcy9GQpvHz6wTUAYMvL7HDydHhVQJECVsDjh8NuKOljXU_exxcez5RkT0qKDdT4AkFnTvRBF6YhSjXTkT_pwAKKFdT19H49VEhwnxB3BdULTzZQ_ULGBIJo4O9gxZyN-oUOCakERIglxDG9ANCiCDpkcIRlO4stHD7_caBLgT4Mjop8F19WLNvf7N7NJOsnM2kCVfyCr4uxgQoRoOIcalL8yleSEu2v-ZruAKu4b_1Mi3xJmqy_I210-CGF-HP-YQFZ-T2Sw2-hPR3-iXRPfEbEn3NpvaaXI8Q1JDXlxBgCKbxI1lBRu-zhbKwMcSCqwm-2_6aM6BkDGd6_uAWMfQ6tNRrN4GZ3W-qU7tbaLXqhNEqwwjdoabLox15aDh7UODZDXxQdQjkcQejrWVyjhdymcpNuxAK3Sc43PE9jni2abZLLvFzVVZqs1nlRx1mdl3GWppt0XcbxplioLY_5KomTIsnTPM4iHmd5VuSreFVsCrEp2SrGTqg2attTFxl7XCjnBtwmCd-s0kUrSmxduOJzrvEMYZeug9l-Ybd0aFkOR8dWcaucd3c1XvkWtz9n83a6m9MksHboqaHepu1isO32cd5P870yHeMfpHX6LHtr_oOVpysBYXGMf0xgT1v-_wAAAP__5U-gBQ">