convert VOP_UNLOCK and vrele into vput's; add proc parameter to union_dircache
[unix-history] / usr / src / sys / kern / sys_process.c
index 57bdda4..041a40b 100644 (file)
@@ -1,25 +1,34 @@
 /*-
 /*-
- * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
  *
  * %sccs.include.proprietary.c%
  *
  *
  * %sccs.include.proprietary.c%
  *
- *     @(#)sys_process.c       7.25 (Berkeley) %G%
+ *     @(#)sys_process.c       8.6 (Berkeley) %G%
  */
 
 #define IPCREG
  */
 
 #define IPCREG
-#include "param.h"
-#include "proc.h"
-#include "vnode.h"
-#include "buf.h"
-#include "ptrace.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/buf.h>
+#include <sys/ptrace.h>
 
 
-#include "machine/reg.h"
-#include "machine/psl.h"
-#include "vm/vm.h"
-#include "vm/vm_page.h"
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
 
 
-#include "user.h"
+#include <machine/reg.h>
+#include <machine/psl.h>
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+#include <sys/user.h>
 
 /*
  * Priority for tracing
 
 /*
  * Priority for tracing
@@ -37,7 +46,7 @@
 struct {
        int     ip_lock;
        int     ip_req;
 struct {
        int     ip_lock;
        int     ip_req;
-       int     *ip_addr;
+       caddr_t ip_addr;
        int     ip_data;
 } ipc;
 
        int     ip_data;
 } ipc;
 
@@ -46,34 +55,65 @@ struct {
  */
 ptrace(curp, uap, retval)
        struct proc *curp;
  */
 ptrace(curp, uap, retval)
        struct proc *curp;
-       register struct args {
-               int     req;
-               int     pid;
-               int     *addr;
-               int     data;
-       } *uap;
-       int *retval;
+       struct ptrace_args /* {
+               syscallarg(int) req;
+               syscallarg(pid_t) pid;
+               syscallarg(caddr_t) addr;
+               syscallarg(int) data;
+       } */ *uap;
+       register_t *retval;
 {
        register struct proc *p;
 {
        register struct proc *p;
+       int error;
 
 
-       if (uap->req <= 0) {
-               curp->p_flag |= STRC;
+       if (SCARG(uap, req) <= 0) {
+               curp->p_flag |= P_TRACED;
                return (0);
        }
                return (0);
        }
-       p = pfind(uap->pid);
-       if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp ||
-           !(p->p_flag & STRC))
+       p = pfind(SCARG(uap, pid));
+       if (p == 0)
+               return (ESRCH);
+       if (SCARG(uap, req) == PT_ATTACH) {
+               /*
+                * Must be root if the process has used set user or group
+                * privileges or does not belong to the real user.  Must
+                * not be already traced.  Can't attach to ourselves.
+                */
+               if ((p->p_flag & P_SUGID ||
+                   p->p_cred->p_ruid != curp->p_cred->p_ruid) &&
+                   (error = suser(p->p_ucred, &p->p_acflag)) != 0)
+                       return (error);
+               if (p->p_flag & P_TRACED)
+                       return (EALREADY);      /* ??? */
+               if (p->p_pid == curp->p_pid)
+                       return (EINVAL);
+               /*
+                * It would be nice if the tracing relationship was separate
+                * from the parent relationship but that would require
+                * another set of links in the proc struct or for "wait"
+                * to scan the entire proc table.  To make life easier,
+                * we just re-parent the process we're trying to trace.
+                * The old parent is remembered so we can put things back
+                * on a "detach".
+                */
+               p->p_flag |= P_TRACED;
+               p->p_oppid = p->p_pptr->p_pid;
+               proc_reparent(p, curp);
+               psignal(p, SIGSTOP);
+               return (0);
+       }
+       if (p->p_stat != SSTOP || p->p_pptr != curp || !(p->p_flag & P_TRACED))
                return (ESRCH);
        while (ipc.ip_lock)
                sleep((caddr_t)&ipc, IPCPRI);
        ipc.ip_lock = p->p_pid;
                return (ESRCH);
        while (ipc.ip_lock)
                sleep((caddr_t)&ipc, IPCPRI);
        ipc.ip_lock = p->p_pid;
-       ipc.ip_data = uap->data;
-       ipc.ip_addr = uap->addr;
-       ipc.ip_req = uap->req;
-       p->p_flag &= ~SWTED;
+       ipc.ip_data = SCARG(uap, data);
+       ipc.ip_addr = SCARG(uap, addr);
+       ipc.ip_req = SCARG(uap, req);
+       p->p_flag &= ~P_WAITED;
        while (ipc.ip_req > 0) {
                if (p->p_stat==SSTOP)
        while (ipc.ip_req > 0) {
                if (p->p_stat==SSTOP)
-                       setrun(p);
+                       setrunnable(p);
                sleep((caddr_t)&ipc, IPCPRI);
        }
        *retval = ipc.ip_data;
                sleep((caddr_t)&ipc, IPCPRI);
        }
        *retval = ipc.ip_data;
@@ -85,6 +125,11 @@ ptrace(curp, uap, retval)
 }
 
 #define        PHYSOFF(p, o) ((caddr_t)(p) + (o))
 }
 
 #define        PHYSOFF(p, o) ((caddr_t)(p) + (o))
+#if defined(hp300) || defined(luna68k)
+#define PHYSALIGNED(a) (((int)(a) & (sizeof(short) - 1)) == 0)
+#else
+#define PHYSALIGNED(a) (((int)(a) & (sizeof(int) - 1)) == 0)
+#endif
 
 #if defined(i386)
 #undef        PC
 
 #if defined(i386)
 #undef        PC
@@ -105,16 +150,17 @@ ptrace(curp, uap, retval)
  * being debugged. This code runs in the context of the child process
  * to fulfill the command requested by the parent.
  */
  * being debugged. This code runs in the context of the child process
  * to fulfill the command requested by the parent.
  */
-procxmt(p)
+trace_req(p)
        register struct proc *p;
 {
        register struct proc *p;
 {
-       register int i, *poff;
+       register int i, *poff, *regs;
        extern char kstack[];
 
        if (ipc.ip_lock != p->p_pid)
                return (0);
        p->p_slptime = 0;
        extern char kstack[];
 
        if (ipc.ip_lock != p->p_pid)
                return (0);
        p->p_slptime = 0;
-       p->p_addr->u_kproc.kp_proc.p_md.md_regs = p->p_md.md_regs; /* u.u_ar0 */
+       regs = p->p_md.md_regs;
+       p->p_addr->u_kproc.kp_proc.p_md.md_regs = regs; /* u.u_ar0 */
        i = ipc.ip_req;
        ipc.ip_req = 0;
        switch (i) {
        i = ipc.ip_req;
        ipc.ip_req = 0;
        switch (i) {
@@ -132,13 +178,8 @@ procxmt(p)
                break;
 
        case PT_READ_U:                 /* read the child's u. */
                break;
 
        case PT_READ_U:                 /* read the child's u. */
-#ifdef HPUXCOMPAT
-               if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE)
-                       i = hpuxtobsduoff(ipc.ip_addr);
-               else
-#endif
                i = (int)ipc.ip_addr;
                i = (int)ipc.ip_addr;
-               if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0)
+               if ((u_int) i > ctob(UPAGES)-sizeof(int) || !PHYSALIGNED(i))
                        goto error;
                ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i);
                break;
                        goto error;
                ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i);
                break;
@@ -149,7 +190,7 @@ procxmt(p)
                        int rv;
 
                        sa = trunc_page((vm_offset_t)ipc.ip_addr);
                        int rv;
 
                        sa = trunc_page((vm_offset_t)ipc.ip_addr);
-                       ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1);
+                       ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int));
                        rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
                                        VM_PROT_DEFAULT, FALSE);
                        if (rv == KERN_SUCCESS) {
                        rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
                                        VM_PROT_DEFAULT, FALSE);
                        if (rv == KERN_SUCCESS) {
@@ -170,21 +211,24 @@ procxmt(p)
                break;
 
        case PT_WRITE_U:                /* write the child's u. */
                break;
 
        case PT_WRITE_U:                /* write the child's u. */
-#ifdef HPUXCOMPAT
-               if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE)
-                       i = hpuxtobsduoff(ipc.ip_addr);
-               else
-#endif
                i = (int)ipc.ip_addr;
 #ifdef mips
                i = (int)ipc.ip_addr;
 #ifdef mips
-               poff = (int *)PHYSOFF(curproc->p_addr, i);
+               poff = (int *)PHYSOFF(p->p_addr, i);
 #else
                poff = (int *)PHYSOFF(kstack, i);
 #endif
                for (i=0; i<NIPCREG; i++)
 #else
                poff = (int *)PHYSOFF(kstack, i);
 #endif
                for (i=0; i<NIPCREG; i++)
-                       if (poff == &p->p_md.md_regs[ipcreg[i]])
+                       if (poff == &regs[ipcreg[i]])
                                goto ok;
                                goto ok;
-               if (poff == &p->p_md.md_regs[PS]) {
+#if defined(hp300) || defined(luna68k)
+               /*
+                * In the new frame layout, PS/PC are skewed by 2 bytes.
+                */
+               regs = (int *)((short *)regs + 1);
+               if (poff == &regs[PC])
+                       goto ok;
+#endif
+               if (poff == &regs[PS]) {
                        ipc.ip_data |= PSL_USERSET;
                        ipc.ip_data &= ~PSL_USERCLR;
 #ifdef PSL_CM_CLR
                        ipc.ip_data |= PSL_USERSET;
                        ipc.ip_data &= ~PSL_USERCLR;
 #ifdef PSL_CM_CLR
@@ -208,22 +252,48 @@ procxmt(p)
 
        case PT_STEP:                   /* single step the child */
        case PT_CONTINUE:               /* continue the child */
 
        case PT_STEP:                   /* single step the child */
        case PT_CONTINUE:               /* continue the child */
+#ifndef mips
+               regs = (int *)((short *)regs + 1);
+#endif
+               if ((unsigned)ipc.ip_data >= NSIG)
+                       goto error;
                if ((int)ipc.ip_addr != 1)
                if ((int)ipc.ip_addr != 1)
-                       p->p_md.md_regs[PC] = (int)ipc.ip_addr;
-               if ((unsigned)ipc.ip_data > NSIG)
+                       regs[PC] = (int)ipc.ip_addr;
+               p->p_xstat = ipc.ip_data;       /* see issignal */
+#ifdef mips
+               if (i == PT_STEP && cpu_singlestep(p))
                        goto error;
                        goto error;
-               p->p_xstat = ipc.ip_data;       /* see issig */
+#else
 #ifdef PSL_T
                /* need something more machine independent here... */
                if (i == PT_STEP) 
 #ifdef PSL_T
                /* need something more machine independent here... */
                if (i == PT_STEP) 
-                       p->p_md.md_regs[PS] |= PSL_T;
+                       regs[PS] |= PSL_T;
+#endif
 #endif
                wakeup((caddr_t)&ipc);
                return (1);
 
        case PT_KILL:                   /* kill the child process */
                wakeup((caddr_t)&ipc);
 #endif
                wakeup((caddr_t)&ipc);
                return (1);
 
        case PT_KILL:                   /* kill the child process */
                wakeup((caddr_t)&ipc);
-               exit(p, (int)p->p_xstat);
+               exit1(p, (int)p->p_xstat);
+
+       case PT_DETACH:                 /* stop tracing the child */
+               regs = (int *)((short *)regs + 1);
+               if ((unsigned)ipc.ip_data >= NSIG)
+                       goto error;
+               if ((int)ipc.ip_addr != 1)
+                       regs[PC] = (int)ipc.ip_addr;
+               p->p_xstat = ipc.ip_data;       /* see issignal */
+               p->p_flag &= ~P_TRACED;
+               if (p->p_oppid != p->p_pptr->p_pid) {
+                        register struct proc *pp = pfind(p->p_oppid);
+
+                        if (pp)
+                                proc_reparent(p, pp);
+               }
+               p->p_oppid = 0;
+               wakeup((caddr_t)&ipc);
+               return (1);
 
        default:
        error:
 
        default:
        error:
@@ -232,29 +302,3 @@ procxmt(p)
        wakeup((caddr_t)&ipc);
        return (0);
 }
        wakeup((caddr_t)&ipc);
        return (0);
 }
-
-/*
- * Process debugging system call.
- */
-/* ARGSUSED */
-profil(p, uap, retval)
-       struct proc *p;
-       register struct args {
-               short   *bufbase;
-               unsigned bufsize;
-               unsigned pcoffset;
-               unsigned pcscale;
-       } *uap;
-       int *retval;
-{
-       register struct uprof *upp = &p->p_stats->p_prof;
-
-       upp->pr_base = uap->bufbase;
-       upp->pr_size = uap->bufsize;
-       upp->pr_off = uap->pcoffset;
-       upp->pr_scale = uap->pcscale;
-#ifdef PROFTIMER
-       initprofclock();
-#endif
-       return (0);
-}