From patchwork Tue Mar 22 18:37:08 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ken Werner X-Patchwork-Id: 741 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:45:19 -0000 Delivered-To: patches@linaro.org Received: by 10.204.113.5 with SMTP id y5cs10161bkp; Tue, 22 Mar 2011 11:37:15 -0700 (PDT) Received: by 10.14.126.135 with SMTP id b7mr1919170eei.214.1300819032555; Tue, 22 Mar 2011 11:37:12 -0700 (PDT) Received: from mtagate1.uk.ibm.com (mtagate1.uk.ibm.com [194.196.100.161]) by mx.google.com with ESMTPS id q47si9653329eeh.54.2011.03.22.11.37.12 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 22 Mar 2011 11:37:12 -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 p2MIbCu1023370 for ; Tue, 22 Mar 2011 18:37:12 GMT Received: from d06av10.portsmouth.uk.ibm.com (d06av10.portsmouth.uk.ibm.com [9.149.37.251]) by d06nrmr1507.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p2MIbcnf1634554 for ; Tue, 22 Mar 2011 18:37:38 GMT Received: from d06av10.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av10.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p2MIbBK2016731 for ; Tue, 22 Mar 2011 12:37:11 -0600 Received: from localhost.localdomain (dyn-9-152-224-51.boeblingen.de.ibm.com [9.152.224.51]) by d06av10.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p2MIb9Tl016683; Tue, 22 Mar 2011 12:37:11 -0600 From: Ken Werner To: libunwind-devel@nongnu.org Subject: [PATCH 3/3] Use ARM-specific unwinding tables in unw_step Date: Tue, 22 Mar 2011 18:37:08 +0000 Message-Id: <1300819028-31314-4-git-send-email-ken.werner@linaro.org> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1300819028-31314-1-git-send-email-ken.werner@linaro.org> References: <1300819028-31314-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 | 4 +++ src/arm/Gstep.c | 58 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/include/tdep-arm/libunwind_i.h b/include/tdep-arm/libunwind_i.h index 21628cf..acaf6d7 100644 --- a/include/tdep-arm/libunwind_i.h +++ b/include/tdep-arm/libunwind_i.h @@ -260,6 +260,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..8a4ae3e 100644 --- a/src/arm/Ginit_local.c +++ b/src/arm/Ginit_local.c @@ -47,6 +47,10 @@ 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)) + arm_exidx_init_local (); + return common_init (c, 1); } diff --git a/src/arm/Gstep.c b/src/arm/Gstep.c index 5eac5f0..90c5f5b 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,48 @@ 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) +{ + unw_word_t old_ip, old_cfa; + struct arm_exidx_table *table; + struct arm_exidx_entry *entry; + uint8_t buf[32]; + int ret; + + old_ip = c->dwarf.ip; + old_cfa = c->dwarf.cfa; + + /* mark PC unsaved */ + c->dwarf.loc[UNW_ARM_R15] = DWARF_NULL_LOC; + + table = arm_exidx_table_find ((void *)c->dwarf.ip); + if (NULL == table) + return -UNW_ENOINFO; + + entry = arm_exidx_table_lookup (table, (void *)c->dwarf.ip); + if (NULL == entry) + return -UNW_ENOINFO; + + ret = arm_exidx_extract (entry, buf); + if (ret < 0) + return ret; + + ret = arm_exidx_decode (buf, ret, &c->dwarf); + if (ret < 0) + return ret; + + if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa) + { + Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", + __FUNCTION__, (long) c->dwarf.ip); + return -UNW_EBADFRAME; + } + + return (c->dwarf.ip == 0) ? 0 : 1; +} PROTECTED int unw_step (unw_cursor_t *cursor) @@ -33,8 +76,7 @@ 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. */ + /* First, try DWARF-based unwinding. */ if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) { ret = dwarf_step (&c->dwarf); @@ -50,6 +92,18 @@ unw_step (unw_cursor_t *cursor) } } + /* Next, try extbl-based unwinding. */ + if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) + { + ret = arm_exidx_step (c); + if (ret >= 0) + return 1; + if (ret == -UNW_ESTOPUNWIND) + return 0; + } + + /* Fall back on APCS frame parsing. + Note: This won't work in case the ARM EABI is used. */ if (unlikely (ret < 0)) { if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME))