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

    <tr>
        <th>Summary</th>
        <td>
            [PowerPC] missing CFI for ELF32 to unwind cr2, cr3, cr4
        </td>
    </tr>

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

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

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

<pre>
    For PowerPC ELF 32-bit targets, LLVM forgets to provide CFI like `.cfi_offset cr2, -88` for fields cr2, cr3, cr4 in the condition register. Function calls must preserve cr2, cr3, cr4. Because the CFI is missing, an unwinder (like libunwind) can't restore cr2, cr3, cr4, when it unwinds a function call.

I found the bug after OpenBSD/macppc's clang 16.0.6 miscompiled gdb, when a C++ exception crashed gdb by not restoring cr2. I reproduced the bug in 19.0.0git with this example,

```c++
struct flip {
  int *p;
  flip(int *a): p(a) { if (p) *p = 1; }
  ~flip() { if (p) *p = 0; }
};
#define N __attribute__((noinline))
int i;
N void flip2(int *p) { flip f(p); throw 0; }
N void flip1(int *p) { flip f(p); flip2(&i); }
int main() { try { flip1(nullptr); } catch(int) {} }
```

I compiled it with clang++ -O2. The example is small enough to optimize out cr2; I added `noinline` to keep cr2 in the code. The functions _flip1_ and _flip2_ each use cr2 to test some pointer _p_, which is null in _flip1_ and non-null in _flip2_. The C++ exception from `throw 0` unwinds _flip2_ without restoring cr2, then runs the C++ destructor _~flip_ in _flip1_ with a wrong cr2, so `if (p) *p = 0` crashes by writing to a null _p_.

I will soon add a pull request.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyMVU1v4zgP_jXKhYjhyKljH3JomglQoO_MAO9ir4Zi0Ta3sqSV5Ga6h_3tC_kjSaeDxQJBbFPkw4cUP4T31GrEPXs4sIfjSgyhM27_ik5T263ORr7vT8bBd3NB9_0JvrycIOPrMwUIwrUYPONP8PLy-_-gMeM3BAPWmTeSCE-nZ1D0isDyNKkbqkzTeAxQOx7N1kXB8jQaQkOopF8OapdNjy2QhtAh1EZLCmQ0OGzJB3QJnAZdj6JaKOWhH3wA69Cje8PPSAkcsBaDxxEvMiMPPXlPuo0qQsOgL6QlOmC8GGkrOk8yxkuohWZ8F8ChD8b9wkN8XDrUQGGG8iCguWeZsPTI0sfp_xkaM2g58jkPLYgmoINvFvXh_0fGT72ora0Z33moldAtbPIkTfJIuja9JYUSWnm-uhXwxPiB8QPgjxrt5NQJ3016cH4HbRb-pNsYQQLP4NA6I4cab1RIw6ZM0iRtKcCFQgehIw_4Q_RWIeNP93GwPJ1-9eR-kvrghjpAo8gC281CANIBGH-0LLuKogrjxXwiGC9Z9ghRFN-jMVAT78SOn_zRAsuOsGHZAdjuuMD8PeP8m036wSa-LDQYzyQ2pBG-QlWJEBydh4BVNSIW2pBWpDGS4-VkEgnTFeArvBmSYzD8Fo1d2Ix5aGZCkUXonLn8ROgOY_NfMBZnjOc0i65Y0bgXpO8yEtz7FSfi60EpG9zNEmoR6m7yPBtF6S1hy01_LONrNS7FMpbrXIvrbzyB3zpciie2ne-FUoDaDG0X54WxgXr6C8EM03DIDvAMQkqUcXRck5-nUfsV0Uat22yQOLlYes1DNcZYgdByeucVoKg7iAMg2gYDAX0Ab3oEa0jH3qtsNXUT1V3kGRMUvdyjaaPXH-S8mpx_br7GmT7yX646T69zYeEU0xWD_tCUkUOIHe0G7adxNWNLnNrKOKjGeq_u6Y25F3Bx5objTWTw617I03k--DgbLo5CJBAMiCnyylY_DawLKQXeGB0vBwTYqObwzwF9SFZyn8kyK8UK95tdWpRluc2zVbfPsvIhT2Uh5U7maZ5lvCn5JpMZFrnMCrGiPU_5NuV8l_J0y7Mka-R2t9mdt2WRc9kUbJtiL0glSr31iXHtirwfcF9kabldKXFG5ccVxrnGC4yHjPO40dw-2qzPQ-vZNlXkg7-hBApq3H3zfmMPx2UnjCsirqYvL6dsrJfp7j7P_dXg1L4LwXqWPTJ-YvzUUuiGc1KbnvFT9DY_1taZP7AOjJ9Gjp7x0xjDPwEAAP__ymdQhQ">