Mercurial > hg > CbC > CbC_gcc
comparison gcc/unwind-pe.h @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* Exception handling and frame unwind runtime interface routines. | |
2 Copyright (C) 2001, 2002, 2003, 2004, 2008, 2009 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 3, or (at your option) | |
9 any later version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
14 License for more details. | |
15 | |
16 Under Section 7 of GPL version 3, you are granted additional | |
17 permissions described in the GCC Runtime Library Exception, version | |
18 3.1, as published by the Free Software Foundation. | |
19 | |
20 You should have received a copy of the GNU General Public License and | |
21 a copy of the GCC Runtime Library Exception along with this program; | |
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 <http://www.gnu.org/licenses/>. */ | |
24 | |
25 /* @@@ Really this should be out of line, but this also causes link | |
26 compatibility problems with the base ABI. This is slightly better | |
27 than duplicating code, however. */ | |
28 | |
29 #ifndef GCC_UNWIND_PE_H | |
30 #define GCC_UNWIND_PE_H | |
31 | |
32 /* If using C++, references to abort have to be qualified with std::. */ | |
33 #if __cplusplus | |
34 #define __gxx_abort std::abort | |
35 #else | |
36 #define __gxx_abort abort | |
37 #endif | |
38 | |
39 /* Pointer encodings, from dwarf2.h. */ | |
40 #define DW_EH_PE_absptr 0x00 | |
41 #define DW_EH_PE_omit 0xff | |
42 | |
43 #define DW_EH_PE_uleb128 0x01 | |
44 #define DW_EH_PE_udata2 0x02 | |
45 #define DW_EH_PE_udata4 0x03 | |
46 #define DW_EH_PE_udata8 0x04 | |
47 #define DW_EH_PE_sleb128 0x09 | |
48 #define DW_EH_PE_sdata2 0x0A | |
49 #define DW_EH_PE_sdata4 0x0B | |
50 #define DW_EH_PE_sdata8 0x0C | |
51 #define DW_EH_PE_signed 0x08 | |
52 | |
53 #define DW_EH_PE_pcrel 0x10 | |
54 #define DW_EH_PE_textrel 0x20 | |
55 #define DW_EH_PE_datarel 0x30 | |
56 #define DW_EH_PE_funcrel 0x40 | |
57 #define DW_EH_PE_aligned 0x50 | |
58 | |
59 #define DW_EH_PE_indirect 0x80 | |
60 | |
61 | |
62 #ifndef NO_SIZE_OF_ENCODED_VALUE | |
63 | |
64 /* Given an encoding, return the number of bytes the format occupies. | |
65 This is only defined for fixed-size encodings, and so does not | |
66 include leb128. */ | |
67 | |
68 static unsigned int | |
69 size_of_encoded_value (unsigned char encoding) __attribute__ ((unused)); | |
70 | |
71 static unsigned int | |
72 size_of_encoded_value (unsigned char encoding) | |
73 { | |
74 if (encoding == DW_EH_PE_omit) | |
75 return 0; | |
76 | |
77 switch (encoding & 0x07) | |
78 { | |
79 case DW_EH_PE_absptr: | |
80 return sizeof (void *); | |
81 case DW_EH_PE_udata2: | |
82 return 2; | |
83 case DW_EH_PE_udata4: | |
84 return 4; | |
85 case DW_EH_PE_udata8: | |
86 return 8; | |
87 } | |
88 __gxx_abort (); | |
89 } | |
90 | |
91 #endif | |
92 | |
93 #ifndef NO_BASE_OF_ENCODED_VALUE | |
94 | |
95 /* Given an encoding and an _Unwind_Context, return the base to which | |
96 the encoding is relative. This base may then be passed to | |
97 read_encoded_value_with_base for use when the _Unwind_Context is | |
98 not available. */ | |
99 | |
100 static _Unwind_Ptr | |
101 base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context) | |
102 { | |
103 if (encoding == DW_EH_PE_omit) | |
104 return 0; | |
105 | |
106 switch (encoding & 0x70) | |
107 { | |
108 case DW_EH_PE_absptr: | |
109 case DW_EH_PE_pcrel: | |
110 case DW_EH_PE_aligned: | |
111 return 0; | |
112 | |
113 case DW_EH_PE_textrel: | |
114 return _Unwind_GetTextRelBase (context); | |
115 case DW_EH_PE_datarel: | |
116 return _Unwind_GetDataRelBase (context); | |
117 case DW_EH_PE_funcrel: | |
118 return _Unwind_GetRegionStart (context); | |
119 } | |
120 __gxx_abort (); | |
121 } | |
122 | |
123 #endif | |
124 | |
125 /* Read an unsigned leb128 value from P, store the value in VAL, return | |
126 P incremented past the value. We assume that a word is large enough to | |
127 hold any value so encoded; if it is smaller than a pointer on some target, | |
128 pointers should not be leb128 encoded on that target. */ | |
129 | |
130 static const unsigned char * | |
131 read_uleb128 (const unsigned char *p, _uleb128_t *val) | |
132 { | |
133 unsigned int shift = 0; | |
134 unsigned char byte; | |
135 _uleb128_t result; | |
136 | |
137 result = 0; | |
138 do | |
139 { | |
140 byte = *p++; | |
141 result |= ((_uleb128_t)byte & 0x7f) << shift; | |
142 shift += 7; | |
143 } | |
144 while (byte & 0x80); | |
145 | |
146 *val = result; | |
147 return p; | |
148 } | |
149 | |
150 /* Similar, but read a signed leb128 value. */ | |
151 | |
152 static const unsigned char * | |
153 read_sleb128 (const unsigned char *p, _sleb128_t *val) | |
154 { | |
155 unsigned int shift = 0; | |
156 unsigned char byte; | |
157 _uleb128_t result; | |
158 | |
159 result = 0; | |
160 do | |
161 { | |
162 byte = *p++; | |
163 result |= ((_uleb128_t)byte & 0x7f) << shift; | |
164 shift += 7; | |
165 } | |
166 while (byte & 0x80); | |
167 | |
168 /* Sign-extend a negative value. */ | |
169 if (shift < 8 * sizeof(result) && (byte & 0x40) != 0) | |
170 result |= -(((_uleb128_t)1L) << shift); | |
171 | |
172 *val = (_sleb128_t) result; | |
173 return p; | |
174 } | |
175 | |
176 /* Load an encoded value from memory at P. The value is returned in VAL; | |
177 The function returns P incremented past the value. BASE is as given | |
178 by base_of_encoded_value for this encoding in the appropriate context. */ | |
179 | |
180 static const unsigned char * | |
181 read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, | |
182 const unsigned char *p, _Unwind_Ptr *val) | |
183 { | |
184 union unaligned | |
185 { | |
186 void *ptr; | |
187 unsigned u2 __attribute__ ((mode (HI))); | |
188 unsigned u4 __attribute__ ((mode (SI))); | |
189 unsigned u8 __attribute__ ((mode (DI))); | |
190 signed s2 __attribute__ ((mode (HI))); | |
191 signed s4 __attribute__ ((mode (SI))); | |
192 signed s8 __attribute__ ((mode (DI))); | |
193 } __attribute__((__packed__)); | |
194 | |
195 const union unaligned *u = (const union unaligned *) p; | |
196 _Unwind_Internal_Ptr result; | |
197 | |
198 if (encoding == DW_EH_PE_aligned) | |
199 { | |
200 _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p; | |
201 a = (a + sizeof (void *) - 1) & - sizeof(void *); | |
202 result = *(_Unwind_Internal_Ptr *) a; | |
203 p = (const unsigned char *) (_Unwind_Internal_Ptr) (a + sizeof (void *)); | |
204 } | |
205 else | |
206 { | |
207 switch (encoding & 0x0f) | |
208 { | |
209 case DW_EH_PE_absptr: | |
210 result = (_Unwind_Internal_Ptr) u->ptr; | |
211 p += sizeof (void *); | |
212 break; | |
213 | |
214 case DW_EH_PE_uleb128: | |
215 { | |
216 _uleb128_t tmp; | |
217 p = read_uleb128 (p, &tmp); | |
218 result = (_Unwind_Internal_Ptr) tmp; | |
219 } | |
220 break; | |
221 | |
222 case DW_EH_PE_sleb128: | |
223 { | |
224 _sleb128_t tmp; | |
225 p = read_sleb128 (p, &tmp); | |
226 result = (_Unwind_Internal_Ptr) tmp; | |
227 } | |
228 break; | |
229 | |
230 case DW_EH_PE_udata2: | |
231 result = u->u2; | |
232 p += 2; | |
233 break; | |
234 case DW_EH_PE_udata4: | |
235 result = u->u4; | |
236 p += 4; | |
237 break; | |
238 case DW_EH_PE_udata8: | |
239 result = u->u8; | |
240 p += 8; | |
241 break; | |
242 | |
243 case DW_EH_PE_sdata2: | |
244 result = u->s2; | |
245 p += 2; | |
246 break; | |
247 case DW_EH_PE_sdata4: | |
248 result = u->s4; | |
249 p += 4; | |
250 break; | |
251 case DW_EH_PE_sdata8: | |
252 result = u->s8; | |
253 p += 8; | |
254 break; | |
255 | |
256 default: | |
257 __gxx_abort (); | |
258 } | |
259 | |
260 if (result != 0) | |
261 { | |
262 result += ((encoding & 0x70) == DW_EH_PE_pcrel | |
263 ? (_Unwind_Internal_Ptr) u : base); | |
264 if (encoding & DW_EH_PE_indirect) | |
265 result = *(_Unwind_Internal_Ptr *) result; | |
266 } | |
267 } | |
268 | |
269 *val = result; | |
270 return p; | |
271 } | |
272 | |
273 #ifndef NO_BASE_OF_ENCODED_VALUE | |
274 | |
275 /* Like read_encoded_value_with_base, but get the base from the context | |
276 rather than providing it directly. */ | |
277 | |
278 static inline const unsigned char * | |
279 read_encoded_value (struct _Unwind_Context *context, unsigned char encoding, | |
280 const unsigned char *p, _Unwind_Ptr *val) | |
281 { | |
282 return read_encoded_value_with_base (encoding, | |
283 base_of_encoded_value (encoding, context), | |
284 p, val); | |
285 } | |
286 | |
287 #endif | |
288 | |
289 #endif /* unwind-pe.h */ |