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 const unw_proc_info_t *pi,
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 */