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.8 (Berkeley) 06/06/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() 47 { 48 register struct proc *p; 49 register struct a { 50 int req; 51 int pid; 52 int *addr; 53 int data; 54 } *uap; 55 56 uap = (struct a *)u.u_ap; 57 if (uap->req <= 0) { 58 u.u_procp->p_flag |= STRC; 59 return; 60 } 61 p = pfind(uap->pid); 62 if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid || 63 !(p->p_flag & STRC)) { 64 u.u_error = ESRCH; 65 return; 66 } 67 while (ipc.ip_lock) 68 sleep((caddr_t)&ipc, IPCPRI); 69 ipc.ip_lock = p->p_pid; 70 ipc.ip_data = uap->data; 71 ipc.ip_addr = uap->addr; 72 ipc.ip_req = uap->req; 73 p->p_flag &= ~SWTED; 74 while (ipc.ip_req > 0) { 75 if (p->p_stat==SSTOP) 76 setrun(p); 77 sleep((caddr_t)&ipc, IPCPRI); 78 } 79 u.u_r.r_val1 = ipc.ip_data; 80 if (ipc.ip_req < 0) 81 u.u_error = EIO; 82 ipc.ip_lock = 0; 83 wakeup((caddr_t)&ipc); 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 struct vnode *vp; 101 102 if (ipc.ip_lock != p->p_pid) 103 return (0); 104 p->p_slptime = 0; 105 i = ipc.ip_req; 106 ipc.ip_req = 0; 107 switch (i) { 108 109 case PT_READ_I: /* read the child's text space */ 110 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 111 goto error; 112 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 113 break; 114 115 case PT_READ_D: /* read the child's data space */ 116 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 117 goto error; 118 ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 119 break; 120 121 case PT_READ_U: /* read the child's u. */ 122 #ifdef HPUXCOMPAT 123 if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 124 i = hpuxtobsduoff(ipc.ip_addr); 125 else 126 #endif 127 i = (int)ipc.ip_addr; 128 if (i<0 || i > ctob(UPAGES)-sizeof(int)) 129 goto error; 130 ipc.ip_data = *(int *)PHYSOFF(&u, i); 131 break; 132 133 case PT_WRITE_I: /* write the child's text space */ 134 /* 135 * If text, must assure exclusive use 136 */ 137 if (xp = p->p_textp) { 138 vp = xp->x_vptr; 139 VOP_GETATTR(vp, &vattr, u.u_cred); 140 if (xp->x_count!=1 || (vattr.va_mode & VSVTX)) 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 defined(tahoe) 155 /* make sure the old value is not in cache */ 156 ckeyrelease(p->p_ckey); 157 p->p_ckey = getcodekey(); 158 #endif 159 if (xp) { 160 xp->x_flag |= XWRIT; 161 #if defined(tahoe) 162 xp->x_ckey = p->p_ckey; 163 #endif 164 } 165 break; 166 167 case PT_WRITE_D: /* write the child's data space */ 168 if (suword((caddr_t)ipc.ip_addr, 0) < 0) 169 goto error; 170 (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 171 break; 172 173 case PT_WRITE_U: /* write the child's u. */ 174 #ifdef HPUXCOMPAT 175 if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 176 i = hpuxtobsduoff(ipc.ip_addr); 177 else 178 #endif 179 i = (int)ipc.ip_addr; 180 poff = (int *)PHYSOFF(&u, i); 181 for (i=0; i<NIPCREG; i++) 182 if (poff == &u.u_ar0[ipcreg[i]]) 183 goto ok; 184 if (poff == &u.u_ar0[PS]) { 185 ipc.ip_data |= PSL_USERSET; 186 ipc.ip_data &= ~PSL_USERCLR; 187 #ifdef PSL_CM_CLR 188 if (ipc.ip_data & PSL_CM) 189 ipc.ip_data &= ~PSL_CM_CLR; 190 #endif 191 goto ok; 192 } 193 #if defined(hp300) 194 #ifdef FPCOPROC 195 if (poff >= (int *)u.u_pcb.pcb_fpregs.fpf_regs && 196 poff <= (int *)&u.u_pcb.pcb_fpregs.fpf_fpiar) 197 goto ok; 198 #endif 199 #endif 200 goto error; 201 202 ok: 203 *poff = ipc.ip_data; 204 break; 205 206 case PT_STEP: /* single step the child */ 207 case PT_CONTINUE: /* continue the child */ 208 if ((int)ipc.ip_addr != 1) 209 u.u_ar0[PC] = (int)ipc.ip_addr; 210 if ((unsigned)ipc.ip_data > NSIG) 211 goto error; 212 p->p_cursig = ipc.ip_data; /* see issig */ 213 if (i == PT_STEP) 214 u.u_ar0[PS] |= PSL_T; 215 wakeup((caddr_t)&ipc); 216 return (1); 217 218 case PT_KILL: /* kill the child process */ 219 wakeup((caddr_t)&ipc); 220 exit(p, p->p_cursig); 221 222 default: 223 error: 224 ipc.ip_req = -1; 225 } 226 wakeup((caddr_t)&ipc); 227 return (0); 228 } 229