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.25 (Berkeley) 06/04/92 8 */ 9 10 #define IPCREG 11 #include "param.h" 12 #include "proc.h" 13 #include "vnode.h" 14 #include "buf.h" 15 #include "ptrace.h" 16 17 #include "machine/reg.h" 18 #include "machine/psl.h" 19 #include "vm/vm.h" 20 #include "vm/vm_page.h" 21 22 #include "user.h" 23 24 /* 25 * Priority for tracing 26 */ 27 #define IPCPRI PZERO 28 29 /* 30 * Tracing variables. 31 * Used to pass trace command from 32 * parent to child being traced. 33 * This data base cannot be 34 * shared and is locked 35 * per user. 36 */ 37 struct { 38 int ip_lock; 39 int ip_req; 40 int *ip_addr; 41 int ip_data; 42 } ipc; 43 44 /* 45 * Process debugging system call. 46 */ 47 ptrace(curp, uap, retval) 48 struct proc *curp; 49 register struct args { 50 int req; 51 int pid; 52 int *addr; 53 int data; 54 } *uap; 55 int *retval; 56 { 57 register struct proc *p; 58 59 if (uap->req <= 0) { 60 curp->p_flag |= STRC; 61 return (0); 62 } 63 p = pfind(uap->pid); 64 if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp || 65 !(p->p_flag & STRC)) 66 return (ESRCH); 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 *retval = ipc.ip_data; 80 ipc.ip_lock = 0; 81 wakeup((caddr_t)&ipc); 82 if (ipc.ip_req < 0) 83 return (EIO); 84 return (0); 85 } 86 87 #define PHYSOFF(p, o) ((caddr_t)(p) + (o)) 88 89 #if defined(i386) 90 #undef PC 91 #undef SP 92 #undef PS 93 #undef R0 94 #undef R1 95 96 #define PC tEIP 97 #define SP tESP 98 #define PS tEFLAGS 99 #define R0 tEDX 100 #define R1 tECX 101 #endif 102 103 /* 104 * Transmit a tracing request from the parent to the child process 105 * being debugged. This code runs in the context of the child process 106 * to fulfill the command requested by the parent. 107 */ 108 procxmt(p) 109 register struct proc *p; 110 { 111 register int i, *poff; 112 extern char kstack[]; 113 114 if (ipc.ip_lock != p->p_pid) 115 return (0); 116 p->p_slptime = 0; 117 p->p_addr->u_kproc.kp_proc.p_md.md_regs = p->p_md.md_regs; /* u.u_ar0 */ 118 i = ipc.ip_req; 119 ipc.ip_req = 0; 120 switch (i) { 121 122 case PT_READ_I: /* read the child's text space */ 123 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 124 goto error; 125 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 126 break; 127 128 case PT_READ_D: /* read the child's data space */ 129 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 130 goto error; 131 ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 132 break; 133 134 case PT_READ_U: /* read the child's u. */ 135 #ifdef HPUXCOMPAT 136 if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) 137 i = hpuxtobsduoff(ipc.ip_addr); 138 else 139 #endif 140 i = (int)ipc.ip_addr; 141 if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0) 142 goto error; 143 ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i); 144 break; 145 146 case PT_WRITE_I: /* write the child's text space */ 147 if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 148 vm_offset_t sa, ea; 149 int rv; 150 151 sa = trunc_page((vm_offset_t)ipc.ip_addr); 152 ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1); 153 rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, 154 VM_PROT_DEFAULT, FALSE); 155 if (rv == KERN_SUCCESS) { 156 i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 157 (void) vm_map_protect(&p->p_vmspace->vm_map, 158 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, 159 FALSE); 160 } 161 } 162 if (i < 0) 163 goto error; 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 (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) 175 i = hpuxtobsduoff(ipc.ip_addr); 176 else 177 #endif 178 i = (int)ipc.ip_addr; 179 #ifdef mips 180 poff = (int *)PHYSOFF(curproc->p_addr, i); 181 #else 182 poff = (int *)PHYSOFF(kstack, i); 183 #endif 184 for (i=0; i<NIPCREG; i++) 185 if (poff == &p->p_md.md_regs[ipcreg[i]]) 186 goto ok; 187 if (poff == &p->p_md.md_regs[PS]) { 188 ipc.ip_data |= PSL_USERSET; 189 ipc.ip_data &= ~PSL_USERCLR; 190 #ifdef PSL_CM_CLR 191 if (ipc.ip_data & PSL_CM) 192 ipc.ip_data &= ~PSL_CM_CLR; 193 #endif 194 goto ok; 195 } 196 #if defined(hp300) || defined(luna68k) 197 #ifdef FPCOPROC 198 if (poff >= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_regs && 199 poff <= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_fpiar) 200 goto ok; 201 #endif 202 #endif 203 goto error; 204 205 ok: 206 *poff = ipc.ip_data; 207 break; 208 209 case PT_STEP: /* single step the child */ 210 case PT_CONTINUE: /* continue the child */ 211 if ((int)ipc.ip_addr != 1) 212 p->p_md.md_regs[PC] = (int)ipc.ip_addr; 213 if ((unsigned)ipc.ip_data > NSIG) 214 goto error; 215 p->p_xstat = ipc.ip_data; /* see issig */ 216 #ifdef PSL_T 217 /* need something more machine independent here... */ 218 if (i == PT_STEP) 219 p->p_md.md_regs[PS] |= PSL_T; 220 #endif 221 wakeup((caddr_t)&ipc); 222 return (1); 223 224 case PT_KILL: /* kill the child process */ 225 wakeup((caddr_t)&ipc); 226 exit(p, (int)p->p_xstat); 227 228 default: 229 error: 230 ipc.ip_req = -1; 231 } 232 wakeup((caddr_t)&ipc); 233 return (0); 234 } 235 236 /* 237 * Process debugging system call. 238 */ 239 /* ARGSUSED */ 240 profil(p, uap, retval) 241 struct proc *p; 242 register struct args { 243 short *bufbase; 244 unsigned bufsize; 245 unsigned pcoffset; 246 unsigned pcscale; 247 } *uap; 248 int *retval; 249 { 250 register struct uprof *upp = &p->p_stats->p_prof; 251 252 upp->pr_base = uap->bufbase; 253 upp->pr_size = uap->bufsize; 254 upp->pr_off = uap->pcoffset; 255 upp->pr_scale = uap->pcscale; 256 #ifdef PROFTIMER 257 initprofclock(); 258 #endif 259 return (0); 260 } 261