Index: head/share/man/man5/procfs.5 =================================================================== --- head/share/man/man5/procfs.5 +++ head/share/man/man5/procfs.5 @@ -2,7 +2,7 @@ .\" Written by Garrett Wollman .\" This file is in the public domain. .\" -.Dd December 26, 2015 +.Dd March 4, 2017 .Dt PROCFS 5 .Os .Sh NAME @@ -33,48 +33,7 @@ which always refers to the process making the lookup request. .Pp Each node is a directory which contains the following entries: -.Pp -Each directory contains several files: .Bl -tag -width status -.It Pa ctl -a write-only file which supports a variety -of control operations. -Control commands are written as strings to the -.Pa ctl -file. -The control commands are: -.Bl -tag -width detach -compact -.It attach -stops the target process and arranges for the sending -process to become the debug control process. -.It detach -continue execution of the target process and -remove it from control by the debug process (which -need not be the sending process). -.It run -continue running the target process until -a signal is delivered, a breakpoint is hit, or the -target process exits. -.It step -single step the target process, with no signal delivery. -.It wait -wait for the target process to come to a steady -state ready for debugging. -The target process must be in this state before -any of the other commands are allowed. -.El -.Pp -The string can also be the name of a signal, lower case -and without the -.Dv SIG -prefix, -in which case that signal is delivered to the process -(see -.Xr sigaction 2 ) . -.Pp -The -.Xr procctl 8 -utility can be used to clear tracepoints in a stuck process. .It Pa dbregs The debug registers as defined by .Dv "struct dbregs" @@ -188,30 +147,8 @@ .El .El .Pp -In a normal debugging environment, -where the target is fork/exec'd by the debugger, -the debugger should fork and the child should stop -itself (with a self-inflicted -.Dv SIGSTOP -for example). -The parent should issue a -.Dv wait -and then an -.Dv attach -command via the appropriate -.Pa ctl -file. -The child process will receive a -.Dv SIGTRAP -immediately after the call to exec (see -.Xr execve 2 ) . -.Pp Each node is owned by the process's user, and belongs to that user's -primary group, except for the -.Pa mem -node, which belongs to the -.Li kmem -group. +primary group. .Sh FILES .Bl -tag -width /proc/curproc/XXXXXXX -compact .It Pa /proc @@ -224,8 +161,6 @@ directory containing process information for the current process .It Pa /proc/curproc/cmdline the process executable name -.It Pa /proc/curproc/ctl -used to send control messages to the process .It Pa /proc/curproc/etype executable type .It Pa /proc/curproc/file Index: head/sys/conf/files =================================================================== --- head/sys/conf/files +++ head/sys/conf/files @@ -3384,7 +3384,6 @@ fs/nullfs/null_vfsops.c optional nullfs fs/nullfs/null_vnops.c optional nullfs fs/procfs/procfs.c optional procfs -fs/procfs/procfs_ctl.c optional procfs fs/procfs/procfs_dbregs.c optional procfs fs/procfs/procfs_fpregs.c optional procfs fs/procfs/procfs_ioctl.c optional procfs Index: head/sys/fs/procfs/README =================================================================== --- head/sys/fs/procfs/README +++ head/sys/fs/procfs/README @@ -1,113 +0,0 @@ -saute procfs lyonnais - -procfs supports two levels of directory. the filesystem root -directory contains a representation of the system process table. -this consists of an entry for each active and zombie process, and -an additional entry "curproc" which always represents the process -making the lookup request. - -each of the sub-directories contains several files. these files -are used to control and interrogate processes. the files implemented -are: - - file - xxx. the exec'ed file. - - status - r/o. returns process status. - - ctl - w/o. sends a control message to the process. - for example: - echo hup > /proc/curproc/note - will send a SIGHUP to the shell. - whereas - echo attach > /proc/1293/ctl - would set up process 1293 for debugging. - see below for more details. - - mem - r/w. virtual memory image of the process. - parts of the address space are readable - only if they exist in the target process. - a more reasonable alternative might be - to return zero pages instead of an error. - comments? - - note - w/o. writing a string here sends the - equivalent note to the process. - [ not implemented. ] - - notepg - w/o. the same as note, but sends to all - members of the process group. - [ not implemented. ] - - regs - r/w. process register set. this can be read - or written any time even if the process - is not stopped. since the bsd kernel - is single-processor, this implementation - will get the "right" register values. - a multi-proc kernel would need to do some - synchronisation. - -this then looks like: - -% ls -li /proc -total 0 - 9 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 0 - 17 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 1 - 89 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 10 - 25 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 2 -2065 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 257 -2481 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 309 - 265 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 32 -3129 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 390 -3209 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 400 -3217 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 401 -3273 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 408 - 393 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 48 - 409 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 50 - 465 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 57 - 481 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 59 - 537 dr-xr-xr-x 2 root kmem 0 Sep 21 15:06 66 - 545 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 67 - 657 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 81 - 665 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 82 - 673 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 83 - 681 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 84 -3273 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 curproc -% ls -li /proc/curproc -total 408 -3341 --w------- 1 jsp staff 0 Sep 21 15:06 ctl -1554 -r-xr-xr-x 1 bin bin 90112 Mar 29 04:52 file -3339 -rw------- 1 jsp staff 118784 Sep 21 15:06 mem -3343 --w------- 1 jsp staff 0 Sep 21 15:06 note -3344 --w------- 1 jsp staff 0 Sep 21 15:06 notepg -3340 -rw------- 1 jsp staff 0 Sep 21 15:06 regs -3342 -r--r--r-- 1 jsp staff 0 Sep 21 15:06 status -% df /proc/curproc /proc/curproc/file -Filesystem 512-blocks Used Avail Capacity Mounted on -proc 2 2 0 100% /proc -/dev/wd0a 16186 13548 1018 93% / -% cat /proc/curproc/status -cat 446 439 400 81 12,0 ctty 748620684 270000 0 0 0 20000 nochan 11 20 20 20 0 21 117 - - - -the basic sequence of commands written to "ctl" would be - - attach - this stops the target process and - arranges for the sending process - to become the debug control process - wait - wait for the target process to come to - a steady state ready for debugging. - step - single step, with no signal delivery. - run - continue running, with no signal delivery, - until next trap or breakpoint. - - deliver signal and continue running. - detach - continue execution of the target process - and remove it from control by the debug process - -in a normal debugging environment, where the target is fork/exec'd by -the debugger, the debugger should fork and the child should stop itself -(with a self-inflicted SIGSTOP). the parent should do a "wait" then an -"attach". as before, the child will hit a breakpoint on the first -instruction in any newly exec'd image. - -$FreeBSD$ Index: head/sys/fs/procfs/procfs.h =================================================================== --- head/sys/fs/procfs/procfs.h +++ head/sys/fs/procfs/procfs.h @@ -41,7 +41,6 @@ int procfs_docurproc(PFS_FILL_ARGS); int procfs_doosrel(PFS_FILL_ARGS); int procfs_doproccmdline(PFS_FILL_ARGS); -int procfs_doprocctl(PFS_FILL_ARGS); int procfs_doprocdbregs(PFS_FILL_ARGS); int procfs_doprocfile(PFS_FILL_ARGS); int procfs_doprocfpregs(PFS_FILL_ARGS); Index: head/sys/fs/procfs/procfs.c =================================================================== --- head/sys/fs/procfs/procfs.c +++ head/sys/fs/procfs/procfs.c @@ -104,8 +104,7 @@ { /* XXX inefficient, split into separate functions */ - if (strcmp(pn->pn_name, "ctl") == 0 || - strcmp(pn->pn_name, "note") == 0 || + if (strcmp(pn->pn_name, "note") == 0 || strcmp(pn->pn_name, "notepg") == 0) vap->va_mode = 0200; else if (strcmp(pn->pn_name, "mem") == 0 || @@ -166,8 +165,6 @@ procfs_attr, NULL, NULL, PFS_PROCDEP); pfs_create_file(dir, "cmdline", procfs_doproccmdline, NULL, NULL, NULL, PFS_RD); - pfs_create_file(dir, "ctl", procfs_doprocctl, - procfs_attr, NULL, NULL, PFS_WR); pfs_create_file(dir, "dbregs", procfs_doprocdbregs, procfs_attr, procfs_candebug, NULL, PFS_RDWR|PFS_RAW); pfs_create_file(dir, "etype", procfs_doproctype, Index: head/sys/fs/procfs/procfs_ctl.c =================================================================== --- head/sys/fs/procfs/procfs_ctl.c +++ head/sys/fs/procfs/procfs_ctl.c @@ -1,359 +0,0 @@ -/*- - * Copyright (c) 1993 Jan-Simon Pendry - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Jan-Simon Pendry. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94 - * - * From: - * $Id: procfs_ctl.c,v 1.51 2003/12/07 17:40:00 des Exp $ - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -/* - * True iff process (p) is in trace wait state - * relative to process (curp) - */ -#define TRACE_WAIT_P(curp, p) \ - (P_SHOULDSTOP(p) && \ - (p)->p_pptr == (curp) && \ - ((p)->p_flag & P_TRACED)) - -#define PROCFS_CTL_ATTACH 1 -#define PROCFS_CTL_DETACH 2 -#define PROCFS_CTL_STEP 3 -#define PROCFS_CTL_RUN 4 -#define PROCFS_CTL_WAIT 5 - -struct namemap { - const char *nm_name; - int nm_val; -}; - -static struct namemap ctlnames[] = { - /* special /proc commands */ - { "attach", PROCFS_CTL_ATTACH }, - { "detach", PROCFS_CTL_DETACH }, - { "step", PROCFS_CTL_STEP }, - { "run", PROCFS_CTL_RUN }, - { "wait", PROCFS_CTL_WAIT }, - { 0 }, -}; - -static struct namemap signames[] = { - /* regular signal names */ - { "hup", SIGHUP }, { "int", SIGINT }, - { "quit", SIGQUIT }, { "ill", SIGILL }, - { "trap", SIGTRAP }, { "abrt", SIGABRT }, - { "iot", SIGIOT }, { "emt", SIGEMT }, - { "fpe", SIGFPE }, { "kill", SIGKILL }, - { "bus", SIGBUS }, { "segv", SIGSEGV }, - { "sys", SIGSYS }, { "pipe", SIGPIPE }, - { "alrm", SIGALRM }, { "term", SIGTERM }, - { "urg", SIGURG }, { "stop", SIGSTOP }, - { "tstp", SIGTSTP }, { "cont", SIGCONT }, - { "chld", SIGCHLD }, { "ttin", SIGTTIN }, - { "ttou", SIGTTOU }, { "io", SIGIO }, - { "xcpu", SIGXCPU }, { "xfsz", SIGXFSZ }, - { "vtalrm", SIGVTALRM }, { "prof", SIGPROF }, - { "winch", SIGWINCH }, { "info", SIGINFO }, - { "usr1", SIGUSR1 }, { "usr2", SIGUSR2 }, - { 0 }, -}; - -static int procfs_control(struct thread *td, struct proc *p, int op); - -static int -procfs_control(struct thread *td, struct proc *p, int op) -{ - int error = 0; - struct thread *temp; - - /* - * Attach - attaches the target process for debugging - * by the calling process. - */ - if (op == PROCFS_CTL_ATTACH) { - sx_xlock(&proctree_lock); - PROC_LOCK(p); - if ((error = p_candebug(td, p)) != 0) - goto out; - if (p->p_flag & P_TRACED) { - error = EBUSY; - goto out; - } - - /* Can't trace yourself! */ - if (p->p_pid == td->td_proc->p_pid) { - error = EINVAL; - goto out; - } - - /* - * Go ahead and set the trace flag. - * Save the old parent (it's reset in - * _DETACH, and also in kern_exit.c:wait4() - * Reparent the process so that the tracing - * proc gets to see all the action. - * Stop the target. - */ - p->p_flag |= P_TRACED; - faultin(p); - p->p_xsig = 0; /* XXX ? */ - p->p_oppid = p->p_pptr->p_pid; - if (p->p_pptr != td->td_proc) { - proc_reparent(p, td->td_proc); - } - kern_psignal(p, SIGSTOP); -out: - PROC_UNLOCK(p); - sx_xunlock(&proctree_lock); - return (error); - } - - /* - * Authorization check: rely on normal debugging protection, except - * allow processes to disengage debugging on a process onto which - * they have previously attached, but no longer have permission to - * debug. - */ - PROC_LOCK(p); - if (op != PROCFS_CTL_DETACH && - ((error = p_candebug(td, p)))) { - PROC_UNLOCK(p); - return (error); - } - - /* - * Target process must be stopped, owned by (td) and - * be set up for tracing (P_TRACED flag set). - * Allow DETACH to take place at any time for sanity. - * Allow WAIT any time, of course. - */ - switch (op) { - case PROCFS_CTL_DETACH: - case PROCFS_CTL_WAIT: - break; - - default: - if (!TRACE_WAIT_P(td->td_proc, p)) { - PROC_UNLOCK(p); - return (EBUSY); - } - } - - -#ifdef FIX_SSTEP - /* - * do single-step fixup if needed - */ - FIX_SSTEP(FIRST_THREAD_IN_PROC(p)); -#endif - - /* - * Don't deliver any signal by default. - * To continue with a signal, just send - * the signal name to the ctl file - */ - p->p_xsig = 0; - - switch (op) { - /* - * Detach. Cleans up the target process, reparent it if possible - * and set it running once more. - */ - case PROCFS_CTL_DETACH: - /* if not being traced, then this is a painless no-op */ - if ((p->p_flag & P_TRACED) == 0) { - PROC_UNLOCK(p); - return (0); - } - - /* not being traced any more */ - p->p_flag &= ~(P_TRACED | P_STOPPED_TRACE); - - /* remove pending SIGTRAP, else the process will die */ - sigqueue_delete_proc(p, SIGTRAP); - FOREACH_THREAD_IN_PROC(p, temp) - temp->td_dbgflags &= ~TDB_SUSPEND; - PROC_UNLOCK(p); - - /* give process back to original parent */ - sx_xlock(&proctree_lock); - if (p->p_oppid != p->p_pptr->p_pid) { - struct proc *pp; - - pp = pfind(p->p_oppid); - PROC_LOCK(p); - if (pp) { - PROC_UNLOCK(pp); - proc_reparent(p, pp); - } - } else - PROC_LOCK(p); - p->p_oppid = 0; - p->p_stops = 0; - p->p_flag &= ~P_WAITED; /* XXX ? */ - sx_xunlock(&proctree_lock); - - wakeup(td->td_proc); /* XXX for CTL_WAIT below ? */ - - break; - - /* - * Step. Let the target process execute a single instruction. - * What does it mean to single step a threaded program? - */ - case PROCFS_CTL_STEP: - error = proc_sstep(FIRST_THREAD_IN_PROC(p)); - if (error) { - PROC_UNLOCK(p); - return (error); - } - break; - - /* - * Run. Let the target process continue running until a breakpoint - * or some other trap. - */ - case PROCFS_CTL_RUN: - p->p_flag &= ~P_STOPPED_SIG; /* this uses SIGSTOP */ - break; - - /* - * Wait for the target process to stop. - * If the target is not being traced then just wait - * to enter - */ - case PROCFS_CTL_WAIT: - if (p->p_flag & P_TRACED) { - while (error == 0 && - (P_SHOULDSTOP(p)) && - (p->p_flag & P_TRACED) && - (p->p_pptr == td->td_proc)) - error = msleep(p, &p->p_mtx, - PWAIT|PCATCH, "procfsx", 0); - if (error == 0 && !TRACE_WAIT_P(td->td_proc, p)) - error = EBUSY; - } else { - while (error == 0 && P_SHOULDSTOP(p)) - error = msleep(p, &p->p_mtx, - PWAIT|PCATCH, "procfs", 0); - } - PROC_UNLOCK(p); - return (error); - default: - panic("procfs_control"); - } - - PROC_SLOCK(p); - thread_unsuspend(p); /* If it can run, let it do so. */ - PROC_SUNLOCK(p); - PROC_UNLOCK(p); - return (0); -} - -static struct namemap * -findname(struct namemap *nm, char *buf, int buflen) -{ - - for (; nm->nm_name; nm++) - if (bcmp(buf, nm->nm_name, buflen+1) == 0) - return (nm); - - return (0); -} - -int -procfs_doprocctl(PFS_FILL_ARGS) -{ - int error; - struct namemap *nm; - - if (uio == NULL || uio->uio_rw != UIO_WRITE) - return (EOPNOTSUPP); - - /* - * Map signal names into signal generation - * or debug control. Unknown commands and/or signals - * return EOPNOTSUPP. - * - * Sending a signal while the process is being debugged - * also has the side effect of letting the target continue - * to run. There is no way to single-step a signal delivery. - */ - error = EOPNOTSUPP; - - sbuf_trim(sb); - sbuf_finish(sb); - nm = findname(ctlnames, sbuf_data(sb), sbuf_len(sb)); - if (nm) { - printf("procfs: got a %s command\n", sbuf_data(sb)); - error = procfs_control(td, p, nm->nm_val); - } else { - nm = findname(signames, sbuf_data(sb), sbuf_len(sb)); - if (nm) { - printf("procfs: got a sig%s\n", sbuf_data(sb)); - PROC_LOCK(p); - - if (TRACE_WAIT_P(td->td_proc, p)) { - p->p_xsig = nm->nm_val; -#ifdef FIX_SSTEP - FIX_SSTEP(FIRST_THREAD_IN_PROC(p)); -#endif - p->p_flag &= ~P_STOPPED_SIG; - PROC_SLOCK(p); - thread_unsuspend(p); - PROC_SUNLOCK(p); - } else - kern_psignal(p, nm->nm_val); - PROC_UNLOCK(p); - error = 0; - } - } - - return (error); -} Index: head/sys/modules/procfs/Makefile =================================================================== --- head/sys/modules/procfs/Makefile +++ head/sys/modules/procfs/Makefile @@ -6,7 +6,6 @@ SRCS= SRCS+= opt_compat.h SRCS+= vnode_if.h -SRCS+= procfs_ctl.c SRCS+= procfs_dbregs.c SRCS+= procfs_fpregs.c SRCS+= procfs_ioctl.c