From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5058 invoked by alias); 17 Oct 2013 11:31:58 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 5048 invoked by uid 89); 17 Oct 2013 11:31:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_PASS,UNPARSEABLE_RELAY autolearn=ham version=3.3.2 X-HELO: aserp1040.oracle.com Received: from aserp1040.oracle.com (HELO aserp1040.oracle.com) (141.146.126.69) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Thu, 17 Oct 2013 11:31:56 +0000 Received: from acsinet22.oracle.com (acsinet22.oracle.com [141.146.126.238]) by aserp1040.oracle.com (Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.1) with ESMTP id r9HBVmAi008704 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 17 Oct 2013 11:31:49 GMT Received: from aserz7021.oracle.com (aserz7021.oracle.com [141.146.126.230]) by acsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r9HBVlx9017450 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 17 Oct 2013 11:31:48 GMT Received: from abhmt114.oracle.com (abhmt114.oracle.com [141.146.116.66]) by aserz7021.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r9HBVlWh023118; Thu, 17 Oct 2013 11:31:47 GMT Received: from termi.oracle.com (/10.175.44.107) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 17 Oct 2013 04:31:46 -0700 From: jose.marchesi@oracle.com (Jose E. Marchesi) To: Joel Brobecker Cc: Tom Tromey , gdb-patches@sourceware.org Subject: Re: [PATCH] [SPARC64] Figure out where a longjmp will land References: <87y563k71b.fsf@oracle.com> <87d2nffr53.fsf@fleche.redhat.com> <87txgrjupm.fsf@oracle.com> <20131017055736.GC3302@adacore.com> Date: Thu, 17 Oct 2013 11:31:00 -0000 In-Reply-To: <20131017055736.GC3302@adacore.com> (Joel Brobecker's message of "Thu, 17 Oct 2013 09:57:36 +0400") Message-ID: <87r4bk1694.fsf@oracle.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-IsSubscribed: yes X-SW-Source: 2013-10/txt/msg00511.txt.bz2 > 2013-10-08 Jose E. Marchesi > > * sparc-tdep.c (sparc_is_annulled_branch_insn): New function. > * sparc-tdep.h: And its prototype. > > * sparc64-linux-tdep.c (sparc64_linux_get_longjmp_target): New > function. > (sparc64_linux_init_abi): Register the get_longjmp_target hook. This looks reasonable to me, with a minor correction requested below. But Sparc patches normally get reviewed by MarkK, so can you give it another week before checking the final version in? (remember that when you check something in that is different from the patch already posted, an updated patch should be sent to the list, for the record). Noted, but I don't have write access to the CVS so I can't check anything in. I assume that this was validated against our testsuite, and that no new regressions were detected? Yes. I always run the testsuite for regressions before submitting any patch. I tested this on sparc64-unknown-linux-gnu. > +/* Figure out where a longjmp will land. Get the args out of the > + output registers. We expect the first arg to be a pointer to the > + jmp_buf structure from which we extract the address that we will > + land at. This address is copied into PC. This routine returns > + non-zero on success. */ > + > +static int > +sparc64_linux_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) This function is expected to implement a gdbarch callback, so you do not need to repeat the spec, which is expected to already be documented in gdbarch.h. Instead, use: /* Implement the "get_longjmp_target" gdbarch method. */ Amended patch below. 2013-10-08 Jose E. Marchesi * sparc-tdep.c (sparc_is_annulled_branch_insn): New function. * sparc-tdep.h: And its prototype. * sparc64-linux-tdep.c (sparc64_linux_get_longjmp_target): New function. (sparc64_linux_init_abi): Register the get_longjmp_target hook. Index: sparc-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sparc-tdep.c,v retrieving revision 1.233 diff -u -r1.233 sparc-tdep.c --- sparc-tdep.c 24 Jun 2013 22:18:32 -0000 1.233 +++ sparc-tdep.c 17 Oct 2013 11:27:05 -0000 @@ -121,6 +121,17 @@ return ((insn & 0xc1c00000) == 0); } +/* Return non-zero if the instruction corresponding to PC is an + "annulled" branch, i.e. the annul bit is set. */ + +int +sparc_is_annulled_branch_insn (CORE_ADDR pc) +{ + const unsigned long insn = sparc_fetch_instruction (pc); + + return X_A (insn); +} + /* OpenBSD/sparc includes StackGhost, which according to the author's website http://stackghost.cerias.purdue.edu "... transparently and automatically protects applications' stack frames; more Index: sparc-tdep.h =================================================================== RCS file: /cvs/src/src/gdb/sparc-tdep.h,v retrieving revision 1.33 diff -u -r1.33 sparc-tdep.h --- sparc-tdep.h 1 Jan 2013 06:32:51 -0000 1.33 +++ sparc-tdep.h 17 Oct 2013 11:27:05 -0000 @@ -202,6 +202,12 @@ extern void sparc_collect_rwindow (const struct regcache *regcache, CORE_ADDR sp, int regnum); + + +extern int sparc_is_annulled_branch_insn (CORE_ADDR pc); + + + /* Register offsets for SunOS 4. */ extern const struct sparc_gregset sparc32_sunos4_gregset; extern const struct sparc_fpregset sparc32_sunos4_fpregset; Index: sparc64-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sparc64-linux-tdep.c,v retrieving revision 1.31 diff -u -r1.31 sparc64-linux-tdep.c --- sparc64-linux-tdep.c 1 Jan 2013 06:32:51 -0000 1.31 +++ sparc64-linux-tdep.c 17 Oct 2013 11:27:05 -0000 @@ -233,6 +233,50 @@ } +/* Implement the "get_longjmp_target" gdbarch method. */ + +static int +sparc64_linux_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) +{ + struct gdbarch *gdbarch = get_frame_arch (frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + CORE_ADDR jb_addr; + gdb_byte buf[8]; + + jb_addr = get_frame_register_unsigned (frame, SPARC_O0_REGNUM); + + /* setjmp and longjmp in SPARC64 are implemented in glibc using the + setcontext and getcontext system calls respectively. These + system calls operate on ucontext_t structures, which happen to + partially have the same structure than jmp_buf. However the + ucontext returned by getcontext, and thus the jmp_buf structure + returned by setjmp, contains the context of the trap instruction + in the glibc __[sig]setjmp wrapper, not the context of the user + code calling setjmp. + + %o7 in the jmp_buf structure is stored at offset 18*8 in the + mc_gregs array, which is itself located at offset 32 into + jmp_buf. See bits/setjmp.h. This register contains the address + of the 'call setjmp' instruction in user code. + + In order to determine the longjmp target address in the + initiating frame we need to examine the call instruction itself, + in particular whether the annul bit is set. If it is not set + then we need to jump over the instruction at the delay slot. */ + + if (target_read_memory (jb_addr + 32 + (18 * 8), buf, 8)) + return 0; + + *pc = extract_unsigned_integer (buf, 8, gdbarch_byte_order (gdbarch)); + + if (!sparc_is_annulled_branch_insn (*pc)) + *pc += 4; /* delay slot insn */ + *pc += 4; /* call insn */ + + return 1; +} + + static void sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) @@ -272,6 +316,9 @@ /* Make sure we can single-step over signal return system calls. */ tdep->step_trap = sparc64_linux_step_trap; + /* Make sure we can single-step over longjmp calls. */ + set_gdbarch_get_longjmp_target (gdbarch, sparc64_linux_get_longjmp_target); + set_gdbarch_write_pc (gdbarch, sparc64_linux_write_pc); /* Functions for 'catch syscall'. */