Fix messed up accidental commit.
[official-gcc.git] / gcc / unwind-pe.h
blob4bf2cfd3f021c0f0bf9f64fd3a1b48958cadd111
1 /* Exception handling and frame unwind runtime interface routines.
2 Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.)
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.
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. */
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. */
34 /* If using C++, references to abort have to be qualified with std::. */
35 #if __cplusplus
36 #define __gxx_abort std::abort
37 #else
38 #define __gxx_abort abort
39 #endif
41 /* Pointer encodings, from dwarf2.h. */
42 #define DW_EH_PE_absptr 0x00
43 #define DW_EH_PE_omit 0xff
45 #define DW_EH_PE_uleb128 0x01
46 #define DW_EH_PE_udata2 0x02
47 #define DW_EH_PE_udata4 0x03
48 #define DW_EH_PE_udata8 0x04
49 #define DW_EH_PE_sleb128 0x09
50 #define DW_EH_PE_sdata2 0x0A
51 #define DW_EH_PE_sdata4 0x0B
52 #define DW_EH_PE_sdata8 0x0C
53 #define DW_EH_PE_signed 0x08
55 #define DW_EH_PE_pcrel 0x10
56 #define DW_EH_PE_textrel 0x20
57 #define DW_EH_PE_datarel 0x30
58 #define DW_EH_PE_funcrel 0x40
59 #define DW_EH_PE_aligned 0x50
61 #define DW_EH_PE_indirect 0x80
64 #ifndef NO_SIZE_OF_ENCODED_VALUE
66 /* Given an encoding, return the number of bytes the format occupies.
67 This is only defined for fixed-size encodings, and so does not
68 include leb128. */
70 static unsigned int
71 size_of_encoded_value (unsigned char encoding)
73 if (encoding == DW_EH_PE_omit)
74 return 0;
76 switch (encoding & 0x07)
78 case DW_EH_PE_absptr:
79 return sizeof (void *);
80 case DW_EH_PE_udata2:
81 return 2;
82 case DW_EH_PE_udata4:
83 return 4;
84 case DW_EH_PE_udata8:
85 return 8;
87 __gxx_abort ();
90 #endif
92 #ifndef NO_BASE_OF_ENCODED_VALUE
94 /* Given an encoding and an _Unwind_Context, return the base to which
95 the encoding is relative. This base may then be passed to
96 read_encoded_value_with_base for use when the _Unwind_Context is
97 not available. */
99 static _Unwind_Ptr
100 base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context)
102 if (encoding == DW_EH_PE_omit)
103 return 0;
105 switch (encoding & 0x70)
107 case DW_EH_PE_absptr:
108 case DW_EH_PE_pcrel:
109 case DW_EH_PE_aligned:
110 return 0;
112 case DW_EH_PE_textrel:
113 return _Unwind_GetTextRelBase (context);
114 case DW_EH_PE_datarel:
115 return _Unwind_GetDataRelBase (context);
116 case DW_EH_PE_funcrel:
117 return _Unwind_GetRegionStart (context);
119 __gxx_abort ();
122 #endif
124 /* Read an unsigned leb128 value from P, store the value in VAL, return
125 P incremented past the value. We assume that a word is large enough to
126 hold any value so encoded; if it is smaller than a pointer on some target,
127 pointers should not be leb128 encoded on that target. */
129 static const unsigned char *
130 read_uleb128 (const unsigned char *p, _Unwind_Word *val)
132 unsigned int shift = 0;
133 unsigned char byte;
134 _Unwind_Word result;
136 result = 0;
139 byte = *p++;
140 result |= ((_Unwind_Word)byte & 0x7f) << shift;
141 shift += 7;
143 while (byte & 0x80);
145 *val = result;
146 return p;
149 /* Similar, but read a signed leb128 value. */
151 static const unsigned char *
152 read_sleb128 (const unsigned char *p, _Unwind_Sword *val)
154 unsigned int shift = 0;
155 unsigned char byte;
156 _Unwind_Word result;
158 result = 0;
161 byte = *p++;
162 result |= ((_Unwind_Word)byte & 0x7f) << shift;
163 shift += 7;
165 while (byte & 0x80);
167 /* Sign-extend a negative value. */
168 if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
169 result |= -(((_Unwind_Word)1L) << shift);
171 *val = (_Unwind_Sword) result;
172 return p;
175 /* Load an encoded value from memory at P. The value is returned in VAL;
176 The function returns P incremented past the value. BASE is as given
177 by base_of_encoded_value for this encoding in the appropriate context. */
179 static const unsigned char *
180 read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
181 const unsigned char *p, _Unwind_Ptr *val)
183 union unaligned
185 void *ptr;
186 unsigned u2 __attribute__ ((mode (HI)));
187 unsigned u4 __attribute__ ((mode (SI)));
188 unsigned u8 __attribute__ ((mode (DI)));
189 signed s2 __attribute__ ((mode (HI)));
190 signed s4 __attribute__ ((mode (SI)));
191 signed s8 __attribute__ ((mode (DI)));
192 } __attribute__((__packed__));
194 const union unaligned *u = (const union unaligned *) p;
195 _Unwind_Internal_Ptr result;
197 if (encoding == DW_EH_PE_aligned)
199 _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p;
200 a = (a + sizeof (void *) - 1) & - sizeof(void *);
201 result = *(_Unwind_Internal_Ptr *) a;
202 p = (const unsigned char *) (_Unwind_Internal_Ptr) (a + sizeof (void *));
204 else
206 switch (encoding & 0x0f)
208 case DW_EH_PE_absptr:
209 result = (_Unwind_Internal_Ptr) u->ptr;
210 p += sizeof (void *);
211 break;
213 case DW_EH_PE_uleb128:
215 _Unwind_Word tmp;
216 p = read_uleb128 (p, &tmp);
217 result = (_Unwind_Internal_Ptr) tmp;
219 break;
221 case DW_EH_PE_sleb128:
223 _Unwind_Sword tmp;
224 p = read_sleb128 (p, &tmp);
225 result = (_Unwind_Internal_Ptr) tmp;
227 break;
229 case DW_EH_PE_udata2:
230 result = u->u2;
231 p += 2;
232 break;
233 case DW_EH_PE_udata4:
234 result = u->u4;
235 p += 4;
236 break;
237 case DW_EH_PE_udata8:
238 result = u->u8;
239 p += 8;
240 break;
242 case DW_EH_PE_sdata2:
243 result = u->s2;
244 p += 2;
245 break;
246 case DW_EH_PE_sdata4:
247 result = u->s4;
248 p += 4;
249 break;
250 case DW_EH_PE_sdata8:
251 result = u->s8;
252 p += 8;
253 break;
255 default:
256 __gxx_abort ();
259 if (result != 0)
261 result += ((encoding & 0x70) == DW_EH_PE_pcrel
262 ? (_Unwind_Internal_Ptr) u : base);
263 if (encoding & DW_EH_PE_indirect)
264 result = *(_Unwind_Internal_Ptr *) result;
268 *val = result;
269 return p;
272 #ifndef NO_BASE_OF_ENCODED_VALUE
274 /* Like read_encoded_value_with_base, but get the base from the context
275 rather than providing it directly. */
277 static inline const unsigned char *
278 read_encoded_value (struct _Unwind_Context *context, unsigned char encoding,
279 const unsigned char *p, _Unwind_Ptr *val)
281 return read_encoded_value_with_base (encoding,
282 base_of_encoded_value (encoding, context),
283 p, val);
286 #endif