xref: /dflybsd-src/contrib/gcc-8.0/libgcc/unwind-pe.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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