From patchwork Tue Mar 15 18:15:43 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ken Werner X-Patchwork-Id: 586 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:44:00 -0000 Delivered-To: patches@linaro.org Received: by 10.151.46.5 with SMTP id y5cs77949ybj; Tue, 15 Mar 2011 11:15:55 -0700 (PDT) Received: by 10.216.82.68 with SMTP id n46mr10429773wee.57.1300212953953; Tue, 15 Mar 2011 11:15:53 -0700 (PDT) Received: from mtagate1.uk.ibm.com (mtagate1.uk.ibm.com [194.196.100.161]) by mx.google.com with ESMTPS id u18si88747wes.186.2011.03.15.11.15.52 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 15 Mar 2011 11:15:52 -0700 (PDT) Received-SPF: neutral (google.com: 194.196.100.161 is neither permitted nor denied by best guess record for domain of ken.werner@linaro.org) client-ip=194.196.100.161; Authentication-Results: mx.google.com; spf=neutral (google.com: 194.196.100.161 is neither permitted nor denied by best guess record for domain of ken.werner@linaro.org) smtp.mail=ken.werner@linaro.org Received: from d06nrmr1507.portsmouth.uk.ibm.com (d06nrmr1507.portsmouth.uk.ibm.com [9.149.38.233]) by mtagate1.uk.ibm.com (8.13.1/8.13.1) with ESMTP id p2FIFlXB025170 for ; Tue, 15 Mar 2011 18:15:47 GMT Received: from d06av09.portsmouth.uk.ibm.com (d06av09.portsmouth.uk.ibm.com [9.149.37.250]) by d06nrmr1507.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p2FIG6ka1659030 for ; Tue, 15 Mar 2011 18:16:06 GMT Received: from d06av09.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av09.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p2FIFkDR008771 for ; Tue, 15 Mar 2011 12:15:46 -0600 Received: from localhost.localdomain (dyn-9-152-224-51.boeblingen.de.ibm.com [9.152.224.51]) by d06av09.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p2FIFjdd008732; Tue, 15 Mar 2011 12:15:46 -0600 From: Ken Werner To: libunwind-devel@nongnu.org Subject: [PATCH 3/4] Use ARM-specific unwinding tables in unw_step Date: Tue, 15 Mar 2011 18:15:43 +0000 Message-Id: <1300212944-24984-4-git-send-email-ken.werner@linaro.org> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1300212944-24984-1-git-send-email-ken.werner@linaro.org> References: <1300212944-24984-1-git-send-email-ken.werner@linaro.org> From: Zachary T Welch 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 --- 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);