1*49589Sbostic /*- 2*49589Sbostic * Copyright (c) 1982, 1986, 1989 The Regents of the University of California. 3*49589Sbostic * All rights reserved. 423385Smckusick * 5*49589Sbostic * %sccs.include.proprietary.c% 6*49589Sbostic * 7*49589Sbostic * @(#)sys_process.c 7.21 (Berkeley) 05/09/91 823385Smckusick */ 97426Sroot 1030376Skarels #define IPCREG 1117095Sbloom #include "param.h" 1217095Sbloom #include "proc.h" 1337728Smckusick #include "vnode.h" 1417095Sbloom #include "seg.h" 1517095Sbloom #include "buf.h" 1626278Skarels #include "ptrace.h" 177426Sroot 1837520Smckusick #include "machine/reg.h" 1937520Smckusick #include "machine/psl.h" 2048438Skarels #include "vm/vm.h" 2147543Skarels #include "vm/vm_page.h" 2237520Smckusick 2348438Skarels #include "user.h" 2448438Skarels 257501Sroot /* 267501Sroot * Priority for tracing 277501Sroot */ 287501Sroot #define IPCPRI PZERO 297501Sroot 307501Sroot /* 317501Sroot * Tracing variables. 327501Sroot * Used to pass trace command from 337501Sroot * parent to child being traced. 347501Sroot * This data base cannot be 357501Sroot * shared and is locked 367501Sroot * per user. 377501Sroot */ 387501Sroot struct { 397501Sroot int ip_lock; 407501Sroot int ip_req; 417501Sroot int *ip_addr; 427501Sroot int ip_data; 437501Sroot } ipc; 447501Sroot 457501Sroot /* 467501Sroot * sys-trace system call. 477501Sroot */ 4843378Smckusick ptrace(curp, uap, retval) 4943378Smckusick struct proc *curp; 5043378Smckusick register struct args { 517501Sroot int req; 527501Sroot int pid; 537501Sroot int *addr; 547501Sroot int data; 557501Sroot } *uap; 5643378Smckusick int *retval; 5743378Smckusick { 5843378Smckusick register struct proc *p; 597501Sroot 607501Sroot if (uap->req <= 0) { 6143378Smckusick curp->p_flag |= STRC; 6244405Skarels return (0); 637501Sroot } 647501Sroot p = pfind(uap->pid); 6547543Skarels if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp || 6643378Smckusick !(p->p_flag & STRC)) 6744405Skarels return (ESRCH); 687501Sroot while (ipc.ip_lock) 697501Sroot sleep((caddr_t)&ipc, IPCPRI); 707501Sroot ipc.ip_lock = p->p_pid; 717501Sroot ipc.ip_data = uap->data; 727501Sroot ipc.ip_addr = uap->addr; 737501Sroot ipc.ip_req = uap->req; 747501Sroot p->p_flag &= ~SWTED; 757501Sroot while (ipc.ip_req > 0) { 767501Sroot if (p->p_stat==SSTOP) 777501Sroot setrun(p); 787501Sroot sleep((caddr_t)&ipc, IPCPRI); 797501Sroot } 8043378Smckusick *retval = ipc.ip_data; 817501Sroot ipc.ip_lock = 0; 827501Sroot wakeup((caddr_t)&ipc); 8343378Smckusick if (ipc.ip_req < 0) 8444405Skarels return (EIO); 8544405Skarels return (0); 867501Sroot } 877501Sroot 8849246Skarels #define PHYSOFF(p, o) ((caddr_t)(p) + (o)) 8949246Skarels 9045882Swilliam #if defined(i386) 9145882Swilliam #undef PC 9245882Swilliam #undef SP 9345882Swilliam #undef PS 9445882Swilliam #undef R0 9545882Swilliam #undef R1 968952Sroot 9745882Swilliam #define PC tEIP 9845882Swilliam #define SP tESP 9945882Swilliam #define PS tEFLAGS 10045882Swilliam #define R0 tEDX 10145882Swilliam #define R1 tECX 10245882Swilliam #endif 10345882Swilliam 1047501Sroot /* 1057501Sroot * Code that the child process 1067501Sroot * executes to implement the command 1077501Sroot * of the parent process in tracing. 1087501Sroot */ 10942928Smckusick procxmt(p) 11042928Smckusick register struct proc *p; 1117501Sroot { 11242928Smckusick register int i, *poff; 11349246Skarels extern char kstack[]; 1147501Sroot 11542928Smckusick if (ipc.ip_lock != p->p_pid) 1167501Sroot return (0); 11742928Smckusick p->p_slptime = 0; 11849101Skarels p->p_addr->u_kproc.kp_proc.p_regs = p->p_regs; /* u.u_ar0 */ 1197501Sroot i = ipc.ip_req; 1207501Sroot ipc.ip_req = 0; 1217501Sroot switch (i) { 1227501Sroot 12326278Skarels case PT_READ_I: /* read the child's text space */ 1247501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1257501Sroot goto error; 1267501Sroot ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 1277501Sroot break; 1287501Sroot 12926278Skarels case PT_READ_D: /* read the child's data space */ 1307501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1317501Sroot goto error; 1327501Sroot ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 1337501Sroot break; 1347501Sroot 13526278Skarels case PT_READ_U: /* read the child's u. */ 13641991Smckusick #ifdef HPUXCOMPAT 13749101Skarels if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) 13841991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 13941991Smckusick else 14041991Smckusick #endif 1417501Sroot i = (int)ipc.ip_addr; 14249246Skarels if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0) 1437501Sroot goto error; 14449101Skarels ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i); 1457501Sroot break; 1467501Sroot 14726278Skarels case PT_WRITE_I: /* write the child's text space */ 1488952Sroot if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 14945735Smckusick vm_offset_t sa, ea; 15045735Smckusick int rv; 15145735Smckusick 15245735Smckusick sa = trunc_page((vm_offset_t)ipc.ip_addr); 15345735Smckusick ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1); 15447543Skarels rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, 15545735Smckusick VM_PROT_DEFAULT, FALSE); 15645735Smckusick if (rv == KERN_SUCCESS) { 1578952Sroot i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 15847543Skarels (void) vm_map_protect(&p->p_vmspace->vm_map, 15947543Skarels sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, 16047543Skarels FALSE); 16145735Smckusick } 1628952Sroot } 1637501Sroot if (i < 0) 1647501Sroot goto error; 1657501Sroot break; 1667501Sroot 16726278Skarels case PT_WRITE_D: /* write the child's data space */ 1687501Sroot if (suword((caddr_t)ipc.ip_addr, 0) < 0) 1697501Sroot goto error; 1707501Sroot (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 1717501Sroot break; 1727501Sroot 17326278Skarels case PT_WRITE_U: /* write the child's u. */ 17441991Smckusick #ifdef HPUXCOMPAT 17549101Skarels if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) 17641991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 17741991Smckusick else 17841991Smckusick #endif 1797501Sroot i = (int)ipc.ip_addr; 18049246Skarels poff = (int *)PHYSOFF(kstack, i); 1818952Sroot for (i=0; i<NIPCREG; i++) 18247543Skarels if (poff == &p->p_regs[ipcreg[i]]) 1837501Sroot goto ok; 18447543Skarels if (poff == &p->p_regs[PS]) { 1858952Sroot ipc.ip_data |= PSL_USERSET; 18641991Smckusick ipc.ip_data &= ~PSL_USERCLR; 18732863Skarels #ifdef PSL_CM_CLR 18832863Skarels if (ipc.ip_data & PSL_CM) 18932863Skarels ipc.ip_data &= ~PSL_CM_CLR; 19032863Skarels #endif 1917501Sroot goto ok; 1927501Sroot } 19341991Smckusick #if defined(hp300) 19441991Smckusick #ifdef FPCOPROC 19549246Skarels if (poff >= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_regs && 19649246Skarels poff <= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_fpiar) 19741991Smckusick goto ok; 19841991Smckusick #endif 19941991Smckusick #endif 2007501Sroot goto error; 2017501Sroot 2027501Sroot ok: 20342928Smckusick *poff = ipc.ip_data; 2047501Sroot break; 2057501Sroot 20626278Skarels case PT_STEP: /* single step the child */ 20726278Skarels case PT_CONTINUE: /* continue the child */ 2087501Sroot if ((int)ipc.ip_addr != 1) 20947543Skarels p->p_regs[PC] = (int)ipc.ip_addr; 2107501Sroot if ((unsigned)ipc.ip_data > NSIG) 2117501Sroot goto error; 21243895Skarels p->p_xstat = ipc.ip_data; /* see issig */ 21326278Skarels if (i == PT_STEP) 21447543Skarels p->p_regs[PS] |= PSL_T; 2157501Sroot wakeup((caddr_t)&ipc); 2167501Sroot return (1); 2177501Sroot 21826278Skarels case PT_KILL: /* kill the child process */ 2197501Sroot wakeup((caddr_t)&ipc); 22045111Smckusick exit(p, (int)p->p_xstat); 2217501Sroot 2227501Sroot default: 2237501Sroot error: 2247501Sroot ipc.ip_req = -1; 2257501Sroot } 2267501Sroot wakeup((caddr_t)&ipc); 2277501Sroot return (0); 2287501Sroot } 22949534Smckusick 23049534Smckusick /* ARGSUSED */ 23149534Smckusick profil(p, uap, retval) 23249534Smckusick struct proc *p; 23349534Smckusick register struct args { 23449534Smckusick short *bufbase; 23549534Smckusick unsigned bufsize; 23649534Smckusick unsigned pcoffset; 23749534Smckusick unsigned pcscale; 23849534Smckusick } *uap; 23949534Smckusick int *retval; 24049534Smckusick { 24149534Smckusick register struct uprof *upp = &p->p_stats->p_prof; 24249534Smckusick 24349534Smckusick upp->pr_base = uap->bufbase; 24449534Smckusick upp->pr_size = uap->bufsize; 24549534Smckusick upp->pr_off = uap->pcoffset; 24649534Smckusick upp->pr_scale = uap->pcscale; 24749534Smckusick #ifdef PROFTIMER 24849534Smckusick initprofclock(); 24949534Smckusick #endif 25049534Smckusick return (0); 25149534Smckusick } 252