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