]> gcc.gnu.org Git - gcc.git/blame - gcc/frame.c
configure.in (sched_yield): Try librt first, then libposix4.
[gcc.git] / gcc / frame.c
CommitLineData
0021b564
JM
1/* Subroutines needed for unwinding stack frames for exception handling. */
2/* Compile this one with gcc. */
3e2a2957 3/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
0021b564
JM
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"
2467749d 35
f1f53f0b
JW
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
2467749d
KG
41/* fixproto guarantees these system headers exist. */
42#include <stdlib.h>
43#include <unistd.h>
f1f53f0b 44#endif
2467749d 45
0021b564
JM
46#include "defaults.h"
47
48#ifdef DWARF2_UNWIND_INFO
49#include "dwarf2.h"
0021b564 50#include <stddef.h>
956d6950 51#include "frame.h"
f24af81b 52#include "gthr.h"
154bba13
TT
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
0021b564
JM
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
d84e64d4
JM
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)));
0021b564
JM
71typedef unsigned char ubyte;
72
ccb5954f
ML
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
9605fb44 92/* The first few fields of a CIE. The CIE_id field is 0 for a CIE,
0021b564
JM
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;
d84e64d4 98 sword CIE_id;
0021b564
JM
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;
d84e64d4 107 sword CIE_delta;
0021b564
JM
108 void* pc_begin;
109 uaddr pc_range;
110} __attribute__ ((packed, aligned (__alignof__ (void *))));
111
112typedef struct dwarf_fde fde;
113
956d6950 114/* Objects to be searched for frame unwind info. */
0021b564
JM
115
116static struct object *objects;
117
118/* The information we care about from a CIE. */
119
120struct cie_info {
121 char *augmentation;
d84e64d4 122 void *eh_ptr;
0021b564
JM
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};
3e2a2957
TT
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
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 */
0021b564
JM
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
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\f
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
72dd050a
BH
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}
0021b564 285
72dd050a
BH
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
99b13ed3
JW
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. */
72dd050a 325static inline void
99b13ed3 326frame_heapsort (fde_vector *erratic)
72dd050a
BH
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. */
0021b564 389static void
72dd050a 390fde_merge (fde_vector *v1, const fde_vector *v2)
0021b564 391{
72dd050a
BH
392 size_t i1, i2;
393 fde * fde2;
0021b564 394
72dd050a
BH
395 i2 = v2->count;
396 if (i2 > 0)
0021b564 397 {
72dd050a
BH
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;
0021b564
JM
410 }
411}
412
72dd050a
BH
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 ();
99b13ed3 421 frame_heapsort (&accu->erratic);
72dd050a
BH
422 fde_merge (&accu->linear, &accu->erratic);
423 free (accu->erratic.array);
424 return accu->linear.array;
425}
426
0021b564
JM
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 {
d84e64d4 434 /* Skip CIEs and linked once FDE entries. */
97991933 435 if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
0021b564
JM
436 continue;
437
438 ++count;
439 }
440
441 return count;
442}
443
444static void
72dd050a 445add_fdes (fde *this_fde, fde_accumulator *accu, void **beg_ptr, void **end_ptr)
0021b564 446{
0021b564
JM
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 {
d84e64d4 452 /* Skip CIEs and linked once FDE entries. */
97991933 453 if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
0021b564
JM
454 continue;
455
72dd050a 456 fde_insert (accu, this_fde);
0021b564
JM
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
0021b564
JM
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{
0021b564 475 size_t count;
72dd050a 476 fde_accumulator accu;
0021b564
JM
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;
0021b564 489
72dd050a 490 start_fde_sort (&accu, count);
0021b564
JM
491 pc_begin = (void*)(uaddr)-1;
492 pc_end = 0;
0021b564
JM
493
494 if (ob->fde_array)
495 {
496 fde **p = ob->fde_array;
497 for (; *p; ++p)
72dd050a 498 add_fdes (*p, &accu, &pc_begin, &pc_end);
0021b564
JM
499 }
500 else
72dd050a 501 add_fdes (ob->fde_begin, &accu, &pc_begin, &pc_end);
0021b564 502
72dd050a 503 ob->fde_array = end_fde_sort (&accu, count);
0021b564
JM
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
3e2a2957 516 init_object_mutex_once ();
154bba13
TT
517 __gthread_mutex_lock (&object_mutex);
518
0021b564
JM
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
154bba13
TT
527 __gthread_mutex_unlock (&object_mutex);
528
0021b564
JM
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;
db8abea3 540 else if (pc >= f->pc_begin + f->pc_range)
0021b564
JM
541 lo = i + 1;
542 else
543 return f;
544 }
545
546 return 0;
547}
548\f
d84e64d4
JM
549static inline struct dwarf_cie *
550get_cie (fde *f)
551{
552 return ((void *)&f->CIE_delta) - f->CIE_delta;
553}
554
0021b564
JM
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
d84e64d4 564 c->augmentation = get_cie (f)->augmentation;
0021b564
JM
565
566 if (strcmp (c->augmentation, "") != 0
d84e64d4 567 && strcmp (c->augmentation, "eh") != 0
0021b564
JM
568 && c->augmentation[0] != 'z')
569 return 0;
570
571 p = c->augmentation + strlen (c->augmentation) + 1;
572
d84e64d4
JM
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
0021b564
JM
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
38e01259 596/* Decode one instruction's worth of DWARF 2 call frame information.
0021b564
JM
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 default:
718 abort ();
719 }
720 return p;
721}
722\f
723/* Called from crtbegin.o to register the unwind info for an object. */
724
725void
6d8ccdbb 726__register_frame_info (void *begin, struct object *ob)
0021b564 727{
0021b564
JM
728 ob->fde_begin = begin;
729
730 ob->pc_begin = ob->pc_end = 0;
731 ob->fde_array = 0;
732 ob->count = 0;
733
3e2a2957 734 init_object_mutex_once ();
154bba13
TT
735 __gthread_mutex_lock (&object_mutex);
736
0021b564
JM
737 ob->next = objects;
738 objects = ob;
154bba13
TT
739
740 __gthread_mutex_unlock (&object_mutex);
0021b564
JM
741}
742
a3fd4e75
JL
743void
744__register_frame (void *begin)
745{
746 struct object *ob = (struct object *) malloc (sizeof (struct object));
747 __register_frame_info (begin, ob);
748}
749
0021b564
JM
750/* Similar, but BEGIN is actually a pointer to a table of unwind entries
751 for different translation units. Called from the file generated by
752 collect2. */
753
754void
6d8ccdbb 755__register_frame_info_table (void *begin, struct object *ob)
0021b564 756{
0021b564
JM
757 ob->fde_begin = begin;
758 ob->fde_array = begin;
759
760 ob->pc_begin = ob->pc_end = 0;
761 ob->count = 0;
762
3e2a2957 763 init_object_mutex_once ();
154bba13
TT
764 __gthread_mutex_lock (&object_mutex);
765
0021b564
JM
766 ob->next = objects;
767 objects = ob;
154bba13
TT
768
769 __gthread_mutex_unlock (&object_mutex);
0021b564
JM
770}
771
a3fd4e75
JL
772void
773__register_frame_table (void *begin)
774{
775 struct object *ob = (struct object *) malloc (sizeof (struct object));
776 __register_frame_info_table (begin, ob);
777}
778
9605fb44 779/* Called from crtbegin.o to deregister the unwind info for an object. */
0021b564 780
a3fd4e75 781void *
6d8ccdbb 782__deregister_frame_info (void *begin)
0021b564 783{
154bba13 784 struct object **p;
0021b564 785
3e2a2957 786 init_object_mutex_once ();
154bba13
TT
787 __gthread_mutex_lock (&object_mutex);
788
789 p = &objects;
0021b564
JM
790 while (*p)
791 {
792 if ((*p)->fde_begin == begin)
793 {
794 struct object *ob = *p;
795 *p = (*p)->next;
796
6d53d7c2
JM
797 /* If we've run init_frame for this object, free the FDE array. */
798 if (ob->pc_begin)
0021b564 799 free (ob->fde_array);
0021b564 800
154bba13 801 __gthread_mutex_unlock (&object_mutex);
a3fd4e75 802 return (void *) ob;
0021b564
JM
803 }
804 p = &((*p)->next);
805 }
154bba13
TT
806
807 __gthread_mutex_unlock (&object_mutex);
0021b564
JM
808 abort ();
809}
810
a3fd4e75
JL
811void
812__deregister_frame (void *begin)
813{
814 free (__deregister_frame_info (begin));
815}
816
0021b564
JM
817/* Called from __throw to find the registers to restore for a given
818 PC_TARGET. The caller should allocate a local variable of `struct
819 frame_state' (declared in frame.h) and pass its address to STATE_IN. */
820
821struct frame_state *
822__frame_state_for (void *pc_target, struct frame_state *state_in)
823{
824 fde *f;
825 void *insn, *end, *pc;
826 struct cie_info info;
827 struct frame_state_internal state;
828
829 f = find_fde (pc_target);
830 if (f == 0)
831 return 0;
832
833 insn = extract_cie_info (f, &info);
834 if (insn == 0)
835 return 0;
836
837 memset (&state, 0, sizeof (state));
838 state.s.retaddr_column = info.ra_regno;
d84e64d4 839 state.s.eh_ptr = info.eh_ptr;
0021b564
JM
840
841 /* First decode all the insns in the CIE. */
d84e64d4 842 end = next_fde ((fde*) get_cie (f));
0021b564
JM
843 while (insn < end)
844 insn = execute_cfa_insn (insn, &state, &info, 0);
845
846 insn = ((fde *)f) + 1;
847
848 if (info.augmentation[0] == 'z')
849 {
850 int i;
851 insn = decode_uleb128 (insn, &i);
852 insn += i;
853 }
0021b564
JM
854
855 /* Then the insns in the FDE up to our target PC. */
856 end = next_fde (f);
857 pc = f->pc_begin;
13ab2b83 858 while (insn < end && pc <= pc_target)
0021b564
JM
859 insn = execute_cfa_insn (insn, &state, &info, &pc);
860
861 memcpy (state_in, &state.s, sizeof (state.s));
862 return state_in;
863}
864#endif /* DWARF2_UNWIND_INFO */
This page took 0.435269 seconds and 5 git commands to generate.