OSDN Git Service

* gcc.dg/pr31344.c: Move to ...
[pf3gnuchains/gcc-fork.git] / gcc / 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 /* Given an encoding, return the number of bytes the format occupies.
70    This is only defined for fixed-size encodings, and so does not
71    include leb128.  */
72
73 static unsigned int
74 size_of_encoded_value (unsigned char encoding)
75 {
76   if (encoding == DW_EH_PE_omit)
77     return 0;
78
79   switch (encoding & 0x07)
80     {
81     case DW_EH_PE_absptr:
82       return sizeof (void *);
83     case DW_EH_PE_udata2:
84       return 2;
85     case DW_EH_PE_udata4:
86       return 4;
87     case DW_EH_PE_udata8:
88       return 8;
89     }
90   __gxx_abort ();
91 }
92
93 #endif
94
95 #ifndef NO_BASE_OF_ENCODED_VALUE
96
97 /* Given an encoding and an _Unwind_Context, return the base to which
98    the encoding is relative.  This base may then be passed to
99    read_encoded_value_with_base for use when the _Unwind_Context is
100    not available.  */
101
102 static _Unwind_Ptr
103 base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context)
104 {
105   if (encoding == DW_EH_PE_omit)
106     return 0;
107
108   switch (encoding & 0x70)
109     {
110     case DW_EH_PE_absptr:
111     case DW_EH_PE_pcrel:
112     case DW_EH_PE_aligned:
113       return 0;
114
115     case DW_EH_PE_textrel:
116       return _Unwind_GetTextRelBase (context);
117     case DW_EH_PE_datarel:
118       return _Unwind_GetDataRelBase (context);
119     case DW_EH_PE_funcrel:
120       return _Unwind_GetRegionStart (context);
121     }
122   __gxx_abort ();
123 }
124
125 #endif
126
127 /* Read an unsigned leb128 value from P, store the value in VAL, return
128    P incremented past the value.  We assume that a word is large enough to
129    hold any value so encoded; if it is smaller than a pointer on some target,
130    pointers should not be leb128 encoded on that target.  */
131
132 static const unsigned char *
133 read_uleb128 (const unsigned char *p, _uleb128_t *val)
134 {
135   unsigned int shift = 0;
136   unsigned char byte;
137   _uleb128_t result;
138
139   result = 0;
140   do
141     {
142       byte = *p++;
143       result |= ((_uleb128_t)byte & 0x7f) << shift;
144       shift += 7;
145     }
146   while (byte & 0x80);
147
148   *val = result;
149   return p;
150 }
151
152 /* Similar, but read a signed leb128 value.  */
153
154 static const unsigned char *
155 read_sleb128 (const unsigned char *p, _sleb128_t *val)
156 {
157   unsigned int shift = 0;
158   unsigned char byte;
159   _uleb128_t result;
160
161   result = 0;
162   do
163     {
164       byte = *p++;
165       result |= ((_uleb128_t)byte & 0x7f) << shift;
166       shift += 7;
167     }
168   while (byte & 0x80);
169
170   /* Sign-extend a negative value.  */
171   if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
172     result |= -(((_uleb128_t)1L) << shift);
173
174   *val = (_sleb128_t) result;
175   return p;
176 }
177
178 /* Load an encoded value from memory at P.  The value is returned in VAL;
179    The function returns P incremented past the value.  BASE is as given
180    by base_of_encoded_value for this encoding in the appropriate context.  */
181
182 static const unsigned char *
183 read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
184                               const unsigned char *p, _Unwind_Ptr *val)
185 {
186   union unaligned
187     {
188       void *ptr;
189       unsigned u2 __attribute__ ((mode (HI)));
190       unsigned u4 __attribute__ ((mode (SI)));
191       unsigned u8 __attribute__ ((mode (DI)));
192       signed s2 __attribute__ ((mode (HI)));
193       signed s4 __attribute__ ((mode (SI)));
194       signed s8 __attribute__ ((mode (DI)));
195     } __attribute__((__packed__));
196
197   const union unaligned *u = (const union unaligned *) p;
198   _Unwind_Internal_Ptr result;
199
200   if (encoding == DW_EH_PE_aligned)
201     {
202       _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p;
203       a = (a + sizeof (void *) - 1) & - sizeof(void *);
204       result = *(_Unwind_Internal_Ptr *) a;
205       p = (const unsigned char *) (_Unwind_Internal_Ptr) (a + sizeof (void *));
206     }
207   else
208     {
209       switch (encoding & 0x0f)
210         {
211         case DW_EH_PE_absptr:
212           result = (_Unwind_Internal_Ptr) u->ptr;
213           p += sizeof (void *);
214           break;
215
216         case DW_EH_PE_uleb128:
217           {
218             _uleb128_t tmp;
219             p = read_uleb128 (p, &tmp);
220             result = (_Unwind_Internal_Ptr) tmp;
221           }
222           break;
223
224         case DW_EH_PE_sleb128:
225           {
226             _sleb128_t tmp;
227             p = read_sleb128 (p, &tmp);
228             result = (_Unwind_Internal_Ptr) tmp;
229           }
230           break;
231
232         case DW_EH_PE_udata2:
233           result = u->u2;
234           p += 2;
235           break;
236         case DW_EH_PE_udata4:
237           result = u->u4;
238           p += 4;
239           break;
240         case DW_EH_PE_udata8:
241           result = u->u8;
242           p += 8;
243           break;
244
245         case DW_EH_PE_sdata2:
246           result = u->s2;
247           p += 2;
248           break;
249         case DW_EH_PE_sdata4:
250           result = u->s4;
251           p += 4;
252           break;
253         case DW_EH_PE_sdata8:
254           result = u->s8;
255           p += 8;
256           break;
257
258         default:
259           __gxx_abort ();
260         }
261
262       if (result != 0)
263         {
264           result += ((encoding & 0x70) == DW_EH_PE_pcrel
265                      ? (_Unwind_Internal_Ptr) u : base);
266           if (encoding & DW_EH_PE_indirect)
267             result = *(_Unwind_Internal_Ptr *) result;
268         }
269     }
270
271   *val = result;
272   return p;
273 }
274
275 #ifndef NO_BASE_OF_ENCODED_VALUE
276
277 /* Like read_encoded_value_with_base, but get the base from the context
278    rather than providing it directly.  */
279
280 static inline const unsigned char *
281 read_encoded_value (struct _Unwind_Context *context, unsigned char encoding,
282                     const unsigned char *p, _Unwind_Ptr *val)
283 {
284   return read_encoded_value_with_base (encoding,
285                 base_of_encoded_value (encoding, context),
286                 p, val);
287 }
288
289 #endif
290
291 #endif /* unwind-pe.h */