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 */