From 847e0a4b1868f73aad650be605a798d4ba4e9554 Mon Sep 17 00:00:00 2001 From: "hp.com!davidm" <hp.com!davidm> Date: Tue, 3 May 2005 09:13:17 +0000 Subject: [PATCH] (dwarf_misaligned_value_t): Move "attribute" declaration to the type to make newer versions of GCC happy. 2005/02/23 12:55:45-08:00 mostang.com!davidm (dwarf_read_encoded_pointer_inlined): Adjust for ALWAYS_INLINE change. 2004/12/02 00:40:45-08:00 mostang.com!davidm Make it possible for dwarf-config.h to define its own version of dwarf_to_unw_regnum(). 2004/11/23 16:59:56-08:00 mostang.com!davidm (dwarf_to_unw_regnum): Make it a macro so we don't have a dependency just because of including the file when --enable-debug is on (and inlining is off). (dwarf_read_encoded_pointer_inlined): Move from Gpe.c to here and rename from dwarf_read_encoded_pointer(). (Logical change 1.290) --- include/dwarf_i.h | 476 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 476 insertions(+) diff --git a/include/dwarf_i.h b/include/dwarf_i.h index e69de29b..d9c5a619 100644 --- a/include/dwarf_i.h +++ b/include/dwarf_i.h @@ -0,0 +1,476 @@ +#ifndef DWARF_I_H +#define DWARF_I_H + +/* This file contains definitions that cannot be used in code outside + of libunwind. In particular, most inline functions are here + because otherwise they'd generate unresolved references when the + files are compiled with inlining disabled. */ + +#include "dwarf.h" +#include "tdep.h" + +#ifndef dwarf_to_unw_regnum +# define dwarf_to_unw_regnum_map UNW_OBJ (dwarf_to_unw_regnum_map) + + extern uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH]; + + /* REG is evaluated multiple times; it better be side-effects free! */ +# define dwarf_to_unw_regnum(reg) \ + (((reg) <= DWARF_REGNUM_MAP_LENGTH) ? dwarf_to_unw_regnum_map[reg] : 0) +#endif + +#ifdef UNW_LOCAL_ONLY + +/* In the local-only case, we can let the compiler directly access + memory and don't need to worry about differing byte-order. */ + +typedef union __attribute__ ((packed)) + { + int8_t s8; + int16_t s16; + int32_t s32; + int64_t s64; + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; + unw_word_t w; + void *ptr; + } +dwarf_misaligned_value_t; + +static inline int +dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + int8_t *val, void *arg) +{ + dwarf_misaligned_value_t *mvp = (void *) *addr; + + *val = mvp->s8; + *addr += sizeof (mvp->s8); + return 0; +} + +static inline int +dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + int16_t *val, void *arg) +{ + dwarf_misaligned_value_t *mvp = (void *) *addr; + + *val = mvp->s16; + *addr += sizeof (mvp->s16); + return 0; +} + +static inline int +dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + int32_t *val, void *arg) +{ + dwarf_misaligned_value_t *mvp = (void *) *addr; + + *val = mvp->s32; + *addr += sizeof (mvp->s32); + return 0; +} + +static inline int +dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + int64_t *val, void *arg) +{ + dwarf_misaligned_value_t *mvp = (void *) *addr; + + *val = mvp->s64; + *addr += sizeof (mvp->s64); + return 0; +} + +static inline int +dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + uint8_t *val, void *arg) +{ + dwarf_misaligned_value_t *mvp = (void *) *addr; + + *val = mvp->u8; + *addr += sizeof (mvp->u8); + return 0; +} + +static inline int +dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + uint16_t *val, void *arg) +{ + dwarf_misaligned_value_t *mvp = (void *) *addr; + + *val = mvp->u16; + *addr += sizeof (mvp->u16); + return 0; +} + +static inline int +dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + uint32_t *val, void *arg) +{ + dwarf_misaligned_value_t *mvp = (void *) *addr; + + *val = mvp->u32; + *addr += sizeof (mvp->u32); + return 0; +} + +static inline int +dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + uint64_t *val, void *arg) +{ + dwarf_misaligned_value_t *mvp = (void *) *addr; + + *val = mvp->u64; + *addr += sizeof (mvp->u64); + return 0; +} + +static inline int +dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + unw_word_t *val, void *arg) +{ + dwarf_misaligned_value_t *mvp = (void *) *addr; + + *val = mvp->w; + *addr += sizeof (mvp->w); + return 0; +} + +#else /* !UNW_LOCAL_ONLY */ + +static inline int +dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + uint8_t *valp, void *arg) +{ + unw_word_t val, aligned_addr = *addr & -sizeof (unw_word_t); + unw_word_t off = *addr - aligned_addr; + int ret; + + *addr += 1; + ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); +#if __BYTE_ORDER == __LITTLE_ENDIAN + val >>= 8*off; +#else + val >>= 8*(sizeof (unw_word_t) - 1 - off); +#endif + *valp = (uint8_t) val; + return ret; +} + +static inline int +dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + uint16_t *val, void *arg) +{ + uint8_t v0, v1; + int ret; + + if ((ret = dwarf_readu8 (as, a, addr, &v0, arg)) < 0 + || (ret = dwarf_readu8 (as, a, addr, &v1, arg)) < 0) + return ret; + + if (tdep_big_endian (as)) + *val = (uint16_t) v0 << 8 | v1; + else + *val = (uint16_t) v1 << 8 | v0; + return 0; +} + +static inline int +dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + uint32_t *val, void *arg) +{ + uint16_t v0, v1; + int ret; + + if ((ret = dwarf_readu16 (as, a, addr, &v0, arg)) < 0 + || (ret = dwarf_readu16 (as, a, addr, &v1, arg)) < 0) + return ret; + + if (tdep_big_endian (as)) + *val = (uint32_t) v0 << 16 | v1; + else + *val = (uint32_t) v1 << 16 | v0; + return 0; +} + +static inline int +dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + uint64_t *val, void *arg) +{ + uint32_t v0, v1; + int ret; + + if ((ret = dwarf_readu32 (as, a, addr, &v0, arg)) < 0 + || (ret = dwarf_readu32 (as, a, addr, &v1, arg)) < 0) + return ret; + + if (tdep_big_endian (as)) + *val = (uint64_t) v0 << 32 | v1; + else + *val = (uint64_t) v1 << 32 | v0; + return 0; +} + +static inline int +dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + int8_t *val, void *arg) +{ + uint8_t uval; + int ret; + + if ((ret = dwarf_readu8 (as, a, addr, &uval, arg)) < 0) + return ret; + *val = (int8_t) uval; + return 0; +} + +static inline int +dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + int16_t *val, void *arg) +{ + uint16_t uval; + int ret; + + if ((ret = dwarf_readu16 (as, a, addr, &uval, arg)) < 0) + return ret; + *val = (int16_t) uval; + return 0; +} + +static inline int +dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + int32_t *val, void *arg) +{ + uint32_t uval; + int ret; + + if ((ret = dwarf_readu32 (as, a, addr, &uval, arg)) < 0) + return ret; + *val = (int32_t) uval; + return 0; +} + +static inline int +dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + int64_t *val, void *arg) +{ + uint64_t uval; + int ret; + + if ((ret = dwarf_readu64 (as, a, addr, &uval, arg)) < 0) + return ret; + *val = (int64_t) uval; + return 0; +} + +static inline int +dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + unw_word_t *val, void *arg) +{ + switch (sizeof (unw_word_t)) + { + case 4: + return dwarf_readu32 (as, a, addr, (uint32_t *) val, arg); + + case 8: + return dwarf_readu64 (as, a, addr, (uint64_t *) val, arg); + + default: + abort (); + } +} + +#endif /* !UNW_LOCAL_ONLY */ + +/* Read an unsigned "little-endian base 128" value. See Chapter 7.6 + of DWARF spec v3. */ + +static inline int +dwarf_read_uleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + unw_word_t *valp, void *arg) +{ + unw_word_t val = 0, shift = 0; + unsigned char byte; + int ret; + + do + { + if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0) + return ret; + + val |= ((unw_word_t) byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + *valp = val; + return 0; +} + +/* Read a signed "little-endian base 128" value. See Chapter 7.6 of + DWARF spec v3. */ + +static inline int +dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + unw_word_t *valp, void *arg) +{ + unw_word_t val = 0, shift = 0; + unsigned char byte; + int ret; + + do + { + if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0) + return ret; + + val |= ((unw_word_t) byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + if (shift < 8 * sizeof (unw_word_t) && (byte & 0x40) != 0) + /* sign-extend negative value */ + val |= ((unw_word_t) -1) << shift; + + *valp = val; + return 0; +} + +static ALWAYS_INLINE int +dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unsigned char encoding, + const unw_proc_info_t *pi, + unw_word_t *valp, void *arg) +{ + unw_word_t val, initial_addr = *addr; + uint16_t uval16; + uint32_t uval32; + uint64_t uval64; + int16_t sval16; + int32_t sval32; + int64_t sval64; + int ret; + + /* DW_EH_PE_omit and DW_EH_PE_aligned don't follow the normal + format/application encoding. Handle them first. */ + if (encoding == DW_EH_PE_omit) + { + *valp = 0; + return 0; + } + else if (encoding == DW_EH_PE_aligned) + { + *addr = (initial_addr + sizeof (unw_word_t) - 1) & -sizeof (unw_word_t); + return dwarf_readw (as, a, addr, valp, arg); + } + + switch (encoding & DW_EH_PE_FORMAT_MASK) + { + case DW_EH_PE_ptr: + if ((ret = dwarf_readw (as, a, addr, &val, arg)) < 0) + return ret; + break; + + case DW_EH_PE_uleb128: + if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) + return ret; + break; + + case DW_EH_PE_udata2: + if ((ret = dwarf_readu16 (as, a, addr, &uval16, arg)) < 0) + return ret; + val = uval16; + break; + + case DW_EH_PE_udata4: + if ((ret = dwarf_readu32 (as, a, addr, &uval32, arg)) < 0) + return ret; + val = uval32; + break; + + case DW_EH_PE_udata8: + if ((ret = dwarf_readu64 (as, a, addr, &uval64, arg)) < 0) + return ret; + val = uval64; + break; + + case DW_EH_PE_sleb128: + if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) + return ret; + break; + + case DW_EH_PE_sdata2: + if ((ret = dwarf_reads16 (as, a, addr, &sval16, arg)) < 0) + return ret; + val = sval16; + break; + + case DW_EH_PE_sdata4: + if ((ret = dwarf_reads32 (as, a, addr, &sval32, arg)) < 0) + return ret; + val = sval32; + break; + + case DW_EH_PE_sdata8: + if ((ret = dwarf_reads64 (as, a, addr, &sval64, arg)) < 0) + return ret; + val = sval64; + break; + + default: + Debug (1, "unexpected encoding format 0x%x\n", + encoding & DW_EH_PE_FORMAT_MASK); + return -UNW_EINVAL; + } + + if (val == 0) + { + /* 0 is a special value and always absolute. */ + *valp = 0; + return 0; + } + + switch (encoding & DW_EH_PE_APPL_MASK) + { + case DW_EH_PE_absptr: + break; + + case DW_EH_PE_pcrel: + val += initial_addr; + break; + + case DW_EH_PE_datarel: + /* XXX For now, assume that data-relative addresses are relative + to the global pointer. */ + val += pi->gp; + break; + + case DW_EH_PE_funcrel: + val += pi->start_ip; + break; + + case DW_EH_PE_textrel: + /* XXX For now we don't support text-rel values. If there is a + platform which needs this, we probably would have to add a + "segbase" member to unw_proc_info_t. */ + default: + Debug (1, "unexpected application type 0x%x\n", + encoding & DW_EH_PE_APPL_MASK); + return -UNW_EINVAL; + } + + if (encoding & DW_EH_PE_indirect) + { + unw_word_t indirect_addr = val; + + if ((ret = dwarf_readw (as, a, &indirect_addr, &val, arg)) < 0) + return ret; + } + + *valp = val; + return 0; +} + +#endif /* DWARF_I_H */