Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Nov 1997 16:41:56 -0800 (PST)
From:      Sean Eric Fagan <sef@kithrup.com>
To:        hackers@freebsd.org
Subject:   procfs patches
Message-ID:  <199711270041.QAA00355@garth.kithrup.com>

next in thread | raw e-mail | index | archive | help
These are the kernel side of the truss work I've been doing for the past
few years.  I'm running a 2.2 system with these patches.

The truss and procctl programs are at http://www.freebsd.org/~sef/truss --
it works, and even works for linux binaries.  (I'm working on even better
version, that will be able to print out the arguments in an intelligent
fashion, but that's nowhere near ready.)

Enjoy.  I expect to check this stuff in "soon" (hopefully within a couple of
weekends).  Note that you need to rebuild libkvm, ps, gdb, and all LKM's -- I
kinda paniced one of my systems when I forgot about that, and went multiuser
;).  Also note the new file -- sys/pioctl.h.

Index: i386/i386/trap.c
===================================================================
RCS file: /kithrup/cvs/src/sys/i386/i386/trap.c,v
retrieving revision 1.114
diff -u -r1.114 trap.c
--- trap.c	1997/11/06 19:28:09	1.114
+++ trap.c	1997/11/15 05:05:46
@@ -49,6 +49,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
+#include <sys/pioctl.h>
 #include <sys/kernel.h>
 #include <sys/syscall.h>
 #include <sys/sysent.h>
@@ -959,6 +960,8 @@
 	p->p_retval[0] = 0;
 	p->p_retval[1] = frame.tf_edx;
 
+	STOPEVENT(p, S_SCE, callp->sy_narg);
+
 	error = (*callp->sy_call)(p, args);
 
 	switch (error) {
@@ -1009,6 +1012,14 @@
 	if (KTRPOINT(p, KTR_SYSRET))
 		ktrsysret(p->p_tracep, code, error, p->p_retval[0]);
 #endif
+
+	/*
+	 * This works because errno is findable through the
+	 * register set.  If we ever support an emulation where this
+	 * is not the case, this code will need to be revisited.
+	 */
+	STOPEVENT(p, S_SCX, code);
+
 }
 
 /*
Index: kern/init_main.c
===================================================================
RCS file: /kithrup/cvs/src/sys/kern/init_main.c,v
retrieving revision 1.74
diff -u -r1.74 init_main.c
--- init_main.c	1997/11/07 08:52:53	1.74
+++ init_main.c	1997/11/15 05:05:45
@@ -417,6 +417,12 @@
 	 * Charge root for one process.
 	 */
 	(void)chgproccnt(0, 1);
+
+	/*
+	 * Initialize the procfs flags (to 0, of course)
+	 */
+	p->p_stops = p->p_stype = p->p_step = 0;
+
 }
 SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL)
 
Index: kern/kern_exec.c
===================================================================
RCS file: /kithrup/cvs/src/sys/kern/kern_exec.c,v
retrieving revision 1.68
diff -u -r1.68 kern_exec.c
--- kern_exec.c	1997/11/06 19:29:08	1.68
+++ kern_exec.c	1997/11/15 05:05:45
@@ -40,6 +40,7 @@
 #include <sys/imgact_elf.h>
 #include <sys/wait.h>
 #include <sys/proc.h>
+#include <sys/pioctl.h>
 #include <sys/malloc.h>
 #include <sys/namei.h>
 #include <sys/sysent.h>
@@ -338,6 +339,8 @@
 	 * If tracing the process, trap to debugger so breakpoints
 	 * 	can be set before the program executes.
 	 */
+	STOPEVENT(p, S_EXEC, 0);
+
 	if (p->p_flag & P_TRACED)
 		psignal(p, SIGTRAP);
 
Index: kern/kern_exit.c
===================================================================
RCS file: /kithrup/cvs/src/sys/kern/kern_exit.c,v
retrieving revision 1.60
diff -u -r1.60 kern_exit.c
--- kern_exit.c	1997/11/20 19:09:43	1.60
+++ kern_exit.c	1997/11/22 06:55:04
@@ -46,6 +46,7 @@
 #include <sys/sysproto.h>
 #include <sys/malloc.h>
 #include <sys/proc.h>
+#include <sys/pioctl.h>
 #include <sys/tty.h>
 #include <sys/wait.h>
 #include <sys/vnode.h>
@@ -113,6 +114,7 @@
 	register struct proc *q, *nq;
 	register struct vmspace *vm;
 	ele_p ep = exit_list;
+	extern void procfs_exit(pid_t);
 
 	if (p->p_pid == 1) {
 		printf("init died (signal %d, exit %d)\n",
@@ -155,6 +157,14 @@
 #ifdef PGINPROF
 	vmsizmon();
 #endif
+	STOPEVENT(p, S_EXIT, rv);
+
+	/*
+	 * Now that we're back from stopevent(), force a close
+	 * of all open procfs files for this process.
+	 */
+	procfs_exit(p->p_pid);
+
 	/* 
 	 * Check if any LKMs need anything done at process exit.
 	 * e.g. SYSV IPC stuff
Index: kern/kern_sig.c
===================================================================
RCS file: /kithrup/cvs/src/sys/kern/kern_sig.c,v
retrieving revision 1.35
diff -u -r1.35 kern_sig.c
--- kern_sig.c	1997/11/06 19:29:14	1.35
+++ kern_sig.c	1997/11/27 00:34:07
@@ -49,6 +49,7 @@
 #include <sys/namei.h>
 #include <sys/vnode.h>
 #include <sys/proc.h>
+#include <sys/pioctl.h>
 #include <sys/systm.h>
 #include <sys/acct.h>
 #include <sys/fcntl.h>
@@ -743,15 +744,19 @@
 	register sig_t action;
 	int mask;
 
-	if ((u_int)signum >= NSIG || signum == 0)
+	if ((u_int)signum >= NSIG || signum == 0) {
+		printf("psignal: signum %d\n", signum);
 		panic("psignal signal number");
+	}
 	mask = sigmask(signum);
 	prop = sigprop[signum];
 
 	/*
-	 * If proc is traced, always give parent a chance.
+	 * If proc is traced, always give parent a chance;
+	 * if signal event is tracked by procfs, give *that*
+	 * a chance, as well.
 	 */
-	if (p->p_flag & P_TRACED)
+	if ((p->p_flag & P_TRACED) || (p->p_stops & S_SIG))
 		action = SIG_DFL;
 	else {
 		/*
@@ -948,6 +953,8 @@
 	register int signum, mask, prop;
 
 	for (;;) {
+		int traced = (p->p_flag & P_TRACED) || (p->p_stops & S_SIG);
+
 		mask = p->p_siglist & ~p->p_sigmask;
 		if (p->p_flag & P_PPWAIT)
 			mask &= ~stopsigmask;
@@ -956,11 +963,14 @@
 		signum = ffs((long)mask);
 		mask = sigmask(signum);
 		prop = sigprop[signum];
+
+		STOPEVENT(p, S_SIG, signum);
+
 		/*
 		 * We should see pending but ignored signals
 		 * only if P_TRACED was on when they were posted.
 		 */
-		if (mask & p->p_sigignore && (p->p_flag & P_TRACED) == 0) {
+		if ((mask & p->p_sigignore) && (traced == 0)) {
 			p->p_siglist &= ~mask;
 			continue;
 		}
@@ -974,7 +984,8 @@
 			do {
 				stop(p);
 				mi_switch();
-			} while (!trace_req(p) && p->p_flag & P_TRACED);
+			} while (!trace_req(p)
+				 && p->p_flag & P_TRACED);
 
 			/*
 			 * If the traced bit got turned off, go back up
@@ -1118,6 +1129,8 @@
 		    signum, action, ps->ps_flags & SAS_OLDMASK ?
 		    ps->ps_oldmask : p->p_sigmask, 0);
 #endif
+	STOPEVENT(p, S_SIG, signum);
+
 	if (action == SIG_DFL) {
 		/*
 		 * Default action, where the default is to kill
@@ -1235,6 +1248,8 @@
 	struct vattr vattr;
 	int error, error1;
 	char name[MAXCOMLEN+6];		/* progname.core */
+
+	STOPEVENT(p, S_CORE, 0);
 
 	if (p->p_flag & P_SUGID)
 		return (EFAULT);
Index: kern/sys_process.c
===================================================================
RCS file: /kithrup/cvs/src/sys/kern/sys_process.c,v
retrieving revision 1.32
diff -u -r1.32 sys_process.c
--- sys_process.c	1997/11/12 12:28:12	1.32
+++ sys_process.c	1997/11/15 05:05:44
@@ -503,3 +503,22 @@
 {
 	return 1;
 }
+
+/*
+ * stopevent()
+ * Stop a process because of a procfs event;
+ * stay stopped until p->p_step is cleared
+ * (cleared by PIOCCONT in procfs).
+ */
+
+void
+stopevent(struct proc *p, unsigned int event, unsigned int val) {
+	p->p_step = 1;
+
+	do {
+		p->p_xstat = val;
+		p->p_stype = event;	/* Which event caused the stop? */
+		wakeup(&p->p_stype);	/* Wake up any PIOCWAIT'ing procs */
+		tsleep(&p->p_step, PWAIT, "stopevent", 0);
+	} while (p->p_step);
+}
Index: kern/vfs_vnops.c
===================================================================
RCS file: /kithrup/cvs/src/sys/kern/vfs_vnops.c,v
retrieving revision 1.41
diff -u -r1.41 vfs_vnops.c
--- vfs_vnops.c	1997/11/07 08:53:11	1.41
+++ vfs_vnops.c	1997/11/15 05:05:43
@@ -453,8 +453,9 @@
 		/* fall into ... */
 
 	default:
+#if 0
 		return (ENOTTY);
-
+#endif
 	case VFIFO:
 	case VCHR:
 	case VBLK:
Index: miscfs/procfs/procfs_subr.c
===================================================================
RCS file: /kithrup/cvs/src/sys/miscfs/procfs/procfs_subr.c,v
retrieving revision 1.17
diff -u -r1.17 procfs_subr.c
--- procfs_subr.c	1997/08/02 14:32:18	1.17
+++ procfs_subr.c	1997/11/15 05:05:43
@@ -351,3 +351,14 @@
 
 	return (0);
 }
+
+void
+procfs_exit(pid_t pid)
+{
+	struct pfsnode *pfs;
+
+	for (pfs = pfshead; pfs ; pfs = pfs->pfs_next) {
+		if (pfs->pfs_pid == pid)
+			vgone(PFSTOV(pfs));
+	}
+}
Index: miscfs/procfs/procfs_vnops.c
===================================================================
RCS file: /kithrup/cvs/src/sys/miscfs/procfs/procfs_vnops.c,v
retrieving revision 1.42
diff -u -r1.42 procfs_vnops.c
--- procfs_vnops.c	1997/11/07 08:53:15	1.42
+++ procfs_vnops.c	1997/11/15 05:12:51
@@ -55,6 +55,7 @@
 #include <sys/dirent.h>
 #include <machine/reg.h>
 #include <miscfs/procfs/procfs.h>
+#include <sys/pioctl.h>
 
 static int	procfs_abortop __P((struct vop_abortop_args *));
 static int	procfs_access __P((struct vop_access_args *));
@@ -63,6 +64,7 @@
 static int	procfs_close __P((struct vop_close_args *));
 static int	procfs_getattr __P((struct vop_getattr_args *));
 static int	procfs_inactive __P((struct vop_inactive_args *));
+static int	procfs_ioctl __P((struct vop_ioctl_args *));
 static int	procfs_lookup __P((struct vop_lookup_args *));
 static int	procfs_open __P((struct vop_open_args *));
 static int	procfs_print __P((struct vop_print_args *));
@@ -184,6 +186,79 @@
 }
 
 /*
+ * do an ioctl operation on a pfsnode (vp).
+ * (vp) is not locked on entry or exit.
+ */
+static int
+procfs_ioctl(ap)
+	struct vop_ioctl_args *ap;
+{
+	struct pfsnode *pfs = VTOPFS(ap->a_vp);
+	struct proc *procp;
+	int error;
+	int signo;
+	struct procfs_status *psp;
+
+	procp = pfind(pfs->pfs_pid);
+	if (procp == NULL) {
+		return ENOTTY;
+	}
+
+	switch (ap->a_command) {
+	case PIOCBIS:
+	  procp->p_stops |= *(unsigned int*)ap->a_data;
+	  break;
+	case PIOCBIC:
+	  procp->p_stops &= ~*(unsigned int*)ap->a_data;
+	  break;
+	case PIOCSFL:
+	  procp->p_pfsflags = (unsigned char)*(unsigned int*)ap->a_data;
+	  *(unsigned int*)ap->a_data = procp->p_stops;
+	  break;
+	case PIOCSTATUS:
+	  psp = (struct procfs_status *)ap->a_data;
+	  psp->state = (procp->p_step == 0);
+	  psp->flags = procp->p_pfsflags;
+	  psp->events = procp->p_stops;
+	  if (procp->p_step) {
+	    psp->why = procp->p_stype;
+	    psp->val = procp->p_xstat;
+	  } else {
+	    psp->why = psp->val = 0;	/* Not defined values */
+	  }
+	  break;
+	case PIOCWAIT:
+	  psp = (struct procfs_status *)ap->a_data;
+	  if (procp->p_step == 0) {
+	    error = tsleep(&procp->p_stype, PWAIT | PCATCH, "piocwait", 0);
+	    if (error)
+	      return error;
+	  }
+	  psp->state = 1;	/* It stopped */
+	  psp->flags = procp->p_pfsflags;
+	  psp->events = procp->p_stops;
+	  psp->why = procp->p_stype;	/* why it stopped */
+	  psp->val = procp->p_xstat;	/* any extra info */
+	  break;
+	case PIOCCONT:	/* Restart a proc */
+	  if (procp->p_step == 0)
+	    return EINVAL;	/* Can only start a stopped process */
+	  if (ap->a_data && (signo = *(int*)ap->a_data)) {
+	    if (signo >= NSIG || signo <= 0)
+	      return EINVAL;
+	    if (error = psignal(procp, signo))
+	      return error;
+	  }
+	  procp->p_step = 0;
+	  wakeup(&procp->p_step);
+	  break;
+	default:
+	  return (ENOTTY);
+	}
+	return 0;
+}
+
+/*
  * do block mapping for pfsnode (vp).
  * since we don't use the buffer cache
  * for procfs this function should never
@@ -908,6 +983,7 @@
 	{ &vop_setattr_desc,		(vop_t *) procfs_setattr },
 	{ &vop_symlink_desc,		(vop_t *) procfs_badop },
 	{ &vop_write_desc,		(vop_t *) procfs_rw },
+	{ &vop_ioctl_desc,		(vop_t *) procfs_ioctl },
 	{ NULL, NULL }
 };
 static struct vnodeopv_desc procfs_vnodeop_opv_desc =
Index: sys/proc.h
===================================================================
RCS file: /kithrup/cvs/src/sys/sys/proc.h,v
retrieving revision 1.46
diff -u -r1.46 proc.h
--- proc.h	1997/11/06 19:29:45	1.46
+++ proc.h	1997/11/15 05:05:42
@@ -151,6 +151,11 @@
 
 	short	p_locks;		/* DEBUG: lockmgr count of held locks */
 	short	p_simple_locks;		/* DEBUG: count of held simple locks */
+	unsigned int	p_stops;	/* procfs event bitmask */
+	unsigned int	p_stype;	/* procfs stop event type */
+	char	p_step;			/* procfs stop *once* flag */
+	unsigned char	p_pfsflags;	/* procfs flags */
+	char	p_pad3[2];		/* padding for alignment */
 	register_t p_retval[2];		/* syscall aux returns */
 
 /* End area that is zeroed on creation. */
@@ -270,6 +275,10 @@
 	if (--(s)->s_count == 0)					\
 		FREE(s, M_SESSION);					\
 }
+
+extern void stopevent(struct proc*, unsigned int, unsigned int);
+#define	STOPEVENT(p,e,v)	do { \
+	if ((p)->p_stops & (e)) stopevent(p,e,v); } while (0)
 
 /* hold process U-area in memory, normally for ptrace/procfs work */
 #define PHOLD(p) {							\
Index: i386/i386/trap.c
===================================================================
--- /dev/null	Wed Nov 26 16:08:20 1997
+++ sys/pioctl.h	Fri Nov 14 21:08:15 1997
@@ -0,0 +1,33 @@
+#include <sys/ioctl.h>
+
+#if 0
+struct procfs_status {
+	int	state;	/* 0 for running, 1 for stopped */
+	int	why;	/* what event, if any, proc stopped on */
+	unsigned int	val;	/* Any extra data */
+};
+#else
+struct procfs_status {
+	int	state;	/* Running, stopped, something else? */
+	int	flags;	/* Any flags */
+	unsigned long	events;	/* Events to stop on */
+	int	why;	/* What event, if any, proc stopped on */
+	unsigned long	val;	/* Any extra data */
+};
+#endif
+
+#define	PIOCBIS	_IOW('p', 1, unsigned int)	/* Set event flag */
+#define	PIOCBIC	_IOW('p', 2, unsigned int)	/* Clear event flag */
+#define	PIOCSFL	_IOR('p', 3, unsigned int)	/* Set flags */
+			/* wait for proc to stop */
+#define	PIOCWAIT	_IOR('p', 4, struct procfs_status)
+#define	PIOCCONT	_IOW('p', 5, int)	/* Continue a process */
+			/* Get proc status */
+#define	PIOCSTATUS	_IOW('p', 6, struct procfs_status)
+
+#define S_EXEC	0x00000001	/* stop-on-exec */
+#define	S_SIG	0x00000002	/* stop-on-signal */
+#define	S_SCE	0x00000004	/* stop on syscall entry */
+#define	S_SCX	0x00000008	/* stop on syscall exit */
+#define	S_CORE	0x00000010	/* stop on coredump */
+#define	S_EXIT	0x00000020	/* stop on exit */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199711270041.QAA00355>