This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [rfc] Improve NetBSD/i386 signal trampoline detection


I've put together a new patch.

On Thursday 11 October 2007 19:04:28 Daniel Jacobowitz wrote:
> Trivial comments: you've added #includes so Makefile.in needs an
> update (maybe I'll do automatic dependencies sometime soon); please
> include a ChangeLog with all patches;

Both done.

On Thursday 11 October 2007 20:13:14 Mark Kettenis wrote:
> > From: Nick Hudson <nick.hudson@dsl.pipex.com>
> > I think I need to add the instructions for when the
> > setcontext/sigreturn fails as well. Is this correct?
>
> Probably a good idea, since it makes the false positives even less
> likely.

Done.

> By not calling i386bsd_init_abi(), tdep->jb_pc_offset is no longer
> set.  You could initialize tdep->jb_pc_offset in i386nbsd_init_abi(),
> but I'd prefer leaving in the i386bsd_init_abi() call, because it
> shows the inheritance structure a bit more clearly.

OK, no problems - I've put it back.

> It'd also be nice to have some documentation about what versions of
> NetBSD use which sigtramp code (best to stick to official releases
> here).  Perhaps that information could be used to give somewhat more
> meaningfull names to the tramp_frame varaibles.

Each variable is numbered with the NetBSD dot release that the code was first 
seen.

You'll have to forgive the ChangeLog as it's completely alien to me.

Thanks,
Nick
Index: gdb/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.939
diff -u -p -u -r1.939 Makefile.in
--- gdb/Makefile.in	27 Sep 2007 18:48:32 -0000	1.939
+++ gdb/Makefile.in	18 Oct 2007 19:57:10 -0000
@@ -2130,7 +2130,7 @@ i386nbsd-nat.o: i386nbsd-nat.c $(defs_h)
 i386nbsd-tdep.o: i386nbsd-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) \
 	$(gdbcore_h) $(regcache_h) $(regset_h) $(osabi_h) $(symtab_h) \
 	$(gdb_assert_h) $(gdb_string_h) $(i386_tdep_h) $(i387_tdep_h) \
-	$(nbsd_tdep_h) $(solib_svr4_h)
+	$(nbsd_tdep_h) $(solib_svr4_h) $(trad_frame_h) $(tramp_frame_h)
 i386-nto-tdep.o: i386-nto-tdep.c $(defs_h) $(frame_h) $(osabi_h) \
 	$(regcache_h) $(target_h) $(gdb_assert_h) $(gdb_string_h) \
 	$(i386_tdep_h) $(i387_tdep_h) $(nto_tdep_h) $(solib_svr4_h)
Index: gdb/i386nbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386nbsd-tdep.c,v
retrieving revision 1.33
diff -u -p -u -r1.33 i386nbsd-tdep.c
--- gdb/i386nbsd-tdep.c	23 Aug 2007 18:08:34 -0000	1.33
+++ gdb/i386nbsd-tdep.c	18 Oct 2007 19:57:10 -0000
@@ -26,6 +26,8 @@
 #include "regset.h"
 #include "osabi.h"
 #include "symtab.h"
+#include "trad-frame.h"
+#include "tramp-frame.h"
 
 #include "gdb_assert.h"
 #include "gdb_string.h"
@@ -91,109 +93,6 @@ i386nbsd_aout_regset_from_core_section (
   return NULL;
 }
 
-/* Under NetBSD/i386, signal handler invocations can be identified by the
-   designated code sequence that is used to return from a signal handler.
-   In particular, the return address of a signal handler points to the
-   following code sequence:
-
-	leal	0x10(%esp), %eax
-	pushl	%eax
-	pushl	%eax
-	movl	$0x127, %eax		# __sigreturn14
-	int	$0x80
-
-   Each instruction has a unique encoding, so we simply attempt to match
-   the instruction the PC is pointing to with any of the above instructions.
-   If there is a hit, we know the offset to the start of the designated
-   sequence and can then check whether we really are executing in the
-   signal trampoline.  If not, -1 is returned, otherwise the offset from the
-   start of the return sequence is returned.  */
-#define RETCODE_INSN1		0x8d
-#define RETCODE_INSN2		0x50
-#define RETCODE_INSN3		0x50
-#define RETCODE_INSN4		0xb8
-#define RETCODE_INSN5		0xcd
-
-#define RETCODE_INSN2_OFF	4
-#define RETCODE_INSN3_OFF	5
-#define RETCODE_INSN4_OFF	6
-#define RETCODE_INSN5_OFF	11
-
-static const unsigned char sigtramp_retcode[] =
-{
-  RETCODE_INSN1, 0x44, 0x24, 0x10,
-  RETCODE_INSN2,
-  RETCODE_INSN3,
-  RETCODE_INSN4, 0x27, 0x01, 0x00, 0x00,
-  RETCODE_INSN5, 0x80,
-};
-
-static LONGEST
-i386nbsd_sigtramp_offset (struct frame_info *next_frame)
-{
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
-  unsigned char ret[sizeof(sigtramp_retcode)], insn;
-  LONGEST off;
-  int i;
-
-  if (!safe_frame_unwind_memory (next_frame, pc, &insn, 1))
-    return -1;
-
-  switch (insn)
-    {
-    case RETCODE_INSN1:
-      off = 0;
-      break;
-
-    case RETCODE_INSN2:
-      /* INSN2 and INSN3 are the same.  Read at the location of PC+1
-	 to determine if we're actually looking at INSN2 or INSN3.  */
-      if (!safe_frame_unwind_memory (next_frame, pc + 1, &insn, 1))
-	return -1;
-
-      if (insn == RETCODE_INSN3)
-	off = RETCODE_INSN2_OFF;
-      else
-	off = RETCODE_INSN3_OFF;
-      break;
-
-    case RETCODE_INSN4:
-      off = RETCODE_INSN4_OFF;
-      break;
-
-    case RETCODE_INSN5:
-      off = RETCODE_INSN5_OFF;
-      break;
-
-    default:
-      return -1;
-    }
-
-  pc -= off;
-
-  if (!safe_frame_unwind_memory (next_frame, pc, ret, sizeof (ret)))
-    return -1;
-
-  if (memcmp (ret, sigtramp_retcode, sizeof (ret)) == 0)
-    return off;
-
-  return -1;
-}
-
-/* Return whether the frame preceding NEXT_FRAME corresponds to a
-   NetBSD sigtramp routine.  */
-
-static int
-i386nbsd_sigtramp_p (struct frame_info *next_frame)
-{
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
-  char *name;
-
-  find_pc_partial_function (pc, &name, NULL, NULL);
-  return (nbsd_pc_in_sigtramp (pc, name)
-	  || i386nbsd_sigtramp_offset (next_frame) >= 0);
-}
-
 /* From <machine/signal.h>.  */
 int i386nbsd_sc_reg_offset[] =
 {
@@ -215,6 +114,196 @@ int i386nbsd_sc_reg_offset[] =
   0 * 4				/* %gs */
 };
 
+/* From <machine/mcontext.h>.  */
+int i386nbsd_mc_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 */
+  14 * 4,			/* %eip */
+  16 * 4,			/* %eflags */
+  15 * 4,			/* %cs */
+  18 * 4,			/* %ss */
+  3 * 4,			/* %ds */
+  2 * 4,			/* %es */
+  1 * 4,			/* %fs */
+  0 * 4				/* %gs */
+};
+
+static void
+i386nbsd_sigtramp_cache_init (const struct tramp_frame *,
+			     struct frame_info *,
+			     struct trad_frame_cache *,
+			     CORE_ADDR);
+
+static const struct tramp_frame i386nbsd_sigtramp_sc16 =
+{
+  SIGTRAMP_FRAME,
+  1,
+  {
+    { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x10, -1 },
+			/* leal  0x10(%esp), %eax */
+    { 0x50, -1 },	/* pushl %eax */
+    { 0x50, -1 },	/* pushl %eax */
+    { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 },
+			/* movl  $0x127, %eax		# __sigreturn14 */
+    { 0xcd, -1 }, { 0x80, -1},
+			/* int   $0x80 */
+    { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
+			/* movl  $0x1, %eax		# exit */
+    { 0xcd, -1 }, { 0x80, -1},
+			/* int   $0x80 */
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  i386nbsd_sigtramp_cache_init
+};
+
+static const struct tramp_frame i386nbsd_sigtramp_sc2 =
+{
+  SIGTRAMP_FRAME,
+  1,
+  {
+    { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x0c, -1 },
+			/* leal  0x0c(%esp), %eax */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+			/* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 },
+			/* movl  $0x127, %eax		# __sigreturn14 */
+    { 0xcd, -1 }, { 0x80, -1},
+			/* int   $0x80 */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+			/* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
+			/* movl  $0x1, %eax */
+    { 0xcd, -1 }, { 0x80, -1},
+			/* int   $0x80 */
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  i386nbsd_sigtramp_cache_init
+};
+
+static const struct tramp_frame i386nbsd_sigtramp_si2 =
+{
+  SIGTRAMP_FRAME,
+  1,
+  {
+    { 0x8b, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x08, -1 },
+			/* movl  8(%esp),%eax */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+			/* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 },
+			/* movl  $0x134, %eax            # setcontext */
+    { 0xcd, -1 }, { 0x80, -1 },
+			/* int   $0x80 */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+			/* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 },
+			/* movl  $0x1, %eax */
+    { 0xcd, -1 }, { 0x80, -1 },
+			/* int   $0x80 */
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  i386nbsd_sigtramp_cache_init
+};
+
+static const struct tramp_frame i386nbsd_sigtramp_si31 =
+{
+  SIGTRAMP_FRAME,
+  1,
+  {
+    { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 },
+        { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 },
+			/* leal  0x8c(%esp), %eax */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+			/* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 },
+			/* movl  $0x134, %eax            # setcontext */
+    { 0xcd, -1 }, { 0x80, -1},
+			/* int   $0x80 */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+			/* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
+			/* movl  $0x1, %eax */
+    { 0xcd, -1 }, { 0x80, -1},
+			/* int   $0x80 */
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  i386nbsd_sigtramp_cache_init
+};
+
+static const struct tramp_frame i386nbsd_sigtramp_si4 =
+{
+  SIGTRAMP_FRAME,
+  1,
+  {
+    { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 },
+        { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 },
+			/* leal  0x8c(%esp), %eax */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+			/* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 },
+			/* movl  $0x134, %eax            # setcontext */
+    { 0xcd, -1 }, { 0x80, -1},
+			/* int   $0x80 */
+    { 0xc7, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+        { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 },
+			/* movl   $0xffffffff,0x4(%esp) */
+    { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
+			/* movl  $0x1, %eax */
+    { 0xcd, -1 }, { 0x80, -1},
+			/* int   $0x80 */
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  i386nbsd_sigtramp_cache_init
+};
+
+
+static void
+i386nbsd_sigtramp_cache_init (const struct tramp_frame *self,
+			     struct frame_info *next_frame,
+			     struct trad_frame_cache *this_cache,
+			     CORE_ADDR func)
+{
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR sp = frame_unwind_register_unsigned (next_frame, I386_ESP_REGNUM);
+  CORE_ADDR base;
+  int *reg_offset;
+  int num_regs;
+  int i;
+
+  if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2)
+    {
+      reg_offset = i386nbsd_sc_reg_offset;
+      num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset);
+
+      /* Read in the sigcontext address */
+      base = read_memory_unsigned_integer (sp + 8, 4);
+    }
+  else
+    {
+      reg_offset = i386nbsd_mc_reg_offset;
+      num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset);
+
+      /* Read in the ucontext address */
+      base = read_memory_unsigned_integer (sp + 8, 4);
+      /* offsetof(ucontext_t, uc_mcontext) == 36 */
+      base += 36;
+    }
+
+  for (i = 0; i < num_regs; i++)
+    if (reg_offset[i] != -1)
+      trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]);
+
+  /* Construct the frame ID using the function start.  */
+  trad_frame_set_id (this_cache, frame_id_build (sp, func));
+}
+
 static void 
 i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -228,18 +317,22 @@ i386nbsd_init_abi (struct gdbarch_info i
   tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset);
   tdep->sizeof_gregset = 16 * 4;
 
-  /* NetBSD has different signal trampoline conventions.  */
-  tdep->sigtramp_start = 0;
-  tdep->sigtramp_end = 0;
-  tdep->sigtramp_p = i386nbsd_sigtramp_p;
-
   /* NetBSD uses -freg-struct-return by default.  */
   tdep->struct_return = reg_struct_return;
 
-  /* NetBSD has a `struct sigcontext' that's different from the
-     original 4.3 BSD.  */
-  tdep->sc_reg_offset = i386nbsd_sc_reg_offset;
-  tdep->sc_num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset);
+  /* NetBSD uses tramp_frame sniffers for signal trampolines. */
+  tdep->sigcontext_addr= 0;
+  tdep->sigtramp_start = 0;
+  tdep->sigtramp_end = 0;
+  tdep->sigtramp_p = 0;
+  tdep->sc_reg_offset = 0;
+  tdep->sc_num_regs = 0;
+
+  tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16);
+  tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2);
+  tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2);
+  tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31);
+  tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4);
 }
 
 /* NetBSD a.out.  */
Index: gdb/tramp-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/tramp-frame.h,v
retrieving revision 1.9
diff -u -p -u -r1.9 tramp-frame.h
--- gdb/tramp-frame.h	23 Aug 2007 18:08:46 -0000	1.9
+++ gdb/tramp-frame.h	18 Oct 2007 19:57:11 -0000
@@ -62,7 +62,7 @@ struct tramp_frame
   {
     ULONGEST bytes;
     ULONGEST mask;
-  } insn[16];
+  } insn[48];
   /* Initialize a trad-frame cache corresponding to the tramp-frame.
      FUNC is the address of the instruction TRAMP[0] in memory.  */
   void (*init) (const struct tramp_frame *self,

Attachment: ChangeLog
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]