123385Smckusick /* 229105Smckusick * Copyright (c) 1982, 1986 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*30376Skarels * @(#)sys_process.c 7.3 (Berkeley) 01/13/87 723385Smckusick */ 87426Sroot 9*30376Skarels #define IPCREG 109759Ssam #include "../machine/reg.h" 119759Ssam #include "../machine/psl.h" 129759Ssam #include "../machine/pte.h" 139759Ssam 1417095Sbloom #include "param.h" 1517095Sbloom #include "systm.h" 1617095Sbloom #include "dir.h" 1717095Sbloom #include "user.h" 1817095Sbloom #include "proc.h" 1917095Sbloom #include "inode.h" 2017095Sbloom #include "text.h" 2117095Sbloom #include "seg.h" 2217095Sbloom #include "vm.h" 2317095Sbloom #include "buf.h" 2417095Sbloom #include "acct.h" 2526278Skarels #include "ptrace.h" 267426Sroot 277501Sroot /* 287501Sroot * Priority for tracing 297501Sroot */ 307501Sroot #define IPCPRI PZERO 317501Sroot 327501Sroot /* 337501Sroot * Tracing variables. 347501Sroot * Used to pass trace command from 357501Sroot * parent to child being traced. 367501Sroot * This data base cannot be 377501Sroot * shared and is locked 387501Sroot * per user. 397501Sroot */ 407501Sroot struct { 417501Sroot int ip_lock; 427501Sroot int ip_req; 437501Sroot int *ip_addr; 447501Sroot int ip_data; 457501Sroot } ipc; 467501Sroot 477501Sroot /* 487501Sroot * sys-trace system call. 497501Sroot */ 507501Sroot ptrace() 517501Sroot { 527501Sroot register struct proc *p; 537501Sroot register struct a { 547501Sroot int req; 557501Sroot int pid; 567501Sroot int *addr; 577501Sroot int data; 587501Sroot } *uap; 597501Sroot 607501Sroot uap = (struct a *)u.u_ap; 617501Sroot if (uap->req <= 0) { 627501Sroot u.u_procp->p_flag |= STRC; 637501Sroot return; 647501Sroot } 657501Sroot p = pfind(uap->pid); 6612496Ssam if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid || 6712496Ssam !(p->p_flag & STRC)) { 687501Sroot u.u_error = ESRCH; 697501Sroot return; 707501Sroot } 717501Sroot while (ipc.ip_lock) 727501Sroot sleep((caddr_t)&ipc, IPCPRI); 737501Sroot ipc.ip_lock = p->p_pid; 747501Sroot ipc.ip_data = uap->data; 757501Sroot ipc.ip_addr = uap->addr; 767501Sroot ipc.ip_req = uap->req; 777501Sroot p->p_flag &= ~SWTED; 787501Sroot while (ipc.ip_req > 0) { 797501Sroot if (p->p_stat==SSTOP) 807501Sroot setrun(p); 817501Sroot sleep((caddr_t)&ipc, IPCPRI); 827501Sroot } 837501Sroot u.u_r.r_val1 = ipc.ip_data; 847501Sroot if (ipc.ip_req < 0) 857501Sroot u.u_error = EIO; 867501Sroot ipc.ip_lock = 0; 877501Sroot wakeup((caddr_t)&ipc); 887501Sroot } 897501Sroot 908953Sroot #define PHYSOFF(p, o) \ 918952Sroot ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0]))) 928952Sroot 937501Sroot /* 947501Sroot * Code that the child process 957501Sroot * executes to implement the command 967501Sroot * of the parent process in tracing. 977501Sroot */ 987501Sroot procxmt() 997501Sroot { 1007501Sroot register int i; 1017501Sroot register *p; 1027501Sroot register struct text *xp; 1037501Sroot 1047501Sroot if (ipc.ip_lock != u.u_procp->p_pid) 1057501Sroot return (0); 1067501Sroot u.u_procp->p_slptime = 0; 1077501Sroot i = ipc.ip_req; 1087501Sroot ipc.ip_req = 0; 1097501Sroot switch (i) { 1107501Sroot 11126278Skarels case PT_READ_I: /* read the child's text space */ 1127501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1137501Sroot goto error; 1147501Sroot ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 1157501Sroot break; 1167501Sroot 11726278Skarels case PT_READ_D: /* read the child's data space */ 1187501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1197501Sroot goto error; 1207501Sroot ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 1217501Sroot break; 1227501Sroot 12326278Skarels case PT_READ_U: /* read the child's u. */ 1247501Sroot i = (int)ipc.ip_addr; 1257501Sroot if (i<0 || i >= ctob(UPAGES)) 1267501Sroot goto error; 1278952Sroot ipc.ip_data = *(int *)PHYSOFF(&u, i); 1287501Sroot break; 1297501Sroot 13026278Skarels case PT_WRITE_I: /* write the child's text space */ 1317501Sroot /* 1327501Sroot * If text, must assure exclusive use 1337501Sroot */ 1347501Sroot if (xp = u.u_procp->p_textp) { 1357501Sroot if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX) 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; 1777501Sroot goto ok; 1787501Sroot } 1797501Sroot goto error; 1807501Sroot 1817501Sroot ok: 1827501Sroot *p = ipc.ip_data; 1837501Sroot break; 1847501Sroot 18526278Skarels case PT_STEP: /* single step the child */ 18626278Skarels case PT_CONTINUE: /* continue the child */ 1877501Sroot if ((int)ipc.ip_addr != 1) 1887501Sroot u.u_ar0[PC] = (int)ipc.ip_addr; 1897501Sroot if ((unsigned)ipc.ip_data > NSIG) 1907501Sroot goto error; 1917501Sroot u.u_procp->p_cursig = ipc.ip_data; /* see issig */ 19226278Skarels if (i == PT_STEP) 1937501Sroot u.u_ar0[PS] |= PSL_T; 1947501Sroot wakeup((caddr_t)&ipc); 1957501Sroot return (1); 1967501Sroot 19726278Skarels case PT_KILL: /* kill the child process */ 1987501Sroot wakeup((caddr_t)&ipc); 1997501Sroot exit(u.u_procp->p_cursig); 2007501Sroot 2017501Sroot default: 2027501Sroot error: 2037501Sroot ipc.ip_req = -1; 2047501Sroot } 2057501Sroot wakeup((caddr_t)&ipc); 2067501Sroot return (0); 2077501Sroot } 208