source: trunk/third/gcc/frame.c @ 11288

Revision 11288, 14.4 KB checked in by ghudson, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r11287, which included commits to RCS files with non-trunk default branches.
Line 
1/* Subroutines needed for unwinding stack frames for exception handling.  */
2/* Compile this one with gcc.  */
3/* Copyright (C) 1997 Free Software Foundation, Inc.
4   Contributed by Jason Merrill <jason@cygnus.com>.
5
6This file is part of GNU CC.
7
8GNU CC is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2, or (at your option)
11any later version.
12
13GNU CC is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU CC; see the file COPYING.  If not, write to
20the Free Software Foundation, 59 Temple Place - Suite 330,
21Boston, MA 02111-1307, USA.  */
22
23/* As a special exception, if you link this library with other files,
24   some of which are compiled with GCC, to produce an executable,
25   this library does not by itself cause the resulting executable
26   to be covered by the GNU General Public License.
27   This exception does not however invalidate any other reasons why
28   the executable file might be covered by the GNU General Public License.  */
29
30/* It is incorrect to include config.h here, because this file is being
31   compiled for the target, and hence definitions concerning only the host
32   do not apply.  */
33
34#include "tconfig.h"
35#include "defaults.h"
36
37#ifdef DWARF2_UNWIND_INFO
38#include "gansidecl.h"
39#include "dwarf2.h"
40#include <stddef.h>
41#include "frame.h"
42
43/* Don't use `fancy_abort' here even if config.h says to use it.  */
44#ifdef abort
45#undef abort
46#endif
47
48/* Some types used by the DWARF 2 spec.  */
49
50typedef          int  sword __attribute__ ((mode (SI)));
51typedef unsigned int  uword __attribute__ ((mode (SI)));
52typedef unsigned int  uaddr __attribute__ ((mode (pointer)));
53typedef          int  saddr __attribute__ ((mode (pointer)));
54typedef unsigned char ubyte;
55
56/* The first few fields of a CIE.  The CIE_id field is 0xffffffff for a CIE,
57   to distinguish it from a valid FDE.  FDEs are aligned to an addressing
58   unit boundary, but the fields within are unaligned.  */
59
60struct dwarf_cie {
61  uword length;
62  sword CIE_id;
63  ubyte version;
64  char augmentation[0];
65} __attribute__ ((packed, aligned (__alignof__ (void *))));
66
67/* The first few fields of an FDE.  */
68
69struct dwarf_fde {
70  uword length;
71  sword CIE_delta;
72  void* pc_begin;
73  uaddr pc_range;
74} __attribute__ ((packed, aligned (__alignof__ (void *))));
75
76typedef struct dwarf_fde fde;
77
78/* Objects to be searched for frame unwind info.  */
79
80static struct object *objects;
81
82/* The information we care about from a CIE.  */
83
84struct cie_info {
85  char *augmentation;
86  void *eh_ptr;
87  int code_align;
88  int data_align;
89  unsigned ra_regno;
90};
91
92/* The current unwind state, plus a saved copy for DW_CFA_remember_state.  */
93
94struct frame_state_internal
95{
96  struct frame_state s;
97  struct frame_state_internal *saved_state;
98};
99 
100/* Decode the unsigned LEB128 constant at BUF into the variable pointed to
101   by R, and return the new value of BUF.  */
102
103static void *
104decode_uleb128 (unsigned char *buf, unsigned *r)
105{
106  unsigned shift = 0;
107  unsigned result = 0;
108
109  while (1)
110    {
111      unsigned byte = *buf++;
112      result |= (byte & 0x7f) << shift;
113      if ((byte & 0x80) == 0)
114        break;
115      shift += 7;
116    }
117  *r = result;
118  return buf;
119}
120
121/* Decode the signed LEB128 constant at BUF into the variable pointed to
122   by R, and return the new value of BUF.  */
123
124static void *
125decode_sleb128 (unsigned char *buf, int *r)
126{
127  unsigned shift = 0;
128  unsigned result = 0;
129  unsigned byte;
130
131  while (1)
132    {
133      byte = *buf++;
134      result |= (byte & 0x7f) << shift;
135      shift += 7;
136      if ((byte & 0x80) == 0)
137        break;
138    }
139  if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
140    result |= - (1 << shift);
141
142  *r = result;
143  return buf;
144}
145
146/* Read unaligned data from the instruction buffer.  */
147
148union unaligned {
149  void *p;
150  unsigned b2 __attribute__ ((mode (HI)));
151  unsigned b4 __attribute__ ((mode (SI)));
152  unsigned b8 __attribute__ ((mode (DI)));
153} __attribute__ ((packed));
154static inline void *
155read_pointer (void *p)
156{ union unaligned *up = p; return up->p; }
157static inline unsigned
158read_1byte (void *p)
159{ return *(unsigned char *)p; }
160static inline unsigned
161read_2byte (void *p)
162{ union unaligned *up = p; return up->b2; }
163static inline unsigned
164read_4byte (void *p)
165{ union unaligned *up = p; return up->b4; }
166static inline unsigned long
167read_8byte (void *p)
168{ union unaligned *up = p; return up->b8; }
169
170/* Ordering function for FDEs.  Functions can't overlap, so we just compare
171   their starting addresses.  */
172
173static inline saddr
174fde_compare (fde *x, fde *y)
175{
176  return (saddr)x->pc_begin - (saddr)y->pc_begin;
177}
178
179/* Return the address of the FDE after P.  */
180
181static inline fde *
182next_fde (fde *p)
183{
184  return (fde *)(((char *)p) + p->length + sizeof (p->length));
185}
186
187/* One iteration of an insertion sort, for adding new FDEs to the array.
188   Usually the new FDE will go in at the end, so we can expect close to
189   O(n) performance.  If this turns out to be overly optimistic, we can have
190   the linker sort the FDEs so we don't have to do it at run time.  */
191
192static void
193fde_insert (fde **array, size_t i, fde *this_fde)
194{
195  array[i] = this_fde;
196
197  for (; i > 0 && fde_compare (array[i], array[i-1]) < 0; --i)
198    {
199      this_fde = array[i];
200      array[i] = array[i-1];
201      array[i-1] = this_fde;
202    }
203}
204
205static size_t
206count_fdes (fde *this_fde)
207{
208  size_t count;
209
210  for (count = 0; this_fde->length != 0; this_fde = next_fde (this_fde))
211    {
212      /* Skip CIEs and linked once FDE entries.  */
213      if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
214        continue;
215
216      ++count;
217    }
218
219  return count;
220}
221
222static void
223add_fdes (fde *this_fde, fde **array, size_t *i_ptr,
224          void **beg_ptr, void **end_ptr)
225{
226  size_t i = *i_ptr;
227  void *pc_begin = *beg_ptr;
228  void *pc_end = *end_ptr;
229
230  for (; this_fde->length != 0; this_fde = next_fde (this_fde))
231    {
232      /* Skip CIEs and linked once FDE entries.  */
233      if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
234        continue;
235
236      fde_insert (array, i++, this_fde);
237
238      if (this_fde->pc_begin < pc_begin)
239        pc_begin = this_fde->pc_begin;
240      if (this_fde->pc_begin + this_fde->pc_range > pc_end)
241        pc_end = this_fde->pc_begin + this_fde->pc_range;
242    }
243
244  *i_ptr = i;
245  *beg_ptr = pc_begin;
246  *end_ptr = pc_end;
247}
248
249/* Set up a sorted array of pointers to FDEs for a loaded object.  We
250   count up the entries before allocating the array because it's likely to
251   be faster.  */
252
253static void
254frame_init (struct object* ob)
255{
256  fde *this_fde;
257  size_t count;
258  fde **array;
259  void *pc_begin, *pc_end;
260
261  if (ob->fde_array)
262    {
263      fde **p = ob->fde_array;
264      for (count = 0; *p; ++p)
265        count += count_fdes (*p);
266    }
267  else
268    count = count_fdes (ob->fde_begin);
269
270  ob->count = count;
271  array = (fde **) malloc (sizeof (fde *) * count);
272
273  pc_begin = (void*)(uaddr)-1;
274  pc_end = 0;
275  count = 0;
276
277  if (ob->fde_array)
278    {
279      fde **p = ob->fde_array;
280      for (; *p; ++p)
281        add_fdes (*p, array, &count, &pc_begin, &pc_end);
282    }
283  else
284    add_fdes (ob->fde_begin, array, &count, &pc_begin, &pc_end);
285
286  ob->fde_array = array;
287  ob->pc_begin = pc_begin;
288  ob->pc_end = pc_end;
289}
290
291/* Return a pointer to the FDE for the function containing PC.  */
292
293static fde *
294find_fde (void *pc)
295{
296  struct object *ob;
297  size_t lo, hi;
298
299  for (ob = objects; ob; ob = ob->next)
300    {
301      if (ob->pc_begin == 0)
302        frame_init (ob);
303      if (pc >= ob->pc_begin && pc < ob->pc_end)
304        break;
305    }
306
307  if (ob == 0)
308    return 0;
309
310  /* Standard binary search algorithm.  */
311  for (lo = 0, hi = ob->count; lo < hi; )
312    {
313      size_t i = (lo + hi) / 2;
314      fde *f = ob->fde_array[i];
315
316      if (pc < f->pc_begin)
317        hi = i;
318      else if (pc > f->pc_begin + f->pc_range)
319        lo = i + 1;
320      else
321        return f;
322    }
323
324  return 0;
325}
326
327static inline struct dwarf_cie *
328get_cie (fde *f)
329{
330  return ((void *)&f->CIE_delta) - f->CIE_delta;
331}
332
333/* Extract any interesting information from the CIE for the translation
334   unit F belongs to.  */
335
336static void *
337extract_cie_info (fde *f, struct cie_info *c)
338{
339  void *p;
340  int i;
341
342  c->augmentation = get_cie (f)->augmentation;
343
344  if (strcmp (c->augmentation, "") != 0
345      && strcmp (c->augmentation, "eh") != 0
346      && c->augmentation[0] != 'z')
347    return 0;
348
349  p = c->augmentation + strlen (c->augmentation) + 1;
350
351  if (strcmp (c->augmentation, "eh") == 0)
352    {
353      c->eh_ptr = read_pointer (p);
354      p += sizeof (void *);
355    }
356  else
357    c->eh_ptr = 0;
358
359  p = decode_uleb128 (p, &c->code_align);
360  p = decode_sleb128 (p, &c->data_align);
361  c->ra_regno = *(unsigned char *)p++;
362
363  /* If the augmentation starts with 'z', we now see the length of the
364     augmentation fields.  */
365  if (c->augmentation[0] == 'z')
366    {
367      p = decode_uleb128 (p, &i);
368      p += i;
369    }
370
371  return p;
372}
373
374/* Decode one instruction's worth of of DWARF 2 call frame information.
375   Used by __frame_state_for.  Takes pointers P to the instruction to
376   decode, STATE to the current register unwind information, INFO to the
377   current CIE information, and PC to the current PC value.  Returns a
378   pointer to the next instruction.  */
379
380static void *
381execute_cfa_insn (void *p, struct frame_state_internal *state,
382                  struct cie_info *info, void **pc)
383{
384  unsigned insn = *(unsigned char *)p++;
385  unsigned reg;
386  int offset;
387
388  if (insn & DW_CFA_advance_loc)
389    *pc += ((insn & 0x3f) * info->code_align);
390  else if (insn & DW_CFA_offset)
391    {
392      reg = (insn & 0x3f);
393      p = decode_uleb128 (p, &offset);
394      offset *= info->data_align;
395      state->s.saved[reg] = REG_SAVED_OFFSET;
396      state->s.reg_or_offset[reg] = offset;
397    }
398  else if (insn & DW_CFA_restore)
399    {
400      reg = (insn & 0x3f);
401      state->s.saved[reg] = REG_UNSAVED;
402    }
403  else switch (insn)
404    {
405    case DW_CFA_set_loc:
406      *pc = read_pointer (p);
407      p += sizeof (void *);
408      break;
409    case DW_CFA_advance_loc1:
410      *pc += read_1byte (p);
411      p += 1;
412      break;
413    case DW_CFA_advance_loc2:
414      *pc += read_2byte (p);
415      p += 2;
416      break;
417    case DW_CFA_advance_loc4:
418      *pc += read_4byte (p);
419      p += 4;
420      break;
421
422    case DW_CFA_offset_extended:
423      p = decode_uleb128 (p, &reg);
424      p = decode_uleb128 (p, &offset);
425      offset *= info->data_align;
426      state->s.saved[reg] = REG_SAVED_OFFSET;
427      state->s.reg_or_offset[reg] = offset;
428      break;
429    case DW_CFA_restore_extended:
430      p = decode_uleb128 (p, &reg);
431      state->s.saved[reg] = REG_UNSAVED;
432      break;
433
434    case DW_CFA_undefined:
435    case DW_CFA_same_value:
436    case DW_CFA_nop:
437      break;
438
439    case DW_CFA_register:
440      {
441        unsigned reg2;
442        p = decode_uleb128 (p, &reg);
443        p = decode_uleb128 (p, &reg2);
444        state->s.saved[reg] = REG_SAVED_REG;
445        state->s.reg_or_offset[reg] = reg2;
446      }
447      break;
448
449    case DW_CFA_def_cfa:
450      p = decode_uleb128 (p, &reg);
451      p = decode_uleb128 (p, &offset);
452      state->s.cfa_reg = reg;
453      state->s.cfa_offset = offset;
454      break;
455    case DW_CFA_def_cfa_register:
456      p = decode_uleb128 (p, &reg);
457      state->s.cfa_reg = reg;
458      break;
459    case DW_CFA_def_cfa_offset:
460      p = decode_uleb128 (p, &offset);
461      state->s.cfa_offset = offset;
462      break;
463     
464    case DW_CFA_remember_state:
465      {
466        struct frame_state_internal *save =
467          (struct frame_state_internal *)
468          malloc (sizeof (struct frame_state_internal));
469        memcpy (save, state, sizeof (struct frame_state_internal));
470        state->saved_state = save;
471      }
472      break;
473    case DW_CFA_restore_state:
474      {
475        struct frame_state_internal *save = state->saved_state;
476        memcpy (state, save, sizeof (struct frame_state_internal));
477        free (save);
478      }
479      break;
480
481      /* FIXME: Hardcoded for SPARC register window configuration.  */
482    case DW_CFA_GNU_window_save:
483      for (reg = 16; reg < 32; ++reg)
484        {
485          state->s.saved[reg] = REG_SAVED_OFFSET;
486          state->s.reg_or_offset[reg] = (reg - 16) * sizeof (void *);
487        }
488      break;
489
490    case DW_CFA_GNU_args_size:
491      p = decode_uleb128 (p, &offset);
492      state->s.args_size = offset;
493      break;
494
495    default:
496      abort ();
497    }
498  return p;
499}
500
501/* Called from crtbegin.o to register the unwind info for an object.  */
502
503void
504__register_frame_info (void *begin, struct object *ob)
505{
506  ob->fde_begin = begin;
507
508  ob->pc_begin = ob->pc_end = 0;
509  ob->fde_array = 0;
510  ob->count = 0;
511
512  ob->next = objects;
513  objects = ob;
514}
515
516/* Similar, but BEGIN is actually a pointer to a table of unwind entries
517   for different translation units.  Called from the file generated by
518   collect2.  */
519
520void
521__register_frame_info_table (void *begin, struct object *ob)
522{
523  ob->fde_begin = begin;
524  ob->fde_array = begin;
525
526  ob->pc_begin = ob->pc_end = 0;
527  ob->count = 0;
528
529  ob->next = objects;
530  objects = ob;
531}
532
533/* Called from crtend.o to deregister the unwind info for an object.  */
534
535void
536__deregister_frame_info (void *begin)
537{
538  struct object **p = &objects;
539
540  while (*p)
541    {
542      if ((*p)->fde_begin == begin)
543        {
544          struct object *ob = *p;
545          *p = (*p)->next;
546
547          /* If we've run init_frame for this object, free the FDE array.  */
548          if (ob->pc_begin)
549            free (ob->fde_array);
550
551          return;
552        }
553      p = &((*p)->next);
554    }
555  abort ();
556}
557
558/* Called from __throw to find the registers to restore for a given
559   PC_TARGET.  The caller should allocate a local variable of `struct
560   frame_state' (declared in frame.h) and pass its address to STATE_IN.  */
561
562struct frame_state *
563__frame_state_for (void *pc_target, struct frame_state *state_in)
564{
565  fde *f;
566  void *insn, *end, *pc;
567  struct cie_info info;
568  struct frame_state_internal state;
569
570  f = find_fde (pc_target);
571  if (f == 0)
572    return 0;
573
574  insn = extract_cie_info (f, &info);
575  if (insn == 0)
576    return 0;
577
578  memset (&state, 0, sizeof (state));
579  state.s.retaddr_column = info.ra_regno;
580  state.s.eh_ptr = info.eh_ptr;
581
582  /* First decode all the insns in the CIE.  */
583  end = next_fde ((fde*) get_cie (f));
584  while (insn < end)
585    insn = execute_cfa_insn (insn, &state, &info, 0);
586
587  insn = ((fde *)f) + 1;
588
589  if (info.augmentation[0] == 'z')
590    {
591      int i;
592      insn = decode_uleb128 (insn, &i);
593      insn += i;
594    }
595
596  /* Then the insns in the FDE up to our target PC.  */
597  end = next_fde (f);
598  pc = f->pc_begin;
599  while (insn < end && pc <= pc_target)
600    insn = execute_cfa_insn (insn, &state, &info, &pc);
601
602  memcpy (state_in, &state.s, sizeof (state.s));
603  return state_in;
604}
605#endif /* DWARF2_UNWIND_INFO */
Note: See TracBrowser for help on using the repository browser.