http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50737
Bug #: 50737 Summary: FAIL: Throw_3 -O3 execution, generic dwarf2 EH problem? Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target AssignedTo: unassig...@gcc.gnu.org ReportedBy: ubiz...@gmail.com Target: dwarf2 EH targets (alphaev68-pc-linux-gnu) This problem shows on alphaev68-pc-linux-gnu as "FAIL: Throw_3 -O3 execution - source compiled test" in [1], but I believe that it points to generic problem in dwarf2 EH handling. It was uncovered by changing alpha target to use .cfi directives. After java test throws an exception (through libjava/exception.cc), it calls _Unwind_RaiseException from _Jv_Throw. However, one of the functions in unwind chain, just before target function is defined as: $_ZN7Throw_33fooEJiP6JArrayIiE..ng: _ZN7Throw_33fooEJiP6JArrayIiE: .eflag 48 .frame $30,0,$26,0 $LFB3: .loc 1 38 0 .cfi_startproc .prologue 0 $LVL2: $LBB3: .loc 1 38 0 ldl $0,8($17) $LVL3: .loc 1 39 0 addl $0,$0,$0 $LVL4: addl $31,$0,$0 $LBE3: ret $31,($26),1 .cfi_endproc $LFE3: This results in "empty" FDE: 00000030 00000010 00000034 FDE cie=00000000 pc=00000030..00000040 DW_CFA_nop DW_CFA_nop DW_CFA_nop The target function: _ZN7Throw_34mainEJvP6JArrayIPN4java4lang6StringEE: .eflag 48 .frame $30,48,$26,0 .mask 0x4001e00,-48 $LFB1: .loc 1 7 0 .cfi_startproc .cfi_personality 0x9b,DW.ref.__gcj_personality_v0 .cfi_lsda 0x1b,$LLSDA1 $LEHB0: ldah $29,0($27) !gpdisp!8 lda $29,0($29) !gpdisp!8 $_ZN7Throw_34mainEJvP6JArrayIPN4java4lang6StringEE..ng: lda $30,-48($30) $LCFI4: .cfi_def_cfa_offset 48 defines correct .cfi_personality. Tracing the unwinder through libbgcc/unwin.inc, _Unwind_RaiseException shows: (gdb) p cur_context $29 = {reg = {0x11ff10e60, 0x11ff10e68, 0x11ff10e70, 0x11ff10e78, 0x11ff10e80, 0x11ff10e88, 0x11ff10e90, 0x11ff10e98, 0x11ff10ea0, 0x11ff10ea8, 0x11ff10eb0, 0x11ff10eb8, 0x11ff10ec0, 0x11ff10ec8, 0x11ff10ed0, 0x11ff10ed8, 0x11ff10ee0, 0x11ff10ee8, 0x11ff10ef0, 0x11ff10ef8, 0x11ff10f00, 0x11ff10f08, 0x11ff10f10, 0x11ff10f18, 0x11ff10f20, 0x11ff10f28, 0x11ff10f30, 0x11ff10f38, 0x11ff10f40, 0x11ff10f48, 0x0, 0x0, 0x11ff10f68, 0x11ff10f70, 0x11ff10f78, 0x11ff10f80, 0x11ff10f88, 0x11ff10f90, 0x11ff10f98, 0x11ff10fa0, 0x11ff10fa8, 0x11ff10fb0, 0x11ff10fb8, 0x11ff10fc0, 0x11ff10fc8, 0x11ff10fd0, 0x11ff10fd8, 0x11ff10fe0, 0x11ff10fe8, 0x11ff10ff0, 0x11ff10ff8, 0x11ff11000, 0x11ff11008, 0x11ff11010, 0x11ff11018, 0x11ff11020, 0x11ff11028, 0x11ff11030, 0x11ff11038, 0x11ff11040, 0x11ff11048, 0x11ff11050, 0x11ff11058, 0x0, 0x11ff10e50}, cfa = 0x11ff110e0, ra = 0x1200009d4, lsda = 0x0, bases = {tbase = 0x0, dbase = 0x0, func = 0x2000189fc90}, flags = 4611686018427387904, version = 0, args_size = 0, by_value = '\000' <repeats 64 times>} (gdb) p cur_context $30 = {reg = {0x11ff10e60, 0x11ff10e68, 0x11ff10e70, 0x11ff10e78, 0x11ff10e80, 0x11ff10e88, 0x11ff10e90, 0x11ff10e98, 0x11ff10ea0, 0x11ff10ea8, 0x11ff10eb0, 0x11ff10eb8, 0x11ff10ec0, 0x11ff10ec8, 0x11ff10ed0, 0x11ff10ed8, 0x11ff10ee0, 0x11ff10ee8, 0x11ff10ef0, 0x11ff10ef8, 0x11ff10f00, 0x11ff10f08, 0x11ff10f10, 0x11ff10f18, 0x11ff10f20, 0x11ff10f28, 0x11ff10f30, 0x11ff10f38, 0x11ff10f40, 0x11ff10f48, 0x0, 0x0, 0x11ff10f68, 0x11ff10f70, 0x11ff10f78, 0x11ff10f80, 0x11ff10f88, 0x11ff10f90, 0x11ff10f98, 0x11ff10fa0, 0x11ff10fa8, 0x11ff10fb0, 0x11ff10fb8, 0x11ff10fc0, 0x11ff10fc8, 0x11ff10fd0, 0x11ff10fd8, 0x11ff10fe0, 0x11ff10fe8, 0x11ff10ff0, 0x11ff10ff8, 0x11ff11000, 0x11ff11008, 0x11ff11010, 0x11ff11018, 0x11ff11020, 0x11ff11028, 0x11ff11030, 0x11ff11038, 0x11ff11040, 0x11ff11048, 0x11ff11050, 0x11ff11058, 0x0, 0x11ff10e50}, cfa = 0x11ff110e0, ra = 0x120000af4, lsda = 0x0, bases = {tbase = 0x0, dbase = 0x0, func = 0x1200009d0}, flags = 4611686018427387904, version = 0, args_size = 0, by_value = '\000' <repeats 64 times>} where cfa of the former context shows "cfa = 0x11ff110e0" that is equal to cfa from the later context. The return address (ra) from the former points to: 00000001200009d0 <_ZN7Throw_33fooEJiP6JArrayIiE>: 1200009d0: 08 00 11 a0 ldl v0,8(a1) 1200009d4: 00 00 00 40 addl v0,v0,v0 1200009d8: 00 00 e0 43 sextl v0,v0 1200009dc: 01 80 fa 6b ret and the return address of the later context points to: 0000000120000a64 <_ZN7Throw_34mainEJvP6JArrayIPN4java4lang6StringEE>: 120000a64: 02 00 bb 27 ldah gp,2(t12) 120000a68: 2c 8d bd 23 lda gp,-29396(gp) 120000a6c: d0 ff de 23 lda sp,-48(sp) ... 120000af0: 00 40 5b 6b jsr ra,(t12),120000af4 <_ZN7Throw_34mainEJvP6JArrayIPN4java4lang6StringEE+0x90> 120000af4: 02 00 ba 27 ldah gp,2(ra) 120000af8: 9c 8c bd 23 lda gp,-29540(gp) 120000afc: 2e 00 e0 c3 br 120000bb8 <_ZN7Throw_34mainEJvP6JArrayIPN4java4lang6StringEE+0x154> 120000b00: 10 04 ff 47 clr a0 ... After _Unwind_RaiseException finds the personality routine in _ZN7Throw_34mainEJvP6JArrayIPN4java4lang6StringEE, it records cfa of target function in exc->private2 and calls _Unwind_RaiseExcecption_Phase2 with this data. Unfortunately, the cfa of target function (_ZN7Throw_34mainEJvP6JArrayIPN4java4lang6StringEE) matches the cfa of function just before in the chain, namely _ZN7Throw_33fooEJiP6JArrayIiE ! _Unwind_RaiseException_Phase2 repeats the same unwind path, but compares cfa of traced context with exc->private2. In our case, match_handler wrongly determines that _ZN7Throw_33fooEJiP6JArrayIiE is the function with handler, since its cfa matches the one from exc->private2. Since _ZN7Throw_33fooEJiP6JArrayIiE does not define any personality handler, "gcc_assert (!match_handler)" triggers with a controlled crash of the application. Looking a bit further, why we get two functions with the same cfa. This pointer gets updated from uw_update_context_1, but it changes only in CFA_REG_OFFSET and CFA_EXP cases. So with FDE as above, we get two contexts with identical identification. IMO, this points to a bug in generic dwarf2 exception handling, in how context is identified. For illustration, I will attach asm dump, object dump and corresponding .eh_frame --dwarf dump of Throw_3.java. [1] http://gcc.gnu.org/ml/gcc-testresults/2011-10/msg01333.html