1 /* Exception handling and frame unwind runtime interface routines.
2 Copyright (C) 2001, 2002, 2003, 2004 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)
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
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, 51 Franklin Street, Fifth Floor, Boston, MA
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 #ifndef GCC_UNWIND_PE_H
35 #define GCC_UNWIND_PE_H
37 /* If using C++, references to abort have to be qualified with std::. */
39 #define __gxx_abort std::abort
41 #define __gxx_abort abort
44 /* Pointer encodings, from dwarf2.h. */
45 #define DW_EH_PE_absptr 0x00
46 #define DW_EH_PE_omit 0xff
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
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
64 #define DW_EH_PE_indirect 0x80
67 #ifndef NO_SIZE_OF_ENCODED_VALUE
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;
78 # error "What type shall we use for _sleb128_t?"
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
88 size_of_encoded_value (unsigned char encoding)
90 if (encoding == DW_EH_PE_omit)
93 switch (encoding & 0x07)
96 return sizeof (void *);
101 case DW_EH_PE_udata8:
109 #ifndef NO_BASE_OF_ENCODED_VALUE
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
117 base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context)
119 if (encoding == DW_EH_PE_omit)
122 switch (encoding & 0x70)
124 case DW_EH_PE_absptr:
126 case DW_EH_PE_aligned:
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);
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. */
146 static const unsigned char *
147 read_uleb128 (const unsigned char *p, _uleb128_t *val)
149 unsigned int shift = 0;
157 result |= ((_uleb128_t)byte & 0x7f) << shift;
166 /* Similar, but read a signed leb128 value. */
168 static const unsigned char *
169 read_sleb128 (const unsigned char *p, _sleb128_t *val)
171 unsigned int shift = 0;
179 result |= ((_uleb128_t)byte & 0x7f) << shift;
184 /* Sign-extend a negative value. */
185 if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
186 result |= -(((_uleb128_t)1L) << shift);
188 *val = (_sleb128_t) result;
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. */
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)
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__));
211 const union unaligned *u = (const union unaligned *) p;
212 _Unwind_Internal_Ptr result;
214 if (encoding == DW_EH_PE_aligned)
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 *));
223 switch (encoding & 0x0f)
225 case DW_EH_PE_absptr:
226 result = (_Unwind_Internal_Ptr) u->ptr;
227 p += sizeof (void *);
230 case DW_EH_PE_uleb128:
233 p = read_uleb128 (p, &tmp);
234 result = (_Unwind_Internal_Ptr) tmp;
238 case DW_EH_PE_sleb128:
241 p = read_sleb128 (p, &tmp);
242 result = (_Unwind_Internal_Ptr) tmp;
246 case DW_EH_PE_udata2:
250 case DW_EH_PE_udata4:
254 case DW_EH_PE_udata8:
259 case DW_EH_PE_sdata2:
263 case DW_EH_PE_sdata4:
267 case DW_EH_PE_sdata8:
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;
289 #ifndef NO_BASE_OF_ENCODED_VALUE
291 /* Like read_encoded_value_with_base, but get the base from the context
292 rather than providing it directly. */
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)
298 return read_encoded_value_with_base (encoding,
299 base_of_encoded_value (encoding, context),
305 #endif /* unwind-pe.h */