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

[Bug c/13158] New: bad unwind info as a result of sibcall


I have a distinct feeling of deja vue here, but I can't find any previous
discussion around this, so maybe it was never reported.  Anyhow, the problem is
that when GCC applies the sibcall optimization on ia64, it doesn't emit proper
unwind info.  Example:

$ cat bug.c
extern int foo (int);

int main (int argc, char **argv) {
  printf ("hello\n");
  return foo (argc);
}

int foo (int arg) {
  return 0;
}
$ gcc -v
Reading specs from /opt/gcc-pre3.4/lib/gcc/ia64-hp-linux/3.4/specs
Configured with:  : (reconfigured)  : (reconfigured)  : (reconfigured)  :
(reconfigured) 
Thread model: posix
gcc version 3.4 20031121 (experimental)
$ gcc -O2 -c bug.c
$ readelf -u bug.o

Unwind section '.IA_64.unwind' at offset 0xd0 contains 1 entries:

<main>: [0x10-0x70], info at +0x0
  v1, flags=0x0 (), len=8 bytes
    R2:prologue_gr(mask=[rp,ar.pfs],grsave=r33,rlen=5)
        P7:pfs_when(t=0)
        P7:rp_when(t=2)
    R1:body(rlen=13)
$ objdump -d bug.o | tail -19
0000000000000010 <main>:
  10:   0c 10 15 08 80 05       [MFI]       alloc r34=ar.pfs,5,4,0
  16:   00 00 00 02 00 20                   nop.f 0x0
  1c:   04 00 c4 00                         mov r33=b0
  20:   02 20 01 02 00 24       [MII]       addl r36=0,r1
  26:   30 02 04 00 42 00                   mov r35=r1;;
  2c:   00 00 04 00                         nop.i 0x0
  30:   1d 20 01 48 18 10       [MFB]       ld8 r36=[r36]
  36:   00 00 00 02 00 00                   nop.f 0x0
  3c:   08 00 00 50                         br.call.sptk.many b0=30;;
  40:   01 08 00 46 00 21       [MII]       mov r1=r35
  46:   00 08 05 80 03 00                   mov b0=r33
  4c:   20 02 aa 00                         mov.i ar.pfs=r34;;
  50:   1d 10 04 00 80 05       [MFB]       alloc r2=ar.pfs,1,0,0
  56:   00 00 00 02 00 00                   nop.f 0x0
  5c:   08 00 00 40                         br.many 50 <main+0x40>;;
  60:   1d 00 00 00 01 00       [MFB]       nop.m 0x0
  66:   00 00 00 00 00 00                   break.f 0x0
  6c:   00 00 00 20                         nop.b 0x0;;

The problem here is that the unwind info claims that even for the last six
instructions, ar.pfs is saved in r34 and rp in r33.  But after the "alloc"
instruction, those registers are not really valid anymore.  In particular, if
execution gets interrupted anywhere in the last six instructions, the contents
of those no-longer-allocated registers may get clobbered and at that point
unwinding may no longer be possible.

The best fix that I can think of would be to emit

       .restore sp

right before the instruction that restores ar.pfs (i.e., before the 7th-last 
instruction).  That would tell the unwinder that for the last six instructions,
rp and ar.pfs can be found in the default location (and nothing else has been
saved).  Of course, if a function has a memory stack frame, then the .restore sp
will be generated naturally for the instruction that restores the sp, so no such
dummy ".restore sp" directive would be needed.

-- 
           Summary: bad unwind info as a result of sibcall
           Product: gcc
           Version: 3.4
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: davidm at hpl dot hp dot com
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: ia64-hp-linux
  GCC host triplet: ia64-hp-linux
GCC target triplet: ia64-hp-linux


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13158


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