/* @(#)sys_process.c 1.1 85/05/30 SMI; from UCB 5.10 83/07/01 */ #include "../machine/reg.h" #include "../machine/psl.h" #include "../machine/pte.h" #include "../h/param.h" #include "../h/systm.h" #include "../h/user.h" #include "../h/proc.h" #include "../h/vnode.h" #include "../h/text.h" #include "../h/seg.h" #include "../h/vm.h" #include "../h/buf.h" #include "../h/acct.h" /* * Priority for tracing */ #define IPCPRI PZERO /* * Tracing variables. * Used to pass trace command from * parent to child being traced. * This data base cannot be * shared and is locked * per user. */ struct { int ip_lock; int ip_req; int *ip_addr; int ip_data; } ipc; /* * sys-trace system call. */ ptrace() { register struct proc *p; register struct a { int req; int pid; int *addr; int data; } *uap; uap = (struct a *)u.u_ap; if (uap->req <= 0) { u.u_procp->p_flag |= STRC; return; } p = pfind(uap->pid); if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid || !(p->p_flag & STRC)) { u.u_error = ESRCH; return; } 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; while (ipc.ip_req > 0) { if (p->p_stat==SSTOP) setrun(p); sleep((caddr_t)&ipc, IPCPRI); } u.u_r.r_val1 = ipc.ip_data; if (ipc.ip_req < 0) u.u_error = EIO; ipc.ip_lock = 0; wakeup((caddr_t)&ipc); } #ifdef vax #define NIPCREG 16 #endif #ifdef mc68000 #define NIPCREG 17 #endif int ipcreg[NIPCREG] = #ifdef vax {R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,AP,FP,SP,PC}; #endif #ifdef mc68000 {R0,R1,R2,R3,R4,R5,R6,R7,AR0,AR1,AR2,AR3,AR4,AR5,AR6,AR7,PC}; #endif #define PHYSOFF(p, o) \ ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0]))) /* * Code that the child process * executes to implement the command * of the parent process in tracing. */ procxmt() { register int i; register *p; register struct text *xp; if (ipc.ip_lock != u.u_procp->p_pid) return (0); u.u_procp->p_slptime = 0; i = ipc.ip_req; ipc.ip_req = 0; switch (i) { /* read user I */ case 1: if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) goto error; ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); break; /* read user D */ case 2: if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) goto error; ipc.ip_data = fuword((caddr_t)ipc.ip_addr); break; /* read u */ case 3: i = (int)ipc.ip_addr; if (i<0 || i >= ctob(UPAGES)) goto error; ipc.ip_data = *(int *)PHYSOFF(&u, i); break; /* write user I */ /* Must set up to allow writing */ case 4: /* * If text, must assure exclusive use */ if (xp = u.u_procp->p_textp) { struct vattr vattr; struct vnode *vp; vp = xp->x_vptr; VOP_GETATTR(vp, &vattr, u.u_cred); if (xp->x_count != 1 || (vattr.va_mode & VSVTX)) goto error; vp->v_flag &= ~VTEXT; } i = -1; if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { if (chgprot((caddr_t)ipc.ip_addr, RW) && chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW)) i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); (void) chgprot((caddr_t)ipc.ip_addr, RO); (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO); } if (i < 0) goto error; if (xp) xp->x_flag |= XWRIT; break; /* write user D */ case 5: if (suword((caddr_t)ipc.ip_addr, 0) < 0) goto error; (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); break; /* write u */ case 6: i = (int)ipc.ip_addr; p = (int *)PHYSOFF(&u, i); for (i=0; i<NIPCREG; i++) if (p == &u.u_ar0[ipcreg[i]]) goto ok; if (p == &u.u_ar0[PS]) { ipc.ip_data |= PSL_USERSET; ipc.ip_data &= ~PSL_USERCLR; goto ok; } goto error; ok: *p = ipc.ip_data; break; /* set signal and continue */ /* one version causes a trace-trap */ case 9: case 7: if ((int)ipc.ip_addr != 1) u.u_ar0[PC] = (int)ipc.ip_addr; if ((unsigned)ipc.ip_data > NSIG) goto error; u.u_procp->p_cursig = ipc.ip_data; /* see issig */ if (i == 9) u.u_ar0[PS] |= PSL_T; wakeup((caddr_t)&ipc); return (1); /* force exit */ case 8: wakeup((caddr_t)&ipc); exit(u.u_procp->p_cursig); default: error: ipc.ip_req = -1; } wakeup((caddr_t)&ipc); return (0); }