- New function Buf_Append(), which is given a pointer to a string to
[dragonfly.git] / contrib / gcc / frame.c
1 /* Subroutines needed for unwinding stack frames for exception handling.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
4    Contributed by Jason Merrill <jason@cygnus.com>.
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, 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
36 /* We disable this when inhibit_libc, so that gcc can still be built without
37    needing header files first.  */
38 /* ??? This is not a good solution, since prototypes may be required in
39    some cases for correct code.  See also libgcc2.c.  */
40 #ifndef inhibit_libc
41 /* fixproto guarantees these system headers exist. */
42 #include <stdlib.h>
43 #include <unistd.h>
44 #endif
45
46 #include "defaults.h"
47
48 #ifdef DWARF2_UNWIND_INFO
49 #include "dwarf2.h"
50 #include <stddef.h>
51 #include "frame.h"
52 #include "gthr.h"
53
54 #ifdef __GTHREAD_MUTEX_INIT
55 static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
56 #else
57 static __gthread_mutex_t object_mutex;
58 #endif
59
60 /* Don't use `fancy_abort' here even if config.h says to use it.  */
61 #ifdef abort
62 #undef abort
63 #endif
64
65 /* Some types used by the DWARF 2 spec.  */
66
67 typedef          int  sword __attribute__ ((mode (SI)));
68 typedef unsigned int  uword __attribute__ ((mode (SI)));
69 typedef unsigned int  uaddr __attribute__ ((mode (pointer)));
70 typedef          int  saddr __attribute__ ((mode (pointer)));
71 typedef unsigned char ubyte;
72
73 /* Terminology:
74    CIE - Common Information Element
75    FDE - Frame Descriptor Element
76
77    There is one per function, and it describes where the function code
78    is located, and what the register lifetimes and stack layout are
79    within the function.
80
81    The data structures are defined in the DWARF specfication, although
82    not in a very readable way (see LITERATURE).
83
84    Every time an exception is thrown, the code needs to locate the FDE
85    for the current function, and starts to look for exception regions
86    from that FDE. This works in a two-level search:
87    a) in a linear search, find the shared image (i.e. DLL) containing
88       the PC
89    b) using the FDE table for that shared object, locate the FDE using
90       binary search (which requires the sorting).  */   
91
92 /* The first few fields of a CIE.  The CIE_id field is 0 for a CIE,
93    to distinguish it from a valid FDE.  FDEs are aligned to an addressing
94    unit boundary, but the fields within are unaligned.  */
95
96 struct dwarf_cie {
97   uword length;
98   sword CIE_id;
99   ubyte version;
100   char augmentation[0];
101 } __attribute__ ((packed, aligned (__alignof__ (void *))));
102
103 /* The first few fields of an FDE.  */
104
105 struct dwarf_fde {
106   uword length;
107   sword CIE_delta;
108   void* pc_begin;
109   uaddr pc_range;
110 } __attribute__ ((packed, aligned (__alignof__ (void *))));
111
112 typedef struct dwarf_fde fde;
113
114 /* Objects to be searched for frame unwind info.  */
115
116 static struct object *objects;
117
118 /* The information we care about from a CIE.  */
119
120 struct cie_info {
121   char *augmentation;
122   void *eh_ptr;
123   int code_align;
124   int data_align;
125   unsigned ra_regno;
126 };
127
128 /* The current unwind state, plus a saved copy for DW_CFA_remember_state.  */
129
130 struct frame_state_internal
131 {
132   struct frame_state s;
133   struct frame_state_internal *saved_state;
134 };
135 \f
136 /* This is undefined below if we need it to be an actual function.  */
137 #define init_object_mutex_once()
138
139 #if __GTHREADS
140 #ifdef __GTHREAD_MUTEX_INIT_FUNCTION
141
142 /* Helper for init_object_mutex_once.  */
143
144 static void
145 init_object_mutex (void)
146 {
147   __GTHREAD_MUTEX_INIT_FUNCTION (&object_mutex);
148 }
149
150 /* Call this to arrange to initialize the object mutex.  */
151
152 #undef init_object_mutex_once
153 static void
154 init_object_mutex_once (void)
155 {
156   static __gthread_once_t once = __GTHREAD_ONCE_INIT;
157   __gthread_once (&once, init_object_mutex);
158 }
159
160 #endif /* __GTHREAD_MUTEX_INIT_FUNCTION */
161 #endif /* __GTHREADS */
162 \f  
163 /* Decode the unsigned LEB128 constant at BUF into the variable pointed to
164    by R, and return the new value of BUF.  */
165
166 static void *
167 decode_uleb128 (unsigned char *buf, unsigned *r)
168 {
169   unsigned shift = 0;
170   unsigned result = 0;
171
172   while (1)
173     {
174       unsigned byte = *buf++;
175       result |= (byte & 0x7f) << shift;
176       if ((byte & 0x80) == 0)
177         break;
178       shift += 7;
179     }
180   *r = result;
181   return buf;
182 }
183
184 /* Decode the signed LEB128 constant at BUF into the variable pointed to
185    by R, and return the new value of BUF.  */
186
187 static void *
188 decode_sleb128 (unsigned char *buf, int *r)
189 {
190   unsigned shift = 0;
191   unsigned result = 0;
192   unsigned byte;
193
194   while (1)
195     {
196       byte = *buf++;
197       result |= (byte & 0x7f) << shift;
198       shift += 7;
199       if ((byte & 0x80) == 0)
200         break;
201     }
202   if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
203     result |= - (1 << shift);
204
205   *r = result;
206   return buf;
207 }
208
209 /* Read unaligned data from the instruction buffer.  */
210
211 union unaligned {
212   void *p;
213   unsigned b2 __attribute__ ((mode (HI)));
214   unsigned b4 __attribute__ ((mode (SI)));
215   unsigned b8 __attribute__ ((mode (DI)));
216 } __attribute__ ((packed));
217 static inline void *
218 read_pointer (void *p)
219 { union unaligned *up = p; return up->p; }
220 static inline unsigned
221 read_1byte (void *p)
222 { return *(unsigned char *)p; }
223 static inline unsigned
224 read_2byte (void *p)
225 { union unaligned *up = p; return up->b2; }
226 static inline unsigned
227 read_4byte (void *p)
228 { union unaligned *up = p; return up->b4; }
229 static inline unsigned long
230 read_8byte (void *p)
231 { union unaligned *up = p; return up->b8; }
232 \f
233 /* Ordering function for FDEs.  Functions can't overlap, so we just compare
234    their starting addresses.  */
235
236 static inline saddr
237 fde_compare (fde *x, fde *y)
238 {
239   return (saddr)x->pc_begin - (saddr)y->pc_begin;
240 }
241
242 /* Return the address of the FDE after P.  */
243
244 static inline fde *
245 next_fde (fde *p)
246 {
247   return (fde *)(((char *)p) + p->length + sizeof (p->length));
248 }
249
250 /* Sorting an array of FDEs by address.
251    (Ideally we would have the linker sort the FDEs so we don't have to do
252    it at run time. But the linkers are not yet prepared for this.)  */
253
254 /* This is a special mix of insertion sort and heap sort, optimized for
255    the data sets that actually occur. They look like
256    101 102 103 127 128 105 108 110 190 111 115 119 125 160 126 129 130.
257    I.e. a linearly increasing sequence (coming from functions in the text
258    section), with additionally a few unordered elements (coming from functions
259    in gnu_linkonce sections) whose values are higher than the values in the
260    surrounding linear sequence (but not necessarily higher than the values
261    at the end of the linear sequence!).
262    The worst-case total run time is O(N) + O(n log (n)), where N is the
263    total number of FDEs and n is the number of erratic ones.  */
264
265 typedef struct fde_vector
266 {
267   fde **array;
268   size_t count;
269 } fde_vector;
270
271 typedef struct fde_accumulator
272 {
273   fde_vector linear;
274   fde_vector erratic;
275 } fde_accumulator;
276
277 static inline void
278 start_fde_sort (fde_accumulator *accu, size_t count)
279 {
280   accu->linear.array = (fde **) malloc (sizeof (fde *) * count);
281   accu->erratic.array = (fde **) malloc (sizeof (fde *) * count);
282   accu->linear.count = 0;
283   accu->erratic.count = 0;
284 }
285
286 static inline void
287 fde_insert (fde_accumulator *accu, fde *this_fde)
288 {
289   accu->linear.array[accu->linear.count++] = this_fde;
290 }
291
292 /* Split LINEAR into a linear sequence with low values and an erratic
293    sequence with high values, put the linear one (of longest possible
294    length) into LINEAR and the erratic one into ERRATIC. This is O(N).  */
295 static inline void
296 fde_split (fde_vector *linear, fde_vector *erratic)
297 {
298   size_t count = linear->count;
299   size_t linear_max = (size_t) -1;
300   size_t previous_max[count];
301   size_t i, j;
302
303   for (i = 0; i < count; i++)
304     {
305       for (j = linear_max;
306            j != (size_t) -1
307            && fde_compare (linear->array[i], linear->array[j]) < 0;
308            j = previous_max[j])
309         {
310           erratic->array[erratic->count++] = linear->array[j];
311           linear->array[j] = (fde *) NULL;
312         }
313       previous_max[i] = j;
314       linear_max = i;
315     }
316
317   for (i = 0, j = 0; i < count; i++)
318     if (linear->array[i] != (fde *) NULL)
319       linear->array[j++] = linear->array[i];
320   linear->count = j;
321 }
322
323 /* This is O(n log(n)).  BSD/OS defines heapsort in stdlib.h, so we must
324    use a name that does not conflict.  */
325 static inline void
326 frame_heapsort (fde_vector *erratic)
327 {
328   /* For a description of this algorithm, see:
329      Samuel P. Harbison, Guy L. Steele Jr.: C, a reference manual, 2nd ed.,
330      p. 60-61. */
331   fde ** a = erratic->array;
332   /* A portion of the array is called a "heap" if for all i>=0:
333      If i and 2i+1 are valid indices, then a[i] >= a[2i+1].
334      If i and 2i+2 are valid indices, then a[i] >= a[2i+2]. */
335 #define SWAP(x,y) do { fde * tmp = x; x = y; y = tmp; } while (0)
336   size_t n = erratic->count;
337   size_t m = n;
338   size_t i;
339
340   while (m > 0)
341     {
342       /* Invariant: a[m..n-1] is a heap. */
343       m--;
344       for (i = m; 2*i+1 < n; )
345         {
346           if (2*i+2 < n
347               && fde_compare (a[2*i+2], a[2*i+1]) > 0
348               && fde_compare (a[2*i+2], a[i]) > 0)
349             {
350               SWAP (a[i], a[2*i+2]);
351               i = 2*i+2;
352             }
353           else if (fde_compare (a[2*i+1], a[i]) > 0)
354             {
355               SWAP (a[i], a[2*i+1]);
356               i = 2*i+1;
357             }
358           else
359             break;
360         }
361     }
362   while (n > 1)
363     {
364       /* Invariant: a[0..n-1] is a heap. */
365       n--;
366       SWAP (a[0], a[n]);
367       for (i = 0; 2*i+1 < n; )
368         {
369           if (2*i+2 < n
370               && fde_compare (a[2*i+2], a[2*i+1]) > 0
371               && fde_compare (a[2*i+2], a[i]) > 0)
372             {
373               SWAP (a[i], a[2*i+2]);
374               i = 2*i+2;
375             }
376           else if (fde_compare (a[2*i+1], a[i]) > 0)
377             {
378               SWAP (a[i], a[2*i+1]);
379               i = 2*i+1;
380             }
381           else
382             break;
383         }
384     }
385 #undef SWAP
386 }
387
388 /* Merge V1 and V2, both sorted, and put the result into V1. */
389 static void
390 fde_merge (fde_vector *v1, const fde_vector *v2)
391 {
392   size_t i1, i2;
393   fde * fde2;
394
395   i2 = v2->count;
396   if (i2 > 0)
397     {
398       i1 = v1->count;
399       do {
400         i2--;
401         fde2 = v2->array[i2];
402         while (i1 > 0 && fde_compare (v1->array[i1-1], fde2) > 0)
403           {
404             v1->array[i1+i2] = v1->array[i1-1];
405             i1--;
406           }
407         v1->array[i1+i2] = fde2;
408       } while (i2 > 0);
409       v1->count += v2->count;
410     }
411 }
412
413 static fde **
414 end_fde_sort (fde_accumulator *accu, size_t count)
415 {
416   if (accu->linear.count != count)
417     abort ();
418   fde_split (&accu->linear, &accu->erratic);
419   if (accu->linear.count + accu->erratic.count != count)
420     abort ();
421   frame_heapsort (&accu->erratic);
422   fde_merge (&accu->linear, &accu->erratic);
423   free (accu->erratic.array);
424   return accu->linear.array;
425 }
426
427 static size_t
428 count_fdes (fde *this_fde)
429 {
430   size_t count;
431
432   for (count = 0; this_fde->length != 0; this_fde = next_fde (this_fde))
433     {
434       /* Skip CIEs and linked once FDE entries.  */
435       if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
436         continue;
437
438       ++count;
439     }
440
441   return count;
442 }
443
444 static void
445 add_fdes (fde *this_fde, fde_accumulator *accu, void **beg_ptr, void **end_ptr)
446 {
447   void *pc_begin = *beg_ptr;
448   void *pc_end = *end_ptr;
449
450   for (; this_fde->length != 0; this_fde = next_fde (this_fde))
451     {
452       /* Skip CIEs and linked once FDE entries.  */
453       if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
454         continue;
455
456       fde_insert (accu, this_fde);
457
458       if (this_fde->pc_begin < pc_begin)
459         pc_begin = this_fde->pc_begin;
460       if (this_fde->pc_begin + this_fde->pc_range > pc_end)
461         pc_end = this_fde->pc_begin + this_fde->pc_range;
462     }
463
464   *beg_ptr = pc_begin;
465   *end_ptr = pc_end;
466 }
467
468 /* Set up a sorted array of pointers to FDEs for a loaded object.  We
469    count up the entries before allocating the array because it's likely to
470    be faster.  */
471
472 static void
473 frame_init (struct object* ob)
474 {
475   size_t count;
476   fde_accumulator accu;
477   void *pc_begin, *pc_end;
478
479   if (ob->fde_array)
480     {
481       fde **p = ob->fde_array;
482       for (count = 0; *p; ++p)
483         count += count_fdes (*p);
484     }
485   else
486     count = count_fdes (ob->fde_begin);
487
488   ob->count = count;
489
490   start_fde_sort (&accu, count);
491   pc_begin = (void*)(uaddr)-1;
492   pc_end = 0;
493
494   if (ob->fde_array)
495     {
496       fde **p = ob->fde_array;
497       for (; *p; ++p)
498         add_fdes (*p, &accu, &pc_begin, &pc_end);
499     }
500   else
501     add_fdes (ob->fde_begin, &accu, &pc_begin, &pc_end);
502
503   ob->fde_array = end_fde_sort (&accu, count);
504   ob->pc_begin = pc_begin;
505   ob->pc_end = pc_end;
506 }
507
508 /* Return a pointer to the FDE for the function containing PC.  */
509
510 static fde *
511 find_fde (void *pc)
512 {
513   struct object *ob;
514   size_t lo, hi;
515
516   init_object_mutex_once ();
517   __gthread_mutex_lock (&object_mutex);
518
519   for (ob = objects; ob; ob = ob->next)
520     {
521       if (ob->pc_begin == 0)
522         frame_init (ob);
523       if (pc >= ob->pc_begin && pc < ob->pc_end)
524         break;
525     }
526
527   __gthread_mutex_unlock (&object_mutex);
528
529   if (ob == 0)
530     return 0;
531
532   /* Standard binary search algorithm.  */
533   for (lo = 0, hi = ob->count; lo < hi; )
534     {
535       size_t i = (lo + hi) / 2;
536       fde *f = ob->fde_array[i];
537
538       if (pc < f->pc_begin)
539         hi = i;
540       else if (pc >= f->pc_begin + f->pc_range)
541         lo = i + 1;
542       else
543         return f;
544     }
545
546   return 0;
547 }
548 \f
549 static inline struct dwarf_cie *
550 get_cie (fde *f)
551 {
552   return ((void *)&f->CIE_delta) - f->CIE_delta;
553 }
554
555 /* Extract any interesting information from the CIE for the translation
556    unit F belongs to.  */
557
558 static void *
559 extract_cie_info (fde *f, struct cie_info *c)
560 {
561   void *p;
562   int i;
563
564   c->augmentation = get_cie (f)->augmentation;
565
566   if (strcmp (c->augmentation, "") != 0
567       && strcmp (c->augmentation, "eh") != 0
568       && c->augmentation[0] != 'z')
569     return 0;
570
571   p = c->augmentation + strlen (c->augmentation) + 1;
572
573   if (strcmp (c->augmentation, "eh") == 0)
574     {
575       c->eh_ptr = read_pointer (p);
576       p += sizeof (void *);
577     }
578   else
579     c->eh_ptr = 0;
580
581   p = decode_uleb128 (p, &c->code_align);
582   p = decode_sleb128 (p, &c->data_align);
583   c->ra_regno = *(unsigned char *)p++;
584
585   /* If the augmentation starts with 'z', we now see the length of the
586      augmentation fields.  */
587   if (c->augmentation[0] == 'z')
588     {
589       p = decode_uleb128 (p, &i);
590       p += i;
591     }
592
593   return p;
594 }
595
596 /* Decode one instruction's worth of DWARF 2 call frame information.
597    Used by __frame_state_for.  Takes pointers P to the instruction to
598    decode, STATE to the current register unwind information, INFO to the
599    current CIE information, and PC to the current PC value.  Returns a
600    pointer to the next instruction.  */
601
602 static void *
603 execute_cfa_insn (void *p, struct frame_state_internal *state,
604                   struct cie_info *info, void **pc)
605 {
606   unsigned insn = *(unsigned char *)p++;
607   unsigned reg;
608   int offset;
609
610   if (insn & DW_CFA_advance_loc)
611     *pc += ((insn & 0x3f) * info->code_align);
612   else if (insn & DW_CFA_offset)
613     {
614       reg = (insn & 0x3f);
615       p = decode_uleb128 (p, &offset);
616       offset *= info->data_align;
617       state->s.saved[reg] = REG_SAVED_OFFSET;
618       state->s.reg_or_offset[reg] = offset;
619     }
620   else if (insn & DW_CFA_restore)
621     {
622       reg = (insn & 0x3f);
623       state->s.saved[reg] = REG_UNSAVED;
624     }
625   else switch (insn)
626     {
627     case DW_CFA_set_loc:
628       *pc = read_pointer (p);
629       p += sizeof (void *);
630       break;
631     case DW_CFA_advance_loc1:
632       *pc += read_1byte (p);
633       p += 1;
634       break;
635     case DW_CFA_advance_loc2:
636       *pc += read_2byte (p);
637       p += 2;
638       break;
639     case DW_CFA_advance_loc4:
640       *pc += read_4byte (p);
641       p += 4;
642       break;
643
644     case DW_CFA_offset_extended:
645       p = decode_uleb128 (p, &reg);
646       p = decode_uleb128 (p, &offset);
647       offset *= info->data_align;
648       state->s.saved[reg] = REG_SAVED_OFFSET;
649       state->s.reg_or_offset[reg] = offset;
650       break;
651     case DW_CFA_restore_extended:
652       p = decode_uleb128 (p, &reg);
653       state->s.saved[reg] = REG_UNSAVED;
654       break;
655
656     case DW_CFA_undefined:
657     case DW_CFA_same_value:
658     case DW_CFA_nop:
659       break;
660
661     case DW_CFA_register:
662       {
663         unsigned reg2;
664         p = decode_uleb128 (p, &reg);
665         p = decode_uleb128 (p, &reg2);
666         state->s.saved[reg] = REG_SAVED_REG;
667         state->s.reg_or_offset[reg] = reg2;
668       }
669       break;
670
671     case DW_CFA_def_cfa:
672       p = decode_uleb128 (p, &reg);
673       p = decode_uleb128 (p, &offset);
674       state->s.cfa_reg = reg;
675       state->s.cfa_offset = offset;
676       break;
677     case DW_CFA_def_cfa_register:
678       p = decode_uleb128 (p, &reg);
679       state->s.cfa_reg = reg;
680       break;
681     case DW_CFA_def_cfa_offset:
682       p = decode_uleb128 (p, &offset);
683       state->s.cfa_offset = offset;
684       break;
685       
686     case DW_CFA_remember_state:
687       {
688         struct frame_state_internal *save =
689           (struct frame_state_internal *)
690           malloc (sizeof (struct frame_state_internal));
691         memcpy (save, state, sizeof (struct frame_state_internal));
692         state->saved_state = save;
693       }
694       break;
695     case DW_CFA_restore_state:
696       {
697         struct frame_state_internal *save = state->saved_state;
698         memcpy (state, save, sizeof (struct frame_state_internal));
699         free (save);
700       }
701       break;
702
703       /* FIXME: Hardcoded for SPARC register window configuration.  */
704     case DW_CFA_GNU_window_save:
705       for (reg = 16; reg < 32; ++reg)
706         {
707           state->s.saved[reg] = REG_SAVED_OFFSET;
708           state->s.reg_or_offset[reg] = (reg - 16) * sizeof (void *);
709         }
710       break;
711
712     case DW_CFA_GNU_args_size:
713       p = decode_uleb128 (p, &offset);
714       state->s.args_size = offset;
715       break;
716
717     case DW_CFA_GNU_negative_offset_extended:
718       p = decode_uleb128 (p, &reg);
719       p = decode_uleb128 (p, &offset);
720       offset *= info->data_align;
721       state->s.saved[reg] = REG_SAVED_OFFSET;
722       state->s.reg_or_offset[reg] = -offset;
723       break;
724
725     default:
726       abort ();
727     }
728   return p;
729 }
730 \f
731 /* Called from crtbegin.o to register the unwind info for an object.  */
732
733 void
734 __register_frame_info (void *begin, struct object *ob)
735 {
736   ob->fde_begin = begin;
737
738   ob->pc_begin = ob->pc_end = 0;
739   ob->fde_array = 0;
740   ob->count = 0;
741
742   init_object_mutex_once ();
743   __gthread_mutex_lock (&object_mutex);
744
745   ob->next = objects;
746   objects = ob;
747
748   __gthread_mutex_unlock (&object_mutex);
749 }
750
751 void
752 __register_frame (void *begin)
753 {
754   struct object *ob = (struct object *) malloc (sizeof (struct object));
755   __register_frame_info (begin, ob);                       
756 }
757
758 /* Similar, but BEGIN is actually a pointer to a table of unwind entries
759    for different translation units.  Called from the file generated by
760    collect2.  */
761
762 void
763 __register_frame_info_table (void *begin, struct object *ob)
764 {
765   ob->fde_begin = begin;
766   ob->fde_array = begin;
767
768   ob->pc_begin = ob->pc_end = 0;
769   ob->count = 0;
770
771   init_object_mutex_once ();
772   __gthread_mutex_lock (&object_mutex);
773
774   ob->next = objects;
775   objects = ob;
776
777   __gthread_mutex_unlock (&object_mutex);
778 }
779
780 void
781 __register_frame_table (void *begin)
782 {
783   struct object *ob = (struct object *) malloc (sizeof (struct object));
784   __register_frame_info_table (begin, ob);
785 }
786
787 /* Called from crtbegin.o to deregister the unwind info for an object.  */
788
789 void *
790 __deregister_frame_info (void *begin)
791 {
792   struct object **p;
793
794   init_object_mutex_once ();
795   __gthread_mutex_lock (&object_mutex);
796
797   p = &objects;
798   while (*p)
799     {
800       if ((*p)->fde_begin == begin)
801         {
802           struct object *ob = *p;
803           *p = (*p)->next;
804
805           /* If we've run init_frame for this object, free the FDE array.  */
806           if (ob->pc_begin)
807             free (ob->fde_array);
808
809           __gthread_mutex_unlock (&object_mutex);
810           return (void *) ob;
811         }
812       p = &((*p)->next);
813     }
814
815   __gthread_mutex_unlock (&object_mutex);
816   abort ();
817 }
818
819 void
820 __deregister_frame (void *begin)
821 {
822   free (__deregister_frame_info (begin));
823 }
824
825 /* Called from __throw to find the registers to restore for a given
826    PC_TARGET.  The caller should allocate a local variable of `struct
827    frame_state' (declared in frame.h) and pass its address to STATE_IN.  */
828
829 struct frame_state *
830 __frame_state_for (void *pc_target, struct frame_state *state_in)
831 {
832   fde *f;
833   void *insn, *end, *pc;
834   struct cie_info info;
835   struct frame_state_internal state;
836
837   f = find_fde (pc_target);
838   if (f == 0)
839     return 0;
840
841   insn = extract_cie_info (f, &info);
842   if (insn == 0)
843     return 0;
844
845   memset (&state, 0, sizeof (state));
846   state.s.retaddr_column = info.ra_regno;
847   state.s.eh_ptr = info.eh_ptr;
848
849   /* First decode all the insns in the CIE.  */
850   end = next_fde ((fde*) get_cie (f));
851   while (insn < end)
852     insn = execute_cfa_insn (insn, &state, &info, 0);
853
854   insn = ((fde *)f) + 1;
855
856   if (info.augmentation[0] == 'z')
857     {
858       int i;
859       insn = decode_uleb128 (insn, &i);
860       insn += i;
861     }
862
863   /* Then the insns in the FDE up to our target PC.  */
864   end = next_fde (f);
865   pc = f->pc_begin;
866   while (insn < end && pc <= pc_target)
867     insn = execute_cfa_insn (insn, &state, &info, &pc);
868
869   memcpy (state_in, &state.s, sizeof (state.s));
870   return state_in;
871 }
872 #endif /* DWARF2_UNWIND_INFO */