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

Reply via email to