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