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*48438Skarels * @(#)sys_process.c 7.17 (Berkeley) 04/20/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" 19*48438Skarels #include "vm/vm.h" 2047543Skarels #include "vm/vm_page.h" 2137520Smckusick 22*48438Skarels #include "user.h" 23*48438Skarels 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 878953Sroot #define PHYSOFF(p, o) \ 888952Sroot ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0]))) 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; 1127501Sroot 11342928Smckusick if (ipc.ip_lock != p->p_pid) 1147501Sroot return (0); 11542928Smckusick p->p_slptime = 0; 116*48438Skarels u.u_kproc.kp_proc.p_regs = p->p_regs; /* u.u_ar0 */ 1177501Sroot i = ipc.ip_req; 1187501Sroot ipc.ip_req = 0; 1197501Sroot switch (i) { 1207501Sroot 12126278Skarels case PT_READ_I: /* read the child's text space */ 1227501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1237501Sroot goto error; 1247501Sroot ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 1257501Sroot break; 1267501Sroot 12726278Skarels case PT_READ_D: /* read the child's data space */ 1287501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1297501Sroot goto error; 1307501Sroot ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 1317501Sroot break; 1327501Sroot 13326278Skarels case PT_READ_U: /* read the child's u. */ 13441991Smckusick #ifdef HPUXCOMPAT 13541991Smckusick if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 13641991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 13741991Smckusick else 13841991Smckusick #endif 1397501Sroot i = (int)ipc.ip_addr; 14041991Smckusick if (i<0 || i > ctob(UPAGES)-sizeof(int)) 1417501Sroot goto error; 1428952Sroot ipc.ip_data = *(int *)PHYSOFF(&u, i); 1437501Sroot break; 1447501Sroot 14526278Skarels case PT_WRITE_I: /* write the child's text space */ 1468952Sroot if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 14745735Smckusick vm_offset_t sa, ea; 14845735Smckusick int rv; 14945735Smckusick 15045735Smckusick sa = trunc_page((vm_offset_t)ipc.ip_addr); 15145735Smckusick ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1); 15247543Skarels rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, 15345735Smckusick VM_PROT_DEFAULT, FALSE); 15445735Smckusick if (rv == KERN_SUCCESS) { 1558952Sroot i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 15647543Skarels (void) vm_map_protect(&p->p_vmspace->vm_map, 15747543Skarels sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, 15847543Skarels FALSE); 15945735Smckusick } 1608952Sroot } 1617501Sroot if (i < 0) 1627501Sroot goto error; 1637501Sroot break; 1647501Sroot 16526278Skarels case PT_WRITE_D: /* write the child's data space */ 1667501Sroot if (suword((caddr_t)ipc.ip_addr, 0) < 0) 1677501Sroot goto error; 1687501Sroot (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 1697501Sroot break; 1707501Sroot 17126278Skarels case PT_WRITE_U: /* write the child's u. */ 17241991Smckusick #ifdef HPUXCOMPAT 17341991Smckusick if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 17441991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 17541991Smckusick else 17641991Smckusick #endif 1777501Sroot i = (int)ipc.ip_addr; 17842928Smckusick poff = (int *)PHYSOFF(&u, i); 1798952Sroot for (i=0; i<NIPCREG; i++) 18047543Skarels if (poff == &p->p_regs[ipcreg[i]]) 1817501Sroot goto ok; 18247543Skarels if (poff == &p->p_regs[PS]) { 1838952Sroot ipc.ip_data |= PSL_USERSET; 18441991Smckusick ipc.ip_data &= ~PSL_USERCLR; 18532863Skarels #ifdef PSL_CM_CLR 18632863Skarels if (ipc.ip_data & PSL_CM) 18732863Skarels ipc.ip_data &= ~PSL_CM_CLR; 18832863Skarels #endif 1897501Sroot goto ok; 1907501Sroot } 19141991Smckusick #if defined(hp300) 19241991Smckusick #ifdef FPCOPROC 19342928Smckusick if (poff >= (int *)u.u_pcb.pcb_fpregs.fpf_regs && 19442928Smckusick poff <= (int *)&u.u_pcb.pcb_fpregs.fpf_fpiar) 19541991Smckusick goto ok; 19641991Smckusick #endif 19741991Smckusick #endif 1987501Sroot goto error; 1997501Sroot 2007501Sroot ok: 20142928Smckusick *poff = ipc.ip_data; 2027501Sroot break; 2037501Sroot 20426278Skarels case PT_STEP: /* single step the child */ 20526278Skarels case PT_CONTINUE: /* continue the child */ 2067501Sroot if ((int)ipc.ip_addr != 1) 20747543Skarels p->p_regs[PC] = (int)ipc.ip_addr; 2087501Sroot if ((unsigned)ipc.ip_data > NSIG) 2097501Sroot goto error; 21043895Skarels p->p_xstat = ipc.ip_data; /* see issig */ 21126278Skarels if (i == PT_STEP) 21247543Skarels p->p_regs[PS] |= PSL_T; 2137501Sroot wakeup((caddr_t)&ipc); 2147501Sroot return (1); 2157501Sroot 21626278Skarels case PT_KILL: /* kill the child process */ 2177501Sroot wakeup((caddr_t)&ipc); 21845111Smckusick exit(p, (int)p->p_xstat); 2197501Sroot 2207501Sroot default: 2217501Sroot error: 2227501Sroot ipc.ip_req = -1; 2237501Sroot } 2247501Sroot wakeup((caddr_t)&ipc); 2257501Sroot return (0); 2267501Sroot } 227