/* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #include #include #include #include #include #include #include /* * sys-trace system call. */ void ptrace() { register struct proc *p; register struct a { int req; int pid; int *addr; int data; } *uap; uap = (struct a *)u.u_arg; if (uap->req <= 0) { u.u_procp->p_flag |= P_TRACED; return; } p = pfind(uap->pid); if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid || !(p->p_flag & P_TRACED)) { u.u_error = ESRCH; return; } while (ipc.ip_lock) sleep((caddr_t)&ipc, PZERO); ipc.ip_lock = p->p_pid; ipc.ip_data = uap->data; ipc.ip_addr = uap->addr; ipc.ip_req = uap->req; p->p_flag &= ~P_WAITED; setrun(p); while (ipc.ip_req > 0) sleep((caddr_t)&ipc, PZERO); u.u_rval = ipc.ip_data; if (ipc.ip_req < 0) u.u_error = EIO; ipc.ip_lock = 0; wakeup((caddr_t)&ipc); } /* * Code that the child process * executes to implement the command * of the parent process in tracing. */ int procxmt() { register int i, *p; if (ipc.ip_lock != u.u_procp->p_pid) return(0); u.u_procp->p_slptime = 0; i = ipc.ip_req; ipc.ip_req = 0; wakeup ((caddr_t)&ipc); switch (i) { /* read user I */ case PT_READ_I: /* read user D */ case PT_READ_D: if (baduaddr ((caddr_t) ipc.ip_addr)) goto error; ipc.ip_data = *(int*) ipc.ip_addr; break; /* read u */ case PT_READ_U: i = (int) ipc.ip_addr; if (i < 0 || i >= USIZE) goto error; ipc.ip_data = ((unsigned*)&u) [i/sizeof(int)]; break; /* write user I */ case PT_WRITE_I: /* write user D */ case PT_WRITE_D: if (baduaddr ((caddr_t) ipc.ip_addr)) goto error; *(int*) ipc.ip_addr = ipc.ip_data; break; /* write u */ case PT_WRITE_U: i = (int)ipc.ip_addr; p = (int*)&u + i/sizeof(int); for (i=0; i NSIG) goto error; u.u_procp->p_ptracesig = ipc.ip_data; return(1); /* force exit */ case PT_KILL: exit(u.u_procp->p_ptracesig); /*NOTREACHED*/ default: error: ipc.ip_req = -1; } return(0); }