1 /* 2 * Copyright (c) 1982, 1986 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 7.2 (Berkeley) 11/03/86 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 #include "ptrace.h" 25 26 /* 27 * Priority for tracing 28 */ 29 #define IPCPRI PZERO 30 31 /* 32 * Tracing variables. 33 * Used to pass trace command from 34 * parent to child being traced. 35 * This data base cannot be 36 * shared and is locked 37 * per user. 38 */ 39 struct { 40 int ip_lock; 41 int ip_req; 42 int *ip_addr; 43 int ip_data; 44 } ipc; 45 46 /* 47 * sys-trace system call. 48 */ 49 ptrace() 50 { 51 register struct proc *p; 52 register struct a { 53 int req; 54 int pid; 55 int *addr; 56 int data; 57 } *uap; 58 59 uap = (struct a *)u.u_ap; 60 if (uap->req <= 0) { 61 u.u_procp->p_flag |= STRC; 62 return; 63 } 64 p = pfind(uap->pid); 65 if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid || 66 !(p->p_flag & STRC)) { 67 u.u_error = ESRCH; 68 return; 69 } 70 while (ipc.ip_lock) 71 sleep((caddr_t)&ipc, IPCPRI); 72 ipc.ip_lock = p->p_pid; 73 ipc.ip_data = uap->data; 74 ipc.ip_addr = uap->addr; 75 ipc.ip_req = uap->req; 76 p->p_flag &= ~SWTED; 77 while (ipc.ip_req > 0) { 78 if (p->p_stat==SSTOP) 79 setrun(p); 80 sleep((caddr_t)&ipc, IPCPRI); 81 } 82 u.u_r.r_val1 = ipc.ip_data; 83 if (ipc.ip_req < 0) 84 u.u_error = EIO; 85 ipc.ip_lock = 0; 86 wakeup((caddr_t)&ipc); 87 } 88 89 #if defined(vax) 90 #define NIPCREG 16 91 int ipcreg[NIPCREG] = 92 {R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,AP,FP,SP,PC}; 93 #endif 94 #if defined(tahoe) 95 #define NIPCREG 18 96 int ipcreg[NIPCREG] = 97 {R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,FP,SP,PC,RACH,RACL}; 98 #endif 99 100 #define PHYSOFF(p, o) \ 101 ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0]))) 102 103 /* 104 * Code that the child process 105 * executes to implement the command 106 * of the parent process in tracing. 107 */ 108 procxmt() 109 { 110 register int i; 111 register *p; 112 register struct text *xp; 113 114 if (ipc.ip_lock != u.u_procp->p_pid) 115 return (0); 116 u.u_procp->p_slptime = 0; 117 i = ipc.ip_req; 118 ipc.ip_req = 0; 119 switch (i) { 120 121 case PT_READ_I: /* read the child's text space */ 122 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 123 goto error; 124 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 125 break; 126 127 case PT_READ_D: /* read the child's data space */ 128 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 129 goto error; 130 ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 131 break; 132 133 case PT_READ_U: /* read the child's u. */ 134 i = (int)ipc.ip_addr; 135 if (i<0 || i >= ctob(UPAGES)) 136 goto error; 137 ipc.ip_data = *(int *)PHYSOFF(&u, i); 138 break; 139 140 case PT_WRITE_I: /* write the child's text space */ 141 /* 142 * If text, must assure exclusive use 143 */ 144 if (xp = u.u_procp->p_textp) { 145 if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX) 146 goto error; 147 xp->x_flag |= XTRC; 148 } 149 i = -1; 150 if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 151 if (chgprot((caddr_t)ipc.ip_addr, RW) && 152 chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW)) 153 i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 154 (void) chgprot((caddr_t)ipc.ip_addr, RO); 155 (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO); 156 } 157 if (i < 0) 158 goto error; 159 #if defined(tahoe) 160 /* make sure the old value is not in cache */ 161 ckeyrelease(u.u_procp->p_ckey); 162 u.u_procp->p_ckey = getcodekey(); 163 #endif 164 if (xp) { 165 xp->x_flag |= XWRIT; 166 #if defined(tahoe) 167 xp->x_ckey = u.u_procp->p_ckey; 168 #endif 169 } 170 break; 171 172 case PT_WRITE_D: /* write the child's data space */ 173 if (suword((caddr_t)ipc.ip_addr, 0) < 0) 174 goto error; 175 (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 176 break; 177 178 case PT_WRITE_U: /* write the child's u. */ 179 i = (int)ipc.ip_addr; 180 p = (int *)PHYSOFF(&u, i); 181 for (i=0; i<NIPCREG; i++) 182 if (p == &u.u_ar0[ipcreg[i]]) 183 goto ok; 184 if (p == &u.u_ar0[PS]) { 185 ipc.ip_data |= PSL_USERSET; 186 ipc.ip_data &= ~PSL_USERCLR; 187 goto ok; 188 } 189 goto error; 190 191 ok: 192 *p = ipc.ip_data; 193 break; 194 195 case PT_STEP: /* single step the child */ 196 case PT_CONTINUE: /* continue the child */ 197 if ((int)ipc.ip_addr != 1) 198 u.u_ar0[PC] = (int)ipc.ip_addr; 199 if ((unsigned)ipc.ip_data > NSIG) 200 goto error; 201 u.u_procp->p_cursig = ipc.ip_data; /* see issig */ 202 if (i == PT_STEP) 203 u.u_ar0[PS] |= PSL_T; 204 wakeup((caddr_t)&ipc); 205 return (1); 206 207 case PT_KILL: /* kill the child process */ 208 wakeup((caddr_t)&ipc); 209 exit(u.u_procp->p_cursig); 210 211 default: 212 error: 213 ipc.ip_req = -1; 214 } 215 wakeup((caddr_t)&ipc); 216 return (0); 217 } 218