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;