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*47543Skarels * @(#)sys_process.c 7.16 (Berkeley) 03/17/91 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*47543Skarels #include "vm/vm_page.h" 21*47543Skarels #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); 63*47543Skarels if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp || 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]))) 8845882Swilliam #if defined(i386) 8945882Swilliam #undef PC 9045882Swilliam #undef SP 9145882Swilliam #undef PS 9245882Swilliam #undef R0 9345882Swilliam #undef R1 948952Sroot 9545882Swilliam #define PC tEIP 9645882Swilliam #define SP tESP 9745882Swilliam #define PS tEFLAGS 9845882Swilliam #define R0 tEDX 9945882Swilliam #define R1 tECX 10045882Swilliam #endif 10145882Swilliam 1027501Sroot /* 1037501Sroot * Code that the child process 1047501Sroot * executes to implement the command 1057501Sroot * of the parent process in tracing. 1067501Sroot */ 10742928Smckusick procxmt(p) 10842928Smckusick register struct proc *p; 1097501Sroot { 11042928Smckusick register int i, *poff; 1117501Sroot 11242928Smckusick if (ipc.ip_lock != p->p_pid) 1137501Sroot return (0); 11442928Smckusick p->p_slptime = 0; 1157501Sroot i = ipc.ip_req; 1167501Sroot ipc.ip_req = 0; 1177501Sroot switch (i) { 1187501Sroot 11926278Skarels case PT_READ_I: /* read the child's text space */ 1207501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1217501Sroot goto error; 1227501Sroot ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 1237501Sroot break; 1247501Sroot 12526278Skarels case PT_READ_D: /* read the child's data space */ 1267501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1277501Sroot goto error; 1287501Sroot ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 1297501Sroot break; 1307501Sroot 13126278Skarels case PT_READ_U: /* read the child's u. */ 13241991Smckusick #ifdef HPUXCOMPAT 13341991Smckusick if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 13441991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 13541991Smckusick else 13641991Smckusick #endif 1377501Sroot i = (int)ipc.ip_addr; 13841991Smckusick if (i<0 || i > ctob(UPAGES)-sizeof(int)) 1397501Sroot goto error; 1408952Sroot ipc.ip_data = *(int *)PHYSOFF(&u, i); 1417501Sroot break; 1427501Sroot 14326278Skarels case PT_WRITE_I: /* write the child's text space */ 1448952Sroot if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 14545735Smckusick vm_offset_t sa, ea; 14645735Smckusick int rv; 14745735Smckusick 14845735Smckusick sa = trunc_page((vm_offset_t)ipc.ip_addr); 14945735Smckusick ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1); 150*47543Skarels rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, 15145735Smckusick VM_PROT_DEFAULT, FALSE); 15245735Smckusick if (rv == KERN_SUCCESS) { 1538952Sroot i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 154*47543Skarels (void) vm_map_protect(&p->p_vmspace->vm_map, 155*47543Skarels sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, 156*47543Skarels FALSE); 15745735Smckusick } 1588952Sroot } 1597501Sroot if (i < 0) 1607501Sroot goto error; 1617501Sroot break; 1627501Sroot 16326278Skarels case PT_WRITE_D: /* write the child's data space */ 1647501Sroot if (suword((caddr_t)ipc.ip_addr, 0) < 0) 1657501Sroot goto error; 1667501Sroot (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 1677501Sroot break; 1687501Sroot 16926278Skarels case PT_WRITE_U: /* write the child's u. */ 17041991Smckusick #ifdef HPUXCOMPAT 17141991Smckusick if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) 17241991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 17341991Smckusick else 17441991Smckusick #endif 1757501Sroot i = (int)ipc.ip_addr; 17642928Smckusick poff = (int *)PHYSOFF(&u, i); 1778952Sroot for (i=0; i<NIPCREG; i++) 178*47543Skarels if (poff == &p->p_regs[ipcreg[i]]) 1797501Sroot goto ok; 180*47543Skarels if (poff == &p->p_regs[PS]) { 1818952Sroot ipc.ip_data |= PSL_USERSET; 18241991Smckusick ipc.ip_data &= ~PSL_USERCLR; 18332863Skarels #ifdef PSL_CM_CLR 18432863Skarels if (ipc.ip_data & PSL_CM) 18532863Skarels ipc.ip_data &= ~PSL_CM_CLR; 18632863Skarels #endif 1877501Sroot goto ok; 1887501Sroot } 18941991Smckusick #if defined(hp300) 19041991Smckusick #ifdef FPCOPROC 19142928Smckusick if (poff >= (int *)u.u_pcb.pcb_fpregs.fpf_regs && 19242928Smckusick poff <= (int *)&u.u_pcb.pcb_fpregs.fpf_fpiar) 19341991Smckusick goto ok; 19441991Smckusick #endif 19541991Smckusick #endif 1967501Sroot goto error; 1977501Sroot 1987501Sroot ok: 19942928Smckusick *poff = ipc.ip_data; 2007501Sroot break; 2017501Sroot 20226278Skarels case PT_STEP: /* single step the child */ 20326278Skarels case PT_CONTINUE: /* continue the child */ 2047501Sroot if ((int)ipc.ip_addr != 1) 205*47543Skarels p->p_regs[PC] = (int)ipc.ip_addr; 2067501Sroot if ((unsigned)ipc.ip_data > NSIG) 2077501Sroot goto error; 20843895Skarels p->p_xstat = ipc.ip_data; /* see issig */ 20926278Skarels if (i == PT_STEP) 210*47543Skarels p->p_regs[PS] |= PSL_T; 2117501Sroot wakeup((caddr_t)&ipc); 2127501Sroot return (1); 2137501Sroot 21426278Skarels case PT_KILL: /* kill the child process */ 2157501Sroot wakeup((caddr_t)&ipc); 21645111Smckusick exit(p, (int)p->p_xstat); 2177501Sroot 2187501Sroot default: 2197501Sroot error: 2207501Sroot ipc.ip_req = -1; 2217501Sroot } 2227501Sroot wakeup((caddr_t)&ipc); 2237501Sroot return (0); 2247501Sroot } 225