From: Zachary T Welch <[email protected]> Uses ex_tables routines to provide a new means of unwinding the stack. Set UNW_ARM_UNWIND_METHOD=4 to use ARM-specific unwinding tables.
Signed-off-by: Ken Werner <[email protected]> --- include/tdep-arm/libunwind_i.h | 1 + src/arm/Ginit_local.c | 17 +++++++++++++++++ src/arm/Gstep.c | 40 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/include/tdep-arm/libunwind_i.h b/include/tdep-arm/libunwind_i.h index a565d9b..839415c 100644 --- a/include/tdep-arm/libunwind_i.h +++ b/include/tdep-arm/libunwind_i.h @@ -261,6 +261,7 @@ extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, #define UNW_ARM_METHOD_ALL 0xFF #define UNW_ARM_METHOD_DWARF 0x01 #define UNW_ARM_METHOD_FRAME 0x02 +#define UNW_ARM_METHOD_EXIDX 0x04 #define unwi_unwind_method UNW_OBJ(unwind_method) extern int unwi_unwind_method; diff --git a/src/arm/Ginit_local.c b/src/arm/Ginit_local.c index debf5bb..2a0d73a 100644 --- a/src/arm/Ginit_local.c +++ b/src/arm/Ginit_local.c @@ -1,5 +1,6 @@ /* libunwind - a platform-independent unwind library Copyright (C) 2008 CodeSourcery + Copyright 2011 Linaro Limited This file is part of libunwind. @@ -38,6 +39,7 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) PROTECTED int unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) { + register void *current_sp asm ("sp"); struct cursor *c = (struct cursor *) cursor; if (tdep_needs_initialization) @@ -47,6 +49,21 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) c->dwarf.as = unw_local_addr_space; c->dwarf.as_arg = uc; + + if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) + { + int arm_exidx_init_done = 0; + if (!arm_exidx_init_done) + { + arm_exidx_init_done = 1; + arm_exidx_init_local ("libunwind"); + } + c->frame.fp = __builtin_frame_address (0); + c->frame.sp = current_sp; + c->frame.lr = __builtin_return_address (0); + c->frame.pc = &unw_init_local; + } + return common_init (c, 1); } diff --git a/src/arm/Gstep.c b/src/arm/Gstep.c index 5eac5f0..ab556d7 100644 --- a/src/arm/Gstep.c +++ b/src/arm/Gstep.c @@ -1,5 +1,6 @@ /* libunwind - a platform-independent unwind library Copyright (C) 2008 CodeSourcery + Copyright 2011 Linaro Limited This file is part of libunwind. @@ -24,6 +25,33 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" #include "offsets.h" +#include "ex_tables.h" + +static inline int +arm_exidx_step (struct cursor *c) +{ + struct arm_exidx_table *table = arm_exidx_table_find (c->frame.pc); + if (NULL == table) + return -UNW_ENOINFO; + + struct arm_exidx_entry *entry = arm_exidx_table_lookup (table, c->frame.pc); + if (NULL == entry) + return -UNW_ENOINFO; + + struct arm_exidx_vrs s; + arm_exidx_frame_to_vrs (&c->frame, &s); + + uint8_t buf[32]; + int ret = arm_exidx_extract (entry, buf); + if (ret < 0) + return ret; + + ret = arm_exidx_decode (buf, ret, &arm_exidx_vrs_callback, &s); + if (ret < 0) + return -ret; + + return arm_exidx_vrs_to_frame (&s, &c->frame); +} PROTECTED int unw_step (unw_cursor_t *cursor) @@ -33,8 +61,16 @@ unw_step (unw_cursor_t *cursor) Debug (1, "(cursor=%p)\n", c); - /* Try DWARF-based unwinding... this is the only method likely to work for - ARM. */ + if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) + { + ret = arm_exidx_step (c); + if (ret >= 0) + return ret; + if (ret < 0 && ret != -UNW_ENOINFO) + return ret; + } + + /* Next, try DWARF-based unwinding. */ if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) { ret = dwarf_step (&c->dwarf); -- 1.7.4.1 _______________________________________________ Libunwind-devel mailing list [email protected] http://lists.nongnu.org/mailman/listinfo/libunwind-devel
