[3/8] ARM extbl cleanup.

Message ID 1300895706-5424-4-git-send-email-ken.werner@linaro.org
State New
Headers show

Commit Message

Ken Werner March 23, 2011, 3:55 p.m.
Move code that does not necessarily need to reside in the ex_tables.h header
file into ex_tables.c. Add comments and remove unused code.

Signed-off-by: Ken Werner <ken.werner@linaro.org>
---
 include/tdep-arm/ex_tables.h |   37 +-------
 src/arm/ex_tables.c          |  196 ++++++++---------------------------------
 2 files changed, 44 insertions(+), 189 deletions(-)

Patch hide | download patch | download mbox

diff --git a/include/tdep-arm/ex_tables.h b/include/tdep-arm/ex_tables.h
index 7369b35..698792f 100644
--- a/include/tdep-arm/ex_tables.h
+++ b/include/tdep-arm/ex_tables.h
@@ -41,7 +41,6 @@  struct arm_exidx_table {
 #endif
 };
 
-
 typedef enum arm_exbuf_cmd {
   ARM_EXIDX_CMD_FINISH,
   ARM_EXIDX_CMD_DATA_PUSH,
@@ -55,47 +54,21 @@  typedef enum arm_exbuf_cmd {
   ARM_EXIDX_CMD_REFUSED,
 } arm_exbuf_cmd_t;
 
-enum arm_exbuf_cmd_flags {
-  ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
-  ARM_EXIDX_VFP_DOUBLE = 1 << 17,
-};
-
-#define ARM_EXBUF_START(x)	(((x) >> 4) & 0x0f)
-#define ARM_EXBUF_COUNT(x)	((x) & 0x0f)
-#define ARM_EXBUF_END(x)	(ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
-
 struct arm_exbuf_data
 {
   arm_exbuf_cmd_t cmd;
   uint32_t data;
 };
 
-static inline void *
-prel31_to_addr (void *addr)
-{
-  uint32_t offset = ((long)*(uint32_t *)addr << 1) >> 1;
-  return (char *)addr + offset;
-}
 
 int arm_exidx_init_local (const char *appname);
-
-int arm_exidx_table_add (const char *name,
-    struct arm_exidx_entry *start, struct arm_exidx_entry *end);
+int arm_exidx_table_add (const char *name, struct arm_exidx_entry *start,
+			 struct arm_exidx_entry *end);
 struct arm_exidx_table *arm_exidx_table_find (void *pc);
-struct arm_exidx_entry *arm_exidx_table_lookup (
-		struct arm_exidx_table *table, void *pc);
-
-void arm_exidx_section_find (struct elf_image *ei,
-		Elf_W (Shdr) **exidx, Elf_W (Shdr) **extbl);
-int arm_exidx_entry_lookup (struct elf_image *ei,
-		Elf_W (Shdr) *exidx, uint32_t ip);
-int arm_exidx_entry_extract (struct elf_image *ei,
-		Elf_W (Shdr) *exidx, Elf_W (Shdr) *extbl,
-		unsigned i, uint8_t *buf);
+struct arm_exidx_entry *arm_exidx_table_lookup (struct arm_exidx_table *table,
+						void *pc);
 int arm_exidx_extract (struct arm_exidx_entry *entry, uint8_t *buf);
-
-int arm_exidx_decode (const uint8_t *buf, uint8_t len,
-		      struct dwarf_cursor *c);
+int arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c);
 int arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c);
 
 #endif // ARM_EX_TABLES_H
diff --git a/src/arm/ex_tables.c b/src/arm/ex_tables.c
index 6fe2947..abe9a77 100644
--- a/src/arm/ex_tables.c
+++ b/src/arm/ex_tables.c
@@ -24,11 +24,20 @@  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include "libunwind_i.h"
 
+#define ARM_EXBUF_START(x)	(((x) >> 4) & 0x0f)
+#define ARM_EXBUF_COUNT(x)	((x) & 0x0f)
+#define ARM_EXBUF_END(x)	(ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
+
 #define ARM_EXIDX_CANT_UNWIND	0x00000001
 #define ARM_EXIDX_COMPACT	0x80000000
 
 #define ARM_EXTBL_OP_FINISH	0xb0
 
+enum arm_exbuf_cmd_flags {
+  ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
+  ARM_EXIDX_VFP_DOUBLE = 1 << 17,
+};
+
 #ifdef ARM_EXIDX_TABLE_MALLOC
 static struct arm_exidx_table *arm_exidx_table_list;
 #else
@@ -38,6 +47,19 @@  static unsigned arm_exidx_table_count = 0;
 #endif
 static const char *arm_exidx_appname;
 
+static inline uint32_t
+prel31_read (uint32_t prel31)
+{
+  return ((int32_t)prel31 << 1) >> 1;
+}
+
+static inline void *
+prel31_to_addr (void *addr)
+{
+  uint32_t offset = ((long)*(uint32_t *)addr << 1) >> 1;
+  return (char *)addr + offset;
+}
+
 static void
 arm_exidx_table_reset_all (void)
 {
@@ -79,7 +101,7 @@  arm_exidx_table_add (const char *name,
 }
 
 /**
- * Located the appropriate unwind table
+ * Locate the appropriate unwind table from the given PC.
  */
 HIDDEN struct arm_exidx_table *
 arm_exidx_table_find (void *pc)
@@ -100,7 +122,9 @@  arm_exidx_table_find (void *pc)
   return NULL;
 }
 
-/* Based on Linux arm/arm/kernel/unwind.c:search_index() */
+/**
+ * Finds the corresponding arm_exidx_entry from a given index table and PC.
+ */
 HIDDEN struct arm_exidx_entry *
 arm_exidx_table_lookup (struct arm_exidx_table *table, void *pc)
 {
@@ -190,7 +214,10 @@  arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c)
   return ret;
 }
 
-
+/**
+ * Decodes the given unwind instructions into arm_exbuf_data and calls
+ * arm_exidx_apply_cmd that applies the command onto the dwarf_cursor.
+ */
 HIDDEN int
 arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c)
 {
@@ -323,59 +350,11 @@  arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c)
   return 0;
 }
 
-static inline uint32_t
-prel31_read (uint32_t prel31)
-{
-  return ((int32_t)prel31 << 1) >> 1;
-}
-
-/**
- * Finds the index of the table entry for the given address
- * using a binary search.
- * @returns The table index (or -1 if not found).
- */
-HIDDEN int
-arm_exidx_lookup (uint32_t *exidx_data, uint32_t exidx_size, uint32_t ip)
-{
-  unsigned lo = 0, hi = exidx_size / 8;
-  while (lo < hi)
-    {
-      unsigned mid = (lo + hi) / 2;
-      uint32_t base = (uint32_t)(exidx_data + mid * 2);
-      uint32_t addr = base + prel31_read (exidx_data[mid * 2]);
-      if (ip < addr)
-	hi = mid;
-      else
-	lo = mid + 1;
-    }
-  return hi - 1;
-}
-
-HIDDEN int
-arm_exidx_entry_lookup (struct elf_image *ei,
-		Elf_W (Shdr) *exidx, uint32_t ip)
-{
-#if 1
-  return arm_exidx_lookup (ei->image + exidx->sh_offset, exidx->sh_size, ip);
-#else
-  unsigned n_entries = exidx->sh_size / 8;
-  uint32_t *exidx_data = ei->image + exidx->sh_offset;
-  unsigned lo = 0, hi = n_entries;
-
-  while (lo < hi)
-    {
-      unsigned mid = (lo + hi) / 2;
-      uint32_t base = exidx->sh_addr + mid * 8;
-      uint32_t addr = base + prel31_read (exidx_data[mid * 2]);
-      if (ip < addr)
-	hi = mid;
-      else
-	lo = mid + 1;
-    }
-  return hi - 1;
-#endif
-}
-
+/** 
+ * Reads the given entry and extracts the unwind instructions into buf.
+ * Returns the number of the extracted unwind insns or -UNW_ESTOPUNWIND
+ * if the special bit pattern ARM_EXIDX_CANT_UNWIND (0x1) was found.
+ */ 
 HIDDEN int
 arm_exidx_extract (struct arm_exidx_entry *entry, uint8_t *buf)
 {
@@ -417,7 +396,7 @@  arm_exidx_extract (struct arm_exidx_entry *entry, uint8_t *buf)
       else
 	{
 	  void *pers = prel31_to_addr (extbl_data);
-	  Debug (2, "%p Personality routine: %8.8x\n", addr, pers);
+	  Debug (2, "%p Personality routine: %8p\n", addr, pers);
 	  n_table_words = extbl_data[1] >> 24;
 	  buf[nbuf++] = extbl_data[1] >> 16;
 	  buf[nbuf++] = extbl_data[1] >> 8;
@@ -442,105 +421,8 @@  arm_exidx_extract (struct arm_exidx_entry *entry, uint8_t *buf)
   return nbuf;
 }
 
-HIDDEN int
-arm_exidx_entry_extract (struct elf_image *ei,
-		Elf_W (Shdr) *exidx, Elf_W (Shdr) *extbl,
-		unsigned i, uint8_t *buf)
-{
-  int nbuf = 0;
-  uint32_t *exidx_data = ei->image + exidx->sh_offset;
-  uint32_t base = exidx->sh_addr + i * 8;
-  uint32_t one = base + prel31_read (exidx_data[i * 2]);
-
-  uint32_t two = exidx_data[i * 2 + 1];
-  if (two == ARM_EXIDX_CANT_UNWIND)
-    printf ("0x1 [can't unwind]\n");
-  else if (two & ARM_EXIDX_COMPACT)
-    {
-      printf ("compact model %d [%8.8x]\n", (two >> 24) & 0x7f, two);
-      buf[nbuf++] = two >> 16;
-      buf[nbuf++] = two >> 8;
-      buf[nbuf++] = two;
-    }
-  else
-    {
-      assert (NULL != extbl);
-      two = base + prel31_read (two) + 4;
-      uint32_t *extbl_data = ei->image + extbl->sh_offset
-	      + (two - extbl->sh_addr);
-      two = extbl_data[0];
-      unsigned int n_table_words = 0;
-      if (two & ARM_EXIDX_COMPACT)
-	{
-	  int pers = (two >> 24) & 0x0f;
-	  printf ("compact model %d [%8.8x]\n", pers, two);
-	  if (pers == 1 || pers == 2)
-	    {
-	      n_table_words = (two >> 16) & 0xff;
-	      extbl_data += 1;
-	    }
-	  else
-	    buf[nbuf++] = two >> 16;
-	  buf[nbuf++] = two >> 8;
-	  buf[nbuf++] = two;
-	}
-      else
-	{
-	  uint32_t pers = prel31_read (extbl_data[0]);
-	  pers += extbl->sh_addr + i * 8 + 4;
-	  printf ("Personality routine: %8.8x\n", pers);
-	  n_table_words = extbl_data[1] >> 24;
-	  buf[nbuf++] = extbl_data[1] >> 16;
-	  buf[nbuf++] = extbl_data[1] >> 8;
-	  buf[nbuf++] = extbl_data[1];
-	  extbl_data += 2;
-	}
-      assert (n_table_words <= 5);
-      unsigned j;
-      for (j = 0; j < n_table_words; j++)
-	{
-	  two = *extbl_data++;
-	  buf[nbuf++] = two >> 24;
-	  buf[nbuf++] = two >> 16;
-	  buf[nbuf++] = two >> 8;
-	  buf[nbuf++] = two >> 0;
-	}
-    }
-
-  if (nbuf > 0 && buf[nbuf - 1] != ARM_EXTBL_OP_FINISH)
-    buf[nbuf++] = ARM_EXTBL_OP_FINISH;
-
-  return nbuf;
-}
-
-HIDDEN void
-arm_exidx_section_find (struct elf_image *ei,
-		Elf_W (Shdr) **exidx, Elf_W (Shdr) **extbl)
-{
-  Elf_W (Ehdr) *ehdr = ei->image;
-  Elf_W (Shdr) *shdr;
-  shdr = (Elf_W (Shdr) *)((char *)ei->image + ehdr->e_shoff);
-  char *names = (char *)ei->image + shdr[ehdr->e_shstrndx].sh_offset;
-  int i = 0;
-  for (i = 0; i < ehdr->e_shnum; i++)
-    {
-      char *name = names + shdr[i].sh_name;
-      switch (shdr[i].sh_type)
-	{
-	  case SHT_ARM_EXIDX:
-	    *exidx = shdr + i;
-	    break;
-	  case SHT_PROGBITS:
-	    if (strcmp (name, ".ARM.extab") != 0)
-	      break;
-	    *extbl = shdr + i;
-	    break;
-	}
-    }
-}
-
 /**
- * Callback to dl_iterate_phr to find each library's unwind table.
+ * Callback to dl_iterate_phdr to find the unwind tables.
  * If found, calls arm_exidx_table_add to remember it for later lookups.
  */
 static int
@@ -570,13 +452,13 @@  arm_exidx_init_local_cb (struct dl_phdr_info *info, size_t size, void *data)
 }
 
 /**
- * Must be called for local process lookups.
+ * Traverse the program headers of the executable and its loaded
+ * shared objects to collect the unwind tables.
  */
 HIDDEN int
 arm_exidx_init_local (const char *appname)
 {
   arm_exidx_appname = appname;
-  // traverse all libraries and find unwind tables
   arm_exidx_table_reset_all();
   return dl_iterate_phdr (&arm_exidx_init_local_cb, NULL);
 }