123385Smckusick /* 2*37728Smckusick * 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*37728Smckusick * @(#)sys_process.c 7.6 (Berkeley) 05/09/89 723385Smckusick */ 87426Sroot 930376Skarels #define IPCREG 1017095Sbloom #include "param.h" 1117095Sbloom #include "user.h" 1217095Sbloom #include "proc.h" 13*37728Smckusick #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 */ 947501Sroot procxmt() 957501Sroot { 967501Sroot register int i; 977501Sroot register *p; 987501Sroot register struct text *xp; 99*37728Smckusick struct vattr vattr; 100*37728Smckusick struct vnode *vp; 1017501Sroot 1027501Sroot if (ipc.ip_lock != u.u_procp->p_pid) 1037501Sroot return (0); 1047501Sroot u.u_procp->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. */ 1227501Sroot i = (int)ipc.ip_addr; 1237501Sroot if (i<0 || i >= ctob(UPAGES)) 1247501Sroot goto error; 1258952Sroot ipc.ip_data = *(int *)PHYSOFF(&u, i); 1267501Sroot break; 1277501Sroot 12826278Skarels case PT_WRITE_I: /* write the child's text space */ 1297501Sroot /* 1307501Sroot * If text, must assure exclusive use 1317501Sroot */ 1327501Sroot if (xp = u.u_procp->p_textp) { 133*37728Smckusick vp = xp->x_vptr; 134*37728Smckusick VOP_GETATTR(vp, &vattr, u.u_cred); 135*37728Smckusick if (xp->x_count!=1 || (vattr.va_mode & VSVTX)) 1367501Sroot goto error; 13725535Skarels xp->x_flag |= XTRC; 1387501Sroot } 1397501Sroot i = -1; 1408952Sroot if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 1418952Sroot if (chgprot((caddr_t)ipc.ip_addr, RW) && 1428952Sroot chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW)) 1438952Sroot i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 1448952Sroot (void) chgprot((caddr_t)ipc.ip_addr, RO); 1458952Sroot (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO); 1468952Sroot } 1477501Sroot if (i < 0) 1487501Sroot goto error; 14929946Skarels #if defined(tahoe) 15029946Skarels /* make sure the old value is not in cache */ 15129946Skarels ckeyrelease(u.u_procp->p_ckey); 15229946Skarels u.u_procp->p_ckey = getcodekey(); 15329946Skarels #endif 15429946Skarels if (xp) { 1557501Sroot xp->x_flag |= XWRIT; 15629946Skarels #if defined(tahoe) 15729946Skarels xp->x_ckey = u.u_procp->p_ckey; 15829946Skarels #endif 15929946Skarels } 1607501Sroot break; 1617501Sroot 16226278Skarels case PT_WRITE_D: /* write the child's data space */ 1637501Sroot if (suword((caddr_t)ipc.ip_addr, 0) < 0) 1647501Sroot goto error; 1657501Sroot (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 1667501Sroot break; 1677501Sroot 16826278Skarels case PT_WRITE_U: /* write the child's u. */ 1697501Sroot i = (int)ipc.ip_addr; 1708952Sroot p = (int *)PHYSOFF(&u, i); 1718952Sroot for (i=0; i<NIPCREG; i++) 1727501Sroot if (p == &u.u_ar0[ipcreg[i]]) 1737501Sroot goto ok; 1747501Sroot if (p == &u.u_ar0[PS]) { 1758952Sroot ipc.ip_data |= PSL_USERSET; 1767501Sroot ipc.ip_data &= ~PSL_USERCLR; 17732863Skarels #ifdef PSL_CM_CLR 17832863Skarels if (ipc.ip_data & PSL_CM) 17932863Skarels ipc.ip_data &= ~PSL_CM_CLR; 18032863Skarels #endif 1817501Sroot goto ok; 1827501Sroot } 1837501Sroot goto error; 1847501Sroot 1857501Sroot ok: 1867501Sroot *p = ipc.ip_data; 1877501Sroot break; 1887501Sroot 18926278Skarels case PT_STEP: /* single step the child */ 19026278Skarels case PT_CONTINUE: /* continue the child */ 1917501Sroot if ((int)ipc.ip_addr != 1) 1927501Sroot u.u_ar0[PC] = (int)ipc.ip_addr; 1937501Sroot if ((unsigned)ipc.ip_data > NSIG) 1947501Sroot goto error; 1957501Sroot u.u_procp->p_cursig = ipc.ip_data; /* see issig */ 19626278Skarels if (i == PT_STEP) 1977501Sroot u.u_ar0[PS] |= PSL_T; 1987501Sroot wakeup((caddr_t)&ipc); 1997501Sroot return (1); 2007501Sroot 20126278Skarels case PT_KILL: /* kill the child process */ 2027501Sroot wakeup((caddr_t)&ipc); 2037501Sroot exit(u.u_procp->p_cursig); 2047501Sroot 2057501Sroot default: 2067501Sroot error: 2077501Sroot ipc.ip_req = -1; 2087501Sroot } 2097501Sroot wakeup((caddr_t)&ipc); 2107501Sroot return (0); 2117501Sroot } 212