From patchwork Thu Apr 21 15:52:42 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ken Werner X-Patchwork-Id: 1147 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:49:39 -0000 Delivered-To: patches@linaro.org Received: by 10.224.67.148 with SMTP id r20cs169682qai; Thu, 21 Apr 2011 08:53:04 -0700 (PDT) Received: by 10.216.81.69 with SMTP id l47mr2092293wee.78.1303401182946; Thu, 21 Apr 2011 08:53:02 -0700 (PDT) Received: from mtagate2.uk.ibm.com (mtagate2.uk.ibm.com [194.196.100.162]) by mx.google.com with ESMTPS id f82si4444486wef.124.2011.04.21.08.53.02 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 21 Apr 2011 08:53:02 -0700 (PDT) Received-SPF: neutral (google.com: 194.196.100.162 is neither permitted nor denied by best guess record for domain of ken.werner@linaro.org) client-ip=194.196.100.162; Authentication-Results: mx.google.com; spf=neutral (google.com: 194.196.100.162 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 mtagate2.uk.ibm.com (8.13.1/8.13.1) with ESMTP id p3LFqt0a017913 for ; Thu, 21 Apr 2011 15:52:55 GMT Received: from d06av02.portsmouth.uk.ibm.com (d06av02.portsmouth.uk.ibm.com [9.149.37.228]) by d06nrmr1507.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p3LFrqfR1908760 for ; Thu, 21 Apr 2011 16:53:52 +0100 Received: from d06av02.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p3LFqsVg019629 for ; Thu, 21 Apr 2011 09:52:54 -0600 Received: from localhost.localdomain (dyn-9-152-224-51.boeblingen.de.ibm.com [9.152.224.51]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p3LFqroj019567; Thu, 21 Apr 2011 09:52:54 -0600 From: Ken Werner To: libunwind-devel@nongnu.org Subject: [PATCH 5/5] Add initial support for local unw_resume on ARM Linux. Date: Thu, 21 Apr 2011 17:52:42 +0200 Message-Id: <1303401162-14277-6-git-send-email-ken.werner@linaro.org> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1303401162-14277-1-git-send-email-ken.werner@linaro.org> References: <1303401162-14277-1-git-send-email-ken.werner@linaro.org> Provides basic support for resuming execution at a certain stack frame. Signed-off-by: Ken Werner --- src/arm/Ginit.c | 2 +- src/arm/Gresume.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/arm/unwind_i.h | 2 + 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/arm/Ginit.c b/src/arm/Ginit.c index c45a8ef..5d7dcd6 100644 --- a/src/arm/Ginit.c +++ b/src/arm/Ginit.c @@ -199,7 +199,7 @@ arm_local_addr_space_init (void) local_addr_space.acc.access_mem = access_mem; local_addr_space.acc.access_reg = access_reg; local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = 0; /* arm_local_resume? FIXME! */ + local_addr_space.acc.resume = arm_local_resume; local_addr_space.acc.get_proc_name = get_static_proc_name; unw_flush_cache (&local_addr_space, 0, 0); } diff --git a/src/arm/Gresume.c b/src/arm/Gresume.c index 4db1738..4bb4701 100644 --- a/src/arm/Gresume.c +++ b/src/arm/Gresume.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. @@ -22,10 +23,6 @@ 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. */ -/* FIXME for ARM. */ - -#include - #include "unwind_i.h" #ifndef UNW_REMOTE_ONLY @@ -33,13 +30,82 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ HIDDEN inline int arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) { +#ifdef __linux__ + struct cursor *c = (struct cursor *) cursor; + ucontext_t *uc = c->dwarf.as_arg; + unsigned long regs[10]; + + /* Copy the register contents to be restored. */ + regs[0] = uc->uc_mcontext.arm_r4; + regs[1] = uc->uc_mcontext.arm_r5; + regs[2] = uc->uc_mcontext.arm_r6; + regs[3] = uc->uc_mcontext.arm_r7; + regs[4] = uc->uc_mcontext.arm_r8; + regs[5] = uc->uc_mcontext.arm_r9; + regs[6] = uc->uc_mcontext.arm_r10; + regs[7] = uc->uc_mcontext.arm_fp; + regs[8] = uc->uc_mcontext.arm_sp; + regs[9] = uc->uc_mcontext.arm_lr; + + /* Restore the registers. */ + asm __volatile__ ( + "ldmia %0, {r4-r12, lr}\n" + "mov sp, r12\n" + "bx lr\n" + : : "r" (regs) : + ); +#else + printf ("%s: implement me\n", __FUNCTION__); +#endif return -UNW_EINVAL; } #endif /* !UNW_REMOTE_ONLY */ +static inline void +establish_machine_state (struct cursor *c) +{ + unw_addr_space_t as = c->dwarf.as; + void *arg = c->dwarf.as_arg; + unw_fpreg_t fpval; + unw_word_t val; + int reg; + + Debug (8, "copying out cursor state\n"); + + for (reg = 0; reg <= UNW_REG_LAST; ++reg) + { + Debug (16, "copying %s %d\n", unw_regname (reg), reg); + if (unw_is_fpreg (reg)) + { + if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) + as->acc.access_fpreg (as, reg, &fpval, 1, arg); + } + else + { + if (tdep_access_reg (c, reg, &val, 0) >= 0) + as->acc.access_reg (as, reg, &val, 1, arg); + } + } +} + PROTECTED int unw_resume (unw_cursor_t *cursor) { - return -UNW_EINVAL; + struct cursor *c = (struct cursor *) cursor; + + Debug (1, "(cursor=%p)\n", c); + + if (!c->dwarf.ip) + { + /* This can happen easily when the frame-chain gets truncated + due to bad or missing unwind-info. */ + Debug (1, "refusing to resume execution at address 0\n"); + return -UNW_EINVAL; + } + + establish_machine_state (c); + + return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, + c->dwarf.as_arg); } diff --git a/src/arm/unwind_i.h b/src/arm/unwind_i.h index 315aeb2..61ab545 100644 --- a/src/arm/unwind_i.h +++ b/src/arm/unwind_i.h @@ -37,5 +37,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define arm_local_addr_space_init UNW_OBJ(local_addr_space_init) extern void arm_local_addr_space_init (void); +extern int arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, + void *arg); #endif /* unwind_i_h */