diff options
author | Zachary T Welch <zwelch@codesourcery.com> | 2011-03-15 18:15:42 +0000 |
---|---|---|
committer | Arun Sharma <asharma@fb.com> | 2011-03-22 08:14:51 -0700 |
commit | ffc474b8c8972200642acaef3e5aa10ee853609a (patch) | |
tree | b3d95f5d9603a2b822552f00318df7e6965dd1d1 /include/tdep-arm | |
parent | 049e2ba1b9734ec027765cd9449cb29a9bc0d974 (diff) | |
download | libunwind-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.h | 128 | ||||
-rw-r--r-- | include/tdep-arm/libunwind_i.h | 2 |
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; }; |