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*45111Smckusick * @(#)sys_process.c 7.13 (Berkeley) 08/24/90 723385Smckusick */ 87426Sroot 930376Skarels #define IPCREG 1017095Sbloom #include "param.h" 1144405Skarels #include "user.h" 1217095Sbloom #include "proc.h" 1337728Smckusick #include "vnode.h" 1417095Sbloom #include "text.h" 1517095Sbloom #include "seg.h" 1617095Sbloom #include "buf.h" 1726278Skarels #include "ptrace.h" 187426Sroot 1937520Smckusick #include "machine/reg.h" 2037520Smckusick #include "machine/psl.h" 2137520Smckusick #include "machine/pte.h" 2237520Smckusick 237501Sroot /* 247501Sroot * Priority for tracing 257501Sroot */ 267501Sroot #define IPCPRI PZERO 277501Sroot 287501Sroot /* 297501Sroot * Tracing variables. 307501Sroot * Used to pass trace command from 317501Sroot * parent to child being traced. 327501Sroot * This data base cannot be 337501Sroot * shared and is locked 347501Sroot * per user. 357501Sroot */ 367501Sroot struct { 377501Sroot int ip_lock; 387501Sroot int ip_req; 397501Sroot int *ip_addr; 407501Sroot int ip_data; 417501Sroot } ipc; 427501Sroot 437501Sroot /* 447501Sroot * sys-trace system call. 457501Sroot */ 4643378Smckusick ptrace(curp, uap, retval) 4743378Smckusick struct proc *curp; 4843378Smckusick register struct args { 497501Sroot int req; 507501Sroot int pid; 517501Sroot int *addr; 527501Sroot int data; 537501Sroot } *uap; 5443378Smckusick int *retval; 5543378Smckusick { 5643378Smckusick register struct proc *p; 577501Sroot 587501Sroot if (uap->req <= 0) { 5943378Smckusick curp->p_flag |= STRC; 6044405Skarels return (0); 617501Sroot } 627501Sroot p = pfind(uap->pid); 6343378Smckusick if (p == 0 || p->p_stat != SSTOP || p->p_ppid != curp->p_pid || 6443378Smckusick !(p->p_flag & STRC)) 6544405Skarels return (ESRCH); 667501Sroot while (ipc.ip_lock) 677501Sroot sleep((caddr_t)&ipc, IPCPRI); 687501Sroot ipc.ip_lock = p->p_pid; 697501Sroot ipc.ip_data = uap->data; 707501Sroot ipc.ip_addr = uap->addr; 717501Sroot ipc.ip_req = uap->req; 727501Sroot p->p_flag &= ~SWTED; 737501Sroot while (ipc.ip_req > 0) { 747501Sroot if (p->p_stat==SSTOP) 757501Sroot setrun(p); 767501Sroot sleep((caddr_t)&ipc, IPCPRI); 777501Sroot } 7843378Smckusick *retval = ipc.ip_data; 797501Sroot ipc.ip_lock = 0; 807501Sroot wakeup((caddr_t)&ipc); 8143378Smckusick if (ipc.ip_req < 0) 8244405Skarels return (EIO); 8344405Skarels return (0); 847501Sroot } 857501Sroot 868953Sroot #define PHYSOFF(p, o) \ 878952Sroot ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0]))) 888952Sroot 897501Sroot /* 907501Sroot * Code that the child process 917501Sroot * executes to implement the command 927501Sroot * of the parent process in tracing. 937501Sroot */ 9442928Smckusick procxmt(p) 9542928Smckusick register struct proc *p; 967501Sroot { 9742928Smckusick register int i, *poff; 987501Sroot register struct text *xp; 9937728Smckusick struct vattr vattr; 1007501Sroot 10142928Smckusick if (ipc.ip_lock != p->p_pid) 1027501Sroot return (0); 10342928Smckusick p->p_slptime = 0; 1047501Sroot i = ipc.ip_req; 1057501Sroot ipc.ip_req = 0; 1067501Sroot switch (i) { 1077501Sroot 10826278Skarels case PT_READ_I: /* read the child's text space */ 1097501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1107501Sroot goto error; 1117501Sroot ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 1127501Sroot break; 1137501Sroot 11426278Skarels case PT_READ_D: /* read the child's data space */ 1157501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1167501Sroot goto error; 1177501Sroot ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 1187501Sroot break; 1197501Sroot 12026278Skarels case PT_READ_U: /* read the child's u. */ 12141991Smckusick #ifdef HPUXCOMPAT 12241991Smckusick if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 12341991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 12441991Smckusick else 12541991Smckusick #endif 1267501Sroot i = (int)ipc.ip_addr; 12741991Smckusick if (i<0 || i > ctob(UPAGES)-sizeof(int)) 1287501Sroot goto error; 1298952Sroot ipc.ip_data = *(int *)PHYSOFF(&u, i); 1307501Sroot break; 1317501Sroot 13226278Skarels case PT_WRITE_I: /* write the child's text space */ 1337501Sroot /* 1347501Sroot * If text, must assure exclusive use 1357501Sroot */ 13642928Smckusick if (xp = p->p_textp) { 137*45111Smckusick if (xp->x_count != 1 || 138*45111Smckusick VOP_GETATTR(xp->x_vptr, &vattr, u.u_cred) || 139*45111Smckusick (vattr.va_mode & VSVTX)) 1407501Sroot goto error; 14125535Skarels xp->x_flag |= XTRC; 1427501Sroot } 1437501Sroot i = -1; 1448952Sroot if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 14543375Smckusick if (!chgprot((caddr_t)ipc.ip_addr, RW) && 14643375Smckusick !chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW)) 1478952Sroot i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 1488952Sroot (void) chgprot((caddr_t)ipc.ip_addr, RO); 1498952Sroot (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO); 1508952Sroot } 1517501Sroot if (i < 0) 1527501Sroot goto error; 15329946Skarels #if defined(tahoe) 15429946Skarels /* make sure the old value is not in cache */ 15542928Smckusick ckeyrelease(p->p_ckey); 15642928Smckusick p->p_ckey = getcodekey(); 15729946Skarels #endif 15829946Skarels if (xp) { 1597501Sroot xp->x_flag |= XWRIT; 16029946Skarels #if defined(tahoe) 16142928Smckusick xp->x_ckey = p->p_ckey; 16229946Skarels #endif 16329946Skarels } 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 17441991Smckusick if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 17541991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 17641991Smckusick else 17741991Smckusick #endif 1787501Sroot i = (int)ipc.ip_addr; 17942928Smckusick poff = (int *)PHYSOFF(&u, i); 1808952Sroot for (i=0; i<NIPCREG; i++) 18142928Smckusick if (poff == &u.u_ar0[ipcreg[i]]) 1827501Sroot goto ok; 18342928Smckusick if (poff == &u.u_ar0[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 19442928Smckusick if (poff >= (int *)u.u_pcb.pcb_fpregs.fpf_regs && 19542928Smckusick poff <= (int *)&u.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) 2087501Sroot u.u_ar0[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) 2137501Sroot u.u_ar0[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); 219*45111Smckusick 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