summaryrefslogtreecommitdiff
path: root/include/tdep-arm
diff options
context:
space:
mode:
authorZachary T Welch <zwelch@codesourcery.com>2011-03-15 18:15:42 +0000
committerArun Sharma <asharma@fb.com>2011-03-22 08:14:51 -0700
commitffc474b8c8972200642acaef3e5aa10ee853609a (patch)
treeb3d95f5d9603a2b822552f00318df7e6965dd1d1 /include/tdep-arm
parent049e2ba1b9734ec027765cd9449cb29a9bc0d974 (diff)
downloadlibunwind-ffc474b8c8972200642acaef3e5aa10ee853609a.tar.gz
Add module for parsing ARM-specific unwind tables
Handles lookup, extracting unwind entries, and decoding the entry using a callback mechanism. Signed-off-by: Ken Werner <ken.werner@linaro.org>
Diffstat (limited to 'include/tdep-arm')
-rw-r--r--include/tdep-arm/ex_tables.h128
-rw-r--r--include/tdep-arm/libunwind_i.h2
2 files changed, 130 insertions, 0 deletions
diff --git a/include/tdep-arm/ex_tables.h b/include/tdep-arm/ex_tables.h
new file mode 100644
index 00000000..3805c608
--- /dev/null
+++ b/include/tdep-arm/ex_tables.h
@@ -0,0 +1,128 @@
+/* libunwind - a platform-independent unwind library
+ Copyright 2011 Linaro Limited
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef ARM_EX_TABLES_H
+#define ARM_EX_TABLES_H
+
+struct arm_exidx_entry {
+ uint32_t addr;
+ uint32_t data;
+};
+
+struct arm_exidx_table {
+ const char *name;
+ struct arm_exidx_entry *start;
+ struct arm_exidx_entry *end;
+ void *start_addr;
+ void *end_addr;
+#ifdef ARM_EXIDX_TABLE_MALLOC
+ struct arm_exidx_table *next;
+#endif
+};
+
+
+typedef enum arm_exbuf_cmd {
+ ARM_EXIDX_CMD_FINISH,
+ ARM_EXIDX_CMD_DATA_PUSH,
+ ARM_EXIDX_CMD_DATA_POP,
+ ARM_EXIDX_CMD_REG_POP,
+ ARM_EXIDX_CMD_REG_TO_SP,
+ ARM_EXIDX_CMD_VFP_POP,
+ ARM_EXIDX_CMD_WREG_POP,
+ ARM_EXIDX_CMD_WCGR_POP,
+ ARM_EXIDX_CMD_RESERVED,
+ 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_callback_data {
+ uint8_t ops[11];
+ uint8_t n_ops;
+ arm_exbuf_cmd_t cmd;
+ uint32_t data;
+ void *cb_data;
+};
+
+typedef int (*arm_exbuf_callback_t)(struct arm_exbuf_callback_data *aecb);
+
+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);
+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);
+int arm_exidx_extract (struct arm_exidx_entry *entry, uint8_t *buf);
+
+int arm_exidx_decode (const uint8_t *buf, uint8_t len,
+ arm_exbuf_callback_t cb, void *cb_data);
+
+struct arm_stackframe {
+ void *fp;
+ void *sp;
+ void *lr;
+ void *pc;
+};
+
+struct arm_exidx_vrs {
+ uint32_t vrs[16];
+};
+
+enum arm_exidx_vrs_regs {
+ FP_thumb = 7,
+ FP_arm = 11,
+ SP = 13,
+ LR = 14,
+ PC = 15,
+};
+
+void arm_exidx_frame_to_vrs(struct arm_stackframe *f, struct arm_exidx_vrs *s);
+int arm_exidx_vrs_to_frame(struct arm_exidx_vrs *s, struct arm_stackframe *f);
+
+int arm_exidx_vrs_callback (struct arm_exbuf_callback_data *aecd);
+
+#endif // ARM_EX_TABLES_H
diff --git a/include/tdep-arm/libunwind_i.h b/include/tdep-arm/libunwind_i.h
index 5f02ed07..a565d9be 100644
--- a/include/tdep-arm/libunwind_i.h
+++ b/include/tdep-arm/libunwind_i.h
@@ -34,6 +34,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "elf32.h"
#include "mempool.h"
#include "dwarf.h"
+#include "ex_tables.h"
struct unw_addr_space
{
@@ -54,6 +55,7 @@ struct unw_addr_space
struct cursor
{
struct dwarf_cursor dwarf; /* must be first */
+ struct arm_stackframe frame;
unw_word_t sigcontext_addr;
};