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*43378Smckusick * @(#)sys_process.c 7.10 (Berkeley) 06/21/90 723385Smckusick */ 87426Sroot 930376Skarels #define IPCREG 1017095Sbloom #include "param.h" 11*43378Smckusick #include "syscontext.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 */ 46*43378Smckusick ptrace(curp, uap, retval) 47*43378Smckusick struct proc *curp; 48*43378Smckusick register struct args { 497501Sroot int req; 507501Sroot int pid; 517501Sroot int *addr; 527501Sroot int data; 537501Sroot } *uap; 54*43378Smckusick int *retval; 55*43378Smckusick { 56*43378Smckusick register struct proc *p; 577501Sroot 587501Sroot if (uap->req <= 0) { 59*43378Smckusick curp->p_flag |= STRC; 60*43378Smckusick RETURN (0); 617501Sroot } 627501Sroot p = pfind(uap->pid); 63*43378Smckusick if (p == 0 || p->p_stat != SSTOP || p->p_ppid != curp->p_pid || 64*43378Smckusick !(p->p_flag & STRC)) 65*43378Smckusick 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 } 78*43378Smckusick *retval = ipc.ip_data; 797501Sroot ipc.ip_lock = 0; 807501Sroot wakeup((caddr_t)&ipc); 81*43378Smckusick if (ipc.ip_req < 0) 82*43378Smckusick RETURN (EIO); 83*43378Smckusick 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; 10037728Smckusick struct vnode *vp; 1017501Sroot 10242928Smckusick if (ipc.ip_lock != p->p_pid) 1037501Sroot return (0); 10442928Smckusick p->p_slptime = 0; 1057501Sroot i = ipc.ip_req; 1067501Sroot ipc.ip_req = 0; 1077501Sroot switch (i) { 1087501Sroot 10926278Skarels case PT_READ_I: /* read the child's text space */ 1107501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1117501Sroot goto error; 1127501Sroot ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 1137501Sroot break; 1147501Sroot 11526278Skarels case PT_READ_D: /* read the child's data space */ 1167501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1177501Sroot goto error; 1187501Sroot ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 1197501Sroot break; 1207501Sroot 12126278Skarels case PT_READ_U: /* read the child's u. */ 12241991Smckusick #ifdef HPUXCOMPAT 12341991Smckusick if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 12441991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 12541991Smckusick else 12641991Smckusick #endif 1277501Sroot i = (int)ipc.ip_addr; 12841991Smckusick if (i<0 || i > ctob(UPAGES)-sizeof(int)) 1297501Sroot goto error; 1308952Sroot ipc.ip_data = *(int *)PHYSOFF(&u, i); 1317501Sroot break; 1327501Sroot 13326278Skarels case PT_WRITE_I: /* write the child's text space */ 1347501Sroot /* 1357501Sroot * If text, must assure exclusive use 1367501Sroot */ 13742928Smckusick if (xp = p->p_textp) { 13837728Smckusick vp = xp->x_vptr; 13937728Smckusick VOP_GETATTR(vp, &vattr, u.u_cred); 14037728Smckusick if (xp->x_count!=1 || (vattr.va_mode & VSVTX)) 1417501Sroot goto error; 14225535Skarels xp->x_flag |= XTRC; 1437501Sroot } 1447501Sroot i = -1; 1458952Sroot if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 14643375Smckusick if (!chgprot((caddr_t)ipc.ip_addr, RW) && 14743375Smckusick !chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW)) 1488952Sroot i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 1498952Sroot (void) chgprot((caddr_t)ipc.ip_addr, RO); 1508952Sroot (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO); 1518952Sroot } 1527501Sroot if (i < 0) 1537501Sroot goto error; 15429946Skarels #if defined(tahoe) 15529946Skarels /* make sure the old value is not in cache */ 15642928Smckusick ckeyrelease(p->p_ckey); 15742928Smckusick p->p_ckey = getcodekey(); 15829946Skarels #endif 15929946Skarels if (xp) { 1607501Sroot xp->x_flag |= XWRIT; 16129946Skarels #if defined(tahoe) 16242928Smckusick xp->x_ckey = p->p_ckey; 16329946Skarels #endif 16429946Skarels } 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 17541991Smckusick if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 17641991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 17741991Smckusick else 17841991Smckusick #endif 1797501Sroot i = (int)ipc.ip_addr; 18042928Smckusick poff = (int *)PHYSOFF(&u, i); 1818952Sroot for (i=0; i<NIPCREG; i++) 18242928Smckusick if (poff == &u.u_ar0[ipcreg[i]]) 1837501Sroot goto ok; 18442928Smckusick if (poff == &u.u_ar0[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 19542928Smckusick if (poff >= (int *)u.u_pcb.pcb_fpregs.fpf_regs && 19642928Smckusick poff <= (int *)&u.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) 2097501Sroot u.u_ar0[PC] = (int)ipc.ip_addr; 2107501Sroot if ((unsigned)ipc.ip_data > NSIG) 2117501Sroot goto error; 21242928Smckusick p->p_cursig = ipc.ip_data; /* see issig */ 21326278Skarels if (i == PT_STEP) 2147501Sroot u.u_ar0[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); 22042928Smckusick exit(p, p->p_cursig); 2217501Sroot 2227501Sroot default: 2237501Sroot error: 2247501Sroot ipc.ip_req = -1; 2257501Sroot } 2267501Sroot wakeup((caddr_t)&ipc); 2277501Sroot return (0); 2287501Sroot } 229