OSDN Git Service

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