Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: jose.marchesi@oracle.com (Jose E. Marchesi)
To: Joel Brobecker <brobecker@adacore.com>
Cc: Tom Tromey <tromey@redhat.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH] [SPARC64] Figure out where a longjmp will land
Date: Thu, 17 Oct 2013 11:31:00 -0000	[thread overview]
Message-ID: <87r4bk1694.fsf@oracle.com> (raw)
In-Reply-To: <20131017055736.GC3302@adacore.com> (Joel Brobecker's message of	"Thu, 17 Oct 2013 09:57:36 +0400")

    > 2013-10-08  Jose E. Marchesi  <jose.marchesi@oracle.com>
    > 
    > 	* 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  <jose.marchesi@oracle.com>

	* 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);
 
+\f
+
+extern int sparc_is_annulled_branch_insn (CORE_ADDR pc);
+
+\f
+
 /* 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 @@
 }
 
 \f
+/* 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;
+}
+
+\f
 
 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'.  */


  reply	other threads:[~2013-10-17 11:31 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-08 17:25 Jose E. Marchesi
2013-10-08 20:23 ` Tom Tromey
2013-10-08 20:49   ` Sergio Durigan Junior
2013-10-08 21:51   ` Jose E. Marchesi
2013-10-17  5:57     ` Joel Brobecker
2013-10-17 11:31       ` Jose E. Marchesi [this message]
2013-10-20 19:32         ` Mark Kettenis
2013-10-21 12:52           ` Jose E. Marchesi
2013-10-20 19:27       ` Mark Kettenis
2013-10-21 12:53         ` Jose E. Marchesi
2013-10-22  8:22           ` Mark Kettenis
2013-11-18 14:02             ` Jose E. Marchesi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87r4bk1694.fsf@oracle.com \
    --to=jose.marchesi@oracle.com \
    --cc=brobecker@adacore.com \
    --cc=gdb-patches@sourceware.org \
    --cc=tromey@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox