OSDN Git Service

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