149589Sbostic /*- 249589Sbostic * Copyright (c) 1982, 1986, 1989 The Regents of the University of California. 349589Sbostic * All rights reserved. 423385Smckusick * 549589Sbostic * %sccs.include.proprietary.c% 649589Sbostic * 7*52178Smarc * @(#)sys_process.c 7.23 (Berkeley) 01/13/92 823385Smckusick */ 97426Sroot 1030376Skarels #define IPCREG 1117095Sbloom #include "param.h" 1217095Sbloom #include "proc.h" 1337728Smckusick #include "vnode.h" 1417095Sbloom #include "buf.h" 1526278Skarels #include "ptrace.h" 167426Sroot 1737520Smckusick #include "machine/reg.h" 1837520Smckusick #include "machine/psl.h" 1948438Skarels #include "vm/vm.h" 2047543Skarels #include "vm/vm_page.h" 2137520Smckusick 2248438Skarels #include "user.h" 2348438Skarels 247501Sroot /* 257501Sroot * Priority for tracing 267501Sroot */ 277501Sroot #define IPCPRI PZERO 287501Sroot 297501Sroot /* 307501Sroot * Tracing variables. 317501Sroot * Used to pass trace command from 327501Sroot * parent to child being traced. 337501Sroot * This data base cannot be 347501Sroot * shared and is locked 357501Sroot * per user. 367501Sroot */ 377501Sroot struct { 387501Sroot int ip_lock; 397501Sroot int ip_req; 407501Sroot int *ip_addr; 417501Sroot int ip_data; 427501Sroot } ipc; 437501Sroot 447501Sroot /* 4549674Smckusick * Process debugging system call. 467501Sroot */ 4743378Smckusick ptrace(curp, uap, retval) 4843378Smckusick struct proc *curp; 4943378Smckusick register struct args { 507501Sroot int req; 517501Sroot int pid; 527501Sroot int *addr; 537501Sroot int data; 547501Sroot } *uap; 5543378Smckusick int *retval; 5643378Smckusick { 5743378Smckusick register struct proc *p; 587501Sroot 597501Sroot if (uap->req <= 0) { 6043378Smckusick curp->p_flag |= STRC; 6144405Skarels return (0); 627501Sroot } 637501Sroot p = pfind(uap->pid); 6447543Skarels if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp || 6543378Smckusick !(p->p_flag & STRC)) 6644405Skarels return (ESRCH); 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 } 7943378Smckusick *retval = ipc.ip_data; 807501Sroot ipc.ip_lock = 0; 817501Sroot wakeup((caddr_t)&ipc); 8243378Smckusick if (ipc.ip_req < 0) 8344405Skarels return (EIO); 8444405Skarels return (0); 857501Sroot } 867501Sroot 8749246Skarels #define PHYSOFF(p, o) ((caddr_t)(p) + (o)) 8849246Skarels 8945882Swilliam #if defined(i386) 9045882Swilliam #undef PC 9145882Swilliam #undef SP 9245882Swilliam #undef PS 9345882Swilliam #undef R0 9445882Swilliam #undef R1 958952Sroot 9645882Swilliam #define PC tEIP 9745882Swilliam #define SP tESP 9845882Swilliam #define PS tEFLAGS 9945882Swilliam #define R0 tEDX 10045882Swilliam #define R1 tECX 10145882Swilliam #endif 10245882Swilliam 1037501Sroot /* 10449674Smckusick * Transmit a tracing request from the parent to the child process 10549674Smckusick * being debugged. This code runs in the context of the child process 10649674Smckusick * to fulfill the command requested by the parent. 1077501Sroot */ 10842928Smckusick procxmt(p) 10942928Smckusick register struct proc *p; 1107501Sroot { 11142928Smckusick register int i, *poff; 11249246Skarels extern char kstack[]; 1137501Sroot 11442928Smckusick if (ipc.ip_lock != p->p_pid) 1157501Sroot return (0); 11642928Smckusick p->p_slptime = 0; 11749101Skarels p->p_addr->u_kproc.kp_proc.p_regs = p->p_regs; /* u.u_ar0 */ 1187501Sroot i = ipc.ip_req; 1197501Sroot ipc.ip_req = 0; 1207501Sroot switch (i) { 1217501Sroot 12226278Skarels case PT_READ_I: /* read the child's text space */ 1237501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1247501Sroot goto error; 1257501Sroot ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 1267501Sroot break; 1277501Sroot 12826278Skarels case PT_READ_D: /* read the child's data space */ 1297501Sroot if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 1307501Sroot goto error; 1317501Sroot ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 1327501Sroot break; 1337501Sroot 13426278Skarels case PT_READ_U: /* read the child's u. */ 13541991Smckusick #ifdef HPUXCOMPAT 13649101Skarels if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) 13741991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 13841991Smckusick else 13941991Smckusick #endif 1407501Sroot i = (int)ipc.ip_addr; 14149246Skarels if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0) 1427501Sroot goto error; 14349101Skarels ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i); 1447501Sroot break; 1457501Sroot 14626278Skarels case PT_WRITE_I: /* write the child's text space */ 1478952Sroot if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 14845735Smckusick vm_offset_t sa, ea; 14945735Smckusick int rv; 15045735Smckusick 15145735Smckusick sa = trunc_page((vm_offset_t)ipc.ip_addr); 15245735Smckusick ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1); 15347543Skarels rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, 15445735Smckusick VM_PROT_DEFAULT, FALSE); 15545735Smckusick if (rv == KERN_SUCCESS) { 1568952Sroot i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 15747543Skarels (void) vm_map_protect(&p->p_vmspace->vm_map, 15847543Skarels sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, 15947543Skarels FALSE); 16045735Smckusick } 1618952Sroot } 1627501Sroot if (i < 0) 1637501Sroot goto error; 1647501Sroot break; 1657501Sroot 16626278Skarels case PT_WRITE_D: /* write the child's data space */ 1677501Sroot if (suword((caddr_t)ipc.ip_addr, 0) < 0) 1687501Sroot goto error; 1697501Sroot (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 1707501Sroot break; 1717501Sroot 17226278Skarels case PT_WRITE_U: /* write the child's u. */ 17341991Smckusick #ifdef HPUXCOMPAT 17449101Skarels if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) 17541991Smckusick i = hpuxtobsduoff(ipc.ip_addr); 17641991Smckusick else 17741991Smckusick #endif 1787501Sroot i = (int)ipc.ip_addr; 179*52178Smarc #ifdef mips 180*52178Smarc poff = (int *)PHYSOFF(curproc->p_addr, i); 181*52178Smarc #else 18249246Skarels poff = (int *)PHYSOFF(kstack, i); 183*52178Smarc #endif 1848952Sroot for (i=0; i<NIPCREG; i++) 18547543Skarels if (poff == &p->p_regs[ipcreg[i]]) 1867501Sroot goto ok; 18747543Skarels if (poff == &p->p_regs[PS]) { 1888952Sroot ipc.ip_data |= PSL_USERSET; 18941991Smckusick ipc.ip_data &= ~PSL_USERCLR; 19032863Skarels #ifdef PSL_CM_CLR 19132863Skarels if (ipc.ip_data & PSL_CM) 19232863Skarels ipc.ip_data &= ~PSL_CM_CLR; 19332863Skarels #endif 1947501Sroot goto ok; 1957501Sroot } 19641991Smckusick #if defined(hp300) 19741991Smckusick #ifdef FPCOPROC 19849246Skarels if (poff >= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_regs && 19949246Skarels poff <= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_fpiar) 20041991Smckusick goto ok; 20141991Smckusick #endif 20241991Smckusick #endif 2037501Sroot goto error; 2047501Sroot 2057501Sroot ok: 20642928Smckusick *poff = ipc.ip_data; 2077501Sroot break; 2087501Sroot 20926278Skarels case PT_STEP: /* single step the child */ 21026278Skarels case PT_CONTINUE: /* continue the child */ 2117501Sroot if ((int)ipc.ip_addr != 1) 21247543Skarels p->p_regs[PC] = (int)ipc.ip_addr; 2137501Sroot if ((unsigned)ipc.ip_data > NSIG) 2147501Sroot goto error; 21543895Skarels p->p_xstat = ipc.ip_data; /* see issig */ 216*52178Smarc #ifdef PSL_T 217*52178Smarc /* need something more machine independent here... */ 21826278Skarels if (i == PT_STEP) 21947543Skarels p->p_regs[PS] |= PSL_T; 220*52178Smarc #endif 2217501Sroot wakeup((caddr_t)&ipc); 2227501Sroot return (1); 2237501Sroot 22426278Skarels case PT_KILL: /* kill the child process */ 2257501Sroot wakeup((caddr_t)&ipc); 22645111Smckusick exit(p, (int)p->p_xstat); 2277501Sroot 2287501Sroot default: 2297501Sroot error: 2307501Sroot ipc.ip_req = -1; 2317501Sroot } 2327501Sroot wakeup((caddr_t)&ipc); 2337501Sroot return (0); 2347501Sroot } 23549534Smckusick 23649674Smckusick /* 23749674Smckusick * Process debugging system call. 23849674Smckusick */ 23949534Smckusick /* ARGSUSED */ 24049534Smckusick profil(p, uap, retval) 24149534Smckusick struct proc *p; 24249534Smckusick register struct args { 24349534Smckusick short *bufbase; 24449534Smckusick unsigned bufsize; 24549534Smckusick unsigned pcoffset; 24649534Smckusick unsigned pcscale; 24749534Smckusick } *uap; 24849534Smckusick int *retval; 24949534Smckusick { 25049534Smckusick register struct uprof *upp = &p->p_stats->p_prof; 25149534Smckusick 25249534Smckusick upp->pr_base = uap->bufbase; 25349534Smckusick upp->pr_size = uap->bufsize; 25449534Smckusick upp->pr_off = uap->pcoffset; 25549534Smckusick upp->pr_scale = uap->pcscale; 25649534Smckusick #ifdef PROFTIMER 25749534Smckusick initprofclock(); 25849534Smckusick #endif 25949534Smckusick return (0); 26049534Smckusick } 261