-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[PowerPC] missing CFI for ELF32 to unwind cr2, cr3, cr4 #83094
Comments
@llvm/issue-subscribers-backend-powerpc Author: George Koehler (kernigh)
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, 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 I will soon add a pull request. |
Delete the code that skips the CFI for the condition register on ELF32. The code checked !MustSaveCR, which happened only when Subtarget.is32BitELFABI(), where spillCalleeSavedRegisters is spilling cr in a different way. The spill was missing CFI. After deleting this code, a spill of cr2 to cr4 gets CFI in the same way as a spill of r14 to r31. Fixes llvm#83094
Delete the code that skips the CFI for the condition register on ELF32. The code checked !MustSaveCR, which happened only when Subtarget.is32BitELFABI(), where spillCalleeSavedRegisters is spilling cr in a different way. The spill was missing CFI. After deleting this code, a spill of cr2 to cr4 gets CFI in the same way as a spill of r14 to r31. Fixes #83094
Delete the code that skips the CFI for the condition register on ELF32. The code checked !MustSaveCR, which happened only when Subtarget.is32BitELFABI(), where spillCalleeSavedRegisters is spilling cr in a different way. The spill was missing CFI. After deleting this code, a spill of cr2 to cr4 gets CFI in the same way as a spill of r14 to r31. Fixes llvm#83094 (cherry picked from commit 6b70c5d)
Delete the code that skips the CFI for the condition register on ELF32. The code checked !MustSaveCR, which happened only when Subtarget.is32BitELFABI(), where spillCalleeSavedRegisters is spilling cr in a different way. The spill was missing CFI. After deleting this code, a spill of cr2 to cr4 gets CFI in the same way as a spill of r14 to r31. Fixes llvm#83094 (cherry picked from commit 6b70c5d)
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,
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 fromthrow 0
unwinds flip2 without restoring cr2, then runs the C++ destructor ~flip in flip1 with a wrong cr2, soif (p) *p = 0
crashes by writing to a null p.I will soon add a pull request.
The text was updated successfully, but these errors were encountered: