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
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
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
55static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
56#else
57static __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
67typedef          int  sword __attribute__ ((mode (SI)));
68typedef unsigned int  uword __attribute__ ((mode (SI)));
69typedef unsigned int  uaddr __attribute__ ((mode (pointer)));
70typedef          int  saddr __attribute__ ((mode (pointer)));
71typedef 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
96struct 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
105struct dwarf_fde {
106  uword length;
107  sword CIE_delta;
108  void* pc_begin;
109  uaddr pc_range;
110} __attribute__ ((packed, aligned (__alignof__ (void *))));
111
112typedef struct dwarf_fde fde;
113
114/* Objects to be searched for frame unwind info.  */
115
116static struct object *objects;
117
118/* The information we care about from a CIE.  */
119
120struct 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
130struct frame_state_internal
131{
132  struct frame_state s;
133  struct frame_state_internal *saved_state;
134};
135
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
144static void
145init_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
153static void
154init_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
163/* Decode the unsigned LEB128 constant at BUF into the variable pointed to
164   by R, and return the new value of BUF.  */
165
166static void *
167decode_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
187static void *
188decode_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
211union 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));
217static inline void *
218read_pointer (void *p)
219{ union unaligned *up = p; return up->p; }
220static inline unsigned
221read_1byte (void *p)
222{ return *(unsigned char *)p; }
223static inline unsigned
224read_2byte (void *p)
225{ union unaligned *up = p; return up->b2; }
226static inline unsigned
227read_4byte (void *p)
228{ union unaligned *up = p; return up->b4; }
229static inline unsigned long
230read_8byte (void *p)
231{ union unaligned *up = p; return up->b8; }
232
233/* Ordering function for FDEs.  Functions can't overlap, so we just compare
234   their starting addresses.  */
235
236static inline saddr
237fde_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
244static inline fde *
245next_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
265typedef struct fde_vector
266{
267  fde **array;
268  size_t count;
269} fde_vector;
270
271typedef struct fde_accumulator
272{
273  fde_vector linear;
274  fde_vector erratic;
275} fde_accumulator;
276
277static inline void
278start_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
286static inline void
287fde_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).  */
295static inline void
296fde_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.  */
325static inline void
326frame_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. */
389static void
390fde_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
413static fde **
414end_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
427static size_t
428count_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
444static void
445add_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
472static void
473frame_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
510static fde *
511find_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
549static inline struct dwarf_cie *
550get_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
558static void *
559extract_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
602static void *
603execute_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
731/* Called from crtbegin.o to register the unwind info for an object.  */
732
733void
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
751void
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
762void
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
780void
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
789void *
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
819void
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
829struct 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 */
873