1 /*- 2 * Copyright (c) 1982, 1986, 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 * 7 * @(#)sys_process.c 7.22 (Berkeley) 05/11/91 8 */ 9 10 #define IPCREG 11 #include "param.h" 12 #include "proc.h" 13 #include "vnode.h" 14 #include "seg.h" 15 #include "buf.h" 16 #include "ptrace.h" 17 18 #include "machine/reg.h" 19 #include "machine/psl.h" 20 #include "vm/vm.h" 21 #include "vm/vm_page.h" 22 23 #include "user.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 * Process debugging system call. 47 */ 48 ptrace(curp, uap, retval) 49 struct proc *curp; 50 register struct args { 51 int req; 52 int pid; 53 int *addr; 54 int data; 55 } *uap; 56 int *retval; 57 { 58 register struct proc *p; 59 60 if (uap->req <= 0) { 61 curp->p_flag |= STRC; 62 return (0); 63 } 64 p = pfind(uap->pid); 65 if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp || 66 !(p->p_flag & STRC)) 67 return (ESRCH); 68 while (ipc.ip_lock) 69 sleep((caddr_t)&ipc, IPCPRI); 70 ipc.ip_lock = p->p_pid; 71 ipc.ip_data = uap->data; 72 ipc.ip_addr = uap->addr; 73 ipc.ip_req = uap->req; 74 p->p_flag &= ~SWTED; 75 while (ipc.ip_req > 0) { 76 if (p->p_stat==SSTOP) 77 setrun(p); 78 sleep((caddr_t)&ipc, IPCPRI); 79 } 80 *retval = ipc.ip_data; 81 ipc.ip_lock = 0; 82 wakeup((caddr_t)&ipc); 83 if (ipc.ip_req < 0) 84 return (EIO); 85 return (0); 86 } 87 88 #define PHYSOFF(p, o) ((caddr_t)(p) + (o)) 89 90 #if defined(i386) 91 #undef PC 92 #undef SP 93 #undef PS 94 #undef R0 95 #undef R1 96 97 #define PC tEIP 98 #define SP tESP 99 #define PS tEFLAGS 100 #define R0 tEDX 101 #define R1 tECX 102 #endif 103 104 /* 105 * Transmit a tracing request from the parent to the child process 106 * being debugged. This code runs in the context of the child process 107 * to fulfill the command requested by the parent. 108 */ 109 procxmt(p) 110 register struct proc *p; 111 { 112 register int i, *poff; 113 extern char kstack[]; 114 115 if (ipc.ip_lock != p->p_pid) 116 return (0); 117 p->p_slptime = 0; 118 p->p_addr->u_kproc.kp_proc.p_regs = p->p_regs; /* u.u_ar0 */ 119 i = ipc.ip_req; 120 ipc.ip_req = 0; 121 switch (i) { 122 123 case PT_READ_I: /* read the child's text space */ 124 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 125 goto error; 126 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 127 break; 128 129 case PT_READ_D: /* read the child's data space */ 130 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 131 goto error; 132 ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 133 break; 134 135 case PT_READ_U: /* read the child's u. */ 136 #ifdef HPUXCOMPAT 137 if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) 138 i = hpuxtobsduoff(ipc.ip_addr); 139 else 140 #endif 141 i = (int)ipc.ip_addr; 142 if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0) 143 goto error; 144 ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i); 145 break; 146 147 case PT_WRITE_I: /* write the child's text space */ 148 if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 149 vm_offset_t sa, ea; 150 int rv; 151 152 sa = trunc_page((vm_offset_t)ipc.ip_addr); 153 ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1); 154 rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, 155 VM_PROT_DEFAULT, FALSE); 156 if (rv == KERN_SUCCESS) { 157 i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 158 (void) vm_map_protect(&p->p_vmspace->vm_map, 159 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, 160 FALSE); 161 } 162 } 163 if (i < 0) 164 goto error; 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 (p->p_addr->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(kstack, i); 181 for (i=0; i<NIPCREG; i++) 182 if (poff == &p->p_regs[ipcreg[i]]) 183 goto ok; 184 if (poff == &p->p_regs[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 *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_regs && 196 poff <= (int *)&((struct user *)kstack)->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 p->p_regs[PC] = (int)ipc.ip_addr; 210 if ((unsigned)ipc.ip_data > NSIG) 211 goto error; 212 p->p_xstat = ipc.ip_data; /* see issig */ 213 if (i == PT_STEP) 214 p->p_regs[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, (int)p->p_xstat); 221 222 default: 223 error: 224 ipc.ip_req = -1; 225 } 226 wakeup((caddr_t)&ipc); 227 return (0); 228 } 229 230 /* 231 * Process debugging system call. 232 */ 233 /* ARGSUSED */ 234 profil(p, uap, retval) 235 struct proc *p; 236 register struct args { 237 short *bufbase; 238 unsigned bufsize; 239 unsigned pcoffset; 240 unsigned pcscale; 241 } *uap; 242 int *retval; 243 { 244 register struct uprof *upp = &p->p_stats->p_prof; 245 246 upp->pr_base = uap->bufbase; 247 upp->pr_size = uap->bufsize; 248 upp->pr_off = uap->pcoffset; 249 upp->pr_scale = uap->pcscale; 250 #ifdef PROFTIMER 251 initprofclock(); 252 #endif 253 return (0); 254 } 255