1*38fd1498Szrj /* Exception handling and frame unwind runtime interface routines.
2*38fd1498Szrj Copyright (C) 2001-2018 Free Software Foundation, Inc.
3*38fd1498Szrj
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it
7*38fd1498Szrj under the terms of the GNU General Public License as published by
8*38fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj any later version.
10*38fd1498Szrj
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT
12*38fd1498Szrj ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13*38fd1498Szrj or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14*38fd1498Szrj License for more details.
15*38fd1498Szrj
16*38fd1498Szrj Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj
20*38fd1498Szrj You should have received a copy of the GNU General Public License and
21*38fd1498Szrj a copy of the GCC Runtime Library Exception along with this program;
22*38fd1498Szrj see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23*38fd1498Szrj <http://www.gnu.org/licenses/>. */
24*38fd1498Szrj
25*38fd1498Szrj /* @@@ Really this should be out of line, but this also causes link
26*38fd1498Szrj compatibility problems with the base ABI. This is slightly better
27*38fd1498Szrj than duplicating code, however. */
28*38fd1498Szrj
29*38fd1498Szrj #ifndef GCC_UNWIND_PE_H
30*38fd1498Szrj #define GCC_UNWIND_PE_H
31*38fd1498Szrj
32*38fd1498Szrj /* If using C++, references to abort have to be qualified with std::. */
33*38fd1498Szrj #if __cplusplus
34*38fd1498Szrj #define __gxx_abort std::abort
35*38fd1498Szrj #else
36*38fd1498Szrj #define __gxx_abort abort
37*38fd1498Szrj #endif
38*38fd1498Szrj
39*38fd1498Szrj /* Pointer encodings, from dwarf2.h. */
40*38fd1498Szrj #define DW_EH_PE_absptr 0x00
41*38fd1498Szrj #define DW_EH_PE_omit 0xff
42*38fd1498Szrj
43*38fd1498Szrj #define DW_EH_PE_uleb128 0x01
44*38fd1498Szrj #define DW_EH_PE_udata2 0x02
45*38fd1498Szrj #define DW_EH_PE_udata4 0x03
46*38fd1498Szrj #define DW_EH_PE_udata8 0x04
47*38fd1498Szrj #define DW_EH_PE_sleb128 0x09
48*38fd1498Szrj #define DW_EH_PE_sdata2 0x0A
49*38fd1498Szrj #define DW_EH_PE_sdata4 0x0B
50*38fd1498Szrj #define DW_EH_PE_sdata8 0x0C
51*38fd1498Szrj #define DW_EH_PE_signed 0x08
52*38fd1498Szrj
53*38fd1498Szrj #define DW_EH_PE_pcrel 0x10
54*38fd1498Szrj #define DW_EH_PE_textrel 0x20
55*38fd1498Szrj #define DW_EH_PE_datarel 0x30
56*38fd1498Szrj #define DW_EH_PE_funcrel 0x40
57*38fd1498Szrj #define DW_EH_PE_aligned 0x50
58*38fd1498Szrj
59*38fd1498Szrj #define DW_EH_PE_indirect 0x80
60*38fd1498Szrj
61*38fd1498Szrj
62*38fd1498Szrj #ifndef NO_SIZE_OF_ENCODED_VALUE
63*38fd1498Szrj
64*38fd1498Szrj /* Given an encoding, return the number of bytes the format occupies.
65*38fd1498Szrj This is only defined for fixed-size encodings, and so does not
66*38fd1498Szrj include leb128. */
67*38fd1498Szrj
68*38fd1498Szrj static unsigned int
69*38fd1498Szrj size_of_encoded_value (unsigned char encoding) __attribute__ ((unused));
70*38fd1498Szrj
71*38fd1498Szrj static unsigned int
size_of_encoded_value(unsigned char encoding)72*38fd1498Szrj size_of_encoded_value (unsigned char encoding)
73*38fd1498Szrj {
74*38fd1498Szrj if (encoding == DW_EH_PE_omit)
75*38fd1498Szrj return 0;
76*38fd1498Szrj
77*38fd1498Szrj switch (encoding & 0x07)
78*38fd1498Szrj {
79*38fd1498Szrj case DW_EH_PE_absptr:
80*38fd1498Szrj return sizeof (void *);
81*38fd1498Szrj case DW_EH_PE_udata2:
82*38fd1498Szrj return 2;
83*38fd1498Szrj case DW_EH_PE_udata4:
84*38fd1498Szrj return 4;
85*38fd1498Szrj case DW_EH_PE_udata8:
86*38fd1498Szrj return 8;
87*38fd1498Szrj }
88*38fd1498Szrj __gxx_abort ();
89*38fd1498Szrj }
90*38fd1498Szrj
91*38fd1498Szrj #endif
92*38fd1498Szrj
93*38fd1498Szrj #ifndef NO_BASE_OF_ENCODED_VALUE
94*38fd1498Szrj
95*38fd1498Szrj /* Given an encoding and an _Unwind_Context, return the base to which
96*38fd1498Szrj the encoding is relative. This base may then be passed to
97*38fd1498Szrj read_encoded_value_with_base for use when the _Unwind_Context is
98*38fd1498Szrj not available. */
99*38fd1498Szrj
100*38fd1498Szrj static _Unwind_Ptr
base_of_encoded_value(unsigned char encoding,struct _Unwind_Context * context)101*38fd1498Szrj base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context)
102*38fd1498Szrj {
103*38fd1498Szrj if (encoding == DW_EH_PE_omit)
104*38fd1498Szrj return 0;
105*38fd1498Szrj
106*38fd1498Szrj switch (encoding & 0x70)
107*38fd1498Szrj {
108*38fd1498Szrj case DW_EH_PE_absptr:
109*38fd1498Szrj case DW_EH_PE_pcrel:
110*38fd1498Szrj case DW_EH_PE_aligned:
111*38fd1498Szrj return 0;
112*38fd1498Szrj
113*38fd1498Szrj case DW_EH_PE_textrel:
114*38fd1498Szrj return _Unwind_GetTextRelBase (context);
115*38fd1498Szrj case DW_EH_PE_datarel:
116*38fd1498Szrj return _Unwind_GetDataRelBase (context);
117*38fd1498Szrj case DW_EH_PE_funcrel:
118*38fd1498Szrj return _Unwind_GetRegionStart (context);
119*38fd1498Szrj }
120*38fd1498Szrj __gxx_abort ();
121*38fd1498Szrj }
122*38fd1498Szrj
123*38fd1498Szrj #endif
124*38fd1498Szrj
125*38fd1498Szrj /* Read an unsigned leb128 value from P, store the value in VAL, return
126*38fd1498Szrj P incremented past the value. We assume that a word is large enough to
127*38fd1498Szrj hold any value so encoded; if it is smaller than a pointer on some target,
128*38fd1498Szrj pointers should not be leb128 encoded on that target. */
129*38fd1498Szrj
130*38fd1498Szrj static const unsigned char *
read_uleb128(const unsigned char * p,_uleb128_t * val)131*38fd1498Szrj read_uleb128 (const unsigned char *p, _uleb128_t *val)
132*38fd1498Szrj {
133*38fd1498Szrj unsigned int shift = 0;
134*38fd1498Szrj unsigned char byte;
135*38fd1498Szrj _uleb128_t result;
136*38fd1498Szrj
137*38fd1498Szrj result = 0;
138*38fd1498Szrj do
139*38fd1498Szrj {
140*38fd1498Szrj byte = *p++;
141*38fd1498Szrj result |= ((_uleb128_t)byte & 0x7f) << shift;
142*38fd1498Szrj shift += 7;
143*38fd1498Szrj }
144*38fd1498Szrj while (byte & 0x80);
145*38fd1498Szrj
146*38fd1498Szrj *val = result;
147*38fd1498Szrj return p;
148*38fd1498Szrj }
149*38fd1498Szrj
150*38fd1498Szrj /* Similar, but read a signed leb128 value. */
151*38fd1498Szrj
152*38fd1498Szrj static const unsigned char *
read_sleb128(const unsigned char * p,_sleb128_t * val)153*38fd1498Szrj read_sleb128 (const unsigned char *p, _sleb128_t *val)
154*38fd1498Szrj {
155*38fd1498Szrj unsigned int shift = 0;
156*38fd1498Szrj unsigned char byte;
157*38fd1498Szrj _uleb128_t result;
158*38fd1498Szrj
159*38fd1498Szrj result = 0;
160*38fd1498Szrj do
161*38fd1498Szrj {
162*38fd1498Szrj byte = *p++;
163*38fd1498Szrj result |= ((_uleb128_t)byte & 0x7f) << shift;
164*38fd1498Szrj shift += 7;
165*38fd1498Szrj }
166*38fd1498Szrj while (byte & 0x80);
167*38fd1498Szrj
168*38fd1498Szrj /* Sign-extend a negative value. */
169*38fd1498Szrj if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
170*38fd1498Szrj result |= -(((_uleb128_t)1L) << shift);
171*38fd1498Szrj
172*38fd1498Szrj *val = (_sleb128_t) result;
173*38fd1498Szrj return p;
174*38fd1498Szrj }
175*38fd1498Szrj
176*38fd1498Szrj /* Load an encoded value from memory at P. The value is returned in VAL;
177*38fd1498Szrj The function returns P incremented past the value. BASE is as given
178*38fd1498Szrj by base_of_encoded_value for this encoding in the appropriate context. */
179*38fd1498Szrj
180*38fd1498Szrj static const unsigned char *
read_encoded_value_with_base(unsigned char encoding,_Unwind_Ptr base,const unsigned char * p,_Unwind_Ptr * val)181*38fd1498Szrj read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
182*38fd1498Szrj const unsigned char *p, _Unwind_Ptr *val)
183*38fd1498Szrj {
184*38fd1498Szrj union unaligned
185*38fd1498Szrj {
186*38fd1498Szrj void *ptr;
187*38fd1498Szrj unsigned u2 __attribute__ ((mode (HI)));
188*38fd1498Szrj unsigned u4 __attribute__ ((mode (SI)));
189*38fd1498Szrj unsigned u8 __attribute__ ((mode (DI)));
190*38fd1498Szrj signed s2 __attribute__ ((mode (HI)));
191*38fd1498Szrj signed s4 __attribute__ ((mode (SI)));
192*38fd1498Szrj signed s8 __attribute__ ((mode (DI)));
193*38fd1498Szrj } __attribute__((__packed__));
194*38fd1498Szrj
195*38fd1498Szrj const union unaligned *u = (const union unaligned *) p;
196*38fd1498Szrj _Unwind_Internal_Ptr result;
197*38fd1498Szrj
198*38fd1498Szrj if (encoding == DW_EH_PE_aligned)
199*38fd1498Szrj {
200*38fd1498Szrj _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p;
201*38fd1498Szrj a = (a + sizeof (void *) - 1) & - sizeof(void *);
202*38fd1498Szrj result = *(_Unwind_Internal_Ptr *) a;
203*38fd1498Szrj p = (const unsigned char *) (_Unwind_Internal_Ptr) (a + sizeof (void *));
204*38fd1498Szrj }
205*38fd1498Szrj else
206*38fd1498Szrj {
207*38fd1498Szrj switch (encoding & 0x0f)
208*38fd1498Szrj {
209*38fd1498Szrj case DW_EH_PE_absptr:
210*38fd1498Szrj result = (_Unwind_Internal_Ptr) u->ptr;
211*38fd1498Szrj p += sizeof (void *);
212*38fd1498Szrj break;
213*38fd1498Szrj
214*38fd1498Szrj case DW_EH_PE_uleb128:
215*38fd1498Szrj {
216*38fd1498Szrj _uleb128_t tmp;
217*38fd1498Szrj p = read_uleb128 (p, &tmp);
218*38fd1498Szrj result = (_Unwind_Internal_Ptr) tmp;
219*38fd1498Szrj }
220*38fd1498Szrj break;
221*38fd1498Szrj
222*38fd1498Szrj case DW_EH_PE_sleb128:
223*38fd1498Szrj {
224*38fd1498Szrj _sleb128_t tmp;
225*38fd1498Szrj p = read_sleb128 (p, &tmp);
226*38fd1498Szrj result = (_Unwind_Internal_Ptr) tmp;
227*38fd1498Szrj }
228*38fd1498Szrj break;
229*38fd1498Szrj
230*38fd1498Szrj case DW_EH_PE_udata2:
231*38fd1498Szrj result = u->u2;
232*38fd1498Szrj p += 2;
233*38fd1498Szrj break;
234*38fd1498Szrj case DW_EH_PE_udata4:
235*38fd1498Szrj result = u->u4;
236*38fd1498Szrj p += 4;
237*38fd1498Szrj break;
238*38fd1498Szrj case DW_EH_PE_udata8:
239*38fd1498Szrj result = u->u8;
240*38fd1498Szrj p += 8;
241*38fd1498Szrj break;
242*38fd1498Szrj
243*38fd1498Szrj case DW_EH_PE_sdata2:
244*38fd1498Szrj result = u->s2;
245*38fd1498Szrj p += 2;
246*38fd1498Szrj break;
247*38fd1498Szrj case DW_EH_PE_sdata4:
248*38fd1498Szrj result = u->s4;
249*38fd1498Szrj p += 4;
250*38fd1498Szrj break;
251*38fd1498Szrj case DW_EH_PE_sdata8:
252*38fd1498Szrj result = u->s8;
253*38fd1498Szrj p += 8;
254*38fd1498Szrj break;
255*38fd1498Szrj
256*38fd1498Szrj default:
257*38fd1498Szrj __gxx_abort ();
258*38fd1498Szrj }
259*38fd1498Szrj
260*38fd1498Szrj if (result != 0)
261*38fd1498Szrj {
262*38fd1498Szrj result += ((encoding & 0x70) == DW_EH_PE_pcrel
263*38fd1498Szrj ? (_Unwind_Internal_Ptr) u : base);
264*38fd1498Szrj if (encoding & DW_EH_PE_indirect)
265*38fd1498Szrj result = *(_Unwind_Internal_Ptr *) result;
266*38fd1498Szrj }
267*38fd1498Szrj }
268*38fd1498Szrj
269*38fd1498Szrj *val = result;
270*38fd1498Szrj return p;
271*38fd1498Szrj }
272*38fd1498Szrj
273*38fd1498Szrj #ifndef NO_BASE_OF_ENCODED_VALUE
274*38fd1498Szrj
275*38fd1498Szrj /* Like read_encoded_value_with_base, but get the base from the context
276*38fd1498Szrj rather than providing it directly. */
277*38fd1498Szrj
278*38fd1498Szrj static inline const unsigned char *
read_encoded_value(struct _Unwind_Context * context,unsigned char encoding,const unsigned char * p,_Unwind_Ptr * val)279*38fd1498Szrj read_encoded_value (struct _Unwind_Context *context, unsigned char encoding,
280*38fd1498Szrj const unsigned char *p, _Unwind_Ptr *val)
281*38fd1498Szrj {
282*38fd1498Szrj return read_encoded_value_with_base (encoding,
283*38fd1498Szrj base_of_encoded_value (encoding, context),
284*38fd1498Szrj p, val);
285*38fd1498Szrj }
286*38fd1498Szrj
287*38fd1498Szrj #endif
288*38fd1498Szrj
289*38fd1498Szrj #endif /* unwind-pe.h */
290