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*43375Smckusick * @(#)sys_process.c 7.9 (Berkeley) 06/21/90 723385Smckusick */ 87426Sroot 930376Skarels #define IPCREG 1017095Sbloom #include "param.h" 1117095Sbloom #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 */ 467501Sroot ptrace() 477501Sroot { 487501Sroot register struct proc *p; 497501Sroot register struct a { 507501Sroot int req; 517501Sroot int pid; 527501Sroot int *addr; 537501Sroot int data; 547501Sroot } *uap; 557501Sroot 567501Sroot uap = (struct a *)u.u_ap; 577501Sroot if (uap->req <= 0) { 587501Sroot u.u_procp->p_flag |= STRC; 597501Sroot return; 607501Sroot } 617501Sroot p = pfind(uap->pid); 6212496Ssam if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid || 6312496Ssam !(p->p_flag & STRC)) { 647501Sroot u.u_error = ESRCH; 657501Sroot return; 667501Sroot } 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 } 797501Sroot u.u_r.r_val1 = ipc.ip_data; 807501Sroot if (ipc.ip_req < 0) 817501Sroot u.u_error = EIO; 827501Sroot ipc.ip_lock = 0; 837501Sroot wakeup((caddr_t)&ipc); 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) { 146*43375Smckusick if (!chgprot((caddr_t)ipc.ip_addr, RW) && 147*43375Smckusick !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