Eric Botcazou - Unwinding through signal handlers on IA-64/Linux (original) (raw)

This is the mail archive of the gcc@gcc.gnu.orgmailing 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]

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]