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. */
10 #include "libunwind_i.h"
12 /* Unless we are told otherwise, assume that a "machine address" is
13 the size of an unw_word_t. */
14 #ifndef dwarf_addr_size
15 # define dwarf_addr_size(as) (sizeof (unw_word_t))
18 #ifndef dwarf_to_unw_regnum
19 # define dwarf_to_unw_regnum_map UNW_OBJ (dwarf_to_unw_regnum_map)
20 extern const uint8_t dwarf_to_unw_regnum_map
[DWARF_REGNUM_MAP_LENGTH
];
21 /* REG is evaluated multiple times; it better be side-effects free! */
22 # define dwarf_to_unw_regnum(reg) \
23 (((reg) < DWARF_REGNUM_MAP_LENGTH) ? dwarf_to_unw_regnum_map[reg] : 0)
28 /* In the local-only case, we can let the compiler directly access
29 memory and don't need to worry about differing byte-order. */
31 typedef union __attribute__ ((packed
))
43 dwarf_misaligned_value_t
;
46 dwarf_reads8 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
47 int8_t *val
, void *arg
)
49 dwarf_misaligned_value_t
*mvp
= (void *) (uintptr_t) *addr
;
52 *addr
+= sizeof (mvp
->s8
);
57 dwarf_reads16 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
58 int16_t *val
, void *arg
)
60 dwarf_misaligned_value_t
*mvp
= (void *) (uintptr_t) *addr
;
63 *addr
+= sizeof (mvp
->s16
);
68 dwarf_reads32 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
69 int32_t *val
, void *arg
)
71 dwarf_misaligned_value_t
*mvp
= (void *) (uintptr_t) *addr
;
74 *addr
+= sizeof (mvp
->s32
);
79 dwarf_reads64 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
80 int64_t *val
, void *arg
)
82 dwarf_misaligned_value_t
*mvp
= (void *) (uintptr_t) *addr
;
85 *addr
+= sizeof (mvp
->s64
);
90 dwarf_readu8 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
91 uint8_t *val
, void *arg
)
93 dwarf_misaligned_value_t
*mvp
= (void *) (uintptr_t) *addr
;
96 *addr
+= sizeof (mvp
->u8
);
101 dwarf_readu16 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
102 uint16_t *val
, void *arg
)
104 dwarf_misaligned_value_t
*mvp
= (void *) (uintptr_t) *addr
;
107 *addr
+= sizeof (mvp
->u16
);
112 dwarf_readu32 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
113 uint32_t *val
, void *arg
)
115 dwarf_misaligned_value_t
*mvp
= (void *) (uintptr_t) *addr
;
118 *addr
+= sizeof (mvp
->u32
);
123 dwarf_readu64 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
124 uint64_t *val
, void *arg
)
126 dwarf_misaligned_value_t
*mvp
= (void *) (uintptr_t) *addr
;
129 *addr
+= sizeof (mvp
->u64
);
133 #else /* !UNW_LOCAL_ONLY */
136 dwarf_readu8 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
137 uint8_t *valp
, void *arg
)
139 unw_word_t val
, aligned_addr
= *addr
& -sizeof (unw_word_t
);
140 unw_word_t off
= *addr
- aligned_addr
;
144 ret
= (*a
->access_mem
) (as
, aligned_addr
, &val
, 0, arg
);
145 #if __BYTE_ORDER == __LITTLE_ENDIAN
148 val
>>= 8*(sizeof (unw_word_t
) - 1 - off
);
150 *valp
= (uint8_t) val
;
155 dwarf_readu16 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
156 uint16_t *val
, void *arg
)
161 if ((ret
= dwarf_readu8 (as
, a
, addr
, &v0
, arg
)) < 0
162 || (ret
= dwarf_readu8 (as
, a
, addr
, &v1
, arg
)) < 0)
165 if (tdep_big_endian (as
))
166 *val
= (uint16_t) v0
<< 8 | v1
;
168 *val
= (uint16_t) v1
<< 8 | v0
;
173 dwarf_readu32 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
174 uint32_t *val
, void *arg
)
179 if ((ret
= dwarf_readu16 (as
, a
, addr
, &v0
, arg
)) < 0
180 || (ret
= dwarf_readu16 (as
, a
, addr
, &v1
, arg
)) < 0)
183 if (tdep_big_endian (as
))
184 *val
= (uint32_t) v0
<< 16 | v1
;
186 *val
= (uint32_t) v1
<< 16 | v0
;
191 dwarf_readu64 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
192 uint64_t *val
, void *arg
)
197 if ((ret
= dwarf_readu32 (as
, a
, addr
, &v0
, arg
)) < 0
198 || (ret
= dwarf_readu32 (as
, a
, addr
, &v1
, arg
)) < 0)
201 if (tdep_big_endian (as
))
202 *val
= (uint64_t) v0
<< 32 | v1
;
204 *val
= (uint64_t) v1
<< 32 | v0
;
209 dwarf_reads8 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
210 int8_t *val
, void *arg
)
215 if ((ret
= dwarf_readu8 (as
, a
, addr
, &uval
, arg
)) < 0)
217 *val
= (int8_t) uval
;
222 dwarf_reads16 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
223 int16_t *val
, void *arg
)
228 if ((ret
= dwarf_readu16 (as
, a
, addr
, &uval
, arg
)) < 0)
230 *val
= (int16_t) uval
;
235 dwarf_reads32 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
236 int32_t *val
, void *arg
)
241 if ((ret
= dwarf_readu32 (as
, a
, addr
, &uval
, arg
)) < 0)
243 *val
= (int32_t) uval
;
248 dwarf_reads64 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
249 int64_t *val
, void *arg
)
254 if ((ret
= dwarf_readu64 (as
, a
, addr
, &uval
, arg
)) < 0)
256 *val
= (int64_t) uval
;
260 #endif /* !UNW_LOCAL_ONLY */
263 dwarf_readw (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
264 unw_word_t
*val
, void *arg
)
270 switch (dwarf_addr_size (as
))
273 ret
= dwarf_readu32 (as
, a
, addr
, &u32
, arg
);
280 ret
= dwarf_readu64 (as
, a
, addr
, &u64
, arg
);
291 /* Read an unsigned "little-endian base 128" value. See Chapter 7.6
295 dwarf_read_uleb128 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
296 unw_word_t
*valp
, void *arg
)
298 unw_word_t val
= 0, shift
= 0;
304 if ((ret
= dwarf_readu8 (as
, a
, addr
, &byte
, arg
)) < 0)
307 val
|= ((unw_word_t
) byte
& 0x7f) << shift
;
316 /* Read a signed "little-endian base 128" value. See Chapter 7.6 of
320 dwarf_read_sleb128 (unw_addr_space_t as
, unw_accessors_t
*a
, unw_word_t
*addr
,
321 unw_word_t
*valp
, void *arg
)
323 unw_word_t val
= 0, shift
= 0;
329 if ((ret
= dwarf_readu8 (as
, a
, addr
, &byte
, arg
)) < 0)
332 val
|= ((unw_word_t
) byte
& 0x7f) << shift
;
337 if (shift
< 8 * sizeof (unw_word_t
) && (byte
& 0x40) != 0)
338 /* sign-extend negative value */
339 val
|= ((unw_word_t
) -1) << shift
;
345 static ALWAYS_INLINE
int
346 dwarf_read_encoded_pointer_inlined (unw_addr_space_t as
, unw_accessors_t
*a
,
347 unw_word_t
*addr
, unsigned char encoding
,
348 unw_word_t gp
, unw_word_t start_ip
,
349 unw_word_t
*valp
, void *arg
)
351 unw_word_t val
, initial_addr
= *addr
;
360 /* DW_EH_PE_omit and DW_EH_PE_aligned don't follow the normal
361 format/application encoding. Handle them first. */
362 if (encoding
== DW_EH_PE_omit
)
367 else if (encoding
== DW_EH_PE_aligned
)
369 int size
= dwarf_addr_size (as
);
370 *addr
= (initial_addr
+ size
- 1) & -size
;
371 return dwarf_readw (as
, a
, addr
, valp
, arg
);
374 switch (encoding
& DW_EH_PE_FORMAT_MASK
)
377 if ((ret
= dwarf_readw (as
, a
, addr
, &val
, arg
)) < 0)
381 case DW_EH_PE_uleb128
:
382 if ((ret
= dwarf_read_uleb128 (as
, a
, addr
, &val
, arg
)) < 0)
386 case DW_EH_PE_udata2
:
387 if ((ret
= dwarf_readu16 (as
, a
, addr
, &uval16
, arg
)) < 0)
392 case DW_EH_PE_udata4
:
393 if ((ret
= dwarf_readu32 (as
, a
, addr
, &uval32
, arg
)) < 0)
398 case DW_EH_PE_udata8
:
399 if ((ret
= dwarf_readu64 (as
, a
, addr
, &uval64
, arg
)) < 0)
404 case DW_EH_PE_sleb128
:
405 if ((ret
= dwarf_read_uleb128 (as
, a
, addr
, &val
, arg
)) < 0)
409 case DW_EH_PE_sdata2
:
410 if ((ret
= dwarf_reads16 (as
, a
, addr
, &sval16
, arg
)) < 0)
415 case DW_EH_PE_sdata4
:
416 if ((ret
= dwarf_reads32 (as
, a
, addr
, &sval32
, arg
)) < 0)
421 case DW_EH_PE_sdata8
:
422 if ((ret
= dwarf_reads64 (as
, a
, addr
, &sval64
, arg
)) < 0)
428 Debug (1, "unexpected encoding format 0x%x\n",
429 encoding
& DW_EH_PE_FORMAT_MASK
);
435 /* 0 is a special value and always absolute. */
440 switch (encoding
& DW_EH_PE_APPL_MASK
)
442 case DW_EH_PE_absptr
:
449 case DW_EH_PE_datarel
:
450 /* XXX For now, assume that data-relative addresses are relative
451 to the global pointer. */
455 case DW_EH_PE_funcrel
:
459 case DW_EH_PE_textrel
:
460 /* XXX For now we don't support text-rel values. If there is a
461 platform which needs this, we probably would have to add a
462 "segbase" member to unw_proc_info_t. */
464 Debug (1, "unexpected application type 0x%x\n",
465 encoding
& DW_EH_PE_APPL_MASK
);
469 /* Trim off any extra bits. Assume that sign extension isn't
470 required; the only place it is needed is MIPS kernel space
472 if (sizeof (val
) > dwarf_addr_size (as
))
474 assert (dwarf_addr_size (as
) == 4);
475 val
= (uint32_t) val
;
478 if (encoding
& DW_EH_PE_indirect
)
480 unw_word_t indirect_addr
= val
;
482 if ((ret
= dwarf_readw (as
, a
, &indirect_addr
, &val
, arg
)) < 0)
490 #endif /* DWARF_I_H */