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*45735Smckusick * @(#)sys_process.c 7.14 (Berkeley) 12/05/90 723385Smckusick */ 87426Sroot 930376Skarels #define IPCREG 1017095Sbloom #include "param.h" 1144405Skarels #include "user.h" 1217095Sbloom #include "proc.h" 1337728Smckusick #include "vnode.h" 1417095Sbloom #include "seg.h" 1517095Sbloom #include "buf.h" 1626278Skarels #include "ptrace.h" 177426Sroot 1837520Smckusick #include "machine/reg.h" 1937520Smckusick #include "machine/psl.h" 20*45735Smckusick #include "../vm/vm_page.h" 21*45735Smckusick #include "../vm/vm_prot.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 9942928Smckusick if (ipc.ip_lock != p->p_pid) 1007501Sroot return (0); 10142928Smckusick p->p_slptime = 0; 1027501Sroot i = ipc.ip_req; 1037501Sroot ipc.ip_req = 0; 1047501Sroot switch (i) { 1057501Sroot 10626278Skarels case PT_READ_I: /* read the child's text space */ 1077501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1087501Sroot goto error; 1097501Sroot ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 1107501Sroot break; 1117501Sroot 11226278Skarels case PT_READ_D: /* read the child's data space */ 1137501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1147501Sroot goto error; 1157501Sroot ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 1167501Sroot break; 1177501Sroot 11826278Skarels case PT_READ_U: /* read the child's u. */ 11941991Smckusick #ifdef HPUXCOMPAT 12041991Smckusick if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 12141991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 12241991Smckusick else 12341991Smckusick #endif 1247501Sroot i = (int)ipc.ip_addr; 12541991Smckusick if (i<0 || i > ctob(UPAGES)-sizeof(int)) 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 */ 1318952Sroot if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 132*45735Smckusick vm_offset_t sa, ea; 133*45735Smckusick int rv; 134*45735Smckusick 135*45735Smckusick sa = trunc_page((vm_offset_t)ipc.ip_addr); 136*45735Smckusick ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1); 137*45735Smckusick rv = vm_map_protect(p->p_map, sa, ea, 138*45735Smckusick VM_PROT_DEFAULT, FALSE); 139*45735Smckusick if (rv == KERN_SUCCESS) { 1408952Sroot i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 141*45735Smckusick (void) vm_map_protect(p->p_map, sa, ea, 142*45735Smckusick VM_PROT_READ|VM_PROT_EXECUTE, FALSE); 143*45735Smckusick } 1448952Sroot } 1457501Sroot if (i < 0) 1467501Sroot goto error; 1477501Sroot break; 1487501Sroot 14926278Skarels case PT_WRITE_D: /* write the child's data space */ 1507501Sroot if (suword((caddr_t)ipc.ip_addr, 0) < 0) 1517501Sroot goto error; 1527501Sroot (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 1537501Sroot break; 1547501Sroot 15526278Skarels case PT_WRITE_U: /* write the child's u. */ 15641991Smckusick #ifdef HPUXCOMPAT 15741991Smckusick if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 15841991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 15941991Smckusick else 16041991Smckusick #endif 1617501Sroot i = (int)ipc.ip_addr; 16242928Smckusick poff = (int *)PHYSOFF(&u, i); 1638952Sroot for (i=0; i<NIPCREG; i++) 16442928Smckusick if (poff == &u.u_ar0[ipcreg[i]]) 1657501Sroot goto ok; 16642928Smckusick if (poff == &u.u_ar0[PS]) { 1678952Sroot ipc.ip_data |= PSL_USERSET; 16841991Smckusick ipc.ip_data &= ~PSL_USERCLR; 16932863Skarels #ifdef PSL_CM_CLR 17032863Skarels if (ipc.ip_data & PSL_CM) 17132863Skarels ipc.ip_data &= ~PSL_CM_CLR; 17232863Skarels #endif 1737501Sroot goto ok; 1747501Sroot } 17541991Smckusick #if defined(hp300) 17641991Smckusick #ifdef FPCOPROC 17742928Smckusick if (poff >= (int *)u.u_pcb.pcb_fpregs.fpf_regs && 17842928Smckusick poff <= (int *)&u.u_pcb.pcb_fpregs.fpf_fpiar) 17941991Smckusick goto ok; 18041991Smckusick #endif 18141991Smckusick #endif 1827501Sroot goto error; 1837501Sroot 1847501Sroot ok: 18542928Smckusick *poff = ipc.ip_data; 1867501Sroot break; 1877501Sroot 18826278Skarels case PT_STEP: /* single step the child */ 18926278Skarels case PT_CONTINUE: /* continue the child */ 1907501Sroot if ((int)ipc.ip_addr != 1) 1917501Sroot u.u_ar0[PC] = (int)ipc.ip_addr; 1927501Sroot if ((unsigned)ipc.ip_data > NSIG) 1937501Sroot goto error; 19443895Skarels p->p_xstat = ipc.ip_data; /* see issig */ 19526278Skarels if (i == PT_STEP) 1967501Sroot u.u_ar0[PS] |= PSL_T; 1977501Sroot wakeup((caddr_t)&ipc); 1987501Sroot return (1); 1997501Sroot 20026278Skarels case PT_KILL: /* kill the child process */ 2017501Sroot wakeup((caddr_t)&ipc); 20245111Smckusick exit(p, (int)p->p_xstat); 2037501Sroot 2047501Sroot default: 2057501Sroot error: 2067501Sroot ipc.ip_req = -1; 2077501Sroot } 2087501Sroot wakeup((caddr_t)&ipc); 2097501Sroot return (0); 2107501Sroot } 211