OSDN Git Service

9eda448b4328f0c527c6a2b0fc1ad75bc5526e78
[pf3gnuchains/gcc-fork.git] / gcc / unwind-pe.h
1 /* Exception handling and frame unwind runtime interface routines.
2    Copyright (C) 2001 Free Software Foundation, Inc.
3
4    This file is part of GNU CC.
5
6    GNU CC is free software; you can redistribute it and/or modify
7    it 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    GNU CC is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GNU CC; see the file COPYING.  If not, write to
18    the Free Software Foundation, 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 /* @@@ Really this should be out of line, but this also causes link
22    compatibility problems with the base ABI.  This is slightly better
23    than duplicating code, however.  */
24
25 /* Pointer encodings, from dwarf2.h.  */
26 #define DW_EH_PE_absptr         0x00
27 #define DW_EH_PE_omit           0xff
28
29 #define DW_EH_PE_uleb128        0x01
30 #define DW_EH_PE_udata2         0x02
31 #define DW_EH_PE_udata4         0x03
32 #define DW_EH_PE_udata8         0x04
33 #define DW_EH_PE_sleb128        0x09
34 #define DW_EH_PE_sdata2         0x0A
35 #define DW_EH_PE_sdata4         0x0B
36 #define DW_EH_PE_sdata8         0x0C
37 #define DW_EH_PE_signed         0x08
38
39 #define DW_EH_PE_pcrel          0x10
40 #define DW_EH_PE_textrel        0x20
41 #define DW_EH_PE_datarel        0x30
42 #define DW_EH_PE_funcrel        0x40
43
44 #define DW_EH_PE_indirect       0x80
45
46 static unsigned int
47 size_of_encoded_value (unsigned char encoding)
48 {
49   if (encoding == DW_EH_PE_omit)
50     return 0;
51
52   switch (encoding & 0x07)
53     {
54     case DW_EH_PE_absptr:
55       return sizeof (void *);
56     case DW_EH_PE_udata2:
57       return 2;
58     case DW_EH_PE_udata4:
59       return 4;
60     case DW_EH_PE_udata8:
61       return 8;
62     }
63   abort ();
64 }
65
66 static _Unwind_Ptr
67 base_of_encoded_value (unsigned char encoding, _Unwind_Context *context)
68 {
69   if (encoding == DW_EH_PE_omit)
70     return 0;
71
72   switch (encoding & 0x70)
73     {
74     case DW_EH_PE_absptr:
75     case DW_EH_PE_pcrel:
76       return 0;
77
78     case DW_EH_PE_textrel:
79       return _Unwind_GetTextRelBase (context);
80     case DW_EH_PE_datarel:
81       return _Unwind_GetDataRelBase (context);
82     case DW_EH_PE_funcrel:
83       return _Unwind_GetRegionStart (context);
84     }
85   abort ();
86 }
87
88 static const unsigned char *
89 read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
90                               const unsigned char *p, _Unwind_Ptr *val)
91 {
92   union unaligned
93     {
94       void *ptr;
95       unsigned u2 __attribute__ ((mode (HI)));
96       unsigned u4 __attribute__ ((mode (SI)));
97       unsigned u8 __attribute__ ((mode (DI)));
98       signed s2 __attribute__ ((mode (HI)));
99       signed s4 __attribute__ ((mode (SI)));
100       signed s8 __attribute__ ((mode (DI)));
101     } __attribute__((__packed__));
102
103   union unaligned *u = (union unaligned *) p;
104   _Unwind_Ptr result;
105
106   switch (encoding & 0x0f)
107     {
108     case DW_EH_PE_absptr:
109       result = (_Unwind_Ptr) u->ptr;
110       p += sizeof (void *);
111       break;
112
113     case DW_EH_PE_uleb128:
114       {
115         unsigned int shift = 0;
116         unsigned char byte;
117
118         result = 0;
119         do
120           {
121             byte = *p++;
122             result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
123             shift += 7;
124           }
125         while (byte & 0x80);
126       }
127       break;
128
129     case DW_EH_PE_sleb128:
130       {
131         unsigned int shift = 0;
132         unsigned char byte;
133
134         result = 0;
135         do
136           {
137             byte = *p++;
138             result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
139             shift += 7;
140           }
141         while (byte & 0x80);
142
143         if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
144           result |= -(1L << shift);
145       }
146       break;
147
148     case DW_EH_PE_udata2:
149       result = u->u2;
150       p += 2;
151       break;
152     case DW_EH_PE_udata4:
153       result = u->u4;
154       p += 4;
155       break;
156     case DW_EH_PE_udata8:
157       result = u->u8;
158       p += 8;
159       break;
160
161     case DW_EH_PE_sdata2:
162       result = u->s2;
163       p += 2;
164       break;
165     case DW_EH_PE_sdata4:
166       result = u->s4;
167       p += 4;
168       break;
169     case DW_EH_PE_sdata8:
170       result = u->s8;
171       p += 8;
172       break;
173
174     default:
175       abort ();
176     }
177
178   if (result != 0)
179     {
180       result += ((encoding & 0x70) == DW_EH_PE_pcrel ? (_Unwind_Ptr)u : base);
181       if (encoding & DW_EH_PE_indirect)
182         result = *(_Unwind_Ptr *)result;
183     }
184
185   *val = result;
186   return p;
187 }
188
189 static inline const unsigned char *
190 read_encoded_value (_Unwind_Context *context, unsigned char encoding,
191                     const unsigned char *p, _Unwind_Ptr *val)
192 {
193   return read_encoded_value_with_base (encoding, 
194                 base_of_encoded_value (encoding, context),
195                 p, val);
196 }
197
198 static inline const unsigned char *
199 read_uleb128 (const unsigned char *p, _Unwind_Ptr *val)
200 {
201   return read_encoded_value_with_base (DW_EH_PE_uleb128, 0, p, val);
202 }
203
204 static inline const unsigned char *
205 read_sleb128 (const unsigned char *p, _Unwind_Ptr *val)
206 {
207   return read_encoded_value_with_base (DW_EH_PE_sleb128, 0, p, val);
208 }