This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Unwinding through signal handlers on IA-64/Linux


Hi,

It works if the unwind library is HP's libunwind (aka system libunwind) but 
doesn't if the unwind library is the bundled one (config/ia64/unwind-ia64.c).
That's with a 3.4.5pre-based compiler on SLES 9, but the problem is very 
likely present on all branches.

The bottom line is that the CFM register is incorrectly restored: it is loaded 
with the value of the AR.PFS register when the signal is raised.

Breakpoint 3, 0x4000000000003300 in _ada_p ()
(gdb) info reg cfm
cfm            0x287    647
(gdb) info reg pfs
pfs            0xc000000000000388       -4611686018427387000
(gdb) continue
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x4000000000003300 in _ada_p ()
(gdb)
Continuing.

Breakpoint 1, 0x40000000000033f2 in _ada_p ()
(gdb) info reg cfm
cfm            0x388    904


Debug session with the same executable using HP's libunwind:

Breakpoint 3, 0x4000000000003300 in _ada_p ()
(gdb) info reg cfm
cfm            0x287    647
(gdb) info reg pfs
pfs            0xc000000000000388       -4611686018427387000
(gdb) continue
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x4000000000003300 in _ada_p ()
(gdb)
Continuing.

Breakpoint 1, 0x40000000000033f2 in _ada_p ()
(gdb) info reg cfm
cfm            0x287    647


Now the unwinder gets it almost right, that is fs->curr.reg[UNW_REG_PFS] holds 
the right values (val = 224, where = UNW_WHERE_SPREL, when = -1).  But there 
are these lines in ia64_handle_unwabi:

      /* pfs_loc already set above.  Without this pfs_loc would point
	 incorrectly to sc_cfm instead of sc_ar_pfs.  */
      fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE;

The problem is that we want pfs_loc to essentially[1] point to sc_cfm, which 
is the saved CFM in the signal context, because we use the target AR.PFS to 
restore the CFM with the help of br.ret; we certainly don't want it to point 
to the saved AR.PFS in the signal context, which is a dead value if a 
register frame has been allocated[2].

These lines look very questionable to me; if they are removed, all works fine 
for the attached testcase (compile with -gnatp).  Maybe some confusion comes 
from

      context->pfs_loc = &(sc->sc_ar_pfs);

a few lines above, which is a dead statement if considered alone.

Can anyone shed some light on this?  Thanks in advance.


[1] essentially because we probably would want pfs_loc to point to a CFM+EC 
value.  But I skimmed through HP's libunwind and I didn't find any attempt to 
put together a full AR.PFS value from saved CFM and EC.

[2] if a register frame has not been allocated then AR.PFS is live in the 
procedure and would need to be restored too.  Incidentally, the current code 
probably works in that case, but I think it cannot happen in practice.

-- 
Eric Botcazou
with Ada.Text_IO;

procedure P is
   type Int_Ptr is access all Integer;
   Data : Int_Ptr := null;
begin
   Data.all := 0;
exception
   when others =>
      Ada.Text_IO.Put_Line ("Exception handled");
end P;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]