Subversion Repositories Kolibri OS

Rev

Rev 4383 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4383 Serge 1
/* Exception handling and frame unwind runtime interface routines.
5963 serge 2
   Copyright (C) 2001-2013 Free Software Foundation, Inc.
4383 Serge 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
   .  */
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 */