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 | |
---|
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 | #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 | |
---|
50 | typedef int sword __attribute__ ((mode (SI))); |
---|
51 | typedef unsigned int uword __attribute__ ((mode (SI))); |
---|
52 | typedef unsigned int uaddr __attribute__ ((mode (pointer))); |
---|
53 | typedef int saddr __attribute__ ((mode (pointer))); |
---|
54 | typedef 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 | |
---|
60 | struct 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 | |
---|
69 | struct dwarf_fde { |
---|
70 | uword length; |
---|
71 | sword CIE_delta; |
---|
72 | void* pc_begin; |
---|
73 | uaddr pc_range; |
---|
74 | } __attribute__ ((packed, aligned (__alignof__ (void *)))); |
---|
75 | |
---|
76 | typedef struct dwarf_fde fde; |
---|
77 | |
---|
78 | /* Objects to be searched for frame unwind info. */ |
---|
79 | |
---|
80 | static struct object *objects; |
---|
81 | |
---|
82 | /* The information we care about from a CIE. */ |
---|
83 | |
---|
84 | struct 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 | |
---|
94 | struct 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 | |
---|
103 | static void * |
---|
104 | decode_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 | |
---|
124 | static void * |
---|
125 | decode_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 | |
---|
148 | union 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)); |
---|
154 | static inline void * |
---|
155 | read_pointer (void *p) |
---|
156 | { union unaligned *up = p; return up->p; } |
---|
157 | static inline unsigned |
---|
158 | read_1byte (void *p) |
---|
159 | { return *(unsigned char *)p; } |
---|
160 | static inline unsigned |
---|
161 | read_2byte (void *p) |
---|
162 | { union unaligned *up = p; return up->b2; } |
---|
163 | static inline unsigned |
---|
164 | read_4byte (void *p) |
---|
165 | { union unaligned *up = p; return up->b4; } |
---|
166 | static inline unsigned long |
---|
167 | read_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 | |
---|
173 | static inline saddr |
---|
174 | fde_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 | |
---|
181 | static inline fde * |
---|
182 | next_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 | |
---|
192 | static void |
---|
193 | fde_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 | |
---|
205 | static size_t |
---|
206 | count_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 | |
---|
222 | static void |
---|
223 | add_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 | |
---|
253 | static void |
---|
254 | frame_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 | |
---|
293 | static fde * |
---|
294 | find_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 | |
---|
327 | static inline struct dwarf_cie * |
---|
328 | get_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 | |
---|
336 | static void * |
---|
337 | extract_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 | |
---|
380 | static void * |
---|
381 | execute_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, ®); |
---|
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, ®); |
---|
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, ®); |
---|
443 | p = decode_uleb128 (p, ®2); |
---|
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, ®); |
---|
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, ®); |
---|
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 | |
---|
503 | void |
---|
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 | |
---|
520 | void |
---|
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 | |
---|
535 | void |
---|
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 | |
---|
562 | struct 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 */ |
---|