123385Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 323385Smckusick * All rights reserved. The Berkeley software License Agreement 423385Smckusick * specifies the terms and conditions for redistribution. 523385Smckusick * 6*49534Smckusick * @(#)sys_process.c 7.20 (Berkeley) 05/09/91 723385Smckusick */ 87426Sroot 930376Skarels #define IPCREG 1017095Sbloom #include "param.h" 1117095Sbloom #include "proc.h" 1237728Smckusick #include "vnode.h" 1317095Sbloom #include "seg.h" 1417095Sbloom #include "buf.h" 1526278Skarels #include "ptrace.h" 167426Sroot 1737520Smckusick #include "machine/reg.h" 1837520Smckusick #include "machine/psl.h" 1948438Skarels #include "vm/vm.h" 2047543Skarels #include "vm/vm_page.h" 2137520Smckusick 2248438Skarels #include "user.h" 2348438Skarels 247501Sroot /* 257501Sroot * Priority for tracing 267501Sroot */ 277501Sroot #define IPCPRI PZERO 287501Sroot 297501Sroot /* 307501Sroot * Tracing variables. 317501Sroot * Used to pass trace command from 327501Sroot * parent to child being traced. 337501Sroot * This data base cannot be 347501Sroot * shared and is locked 357501Sroot * per user. 367501Sroot */ 377501Sroot struct { 387501Sroot int ip_lock; 397501Sroot int ip_req; 407501Sroot int *ip_addr; 417501Sroot int ip_data; 427501Sroot } ipc; 437501Sroot 447501Sroot /* 457501Sroot * sys-trace system call. 467501Sroot */ 4743378Smckusick ptrace(curp, uap, retval) 4843378Smckusick struct proc *curp; 4943378Smckusick register struct args { 507501Sroot int req; 517501Sroot int pid; 527501Sroot int *addr; 537501Sroot int data; 547501Sroot } *uap; 5543378Smckusick int *retval; 5643378Smckusick { 5743378Smckusick register struct proc *p; 587501Sroot 597501Sroot if (uap->req <= 0) { 6043378Smckusick curp->p_flag |= STRC; 6144405Skarels return (0); 627501Sroot } 637501Sroot p = pfind(uap->pid); 6447543Skarels if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp || 6543378Smckusick !(p->p_flag & STRC)) 6644405Skarels return (ESRCH); 677501Sroot while (ipc.ip_lock) 687501Sroot sleep((caddr_t)&ipc, IPCPRI); 697501Sroot ipc.ip_lock = p->p_pid; 707501Sroot ipc.ip_data = uap->data; 717501Sroot ipc.ip_addr = uap->addr; 727501Sroot ipc.ip_req = uap->req; 737501Sroot p->p_flag &= ~SWTED; 747501Sroot while (ipc.ip_req > 0) { 757501Sroot if (p->p_stat==SSTOP) 767501Sroot setrun(p); 777501Sroot sleep((caddr_t)&ipc, IPCPRI); 787501Sroot } 7943378Smckusick *retval = ipc.ip_data; 807501Sroot ipc.ip_lock = 0; 817501Sroot wakeup((caddr_t)&ipc); 8243378Smckusick if (ipc.ip_req < 0) 8344405Skarels return (EIO); 8444405Skarels return (0); 857501Sroot } 867501Sroot 8749246Skarels #define PHYSOFF(p, o) ((caddr_t)(p) + (o)) 8849246Skarels 8945882Swilliam #if defined(i386) 9045882Swilliam #undef PC 9145882Swilliam #undef SP 9245882Swilliam #undef PS 9345882Swilliam #undef R0 9445882Swilliam #undef R1 958952Sroot 9645882Swilliam #define PC tEIP 9745882Swilliam #define SP tESP 9845882Swilliam #define PS tEFLAGS 9945882Swilliam #define R0 tEDX 10045882Swilliam #define R1 tECX 10145882Swilliam #endif 10245882Swilliam 1037501Sroot /* 1047501Sroot * Code that the child process 1057501Sroot * executes to implement the command 1067501Sroot * of the parent process in tracing. 1077501Sroot */ 10842928Smckusick procxmt(p) 10942928Smckusick register struct proc *p; 1107501Sroot { 11142928Smckusick register int i, *poff; 11249246Skarels extern char kstack[]; 1137501Sroot 11442928Smckusick if (ipc.ip_lock != p->p_pid) 1157501Sroot return (0); 11642928Smckusick p->p_slptime = 0; 11749101Skarels p->p_addr->u_kproc.kp_proc.p_regs = p->p_regs; /* u.u_ar0 */ 1187501Sroot i = ipc.ip_req; 1197501Sroot ipc.ip_req = 0; 1207501Sroot switch (i) { 1217501Sroot 12226278Skarels case PT_READ_I: /* read the child's text space */ 1237501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1247501Sroot goto error; 1257501Sroot ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 1267501Sroot break; 1277501Sroot 12826278Skarels case PT_READ_D: /* read the child's data space */ 1297501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1307501Sroot goto error; 1317501Sroot ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 1327501Sroot break; 1337501Sroot 13426278Skarels case PT_READ_U: /* read the child's u. */ 13541991Smckusick #ifdef HPUXCOMPAT 13649101Skarels if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) 13741991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 13841991Smckusick else 13941991Smckusick #endif 1407501Sroot i = (int)ipc.ip_addr; 14149246Skarels if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0) 1427501Sroot goto error; 14349101Skarels ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i); 1447501Sroot break; 1457501Sroot 14626278Skarels case PT_WRITE_I: /* write the child's text space */ 1478952Sroot if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 14845735Smckusick vm_offset_t sa, ea; 14945735Smckusick int rv; 15045735Smckusick 15145735Smckusick sa = trunc_page((vm_offset_t)ipc.ip_addr); 15245735Smckusick ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1); 15347543Skarels rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, 15445735Smckusick VM_PROT_DEFAULT, FALSE); 15545735Smckusick if (rv == KERN_SUCCESS) { 1568952Sroot i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 15747543Skarels (void) vm_map_protect(&p->p_vmspace->vm_map, 15847543Skarels sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, 15947543Skarels FALSE); 16045735Smckusick } 1618952Sroot } 1627501Sroot if (i < 0) 1637501Sroot goto error; 1647501Sroot break; 1657501Sroot 16626278Skarels case PT_WRITE_D: /* write the child's data space */ 1677501Sroot if (suword((caddr_t)ipc.ip_addr, 0) < 0) 1687501Sroot goto error; 1697501Sroot (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 1707501Sroot break; 1717501Sroot 17226278Skarels case PT_WRITE_U: /* write the child's u. */ 17341991Smckusick #ifdef HPUXCOMPAT 17449101Skarels if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) 17541991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 17641991Smckusick else 17741991Smckusick #endif 1787501Sroot i = (int)ipc.ip_addr; 17949246Skarels poff = (int *)PHYSOFF(kstack, i); 1808952Sroot for (i=0; i<NIPCREG; i++) 18147543Skarels if (poff == &p->p_regs[ipcreg[i]]) 1827501Sroot goto ok; 18347543Skarels if (poff == &p->p_regs[PS]) { 1848952Sroot ipc.ip_data |= PSL_USERSET; 18541991Smckusick ipc.ip_data &= ~PSL_USERCLR; 18632863Skarels #ifdef PSL_CM_CLR 18732863Skarels if (ipc.ip_data & PSL_CM) 18832863Skarels ipc.ip_data &= ~PSL_CM_CLR; 18932863Skarels #endif 1907501Sroot goto ok; 1917501Sroot } 19241991Smckusick #if defined(hp300) 19341991Smckusick #ifdef FPCOPROC 19449246Skarels if (poff >= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_regs && 19549246Skarels poff <= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_fpiar) 19641991Smckusick goto ok; 19741991Smckusick #endif 19841991Smckusick #endif 1997501Sroot goto error; 2007501Sroot 2017501Sroot ok: 20242928Smckusick *poff = ipc.ip_data; 2037501Sroot break; 2047501Sroot 20526278Skarels case PT_STEP: /* single step the child */ 20626278Skarels case PT_CONTINUE: /* continue the child */ 2077501Sroot if ((int)ipc.ip_addr != 1) 20847543Skarels p->p_regs[PC] = (int)ipc.ip_addr; 2097501Sroot if ((unsigned)ipc.ip_data > NSIG) 2107501Sroot goto error; 21143895Skarels p->p_xstat = ipc.ip_data; /* see issig */ 21226278Skarels if (i == PT_STEP) 21347543Skarels p->p_regs[PS] |= PSL_T; 2147501Sroot wakeup((caddr_t)&ipc); 2157501Sroot return (1); 2167501Sroot 21726278Skarels case PT_KILL: /* kill the child process */ 2187501Sroot wakeup((caddr_t)&ipc); 21945111Smckusick exit(p, (int)p->p_xstat); 2207501Sroot 2217501Sroot default: 2227501Sroot error: 2237501Sroot ipc.ip_req = -1; 2247501Sroot } 2257501Sroot wakeup((caddr_t)&ipc); 2267501Sroot return (0); 2277501Sroot } 228*49534Smckusick 229*49534Smckusick /* ARGSUSED */ 230*49534Smckusick profil(p, uap, retval) 231*49534Smckusick struct proc *p; 232*49534Smckusick register struct args { 233*49534Smckusick short *bufbase; 234*49534Smckusick unsigned bufsize; 235*49534Smckusick unsigned pcoffset; 236*49534Smckusick unsigned pcscale; 237*49534Smckusick } *uap; 238*49534Smckusick int *retval; 239*49534Smckusick { 240*49534Smckusick register struct uprof *upp = &p->p_stats->p_prof; 241*49534Smckusick 242*49534Smckusick upp->pr_base = uap->bufbase; 243*49534Smckusick upp->pr_size = uap->bufsize; 244*49534Smckusick upp->pr_off = uap->pcoffset; 245*49534Smckusick upp->pr_scale = uap->pcscale; 246*49534Smckusick #ifdef PROFTIMER 247*49534Smckusick initprofclock(); 248*49534Smckusick #endif 249*49534Smckusick return (0); 250*49534Smckusick } 251