blob: 55320c2d13fe02fe0f6c2f11711e31bccc88f09c [file] [log] [blame]
David Mosberger-Tangf176ad62006-07-25 21:32:28 -06001#ifndef DWARF_I_H
2#define DWARF_I_H
3
4/* This file contains definitions that cannot be used in code outside
5 of libunwind. In particular, most inline functions are here
6 because otherwise they'd generate unresolved references when the
7 files are compiled with inlining disabled. */
8
9#include "dwarf.h"
10#include "tdep.h"
11
12#define dwarf_to_unw_regnum_map UNW_OBJ (dwarf_to_unw_regnum_map)
13
14extern uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH];
15
16static inline unw_regnum_t
17dwarf_to_unw_regnum (unw_word_t regnum)
18{
19 if (regnum <= DWARF_REGNUM_MAP_LENGTH)
20 return dwarf_to_unw_regnum_map[regnum];
21 return 0;
22}
23
24#ifdef UNW_LOCAL_ONLY
25
26/* In the local-only case, we can let the compiler directly access
27 memory and don't need to worry about differing byte-order. */
28
29typedef union
30 {
31 int8_t s8;
32 int16_t s16;
33 int32_t s32;
34 int64_t s64;
35 uint8_t u8;
36 uint16_t u16;
37 uint32_t u32;
38 uint64_t u64;
39 unw_word_t w;
40 void *ptr;
41 }
42dwarf_misaligned_value_t __attribute__ ((packed));
43
44static inline int
45dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
46 int8_t *val, void *arg)
47{
48 dwarf_misaligned_value_t *mvp = (void *) *addr;
49
50 *val = mvp->s8;
51 *addr += sizeof (mvp->s8);
52 return 0;
53}
54
55static inline int
56dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
57 int16_t *val, void *arg)
58{
59 dwarf_misaligned_value_t *mvp = (void *) *addr;
60
61 *val = mvp->s16;
62 *addr += sizeof (mvp->s16);
63 return 0;
64}
65
66static inline int
67dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
68 int32_t *val, void *arg)
69{
70 dwarf_misaligned_value_t *mvp = (void *) *addr;
71
72 *val = mvp->s32;
73 *addr += sizeof (mvp->s32);
74 return 0;
75}
76
77static inline int
78dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
79 int64_t *val, void *arg)
80{
81 dwarf_misaligned_value_t *mvp = (void *) *addr;
82
83 *val = mvp->s64;
84 *addr += sizeof (mvp->s64);
85 return 0;
86}
87
88static inline int
89dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
90 uint8_t *val, void *arg)
91{
92 dwarf_misaligned_value_t *mvp = (void *) *addr;
93
94 *val = mvp->u8;
95 *addr += sizeof (mvp->u8);
96 return 0;
97}
98
99static inline int
100dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
101 uint16_t *val, void *arg)
102{
103 dwarf_misaligned_value_t *mvp = (void *) *addr;
104
105 *val = mvp->u16;
106 *addr += sizeof (mvp->u16);
107 return 0;
108}
109
110static inline int
111dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
112 uint32_t *val, void *arg)
113{
114 dwarf_misaligned_value_t *mvp = (void *) *addr;
115
116 *val = mvp->u32;
117 *addr += sizeof (mvp->u32);
118 return 0;
119}
120
121static inline int
122dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
123 uint64_t *val, void *arg)
124{
125 dwarf_misaligned_value_t *mvp = (void *) *addr;
126
127 *val = mvp->u64;
128 *addr += sizeof (mvp->u64);
129 return 0;
130}
131
132static inline int
133dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
134 unw_word_t *val, void *arg)
135{
136 dwarf_misaligned_value_t *mvp = (void *) *addr;
137
138 *val = mvp->w;
139 *addr += sizeof (mvp->w);
140 return 0;
141}
142
143#else /* !UNW_LOCAL_ONLY */
144
145static inline int
146dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
147 uint8_t *valp, void *arg)
148{
149 unw_word_t val, aligned_addr = *addr & -sizeof (unw_word_t);
150 unw_word_t off = *addr - aligned_addr;
151 int ret;
152
153 *addr += 1;
154 ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg);
155#if __BYTE_ORDER == __LITTLE_ENDIAN
156 val >>= 8*off;
157#else
158 val >>= 8*(sizeof (unw_word_t) - 1 - off);
159#endif
160 *valp = (uint8_t) val;
161 return ret;
162}
163
164static inline int
165dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
166 uint16_t *val, void *arg)
167{
168 uint8_t v0, v1;
169 int ret;
170
171 if ((ret = dwarf_readu8 (as, a, addr, &v0, arg)) < 0
172 || (ret = dwarf_readu8 (as, a, addr, &v1, arg)) < 0)
173 return ret;
174
175 if (tdep_big_endian (as))
176 *val = (uint16_t) v0 << 8 | v1;
177 else
178 *val = (uint16_t) v1 << 8 | v0;
179 return 0;
180}
181
182static inline int
183dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
184 uint32_t *val, void *arg)
185{
186 uint16_t v0, v1;
187 int ret;
188
189 if ((ret = dwarf_readu16 (as, a, addr, &v0, arg)) < 0
190 || (ret = dwarf_readu16 (as, a, addr, &v1, arg)) < 0)
191 return ret;
192
193 if (tdep_big_endian (as))
194 *val = (uint32_t) v0 << 16 | v1;
195 else
196 *val = (uint32_t) v1 << 16 | v0;
197 return 0;
198}
199
200static inline int
201dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
202 uint64_t *val, void *arg)
203{
204 uint32_t v0, v1;
205 int ret;
206
207 if ((ret = dwarf_readu32 (as, a, addr, &v0, arg)) < 0
208 || (ret = dwarf_readu32 (as, a, addr, &v1, arg)) < 0)
209 return ret;
210
211 if (tdep_big_endian (as))
212 *val = (uint64_t) v0 << 32 | v1;
213 else
214 *val = (uint64_t) v1 << 32 | v0;
215 return 0;
216}
217
218static inline int
219dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
220 int8_t *val, void *arg)
221{
222 uint8_t uval;
223 int ret;
224
225 if ((ret = dwarf_readu8 (as, a, addr, &uval, arg)) < 0)
226 return ret;
227 *val = (int8_t) uval;
228 return 0;
229}
230
231static inline int
232dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
233 int16_t *val, void *arg)
234{
235 uint16_t uval;
236 int ret;
237
238 if ((ret = dwarf_readu16 (as, a, addr, &uval, arg)) < 0)
239 return ret;
240 *val = (int16_t) uval;
241 return 0;
242}
243
244static inline int
245dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
246 int32_t *val, void *arg)
247{
248 uint32_t uval;
249 int ret;
250
251 if ((ret = dwarf_readu32 (as, a, addr, &uval, arg)) < 0)
252 return ret;
253 *val = (int32_t) uval;
254 return 0;
255}
256
257static inline int
258dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
259 int64_t *val, void *arg)
260{
261 uint64_t uval;
262 int ret;
263
264 if ((ret = dwarf_readu64 (as, a, addr, &uval, arg)) < 0)
265 return ret;
266 *val = (int64_t) uval;
267 return 0;
268}
269
270static inline int
271dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
272 unw_word_t *val, void *arg)
273{
274 switch (sizeof (unw_word_t))
275 {
276 case 4:
277 return dwarf_readu32 (as, a, addr, (uint32_t *) val, arg);
278
279 case 8:
280 return dwarf_readu64 (as, a, addr, (uint64_t *) val, arg);
281
282 default:
283 abort ();
284 }
285}
286
287#endif /* !UNW_LOCAL_ONLY */
288
289/* Read an unsigned "little-endian base 128" value. See Chapter 7.6
290 of DWARF spec v3. */
291
292static inline int
293dwarf_read_uleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
294 unw_word_t *valp, void *arg)
295{
296 unw_word_t val = 0, shift = 0;
297 unsigned char byte;
298 int ret;
299
300 do
301 {
302 if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
303 return ret;
304
305 val |= ((unw_word_t) byte & 0x7f) << shift;
306 shift += 7;
307 }
308 while (byte & 0x80);
309
310 *valp = val;
311 return 0;
312}
313
314/* Read a signed "little-endian base 128" value. See Chapter 7.6 of
315 DWARF spec v3. */
316
317static inline int
318dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
319 unw_word_t *valp, void *arg)
320{
321 unw_word_t val = 0, shift = 0;
322 unsigned char byte;
323 int ret;
324
325 do
326 {
327 if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0)
328 return ret;
329
330 val |= ((unw_word_t) byte & 0x7f) << shift;
331 shift += 7;
332 }
333 while (byte & 0x80);
334
335 if (shift < 8 * sizeof (unw_word_t) && (byte & 0x40) != 0)
336 /* sign-extend negative value */
337 val |= ((unw_word_t) -1) << shift;
338
339 *valp = val;
340 return 0;
341}
342
343#endif /* DWARF_I_H */