Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Samuel Thibault <samuel.thibault@gnu.org>
To: gdb-patches@sourceware.org
Cc: Thomas Schwinge <thomas@codesourcery.com>,
	thomas@schwinge.name, bug-hurd@gnu.org
Subject: [PATCH] hurd: unwinding support over signal trampolines
Date: Sat, 30 May 2020 01:00:49 +0200	[thread overview]
Message-ID: <20200529230049.jmsn5nincf2453jy@function> (raw)

gdb/ChangeLog:

2020-05-29  Samuel Thibault  <samuel.thibault@ens-lyon.org>

	* i386-gnu-tdep.c: Include "gdbcore.h"
	(gnu_sigtramp_code, i386_gnu_sc_reg_offset): New arrays.
        (GNU_SIGTRAMP_LEN, GNU_SIGTRAMP_TAIL,
        I386_GNU_SIGCONTEXT_THREAD_STATE_OFFSET): New macros
        (i386_gnu_sigtramp_start, i386_gnu_sigtramp_p,
        i386_gnu_sigcontext_addr): New functions
        (i386gnu_init_abi): Register i386_gnu_sigtramp_p,
        i386_gnu_sigcontext_addr, and i386_gnu_sc_reg_offset in the gdbarch
        tdep.

Index: binutils-gdb/gdb/i386-gnu-tdep.c
===================================================================
--- binutils-gdb.orig/gdb/i386-gnu-tdep.c
+++ binutils-gdb/gdb/i386-gnu-tdep.c
@@ -17,11 +17,138 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "gdbcore.h"
 #include "osabi.h"
 #include "solib-svr4.h"
 
 #include "i386-tdep.h"
 
+/* Recognizing signal handler frames.  */
+
+/* When the GNU/Hurd libc calls a signal handler, the return address points
+   inside the trampoline assembly snippet.
+
+   If the trampoline function name can not be identified, we resort to reading
+   memory from the process in order to identify it.  */
+
+static const gdb_byte gnu_sigtramp_code[] =
+{
+/* rpc_wait_trampoline: */
+  0xb8, 0xe7, 0xff, 0xff, 0xff,			/* mov    $-25,%eax */
+  0x9a, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,	/* lcall  $7,$0 */
+  0x89, 0x01,					/* movl   %eax, (%ecx) */
+  0x89, 0xdc,					/* movl   %ebx, %esp */
+
+/* trampoline: */
+  0xff, 0xd2,					/* call   *%edx */
+/* RA HERE */
+  0x83, 0xc4, 0x0c,				/* addl   $12, %esp */
+  0xc3,						/* ret */
+
+/* firewall: */
+  0xf4,						/* hlt */
+};
+
+#define GNU_SIGTRAMP_LEN (sizeof gnu_sigtramp_code)
+#define GNU_SIGTRAMP_TAIL 5			/* length of tail after RA */
+
+/* If THIS_FRAME is a sigtramp routine, return the address of the
+   start of the routine.  Otherwise, return 0.  */
+
+static CORE_ADDR
+i386_gnu_sigtramp_start (struct frame_info *this_frame)
+{
+  CORE_ADDR pc = get_frame_pc (this_frame);
+  gdb_byte buf[GNU_SIGTRAMP_LEN];
+
+  if (!safe_frame_unwind_memory (this_frame,
+				 pc + GNU_SIGTRAMP_TAIL - GNU_SIGTRAMP_LEN,
+				 buf, GNU_SIGTRAMP_LEN))
+    return 0;
+
+  if (memcmp (buf, gnu_sigtramp_code, GNU_SIGTRAMP_LEN) != 0)
+    return 0;
+
+  return pc;
+}
+
+/* Return whether THIS_FRAME corresponds to a GNU/Linux sigtramp
+   routine.  */
+
+static int
+i386_gnu_sigtramp_p (struct frame_info *this_frame)
+{
+  CORE_ADDR pc = get_frame_pc (this_frame);
+  const char *name;
+
+  find_pc_partial_function (pc, &name, NULL, NULL);
+
+  /* If we have a NAME, we can check for the trampoline function */
+  if (name != NULL && strcmp (name, "trampoline") == 0)
+    return 1;
+
+  return i386_gnu_sigtramp_start (this_frame) != 0;
+}
+
+/* Offset to sc_i386_thread_state in sigcontext, from <bits/sigcontext.h>.  */
+#define I386_GNU_SIGCONTEXT_THREAD_STATE_OFFSET 20
+
+/* Assuming THIS_FRAME is a GNU/Linux sigtramp routine, return the
+   address of the associated sigcontext structure.  */
+
+static CORE_ADDR
+i386_gnu_sigcontext_addr (struct frame_info *this_frame)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  CORE_ADDR pc;
+  CORE_ADDR sp;
+  gdb_byte buf[4];
+
+  get_frame_register (this_frame, I386_ESP_REGNUM, buf);
+  sp = extract_unsigned_integer (buf, 4, byte_order);
+
+  pc = i386_gnu_sigtramp_start (this_frame);
+  if (pc)
+    {
+      CORE_ADDR sigcontext_addr;
+
+      /* The sigcontext structure address is passed as the third argument to
+	 the signal handler. */
+      read_memory (sp + 8, buf, 4);
+      sigcontext_addr = extract_unsigned_integer (buf, 4, byte_order);
+      return sigcontext_addr + I386_GNU_SIGCONTEXT_THREAD_STATE_OFFSET;
+    }
+
+  error (_("Couldn't recognize signal trampoline."));
+  return 0;
+}
+
+/* Mapping between the general-purpose registers in `struct
+   sigcontext' format (starting at sc_i386_thread_state)
+   and GDB's register cache layout.  */
+
+/* From <bits/sigcontext.h>.  */
+static int i386_gnu_sc_reg_offset[] =
+{
+  11 * 4,			/* %eax */
+  10 * 4,			/* %ecx */
+  9 * 4,			/* %edx */
+  8 * 4,			/* %ebx */
+  7 * 4,			/* %esp */
+  6 * 4,			/* %ebp */
+  5 * 4,			/* %esi */
+  4 * 4,			/* %edi */
+  12 * 4,			/* %eip */
+  14 * 4,			/* %eflags */
+  13 * 4,			/* %cs */
+  16 * 4,			/* %ss */
+  3 * 4,			/* %ds */
+  2 * 4,			/* %es */
+  1 * 4,			/* %fs */
+  0 * 4				/* %gs */
+};
+
 /* From <sys/ucontext.h>.  */
 static int i386gnu_gregset_reg_offset[] =
 {
@@ -59,6 +186,11 @@ i386gnu_init_abi (struct gdbarch_info in
   tdep->sizeof_gregset = 19 * 4;
 
   tdep->jb_pc_offset = 20;	/* From <bits/setjmp.h>.  */
+
+  tdep->sigtramp_p = i386_gnu_sigtramp_p;
+  tdep->sigcontext_addr = i386_gnu_sigcontext_addr;
+  tdep->sc_reg_offset = i386_gnu_sc_reg_offset;
+  tdep->sc_num_regs = ARRAY_SIZE (i386_gnu_sc_reg_offset);
 }
 
 void _initialize_i386gnu_tdep ();


             reply	other threads:[~2020-05-29 23:00 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-29 23:00 Samuel Thibault [this message]
2020-05-30 15:07 ` Simon Marchi

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=20200529230049.jmsn5nincf2453jy@function \
    --to=samuel.thibault@gnu.org \
    --cc=bug-hurd@gnu.org \
    --cc=gdb-patches@sourceware.org \
    --cc=thomas@codesourcery.com \
    --cc=thomas@schwinge.name \
    /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