]> git.pld-linux.org Git - packages/gcc.git/blob - gcc-unwind-through-signal-frames.patch
- up to 4.1.2 final
[packages/gcc.git] / gcc-unwind-through-signal-frames.patch
1 --- gcc/unwind-compat.c (revision 111580)
2 +++ gcc/unwind-compat.c (revision 111581)
3 @@ -136,6 +136,13 @@
4  }
5  symver (_Unwind_GetIP, GCC_3.0);
6  
7 +_Unwind_Ptr
8 +_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
9 +{
10 +  *ip_before_insn = 0;
11 +  return __libunwind_Unwind_GetIP (context);
12 +}
13 +
14  extern void *__libunwind_Unwind_GetLanguageSpecificData
15    (struct _Unwind_Context *);
16  
17 --- gcc/unwind-dw2.c    (revision 111580)
18 +++ gcc/unwind-dw2.c    (revision 111581)
19 @@ -71,6 +71,7 @@
20    void *lsda;
21    struct dwarf_eh_bases bases;
22    _Unwind_Word args_size;
23 +  char signal_frame;
24  };
25  
26  /* Byte size of every register managed by these routines.  */
27 @@ -207,6 +208,16 @@
28    return (_Unwind_Ptr) context->ra;
29  }
30  
31 +/* Retrieve the return address and flag whether that IP is before
32 +   or after first not yet fully executed instruction.  */
33 +
34 +inline _Unwind_Ptr
35 +_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
36 +{
37 +  *ip_before_insn = context->signal_frame != 0;
38 +  return (_Unwind_Ptr) context->ra;
39 +}
40 +
41  /* Overwrite the return address for CONTEXT with VAL.  */
42  
43  inline void
44 @@ -327,6 +338,13 @@
45           aug += 1;
46         }
47  
48 +      /* "S" indicates a signal frame.  */
49 +      else if (aug[0] == 'S')
50 +       {
51 +         fs->signal_frame = 1;
52 +         aug += 1;
53 +       }
54 +
55        /* Otherwise we have an unknown augmentation string.
56          Bail unless we saw a 'z' prefix.  */
57        else
58 @@ -761,8 +779,10 @@
59       a different stack configuration that we are not interested in.  We
60       assume that the call itself is unwind info-neutral; if not, or if
61       there are delay instructions that adjust the stack, these must be
62 -     reflected at the point immediately before the call insn.  */
63 -  while (insn_ptr < insn_end && fs->pc < context->ra)
64 +     reflected at the point immediately before the call insn.
65 +     In signal frames, return address is after last completed instruction,
66 +     so we add 1 to return address to make the comparison <=.  */
67 +  while (insn_ptr < insn_end && fs->pc < context->ra + context->signal_frame)
68      {
69        unsigned char insn = *insn_ptr++;
70        _Unwind_Word reg, utmp;
71 @@ -974,7 +994,8 @@
72    if (context->ra == 0)
73      return _URC_END_OF_STACK;
74  
75 -  fde = _Unwind_Find_FDE (context->ra - 1, &context->bases);
76 +  fde = _Unwind_Find_FDE (context->ra + context->signal_frame - 1,
77 +                         &context->bases);
78    if (fde == NULL)
79      {
80  #ifdef MD_FALLBACK_FRAME_STATE_FOR
81 @@ -1192,6 +1213,8 @@
82         break;
83        }
84  
85 +  context->signal_frame = fs->signal_frame;
86 +
87  #ifdef MD_FROB_UPDATE_CONTEXT
88    MD_FROB_UPDATE_CONTEXT (context, fs);
89  #endif
90 --- gcc/unwind-dw2.h    (revision 111580)
91 +++ gcc/unwind-dw2.h    (revision 111581)
92 @@ -83,6 +83,7 @@
93    unsigned char fde_encoding;
94    unsigned char lsda_encoding;
95    unsigned char saw_z;
96 +  unsigned char signal_frame;
97    void *eh_ptr;
98  } _Unwind_FrameState;
99  
100 --- gcc/unwind-c.c      (revision 111580)
101 +++ gcc/unwind-c.c      (revision 111581)
102 @@ -127,6 +127,7 @@
103    lsda_header_info info;
104    const unsigned char *language_specific_data, *p, *action_record;
105    _Unwind_Ptr landing_pad, ip;
106 +  int ip_before_insn = 0;
107  
108  #ifdef __ARM_EABI_UNWINDER__
109    if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING)
110 @@ -156,7 +157,9 @@
111  
112    /* Parse the LSDA header.  */
113    p = parse_lsda_header (context, language_specific_data, &info);
114 -  ip = _Unwind_GetIP (context) - 1;
115 +  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
116 +  if (! ip_before_insn)
117 +    --ip;
118    landing_pad = 0;
119  
120  #ifdef __USING_SJLJ_EXCEPTIONS__
121 --- gcc/unwind-sjlj.c   (revision 111580)
122 +++ gcc/unwind-sjlj.c   (revision 111581)
123 @@ -214,6 +214,13 @@
124    return context->fc->call_site + 1;
125  }
126  
127 +_Unwind_Ptr
128 +_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
129 +{
130 +  *ip_before_insn = 0;
131 +  return context->fc->call_site + 1;
132 +}
133 +
134  /* Set the return landing pad index in CONTEXT.  */
135  
136  void
137 --- gcc/unwind-generic.h        (revision 111580)
138 +++ gcc/unwind-generic.h        (revision 111581)
139 @@ -155,6 +155,7 @@
140  extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word);
141  
142  extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
143 +extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
144  extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr);
145  
146  /* @@@ Retrieve the CFA of the given context.  */
147 --- gcc/config/s390/linux-unwind.h      (revision 111580)
148 +++ gcc/config/s390/linux-unwind.h      (revision 111581)
149 @@ -113,27 +113,11 @@
150    fs->regs.reg[32].how = REG_SAVED_OFFSET;
151    fs->regs.reg[32].loc.offset = (long)&regs->psw_addr - new_cfa;
152    fs->retaddr_column = 32;
153 +  /* SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr
154 +     after the faulting instruction rather than before it.
155 +     Don't set FS->signal_frame in that case.  */
156 +  if (!signo || (*signo != 4 && *signo != 5 && *signo != 8))
157 +    fs->signal_frame = 1;
158  
159 -  /* If we got a SIGSEGV or a SIGBUS, the PSW address points *to*
160 -     the faulting instruction, not after it.  This causes the logic
161 -     in unwind-dw2.c that decrements the RA to determine the correct
162 -     CFI region to get confused.  To fix that, we *increment* the RA
163 -     here in that case.  Note that we cannot modify the RA in place,
164 -     and the frame state wants a *pointer*, not a value; thus we put
165 -     the modified RA value into the unused register 33 slot of FS and
166 -     have the register 32 save address point to that slot.
167 -
168 -     Unfortunately, for regular signals on old kernels, we don't know
169 -     the signal number.  We default to not fiddling with the RA;
170 -     that can fail in rare cases.  Upgrade your kernel.  */
171 -
172 -  if (signo && (*signo == 11 || *signo == 7))
173 -    {
174 -      fs->regs.reg[33].loc.exp =
175 -       (unsigned char *)regs->psw_addr + 1;
176 -      fs->regs.reg[32].loc.offset =
177 -       (long)&fs->regs.reg[33].loc.exp - new_cfa;
178 -    }
179 -
180    return _URC_NO_REASON;
181  }
182 --- gcc/config/ia64/unwind-ia64.c       (revision 111580)
183 +++ gcc/config/ia64/unwind-ia64.c       (revision 111581)
184 @@ -1704,6 +1704,13 @@
185    return context->rp;
186  }
187  
188 +inline _Unwind_Ptr
189 +_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
190 +{
191 +  *ip_before_insn = 0;
192 +  return context->rp;
193 +}
194 +
195  /* Overwrite the return address for CONTEXT with VAL.  */
196  
197  inline void
198 --- gcc/config/i386/linux-unwind.h      (revision 111580)
199 +++ gcc/config/i386/linux-unwind.h      (revision 111581)
200 @@ -100,6 +100,7 @@
201    fs->regs.reg[16].how = REG_SAVED_OFFSET;
202    fs->regs.reg[16].loc.offset = (long)&sc->rip - new_cfa;
203    fs->retaddr_column = 16;
204 +  fs->signal_frame = 1;
205    return _URC_NO_REASON;
206  }
207  
208 @@ -172,6 +173,7 @@
209    fs->regs.reg[8].how = REG_SAVED_OFFSET;
210    fs->regs.reg[8].loc.offset = (long)&sc->REG_NAME(eip) - new_cfa;
211    fs->retaddr_column = 8;
212 +  fs->signal_frame = 1;
213    return _URC_NO_REASON;
214  }
215  #endif /* not glibc 2.0 */
216 --- gcc/config/rs6000/linux-unwind.h    (revision 111580)
217 +++ gcc/config/rs6000/linux-unwind.h    (revision 111581)
218 @@ -89,26 +89,6 @@
219  
220  enum { SIGNAL_FRAMESIZE = 128 };
221  
222 -/* If the current unwind info (FS) does not contain explicit info
223 -   saving R2, then we have to do a minor amount of code reading to
224 -   figure out if it was saved.  The big problem here is that the
225 -   code that does the save/restore is generated by the linker, so
226 -   we have no good way to determine at compile time what to do.  */
227 -
228 -#define MD_FROB_UPDATE_CONTEXT frob_update_context
229 -
230 -static void
231 -frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
232 -{
233 -  if (fs->regs.reg[2].how == REG_UNSAVED)
234 -    {
235 -      unsigned int *insn
236 -       = (unsigned int *) _Unwind_GetGR (context, LINK_REGISTER_REGNUM);
237 -      if (*insn == 0xE8410028)
238 -       _Unwind_SetGRPtr (context, 2, context->cfa + 40);
239 -    }
240 -}
241 -
242  /* If PC is at a sigreturn trampoline, return a pointer to the
243     regs.  Otherwise return NULL.  */
244  
245 @@ -272,6 +252,7 @@
246    fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET;
247    fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) &regs->nip - new_cfa;
248    fs->retaddr_column = ARG_POINTER_REGNUM;
249 +  fs->signal_frame = 1;
250  
251    if (hwcap == 0)
252      {
253 @@ -322,3 +303,46 @@
254  
255    return _URC_NO_REASON;
256  }
257 +
258 +#define MD_FROB_UPDATE_CONTEXT frob_update_context
259 +
260 +static void
261 +frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
262 +{
263 +  const unsigned int *pc = (const unsigned int *) context->ra;
264 +
265 +  /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't
266 +     have S flag in it.  */
267 +#ifdef __powerpc64__
268 +  /* addi r1, r1, 128; li r0, 0x0077; sc  (sigreturn) */
269 +  /* addi r1, r1, 128; li r0, 0x00AC; sc  (rt_sigreturn) */
270 +  if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE
271 +      && (pc[1] == 0x38000077 || pc[1] == 0x380000AC)
272 +      && pc[2] == 0x44000002)
273 +    context->signal_frame = 1;
274 +#else
275 +  /* li r0, 0x7777; sc  (sigreturn old)  */
276 +  /* li r0, 0x0077; sc  (sigreturn new)  */
277 +  /* li r0, 0x6666; sc  (rt_sigreturn old)  */
278 +  /* li r0, 0x00AC; sc  (rt_sigreturn new)  */
279 +  if ((pc[0] == 0x38007777 || pc[0] == 0x38000077
280 +       || pc[0] == 0x38006666 || pc[0] == 0x380000AC)
281 +      && pc[1] == 0x44000002)
282 +    context->signal_frame = 1;
283 +#endif
284 +
285 +#ifdef __powerpc64__
286 +  if (fs->regs.reg[2].how == REG_UNSAVED)
287 +    {
288 +      /* If the current unwind info (FS) does not contain explicit info
289 +        saving R2, then we have to do a minor amount of code reading to
290 +        figure out if it was saved.  The big problem here is that the
291 +        code that does the save/restore is generated by the linker, so
292 +        we have no good way to determine at compile time what to do.  */
293 +      unsigned int *insn
294 +       = (unsigned int *) _Unwind_GetGR (context, LINK_REGISTER_REGNUM);
295 +      if (*insn == 0xE8410028)
296 +       _Unwind_SetGRPtr (context, 2, context->cfa + 40);
297 +    }
298 +#endif
299 +}
300 --- gcc/config/arm/unwind-arm.h (revision 111580)
301 +++ gcc/config/arm/unwind-arm.h (revision 111581)
302 @@ -250,6 +250,9 @@
303  #define _Unwind_GetIP(context) \
304    (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
305  
306 +#define _Unwind_GetIP(context, ip_before_insn) \
307 +  (*ip_before_insn = 0, _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
308 +
309    static inline void
310    _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val)
311      {
312 --- gcc/libgcc-std.ver  (revision 111580)
313 +++ gcc/libgcc-std.ver  (revision 111581)
314 @@ -256,3 +256,7 @@
315  %inherit GCC_4.1.0 GCC_4.0.0
316  GCC_4.1.0 {
317  }
318 +
319 +GCC_4.2.0 {
320 +  _Unwind_GetIPInfo
321 +}
322 --- libstdc++-v3/libsupc++/eh_personality.cc    (revision 111580)
323 +++ libstdc++-v3/libsupc++/eh_personality.cc    (revision 111581)
324 @@ -365,6 +365,7 @@
325    int handler_switch_value;
326    void* thrown_ptr = ue_header + 1;
327    bool foreign_exception;
328 +  int ip_before_insn = 0;
329  
330  #ifdef __ARM_EABI_UNWINDER__
331    _Unwind_Action actions;
332 @@ -431,7 +432,9 @@
333    // Parse the LSDA header.
334    p = parse_lsda_header (context, language_specific_data, &info);
335    info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
336 -  ip = _Unwind_GetIP (context) - 1;
337 +  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
338 +  if (! ip_before_insn)
339 +    --ip;
340    landing_pad = 0;
341    action_record = 0;
342    handler_switch_value = 0;
343 --- libjava/exception.cc        (revision 111580)
344 +++ libjava/exception.cc        (revision 111581)
345 @@ -197,6 +197,7 @@
346    int handler_switch_value;
347    bool saw_cleanup;
348    bool saw_handler;
349 +  int ip_before_insn = 0;
350  
351  
352    // Interface version check.
353 @@ -212,10 +213,10 @@
354        goto install_context;
355      }
356  
357 -  // FIXME: In Phase 1, record _Unwind_GetIP in xh->obj as a part of
358 +  // FIXME: In Phase 1, record _Unwind_GetIPInfo in xh->obj as a part of
359    // the stack trace for this exception.  This will only collect Java
360    // frames, but perhaps that is acceptable.
361 -  // FIXME2: _Unwind_GetIP is nonsensical for SJLJ, being a call-site
362 +  // FIXME2: _Unwind_GetIPInfo is nonsensical for SJLJ, being a call-site
363    // index instead of a PC value.  We could perhaps arrange for
364    // _Unwind_GetRegionStart to return context->fc->jbuf[1], which
365    // is the address of the handler label for __builtin_longjmp, but
366 @@ -230,7 +231,9 @@
367  
368    // Parse the LSDA header.
369    p = parse_lsda_header (context, language_specific_data, &info);
370 -  ip = _Unwind_GetIP (context) - 1;
371 +  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
372 +  if (! ip_before_insn)
373 +    --ip;
374    landing_pad = 0;
375    action_record = 0;
376    handler_switch_value = 0;
377 --- libjava/include/i386-signal.h       (revision 111580)
378 +++ libjava/include/i386-signal.h       (revision 111581)
379 @@ -22,19 +22,7 @@
380  #define SIGNAL_HANDLER(_name)  \
381  static void _name (int _dummy __attribute__ ((__unused__)))
382  
383 -#define MAKE_THROW_FRAME(_exception)                                   \
384 -do                                                                     \
385 -{                                                                      \
386 -  void **_p = (void **)&_dummy;                                                \
387 -  volatile struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \
388 -                                                                       \
389 -  /* Advance the program counter so that it is after the start of the  \
390 -     instruction:  the x86 exception handler expects                   \
391 -     the PC to point to the instruction after a call. */               \
392 -  _regs->eip += 2;                                                     \
393 -                                                                       \
394 -}                                                                      \
395 -while (0)
396 +#define MAKE_THROW_FRAME(_exception)
397  
398  #define HANDLE_DIVIDE_OVERFLOW                                         \
399  do                                                                     \
400 @@ -91,14 +79,6 @@
401           _regs->eip = (unsigned long)_eip;                             \
402           return;                                                       \
403         }                                                               \
404 -      else                                                             \
405 -       {                                                               \
406 -         /* Advance the program counter so that it is after the start  \
407 -            of the instruction: this is because the x86 exception      \
408 -            handler expects the PC to point to the instruction after a \
409 -            call. */                                                   \
410 -         _regs->eip += 2;                                              \
411 -       }                                                               \
412      }                                                                  \
413  }                                                                      \
414  while (0)
415 --- libjava/include/powerpc-signal.h    (revision 111580)
416 +++ libjava/include/powerpc-signal.h    (revision 111581)
417 @@ -22,18 +22,12 @@
418  #define SIGNAL_HANDLER(_name)                                          \
419    static void _name (int /* _signal */, struct sigcontext *_sc)
420  
421 -/* PPC either leaves PC pointing at a faulting instruction or the
422 -   following instruction, depending on the signal.  SEGV always does
423 -   the former, so we adjust the saved PC to point to the following
424 -   instruction. This is what the handler in libgcc expects.  */
425 +/* MD_FALBACK_FRAME_STATE_FOR takes care of special casing PC
426 +   before the faulting instruction, so we don't need to do anything
427 +   here.  */
428  
429 -#define MAKE_THROW_FRAME(_exception)                                   \
430 -do                                                                     \
431 -  {                                                                    \
432 -    _sc->regs->nip += 4;                                               \
433 -  }                                                                    \
434 -while (0)
435 -  
436 +#define MAKE_THROW_FRAME(_exception)
437 +
438  /* For an explanation why we cannot simply use sigaction to
439     install the handlers, see i386-signal.h.  */
440  
441 --- libjava/include/x86_64-signal.h     (revision 111580)
442 +++ libjava/include/x86_64-signal.h     (revision 111581)
443 @@ -34,17 +34,7 @@
444    };
445  }
446  
447 -#define MAKE_THROW_FRAME(_exception)                                        \
448 -do                                                                          \
449 -{                                                                           \
450 -  /* Advance the program counter so that it is after the start of the       \
451 -     instruction:  the x86_64 exception handler expects                             \
452 -     the PC to point to the instruction after a call. */                    \
453 -  struct ucontext *_uc = (struct ucontext *)_p;                                     \
454 -  volatile struct sigcontext *_sc = (struct sigcontext *) &_uc->uc_mcontext; \
455 -  _sc->rip += 2;                                                            \
456 -}                                                                           \
457 -while (0)
458 +#define MAKE_THROW_FRAME(_exception)
459  
460  #define RESTORE(name, syscall) RESTORE2 (name, syscall)
461  #define RESTORE2(name, syscall)                        \
This page took 0.059931 seconds and 3 git commands to generate.