This is the mail archive of the gdb-patches@sources.redhat.com 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]

[PATCH] Fix FreeBSD/i386 sigtramp recognition


This fixes backtracing through signal handlers on FreeBSD/i386 4.0 and
up (and keeps older FreeBSD versions working).  Only for a native GDB
though.  This is also a small step in the process of multi-arching the
i386.

Stu, can you check whether this fixes your backtracing problems on
FreeBSD 4.2?  The difference in behaviour between this code and your
code should be minimal.  This patch detects the location of the
sigtramp at runtime using sysclt(3).  And I placed the beginning of
the sigtramp at 128 bytes under PS_STRINGS instead of 100 (Why?  Uhm,
it's it power of 2).  Oh and leaving SIGTRAMP_START and SIGTRAMP_END
defined makes GDB recognize the sigtramp as a function (with the name
<sigtramp>).

Checked in.

Mark

Index: ChangeLog
from  Mark Kettenis  <kettenis@gnu.org>

	* i386bsd-nat.c: Include <signal.h>, <stddef.h> and
	<sys/sysctl.h>.
	(store_inferior_registers): Wrap long line.
	(i386bsd_dr_get_status): Fix typo in comment.
	(_initialize_i386bsd_nat): New function.  * i386bsd-tdep.c: New
	file.  * config/i386/tm-fbsd.h (IN_SIGTRAMP): New define.
	(i386bsd_in_sigtramp): New prototype.
	(SIGTRAMP_START, SIGTRAMP_END): Redefine in terms...
	(i386bsd_sigtramp_start, i386bsd_sigtramp_end): ...these new
	(external) variables.
	(SIGCONTEXT_PC_OFFSET): Removed.
	(FRAME_SAVED_PC): New define.
	(i386bsd_frame_saved_pc): New function.
	* config/i386/fbsd.mt (TDEPFILES): Add i386bsd-tdep.o.

Index: i386bsd-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/i386bsd-nat.c,v
retrieving revision 1.7
diff -u -p -r1.7 i386bsd-nat.c
--- i386bsd-nat.c 2001/05/04 04:15:25 1.7
+++ i386bsd-nat.c 2001/07/13 18:24:49
@@ -23,6 +23,8 @@
 #include "regcache.h"
 
 #include "gdb_assert.h"
+#include <signal.h>
+#include <stddef.h>
 #include <sys/types.h>
 #include <sys/ptrace.h>
 #include <machine/reg.h>
@@ -198,7 +200,8 @@ store_inferior_registers (int regno)
 
   fill_gregset (&gregs, regno);
 
-  if (ptrace (PT_SETREGS, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
+  if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
+	      (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
     perror_with_name ("Couldn't write registers");
 
   if (regno == -1 || regno >= FP0_REGNUM)
@@ -279,7 +282,7 @@ i386bsd_dr_get_status (void)
   /* FIXME: kettenis/2001-03-31: Calling perror_with_name if the
      ptrace call fails breaks debugging remote targets.  The correct
      way to fix this is to add the hardware breakpoint and watchpoint
-     stuff to the target vectore.  For now, just return zero if the
+     stuff to the target vector.  For now, just return zero if the
      ptrace call fails.  */
   if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
 	      (PTRACE_ARG3_TYPE) & dbregs, 0) == -1)
@@ -315,4 +318,46 @@ int
 kernel_u_size (void)
 {
   return (sizeof (struct user));
+}
+
+/* See i386bsd-tdep.c.  */
+extern int i386bsd_sigcontext_pc_offset;
+
+#include <sys/sysctl.h>
+
+void
+_initialize_i386bsd_nat (void)
+{
+  /* To support the recognition of signal handlers, i386bsd-tdep.c
+     hardcodes some constants.  Inclusion of this file means that we
+     are compiling a native debugger, which means that we can use the
+     system header files and sysctl(3) to get at the relevant
+     information.  */
+
+  /* Override the default value for the offset of the program counter
+     in the sigcontext structure.  */
+  i386bsd_sigcontext_pc_offset = offsetof (struct sigcontext, sc_pc);
+
+  /* FreeBSD provides a kern.ps_strings sysctl that we can use to
+     locate the sigtramp.  That way we can still recognize a sigtramp
+     if it's location is changed in a new kernel.  Of course this is
+     still based on the assumption that the sigtramp is placed
+     directly under the location where the program arguments and
+     environment can be found.  */
+#ifdef KERN_PS_STRINGS
+  {
+    int mib[2];
+    int ps_strings;
+    size_t len;
+
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_PS_STRINGS;
+    len = sizeof (ps_strings);
+    if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
+      {
+	i386bsd_sigtramp_start = ps_strings - 128;
+	i386bsd_sigtramp_end = ps_strings;
+      }
+  }
+#endif
 }
Index: config/i386/tm-fbsd.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-fbsd.h,v
retrieving revision 1.3
diff -u -p -r1.3 tm-fbsd.h
--- config/i386/tm-fbsd.h 2001/03/06 08:21:28 1.3
+++ config/i386/tm-fbsd.h 2001/07/13 18:24:49
@@ -1,5 +1,5 @@
 /* Target-dependent definitions for FreeBSD/i386.
-   Copyright 1997, 1999, 2000 Free Software Foundation, Inc.
+   Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -40,21 +40,31 @@
 /* Figure out where the longjmp will land.  Store the address that
    longjmp will jump to in *ADDR, and return non-zero if successful.  */
 
-extern int get_longjmp_target (CORE_ADDR *addr);
 #define GET_LONGJMP_TARGET(addr) get_longjmp_target (addr)
+extern int get_longjmp_target (CORE_ADDR *addr);
 
 
 /* Support for signal handlers.  */
+
+#define IN_SIGTRAMP(pc, name) i386bsd_in_sigtramp (pc, name)
+extern int i386bsd_in_sigtramp (CORE_ADDR pc, char *name);
+
+/* These defines allow the recognition of sigtramps as a function name
+   <sigtramp>.
+
+   FIXME: kettenis/2001-07-13: These should be added to the target
+   vector and turned into functions when we go "multi-arch".  */
 
-/* The sigtramp is above the user stack and immediately below
-   the user area.  Using constants here allows for cross debugging.
-   These are tested for FreeBSD 3.4.  */
+#define SIGTRAMP_START(pc) i386bsd_sigtramp_start
+#define SIGTRAMP_END(pc) i386bsd_sigtramp_end
+extern CORE_ADDR i386bsd_sigtramp_start;
+extern CORE_ADDR i386bsd_sigtramp_end;
 
-#define SIGTRAMP_START(pc)	0xbfbfdf20
-#define SIGTRAMP_END(pc)	0xbfbfdff0
+/* Override FRAME_SAVED_PC to enable the recognition of signal handlers.  */
 
-/* Offset to saved PC in sigcontext, from <sys/signal.h>.  */
-#define SIGCONTEXT_PC_OFFSET 20
+#undef FRAME_SAVED_PC
+#define FRAME_SAVED_PC(frame) i386bsd_frame_saved_pc (frame)
+extern CORE_ADDR i386bsd_frame_saved_pc (struct frame_info *frame);
 
 
 /* Shared library support.  */
Index: config/i386/fbsd.mt
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/fbsd.mt,v
retrieving revision 1.2
diff -u -p -r1.2 fbsd.mt
--- config/i386/fbsd.mt 2000/05/24 22:32:58 1.2
+++ config/i386/fbsd.mt 2001/07/13 18:24:49
@@ -1,3 +1,3 @@
 # Target: Intel 386 running FreeBSD
-TDEPFILES= i386-tdep.o i387-tdep.o
+TDEPFILES= i386-tdep.o i387-tdep.o i386bsd-tdep.o
 TM_FILE= tm-fbsd.h
--- /dev/null	Thu Feb 19 16:30:24 1998
+++ i386bsd-tdep.c	Fri Jul 13 18:55:50 2001
@@ -0,0 +1,84 @@
+/* Target-dependent code for i386 BSD's.
+   Copyright 2001 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "frame.h"
+#include "gdbcore.h"
+#include "regcache.h"
+
+/* Support for signal handlers.  */
+
+/* Range in which to find the signaltramp routine, traditionally found
+   on the use stack, just below the user area.  Initialized to values
+   that work for NetBSD and FreeBSD.  */
+
+CORE_ADDR i386bsd_sigtramp_start = 0xbfbfdf20;
+CORE_ADDR i386bsd_sigtramp_end = 0xbfbfdff0;
+
+/* Return whether PC is in a BSD sigtramp routine.  */
+
+int
+i386bsd_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  return (pc >= i386bsd_sigtramp_start && pc < i386bsd_sigtramp_end);
+}
+
+/* Offset in the sigcontext structure of the program counter.
+   Initialized to the value from 4.4 BSD Lite.  */
+int i386bsd_sigcontext_pc_offset = 20;
+
+/* Assuming FRAME is for a BSD sigtramp routine, return the address of
+   the associated sigcontext structure.  */
+
+static CORE_ADDR
+i386bsd_sigcontext_addr (struct frame_info *frame)
+{
+  if (frame->next)
+    /* If this isn't the top frame, the next frame must be for the
+       signal handler itself.  A pointer to the sigcontext structure
+       is passed as the third argument to the signal handler.  */
+    return read_memory_unsigned_integer (frame->next->frame + 16, 4);
+
+  /* This is the top frame.  We'll have to find the address of the
+     sigcontext structure by looking at the stack pointer.  */
+  return read_memory_unsigned_integer (read_register (SP_REGNUM) + 8, 4);
+}
+
+/* Assuming FRAME is for a BSD sigtramp routine, return the saved
+   program counter.  */
+
+static CORE_ADDR
+i386bsd_sigtramp_saved_pc (struct frame_info *frame)
+{
+  CORE_ADDR addr;
+  addr = i386bsd_sigcontext_addr (frame);
+  return read_memory_unsigned_integer (addr + i386bsd_sigcontext_pc_offset, 4);
+}
+
+/* Return the saved program counter for FRAME.  */
+
+CORE_ADDR
+i386bsd_frame_saved_pc (struct frame_info *frame)
+{
+  if (frame->signal_handler_caller)
+    return i386bsd_sigtramp_saved_pc (frame);
+
+  return read_memory_unsigned_integer (frame->frame + 4, 4);
+}


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