1 /* 2 * Copyright (c) 1982 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)sys_process.c 6.4 (Berkeley) 06/08/85 7 */ 8 9 #include "../machine/reg.h" 10 #include "../machine/psl.h" 11 #include "../machine/pte.h" 12 13 #include "param.h" 14 #include "systm.h" 15 #include "dir.h" 16 #include "user.h" 17 #include "proc.h" 18 #include "inode.h" 19 #include "text.h" 20 #include "seg.h" 21 #include "vm.h" 22 #include "buf.h" 23 #include "acct.h" 24 25 /* 26 * Priority for tracing 27 */ 28 #define IPCPRI PZERO 29 30 /* 31 * Tracing variables. 32 * Used to pass trace command from 33 * parent to child being traced. 34 * This data base cannot be 35 * shared and is locked 36 * per user. 37 */ 38 struct { 39 int ip_lock; 40 int ip_req; 41 int *ip_addr; 42 int ip_data; 43 } ipc; 44 45 /* 46 * sys-trace system call. 47 */ 48 ptrace() 49 { 50 register struct proc *p; 51 register struct a { 52 int req; 53 int pid; 54 int *addr; 55 int data; 56 } *uap; 57 58 uap = (struct a *)u.u_ap; 59 if (uap->req <= 0) { 60 u.u_procp->p_flag |= STRC; 61 return; 62 } 63 p = pfind(uap->pid); 64 if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid || 65 !(p->p_flag & STRC)) { 66 u.u_error = ESRCH; 67 return; 68 } 69 while (ipc.ip_lock) 70 sleep((caddr_t)&ipc, IPCPRI); 71 ipc.ip_lock = p->p_pid; 72 ipc.ip_data = uap->data; 73 ipc.ip_addr = uap->addr; 74 ipc.ip_req = uap->req; 75 p->p_flag &= ~SWTED; 76 while (ipc.ip_req > 0) { 77 if (p->p_stat==SSTOP) 78 setrun(p); 79 sleep((caddr_t)&ipc, IPCPRI); 80 } 81 u.u_r.r_val1 = ipc.ip_data; 82 if (ipc.ip_req < 0) 83 u.u_error = EIO; 84 ipc.ip_lock = 0; 85 wakeup((caddr_t)&ipc); 86 } 87 88 #ifdef vax 89 #define NIPCREG 16 90 int ipcreg[NIPCREG] = 91 {R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,AP,FP,SP,PC}; 92 #endif 93 94 #define PHYSOFF(p, o) \ 95 ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0]))) 96 97 /* 98 * Code that the child process 99 * executes to implement the command 100 * of the parent process in tracing. 101 */ 102 procxmt() 103 { 104 register int i; 105 register *p; 106 register struct text *xp; 107 108 if (ipc.ip_lock != u.u_procp->p_pid) 109 return (0); 110 u.u_procp->p_slptime = 0; 111 i = ipc.ip_req; 112 ipc.ip_req = 0; 113 switch (i) { 114 115 /* read user I */ 116 case 1: 117 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 118 goto error; 119 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 120 break; 121 122 /* read user D */ 123 case 2: 124 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 125 goto error; 126 ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 127 break; 128 129 /* read u */ 130 case 3: 131 i = (int)ipc.ip_addr; 132 if (i<0 || i >= ctob(UPAGES)) 133 goto error; 134 ipc.ip_data = *(int *)PHYSOFF(&u, i); 135 break; 136 137 /* write user I */ 138 /* Must set up to allow writing */ 139 case 4: 140 /* 141 * If text, must assure exclusive use 142 */ 143 if (xp = u.u_procp->p_textp) { 144 if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX) 145 goto error; 146 xp->x_iptr->i_flag |= IXMOD; /* XXX */ 147 } 148 i = -1; 149 if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 150 if (chgprot((caddr_t)ipc.ip_addr, RW) && 151 chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW)) 152 i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 153 (void) chgprot((caddr_t)ipc.ip_addr, RO); 154 (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO); 155 } 156 if (i < 0) 157 goto error; 158 if (xp) 159 xp->x_flag |= XWRIT; 160 break; 161 162 /* write user D */ 163 case 5: 164 if (suword((caddr_t)ipc.ip_addr, 0) < 0) 165 goto error; 166 (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 167 break; 168 169 /* write u */ 170 case 6: 171 i = (int)ipc.ip_addr; 172 p = (int *)PHYSOFF(&u, i); 173 for (i=0; i<NIPCREG; i++) 174 if (p == &u.u_ar0[ipcreg[i]]) 175 goto ok; 176 if (p == &u.u_ar0[PS]) { 177 ipc.ip_data |= PSL_USERSET; 178 ipc.ip_data &= ~PSL_USERCLR; 179 goto ok; 180 } 181 goto error; 182 183 ok: 184 *p = ipc.ip_data; 185 break; 186 187 /* set signal and continue */ 188 /* one version causes a trace-trap */ 189 case 9: 190 case 7: 191 if ((int)ipc.ip_addr != 1) 192 u.u_ar0[PC] = (int)ipc.ip_addr; 193 if ((unsigned)ipc.ip_data > NSIG) 194 goto error; 195 u.u_procp->p_cursig = ipc.ip_data; /* see issig */ 196 if (i == 9) 197 u.u_ar0[PS] |= PSL_T; 198 wakeup((caddr_t)&ipc); 199 return (1); 200 201 /* force exit */ 202 case 8: 203 wakeup((caddr_t)&ipc); 204 exit(u.u_procp->p_cursig); 205 206 default: 207 error: 208 ipc.ip_req = -1; 209 } 210 wakeup((caddr_t)&ipc); 211 return (0); 212 } 213