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