source: libcfa/src/lsda.h@ e873838

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since e873838 was bf71cfd, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Moved up many directories in source

  • Property mode set to 100644
File size: 6.8 KB
Line 
1//This code was stolen from gcc to read exception tables
2
3
4/* If using C++, references to abort have to be qualified with std::. */
5#if __cplusplus
6#define __gxx_abort std::abort
7#else
8#define __gxx_abort abort
9#endif
10
11/* Pointer encodings, from dwarf2.h. */
12#define DW_EH_PE_absptr 0x00
13#define DW_EH_PE_omit 0xff
14
15#define DW_EH_PE_uleb128 0x01
16#define DW_EH_PE_udata2 0x02
17#define DW_EH_PE_udata4 0x03
18#define DW_EH_PE_udata8 0x04
19#define DW_EH_PE_sleb128 0x09
20#define DW_EH_PE_sdata2 0x0A
21#define DW_EH_PE_sdata4 0x0B
22#define DW_EH_PE_sdata8 0x0C
23#define DW_EH_PE_signed 0x08
24
25#define DW_EH_PE_pcrel 0x10
26#define DW_EH_PE_textrel 0x20
27#define DW_EH_PE_datarel 0x30
28#define DW_EH_PE_funcrel 0x40
29#define DW_EH_PE_aligned 0x50
30
31#define DW_EH_PE_indirect 0x80
32
33
34
35int handler_found = 0;
36
37/* Given an encoding, return the number of bytes the format occupies.
38This is only defined for fixed-size encodings, and so does not
39include leb128. */
40static unsigned int size_of_encoded_value (unsigned char encoding) __attribute__ ((unused));
41
42static unsigned int size_of_encoded_value (unsigned char encoding)
43{
44 if (encoding == DW_EH_PE_omit) return 0;
45
46 switch (encoding & 0x07) {
47 case DW_EH_PE_absptr: return sizeof (void *);
48 case DW_EH_PE_udata2: return 2;
49 case DW_EH_PE_udata4: return 4;
50 case DW_EH_PE_udata8: return 8;
51 }
52 __gxx_abort ();
53}
54
55/* Given an encoding and an _Unwind_Context, return the base to which
56the encoding is relative. This base may then be passed to
57read_encoded_value_with_base for use when the _Unwind_Context is
58not available. */
59static _Unwind_Ptr base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context)
60{
61 if (encoding == DW_EH_PE_omit) return 0;
62
63 switch (encoding & 0x70) {
64 case DW_EH_PE_absptr:
65 case DW_EH_PE_pcrel:
66 case DW_EH_PE_aligned:
67 return 0;
68 case DW_EH_PE_textrel:
69 return _Unwind_GetTextRelBase (context);
70 case DW_EH_PE_datarel:
71 return _Unwind_GetDataRelBase (context);
72 case DW_EH_PE_funcrel:
73 return _Unwind_GetRegionStart (context);
74 }
75 __gxx_abort ();
76}
77
78/* Read an unsigned leb128 value from P, store the value in VAL, return
79P incremented past the value. We assume that a word is large enough to
80hold any value so encoded; if it is smaller than a pointer on some target,
81pointers should not be leb128 encoded on that target. */
82static const unsigned char * read_uleb128 (const unsigned char *p, _uleb128_t *val)
83{
84 unsigned int shift = 0;
85 unsigned char byte;
86 _uleb128_t result;
87
88 result = 0;
89 do
90 {
91 byte = *p++;
92 result |= ((_uleb128_t)byte & 0x7f) << shift;
93 shift += 7;
94 }
95 while (byte & 0x80);
96
97 *val = result;
98 return p;
99}
100
101/* Similar, but read a signed leb128 value. */
102static const unsigned char * read_sleb128 (const unsigned char *p, _sleb128_t *val)
103{
104 unsigned int shift = 0;
105 unsigned char byte;
106 _uleb128_t result;
107
108 result = 0;
109 do
110 {
111 byte = *p++;
112 result |= ((_uleb128_t)byte & 0x7f) << shift;
113 shift += 7;
114 }
115 while (byte & 0x80);
116
117 /* Sign-extend a negative value. */
118 if (shift < 8 * sizeof(result) && (byte & 0x40) != 0) result |= -(((_uleb128_t)1L) << shift);
119
120 *val = (_sleb128_t) result;
121 return p;
122}
123
124/* Load an encoded value from memory at P. The value is returned in VAL;
125The function returns P incremented past the value. BASE is as given
126by base_of_encoded_value for this encoding in the appropriate context. */
127
128static const unsigned char * read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, const unsigned char *p, _Unwind_Ptr *val)
129{
130 union unaligned
131 {
132 void *ptr;
133 unsigned u2 __attribute__ ((mode (HI)));
134 unsigned u4 __attribute__ ((mode (SI)));
135 unsigned u8 __attribute__ ((mode (DI)));
136 signed s2 __attribute__ ((mode (HI)));
137 signed s4 __attribute__ ((mode (SI)));
138 signed s8 __attribute__ ((mode (DI)));
139 } __attribute__((__packed__));
140
141 const union unaligned *u = (const union unaligned *) p;
142 _Unwind_Internal_Ptr result;
143
144 if (encoding == DW_EH_PE_aligned)
145 {
146 _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p;
147 a = (a + sizeof (void *) - 1) & - sizeof(void *);
148 result = *(_Unwind_Internal_Ptr *) a;
149 p = (const unsigned char *) (_Unwind_Internal_Ptr) (a + sizeof (void *));
150 }
151 else
152 {
153 switch (encoding & 0x0f)
154 {
155 case DW_EH_PE_absptr:
156 result = (_Unwind_Internal_Ptr) u->ptr;
157 p += sizeof (void *);
158 break;
159 case DW_EH_PE_uleb128:
160 {
161 _uleb128_t tmp;
162 p = read_uleb128 (p, &tmp);
163 result = (_Unwind_Internal_Ptr) tmp;
164 }
165 break;
166
167 case DW_EH_PE_sleb128:
168 {
169 _sleb128_t tmp;
170 p = read_sleb128 (p, &tmp);
171 result = (_Unwind_Internal_Ptr) tmp;
172 }
173 break;
174
175 case DW_EH_PE_udata2:
176 result = u->u2;
177 p += 2;
178 break;
179 case DW_EH_PE_udata4:
180 result = u->u4;
181 p += 4;
182 break;
183 case DW_EH_PE_udata8:
184 result = u->u8;
185 p += 8;
186 break;
187 case DW_EH_PE_sdata2:
188 result = u->s2;
189 p += 2;
190 break;
191 case DW_EH_PE_sdata4:
192 result = u->s4;
193 p += 4;
194 break;
195 case DW_EH_PE_sdata8:
196 result = u->s8;
197 p += 8;
198 break;
199 default:
200 __gxx_abort();
201 }
202
203 if (result != 0)
204 {
205 result += ((encoding & 0x70) == DW_EH_PE_pcrel ? (_Unwind_Internal_Ptr) u : base);
206
207 if (encoding & DW_EH_PE_indirect) result = *(_Unwind_Internal_Ptr *) result;
208 }
209 }
210
211 *val = result;
212 return p;
213}
214
215/* Like read_encoded_value_with_base, but get the base from the context
216rather than providing it directly. */
217static inline const unsigned char * read_encoded_value (struct _Unwind_Context *context, unsigned char encoding, const unsigned char *p, _Unwind_Ptr *val)
218{
219 return read_encoded_value_with_base (encoding, base_of_encoded_value (encoding, context), p, val);
220}
221
222typedef struct
223{
224 _Unwind_Ptr Start;
225 _Unwind_Ptr LPStart;
226 _Unwind_Ptr ttype_base;
227 const unsigned char *TType;
228 const unsigned char *action_table;
229 unsigned char ttype_encoding;
230 unsigned char call_site_encoding;
231} lsda_header_info;
232
233static const unsigned char * parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p, lsda_header_info *info)
234{
235 _uleb128_t tmp;
236 unsigned char lpstart_encoding;
237
238 info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
239
240 /* Find @LPStart, the base to which landing pad offsets are relative. */
241 lpstart_encoding = *p++;
242 if (lpstart_encoding != DW_EH_PE_omit) p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
243
244 else info->LPStart = info->Start;
245
246 /* Find @TType, the base of the handler and exception spec type data. */
247 info->ttype_encoding = *p++;
248 if (info->ttype_encoding != DW_EH_PE_omit)
249 {
250 p = read_uleb128 (p, &tmp);
251 info->TType = p + tmp;
252 }
253 else info->TType = 0;
254
255 /* The encoding and length of the call-site table; the action table
256 immediately follows. */
257 info->call_site_encoding = *p++;
258 p = read_uleb128 (p, &tmp);
259 info->action_table = p + tmp;
260
261 return p;
262}
Note: See TracBrowser for help on using the repository browser.