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.1 (Berkeley) 06/05/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 95 #define PHYSOFF(p, o) \ 96 ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0]))) 97 98 /* 99 * Code that the child process 100 * executes to implement the command 101 * of the parent process in tracing. 102 */ 103 procxmt() 104 { 105 register int i; 106 register *p; 107 register struct text *xp; 108 109 if (ipc.ip_lock != u.u_procp->p_pid) 110 return (0); 111 u.u_procp->p_slptime = 0; 112 i = ipc.ip_req; 113 ipc.ip_req = 0; 114 switch (i) { 115 116 case PT_READ_I: /* read the child's text space */ 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 case PT_READ_D: /* read the child's data space */ 123 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 124 goto error; 125 ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 126 break; 127 128 case PT_READ_U: /* read the child's u. */ 129 i = (int)ipc.ip_addr; 130 if (i<0 || i >= ctob(UPAGES)) 131 goto error; 132 ipc.ip_data = *(int *)PHYSOFF(&u, i); 133 break; 134 135 case PT_WRITE_I: /* write the child's text space */ 136 /* 137 * If text, must assure exclusive use 138 */ 139 if (xp = u.u_procp->p_textp) { 140 if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX) 141 goto error; 142 xp->x_flag |= XTRC; 143 } 144 i = -1; 145 if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 146 if (chgprot((caddr_t)ipc.ip_addr, RW) && 147 chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW)) 148 i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 149 (void) chgprot((caddr_t)ipc.ip_addr, RO); 150 (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO); 151 } 152 if (i < 0) 153 goto error; 154 if (xp) 155 xp->x_flag |= XWRIT; 156 break; 157 158 case PT_WRITE_D: /* write the child's data space */ 159 if (suword((caddr_t)ipc.ip_addr, 0) < 0) 160 goto error; 161 (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 162 break; 163 164 case PT_WRITE_U: /* write the child's u. */ 165 i = (int)ipc.ip_addr; 166 p = (int *)PHYSOFF(&u, i); 167 for (i=0; i<NIPCREG; i++) 168 if (p == &u.u_ar0[ipcreg[i]]) 169 goto ok; 170 if (p == &u.u_ar0[PS]) { 171 ipc.ip_data |= PSL_USERSET; 172 ipc.ip_data &= ~PSL_USERCLR; 173 goto ok; 174 } 175 goto error; 176 177 ok: 178 *p = ipc.ip_data; 179 break; 180 181 case PT_STEP: /* single step the child */ 182 case PT_CONTINUE: /* continue the child */ 183 if ((int)ipc.ip_addr != 1) 184 u.u_ar0[PC] = (int)ipc.ip_addr; 185 if ((unsigned)ipc.ip_data > NSIG) 186 goto error; 187 u.u_procp->p_cursig = ipc.ip_data; /* see issig */ 188 if (i == PT_STEP) 189 u.u_ar0[PS] |= PSL_T; 190 wakeup((caddr_t)&ipc); 191 return (1); 192 193 case PT_KILL: /* kill the child process */ 194 wakeup((caddr_t)&ipc); 195 exit(u.u_procp->p_cursig); 196 197 default: 198 error: 199 ipc.ip_req = -1; 200 } 201 wakeup((caddr_t)&ipc); 202 return (0); 203 } 204