1 | /* Subroutines needed for unwinding stack frames for exception handling. */ |
2 | /* Copyright (C) 1997-2022 Free Software Foundation, Inc. |
3 | |
4 | This file is part of the GNU C Library. |
5 | |
6 | The GNU C Library is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Lesser General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2.1 of the License, or (at your option) any later version. |
10 | |
11 | The GNU C Library is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Lesser General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Lesser General Public |
17 | License along with the GNU C Library; if not, see |
18 | <https://www.gnu.org/licenses/>. */ |
19 | |
20 | |
21 | struct fde_vector |
22 | { |
23 | void *orig_data; |
24 | size_t count; |
25 | struct dwarf_fde *array __flexarr; |
26 | }; |
27 | |
28 | #ifdef _LIBC |
29 | #include <gccframe.h> |
30 | #else |
31 | struct object |
32 | { |
33 | void *pc_begin; |
34 | void *tbase; |
35 | void *dbase; |
36 | union { |
37 | struct dwarf_fde *single; |
38 | struct dwarf_fde **array; |
39 | struct fde_vector *sort; |
40 | } u; |
41 | |
42 | union { |
43 | struct { |
44 | unsigned long sorted : 1; |
45 | unsigned long from_array : 1; |
46 | unsigned long mixed_encoding : 1; |
47 | unsigned long encoding : 8; |
48 | /* ??? Wish there was an easy way to detect a 64-bit host here; |
49 | we've got 32 bits left to play with... */ |
50 | unsigned long count : 21; |
51 | } b; |
52 | size_t i; |
53 | } s; |
54 | |
55 | #ifdef DWARF2_OBJECT_END_PTR_EXTENSION |
56 | char *fde_end; |
57 | #endif |
58 | |
59 | struct object *next; |
60 | }; |
61 | #endif |
62 | |
63 | /* This is the original definition of struct object. While the struct |
64 | itself was opaque to users, they did know how large it was, and |
65 | allocate one statically in crtbegin for each DSO. Keep this around |
66 | so that we're aware of the static size limitations for the new struct. */ |
67 | struct old_object |
68 | { |
69 | void *pc_begin; |
70 | void *pc_end; |
71 | struct dwarf_fde *fde_begin; |
72 | struct dwarf_fde **fde_array; |
73 | size_t count; |
74 | struct old_object *next; |
75 | }; |
76 | |
77 | struct dwarf_eh_bases |
78 | { |
79 | void *tbase; |
80 | void *dbase; |
81 | void *func; |
82 | }; |
83 | |
84 | |
85 | extern void __register_frame_info_bases (void *, struct object *, |
86 | void *, void *); |
87 | extern void __register_frame_info (void *, struct object *); |
88 | extern void __register_frame (void *); |
89 | extern void __register_frame_info_table_bases (void *, struct object *, |
90 | void *, void *); |
91 | extern void __register_frame_info_table (void *, struct object *); |
92 | extern void __register_frame_table (void *); |
93 | extern void *__deregister_frame_info (void *); |
94 | extern void *__deregister_frame_info_bases (void *); |
95 | extern void __deregister_frame (void *); |
96 | |
97 | |
98 | typedef int sword __attribute__ ((mode (SI))); |
99 | typedef unsigned int uword __attribute__ ((mode (SI))); |
100 | typedef unsigned int uaddr __attribute__ ((mode (pointer))); |
101 | typedef int saddr __attribute__ ((mode (pointer))); |
102 | typedef unsigned char ubyte; |
103 | |
104 | /* Terminology: |
105 | CIE - Common Information Element |
106 | FDE - Frame Descriptor Element |
107 | |
108 | There is one per function, and it describes where the function code |
109 | is located, and what the register lifetimes and stack layout are |
110 | within the function. |
111 | |
112 | The data structures are defined in the DWARF specification, although |
113 | not in a very readable way (see LITERATURE). |
114 | |
115 | Every time an exception is thrown, the code needs to locate the FDE |
116 | for the current function, and starts to look for exception regions |
117 | from that FDE. This works in a two-level search: |
118 | a) in a linear search, find the shared image (i.e. DLL) containing |
119 | the PC |
120 | b) using the FDE table for that shared object, locate the FDE using |
121 | binary search (which requires the sorting). */ |
122 | |
123 | /* The first few fields of a CIE. The CIE_id field is 0 for a CIE, |
124 | to distinguish it from a valid FDE. FDEs are aligned to an addressing |
125 | unit boundary, but the fields within are unaligned. */ |
126 | struct dwarf_cie |
127 | { |
128 | uword length; |
129 | sword CIE_id; |
130 | ubyte version; |
131 | unsigned char augmentation __flexarr; |
132 | } __attribute__ ((packed, aligned (__alignof__ (void *)))); |
133 | |
134 | /* The first few fields of an FDE. */ |
135 | struct dwarf_fde |
136 | { |
137 | uword length; |
138 | sword CIE_delta; |
139 | unsigned char pc_begin __flexarr; |
140 | } __attribute__ ((packed, aligned (__alignof__ (void *)))); |
141 | |
142 | typedef struct dwarf_fde fde; |
143 | |
144 | /* Locate the CIE for a given FDE. */ |
145 | |
146 | static inline struct dwarf_cie * |
147 | get_cie (struct dwarf_fde *f) |
148 | { |
149 | return (void *)&f->CIE_delta - f->CIE_delta; |
150 | } |
151 | |
152 | static inline fde * |
153 | next_fde (fde *f) |
154 | { |
155 | return (fde *) ((char *) f + f->length + sizeof (f->length)); |
156 | } |
157 | |
158 | extern fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *); |
159 | |
160 | static inline int |
161 | last_fde (struct object *obj __attribute__ ((__unused__)), fde *f) |
162 | { |
163 | #ifdef DWARF2_OBJECT_END_PTR_EXTENSION |
164 | return (char *)f == obj->fde_end || f->length == 0; |
165 | #else |
166 | return f->length == 0; |
167 | #endif |
168 | } |
169 | |