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]
Other format: [Raw text]

PATCH: Detect support for fork tracing on Linux


I got bogged down submitting the patches for fork event tracing.  This is an
attempt to come back at the problem from another angle.

This patch adds runtime detection of fork event support.  Instead of always
showing "not implemented yet", the code will select between "not implemented
yet" and "not available on your system".  Pretty useless on its own, but it
provides framework to move forward.

Unfortunately the error moves from when the catchpoint is requested to when
it is inserted.  Fixing this will require more target methods, and it's
purely cosmetic, so I left it off for now.  I have a good idea of what I'd
want the new method to look like but I don't want to do it until we've
cleaned up breakpoint/catchpoint handling a bit as discussed by Andrew.

Anyone have comments on this patch?  If not I'll probably check it in next
week.  Then the other pieces can start to come in incrementally.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2003-03-26  Daniel Jacobowitz  <drow at mvista dot com>

	* Makefile.in (linux-nat.o): Add rule.
	* linux-nat.c: New file.
	* config/nm-linux.h (CHILD_INSERT_FORK_CATCHPOINT): Define.
	(CHILD_INSERT_VFORK_CATCHPOINT): Define.
	(CHILD_INSERT_EXEC_CATCHPOINT): Define.
	* config/alpha/alpha-linux.mh (NATDEPFILES): Add linux-nat.o.
	* config/arm/linux.mh (NATDEPFILES): Likewise.
	* config/i386/linux.mh (NATDEPFILES): Likewise.
	* config/i386/x86-64linux.mh (NATDEPFILES): Likewise.
	* config/ia64/linux.mh (NATDEPFILES): Likewise.
	* config/m68k/linux.mh (NATDEPFILES): Likewise.
	* config/mips/linux.mh (NATDEPFILES): Likewise.
	* config/powerpc/linux.mh (NATDEPFILES): Likewise.
	* config/s390/s390.mh (NATDEPFILES): Likewise.
	* config/sparc/linux.mh (NATDEPFILES): Likewise.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.351
diff -u -p -r1.351 Makefile.in
--- Makefile.in	26 Mar 2003 03:39:42 -0000	1.351
+++ Makefile.in	26 Mar 2003 19:59:44 -0000
@@ -1864,6 +1864,7 @@ lin-lwp.o: lin-lwp.c $(defs_h) $(gdb_ass
 linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \
 	$(symfile_h) $(objfiles_h) $(demangle_h) $(value_h) $(completer_h) \
 	$(cp_abi_h) $(source_h) $(parser_defs_h) $(block_h)
+linux-nat.o: linux-nat.c $(defs_h) $(inferior_h) $(target_h) $(gdb_wait_h)
 linux-proc.o: linux-proc.c $(defs_h) $(inferior_h) $(regcache_h) \
 	$(gregset_h) $(gdbcore_h) $(gdbthread_h) $(elf_bfd_h) \
 	$(cli_decode_h) $(gdb_string_h)
Index: linux-nat.c
===================================================================
RCS file: linux-nat.c
diff -N linux-nat.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linux-nat.c	26 Mar 2003 19:59:44 -0000
@@ -0,0 +1,176 @@
+/* GNU/Linux native-dependent code common to multiple platforms.
+   Copyright (C) 2003 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 "inferior.h"
+#include "target.h"
+
+#include "gdb_wait.h"
+#include <sys/ptrace.h>
+
+/* If the system headers did not provide the constants, hard-code the normal
+   values.  */
+#ifndef PTRACE_EVENT_FORK
+
+#define PTRACE_SETOPTIONS	0x4200
+#define PTRACE_GETEVENTMSG	0x4201
+
+/* options set using PTRACE_SETOPTIONS */
+#define PTRACE_O_TRACESYSGOOD	0x00000001
+#define PTRACE_O_TRACEFORK	0x00000002
+#define PTRACE_O_TRACEVFORK	0x00000004
+#define PTRACE_O_TRACECLONE	0x00000008
+#define PTRACE_O_TRACEEXEC	0x00000010
+
+/* Wait extended result codes for the above trace options.  */
+#define PTRACE_EVENT_FORK	1
+#define PTRACE_EVENT_VFORK	2
+#define PTRACE_EVENT_CLONE	3
+#define PTRACE_EVENT_EXEC	4
+
+#endif /* PTRACE_EVENT_FORK */
+
+/* We can't always assume that this flag is available, but all systems
+   with the ptrace event handlers also have __WALL, so it's safe to use
+   here.  */
+#ifndef __WALL
+#define __WALL          0x40000000 /* Wait for any child.  */
+#endif
+
+/* This variable is a tri-state flag: -1 for unknown, 0 if PTRACE_O_TRACEFORK
+   can not be used, 1 if it can.  */
+
+static int linux_supports_tracefork_flag = -1;
+
+
+/* A helper function for linux_test_for_tracefork, called after fork ().  */
+
+static void
+linux_tracefork_child (void)
+{
+  int ret;
+
+  ptrace (PTRACE_TRACEME, 0, 0, 0);
+  kill (getpid (), SIGSTOP);
+  fork ();
+  exit (0);
+}
+
+/* Determine if PTRACE_O_TRACEFORK can be used to follow fork events.  We
+   create a child process, attach to it, use PTRACE_SETOPTIONS to enable
+   fork tracing, and let it fork.  If the process exits, we assume that
+   we can't use TRACEFORK; if we get the fork notification, and we can
+   extract the new child's PID, then we assume that we can.  */
+
+static void
+linux_test_for_tracefork (void)
+{
+  int child_pid, ret, status;
+  long second_pid;
+
+  child_pid = fork ();
+  if (child_pid == -1)
+    perror_with_name ("linux_test_for_tracefork: fork");
+
+  if (child_pid == 0)
+    linux_tracefork_child ();
+
+  ret = waitpid (child_pid, &status, 0);
+  if (ret == -1)
+    perror_with_name ("linux_test_for_tracefork: waitpid");
+  else if (ret != child_pid)
+    error ("linux_test_for_tracefork: waitpid: unexpected result %d.", ret);
+  if (! WIFSTOPPED (status))
+    error ("linux_test_for_tracefork: waitpid: unexpected status %d.", status);
+
+  linux_supports_tracefork_flag = 0;
+
+  ret = ptrace (PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACEFORK);
+  if (ret != 0)
+    {
+      ptrace (PTRACE_KILL, child_pid, 0, 0);
+      waitpid (child_pid, &status, 0);
+      return;
+    }
+
+  ptrace (PTRACE_CONT, child_pid, 0, 0);
+  ret = waitpid (child_pid, &status, 0);
+  if (ret == child_pid && WIFSTOPPED (status)
+      && status >> 16 == PTRACE_EVENT_FORK)
+    {
+      second_pid = 0;
+      ret = ptrace (PTRACE_GETEVENTMSG, child_pid, 0, &second_pid);
+      if (ret == 0 && second_pid != 0)
+	{
+	  int second_status;
+
+	  linux_supports_tracefork_flag = 1;
+	  waitpid (second_pid, &second_status, 0);
+	  ptrace (PTRACE_DETACH, second_pid, 0, 0);
+	}
+    }
+
+  if (WIFSTOPPED (status))
+    {
+      ptrace (PTRACE_DETACH, child_pid, 0, 0);
+      waitpid (child_pid, &status, 0);
+    }
+}
+
+/* Return non-zero iff we have tracefork functionality available.
+   This function also sets linux_supports_tracefork_flag.  */
+
+static int
+linux_supports_tracefork (void)
+{
+  if (linux_supports_tracefork_flag == -1)
+    linux_test_for_tracefork ();
+  return linux_supports_tracefork_flag;
+}
+
+
+int
+child_insert_fork_catchpoint (int pid)
+{
+  if (linux_supports_tracefork ())
+    error ("Fork catchpoints have not been implemented yet.");
+  else
+    error ("Your system does not support fork catchpoints.");
+}
+
+int
+child_insert_vfork_catchpoint (int pid)
+{
+  if (linux_supports_tracefork ())
+    error ("Vfork catchpoints have not been implemented yet.");
+  else
+    error ("Your system does not support vfork catchpoints.");
+}
+
+int
+child_insert_exec_catchpoint (int pid)
+{
+  if (linux_supports_tracefork ())
+    error ("Exec catchpoints have not been implemented yet.");
+  else
+    error ("Your system does not support exec catchpoints.");
+}
+
+
Index: config/nm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/nm-linux.h,v
retrieving revision 1.13
diff -u -p -r1.13 nm-linux.h
--- config/nm-linux.h	26 Nov 2002 01:23:46 -0000	1.13
+++ config/nm-linux.h	26 Mar 2003 19:59:44 -0000
@@ -75,3 +75,7 @@ struct mem_attrib;
 extern int linux_proc_xfer_memory (CORE_ADDR addr, char *myaddr, int len,
 				   int write, struct mem_attrib *attrib,
 				   struct target_ops *target);
+
+#define CHILD_INSERT_FORK_CATCHPOINT
+#define CHILD_INSERT_VFORK_CATCHPOINT
+#define CHILD_INSERT_EXEC_CATCHPOINT
Index: config/alpha/alpha-linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/alpha/alpha-linux.mh,v
retrieving revision 1.10
diff -u -p -r1.10 alpha-linux.mh
--- config/alpha/alpha-linux.mh	4 Dec 2002 05:40:40 -0000	1.10
+++ config/alpha/alpha-linux.mh	26 Mar 2003 19:59:44 -0000
@@ -2,7 +2,8 @@
 XM_FILE= xm-alphalinux.h
 NAT_FILE= nm-linux.h
 NATDEPFILES= infptrace.o inftarg.o corelow.o alpha-nat.o linux-proc.o \
-	fork-child.o proc-service.o thread-db.o lin-lwp.o gcore.o
+	fork-child.o proc-service.o thread-db.o lin-lwp.o gcore.o \
+	linux-nat.o
 
 LOADLIBES = -ldl -rdynamic
 
Index: config/arm/linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/arm/linux.mh,v
retrieving revision 1.10
diff -u -p -r1.10 linux.mh
--- config/arm/linux.mh	18 Jan 2002 04:50:58 -0000	1.10
+++ config/arm/linux.mh	26 Mar 2003 19:59:44 -0000
@@ -5,7 +5,7 @@ XM_FILE= xm-linux.h
 NAT_FILE= nm-linux.h
 NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o	\
 	core-regset.o arm-linux-nat.o linux-proc.o gcore.o	\
-	proc-service.o thread-db.o lin-lwp.o
+	proc-service.o thread-db.o lin-lwp.o linux-nat.o
 
 LOADLIBES= -ldl -rdynamic
 
Index: config/i386/linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/linux.mh,v
retrieving revision 1.12
diff -u -p -r1.12 linux.mh
--- config/i386/linux.mh	11 May 2002 17:22:27 -0000	1.12
+++ config/i386/linux.mh	26 Mar 2003 19:59:44 -0000
@@ -5,7 +5,8 @@ XM_FILE= xm-i386.h
 NAT_FILE= nm-linux.h
 NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o linux-proc.o \
 	core-aout.o i386-nat.o i386-linux-nat.o \
-	proc-service.o thread-db.o lin-lwp.o linux-proc.o gcore.o
+	proc-service.o thread-db.o lin-lwp.o linux-proc.o gcore.o \
+	linux-nat.o
 
 # The dynamically loaded libthread_db needs access to symbols in the
 # gdb executable.
Index: config/i386/x86-64linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/x86-64linux.mh,v
retrieving revision 1.7
diff -u -p -r1.7 x86-64linux.mh
--- config/i386/x86-64linux.mh	1 Jul 2002 22:09:52 -0000	1.7
+++ config/i386/x86-64linux.mh	26 Mar 2003 19:59:44 -0000
@@ -6,6 +6,6 @@ NAT_FILE= nm-x86-64linux.h
 NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \
 	core-aout.o i386-nat.o x86-64-linux-nat.o \
 	proc-service.o thread-db.o lin-lwp.o \
-	linux-proc.o gcore.o 
+	linux-proc.o gcore.o linux-nat.o
 
 LOADLIBES = -ldl -rdynamic
Index: config/ia64/linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/ia64/linux.mh,v
retrieving revision 1.13
diff -u -p -r1.13 linux.mh
--- config/ia64/linux.mh	4 Feb 2002 19:11:17 -0000	1.13
+++ config/ia64/linux.mh	26 Mar 2003 19:59:44 -0000
@@ -5,6 +5,6 @@ XM_FILE= xm-linux.h
 NAT_FILE= nm-linux.h
 NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o gcore.o \
 	core-aout.o core-regset.o ia64-linux-nat.o linux-proc.o \
-	proc-service.o thread-db.o lin-lwp.o
+	proc-service.o thread-db.o lin-lwp.o linux-nat.o
 
 LOADLIBES = -ldl -rdynamic
Index: config/m68k/linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/m68k/linux.mh,v
retrieving revision 1.10
diff -u -p -r1.10 linux.mh
--- config/m68k/linux.mh	14 Feb 2002 05:48:35 -0000	1.10
+++ config/m68k/linux.mh	26 Mar 2003 19:59:44 -0000
@@ -5,7 +5,7 @@ XM_FILE= xm-linux.h
 NAT_FILE= nm-linux.h
 NATDEPFILES= infptrace.o inftarg.o fork-child.o \
 	corelow.o core-aout.o m68klinux-nat.o linux-proc.o gcore.o \
-	proc-service.o thread-db.o lin-lwp.o 
+	proc-service.o thread-db.o lin-lwp.o linux-nat.o
 
 # The dynamically loaded libthread_db needs access to symbols in the
 # gdb executable.
Index: config/mips/linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/linux.mh,v
retrieving revision 1.4
diff -u -p -r1.4 linux.mh
--- config/mips/linux.mh	18 Jan 2002 04:51:03 -0000	1.4
+++ config/mips/linux.mh	26 Mar 2003 19:59:44 -0000
@@ -2,6 +2,7 @@
 XM_FILE= xm-linux.h
 NAT_FILE= nm-linux.h
 NATDEPFILES= infptrace.o inftarg.o fork-child.o mips-linux-nat.o \
-	thread-db.o lin-lwp.o proc-service.o linux-proc.o gcore.o
+	thread-db.o lin-lwp.o proc-service.o linux-proc.o gcore.o \
+	linux-nat.o
 
 LOADLIBES = -ldl -rdynamic
Index: config/powerpc/linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/powerpc/linux.mh,v
retrieving revision 1.12
diff -u -p -r1.12 linux.mh
--- config/powerpc/linux.mh	30 Jul 2002 19:03:49 -0000	1.12
+++ config/powerpc/linux.mh	26 Mar 2003 19:59:44 -0000
@@ -6,7 +6,7 @@ XM_CLIBS=
 NAT_FILE= nm-linux.h
 NATDEPFILES= infptrace.o inftarg.o fork-child.o linux-proc.o \
 	ppc-linux-nat.o proc-service.o thread-db.o lin-lwp.o \
-	gcore.o
+	gcore.o linux-nat.o
 
 LOADLIBES = -ldl -rdynamic
 
Index: config/s390/s390.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/s390/s390.mh,v
retrieving revision 1.6
diff -u -p -r1.6 s390.mh
--- config/s390/s390.mh	28 Apr 2002 00:30:01 -0000	1.6
+++ config/s390/s390.mh	26 Mar 2003 19:59:44 -0000
@@ -6,7 +6,7 @@ XM_CLIBS=
 NAT_FILE= nm-linux.h
 NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o s390-nat.o \
 	core-aout.o core-regset.o linux-proc.o gcore.o thread-db.o lin-lwp.o \
-	proc-service.o
+	proc-service.o linux-nat.o
 LOADLIBES = -ldl -rdynamic
 
 
Index: config/sparc/linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/sparc/linux.mh,v
retrieving revision 1.9
diff -u -p -r1.9 linux.mh
--- config/sparc/linux.mh	4 May 2002 15:52:42 -0000	1.9
+++ config/sparc/linux.mh	26 Mar 2003 19:59:44 -0000
@@ -5,7 +5,7 @@ XM_FILE= xm-linux.h
 NAT_FILE= nm-linux.h
 NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o sparc-nat.o \
 	proc-service.o thread-db.o lin-lwp.o sparc-linux-nat.o \
-	linux-proc.o gcore.o 
+	linux-proc.o gcore.o linux-nat.o
 
 # The dynamically loaded libthread_db needs access to symbols in the
 # gdb executable.


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