-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Description
See https://godbolt.org/z/19c3ohsKs. The generated gcc_except_table is missing the call site table entry for the end of the function:
GCC_except_table0:
.Lexception0:
.byte 255 // @LPStart Encoding = omit
.byte 255 // @TType Encoding = omit
.byte 1 // Call site Encoding = uleb128
.uleb128 .Lcst_end0-.Lcst_begin0
.Lcst_begin0:
.uleb128 .Ltmp0-.Lfunc_begin0 // >> Call Site 1 <<
.uleb128 .Ltmp1-.Ltmp0 // Call between .Ltmp0 and .Ltmp1
.uleb128 .Ltmp2-.Lfunc_begin0 // jumps to .Ltmp2
.byte 0 // On action: cleanup
.Lcst_end0:As a result, any exception thrown through this function will end up terminating, because we'll enter the cleanup, resume unwinding, and then the personality function will be unable to find any call site table entry corresponding to the cleanup PC.
Removing the nounwind attribute from the declaration of either _ZN14has_destructorD1Ev or _Unwind_Resume produces a correct gcc_except_table:
GCC_except_table0:
.Lexception0:
.byte 255 // @LPStart Encoding = omit
.byte 255 // @TType Encoding = omit
.byte 1 // Call site Encoding = uleb128
.uleb128 .Lcst_end0-.Lcst_begin0
.Lcst_begin0:
.uleb128 .Ltmp0-.Lfunc_begin0 // >> Call Site 1 <<
.uleb128 .Ltmp1-.Ltmp0 // Call between .Ltmp0 and .Ltmp1
.uleb128 .Ltmp2-.Lfunc_begin0 // jumps to .Ltmp2
.byte 0 // On action: cleanup
.uleb128 .Ltmp1-.Lfunc_begin0 // >> Call Site 2 <<
.uleb128 .Lfunc_end0-.Ltmp1 // Call between .Ltmp1 and .Lfunc_end0
.byte 0 // has no landing pad
.byte 0 // On action: cleanup
.Lcst_end0:This repros with any target using DWARF unwinding, not just Android AArch64.
I discovered this when building a combined libc++, libc++abi, and libunwind library with LTO, with libunwind providing the actual _Unwind_Resume definition; it resulted in various libc++ functions having bad gcc_except_tables, leading to exception handling issues. That's probably an unusual setup, but I'd still expect it to work.