update for new VM
[unix-history] / usr / src / sys / kern / sys_process.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 * @(#)sys_process.c 7.14 (Berkeley) %G%
7 */
8
9#define IPCREG
10#include "param.h"
11#include "user.h"
12#include "proc.h"
13#include "vnode.h"
14#include "seg.h"
15#include "buf.h"
16#include "ptrace.h"
17
18#include "machine/reg.h"
19#include "machine/psl.h"
20#include "../vm/vm_page.h"
21#include "../vm/vm_prot.h"
22
23/*
24 * Priority for tracing
25 */
26#define IPCPRI PZERO
27
28/*
29 * Tracing variables.
30 * Used to pass trace command from
31 * parent to child being traced.
32 * This data base cannot be
33 * shared and is locked
34 * per user.
35 */
36struct {
37 int ip_lock;
38 int ip_req;
39 int *ip_addr;
40 int ip_data;
41} ipc;
42
43/*
44 * sys-trace system call.
45 */
46ptrace(curp, uap, retval)
47 struct proc *curp;
48 register struct args {
49 int req;
50 int pid;
51 int *addr;
52 int data;
53 } *uap;
54 int *retval;
55{
56 register struct proc *p;
57
58 if (uap->req <= 0) {
59 curp->p_flag |= STRC;
60 return (0);
61 }
62 p = pfind(uap->pid);
63 if (p == 0 || p->p_stat != SSTOP || p->p_ppid != curp->p_pid ||
64 !(p->p_flag & STRC))
65 return (ESRCH);
66 while (ipc.ip_lock)
67 sleep((caddr_t)&ipc, IPCPRI);
68 ipc.ip_lock = p->p_pid;
69 ipc.ip_data = uap->data;
70 ipc.ip_addr = uap->addr;
71 ipc.ip_req = uap->req;
72 p->p_flag &= ~SWTED;
73 while (ipc.ip_req > 0) {
74 if (p->p_stat==SSTOP)
75 setrun(p);
76 sleep((caddr_t)&ipc, IPCPRI);
77 }
78 *retval = ipc.ip_data;
79 ipc.ip_lock = 0;
80 wakeup((caddr_t)&ipc);
81 if (ipc.ip_req < 0)
82 return (EIO);
83 return (0);
84}
85
86#define PHYSOFF(p, o) \
87 ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0])))
88
89/*
90 * Code that the child process
91 * executes to implement the command
92 * of the parent process in tracing.
93 */
94procxmt(p)
95 register struct proc *p;
96{
97 register int i, *poff;
98
99 if (ipc.ip_lock != p->p_pid)
100 return (0);
101 p->p_slptime = 0;
102 i = ipc.ip_req;
103 ipc.ip_req = 0;
104 switch (i) {
105
106 case PT_READ_I: /* read the child's text space */
107 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
108 goto error;
109 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
110 break;
111
112 case PT_READ_D: /* read the child's data space */
113 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
114 goto error;
115 ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
116 break;
117
118 case PT_READ_U: /* read the child's u. */
119#ifdef HPUXCOMPAT
120 if (u.u_pcb.pcb_flags & PCB_HPUXTRACE)
121 i = hpuxtobsduoff(ipc.ip_addr);
122 else
123#endif
124 i = (int)ipc.ip_addr;
125 if (i<0 || i > ctob(UPAGES)-sizeof(int))
126 goto error;
127 ipc.ip_data = *(int *)PHYSOFF(&u, i);
128 break;
129
130 case PT_WRITE_I: /* write the child's text space */
131 if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
132 vm_offset_t sa, ea;
133 int rv;
134
135 sa = trunc_page((vm_offset_t)ipc.ip_addr);
136 ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1);
137 rv = vm_map_protect(p->p_map, sa, ea,
138 VM_PROT_DEFAULT, FALSE);
139 if (rv == KERN_SUCCESS) {
140 i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
141 (void) vm_map_protect(p->p_map, sa, ea,
142 VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
143 }
144 }
145 if (i < 0)
146 goto error;
147 break;
148
149 case PT_WRITE_D: /* write the child's data space */
150 if (suword((caddr_t)ipc.ip_addr, 0) < 0)
151 goto error;
152 (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
153 break;
154
155 case PT_WRITE_U: /* write the child's u. */
156#ifdef HPUXCOMPAT
157 if (u.u_pcb.pcb_flags & PCB_HPUXTRACE)
158 i = hpuxtobsduoff(ipc.ip_addr);
159 else
160#endif
161 i = (int)ipc.ip_addr;
162 poff = (int *)PHYSOFF(&u, i);
163 for (i=0; i<NIPCREG; i++)
164 if (poff == &u.u_ar0[ipcreg[i]])
165 goto ok;
166 if (poff == &u.u_ar0[PS]) {
167 ipc.ip_data |= PSL_USERSET;
168 ipc.ip_data &= ~PSL_USERCLR;
169#ifdef PSL_CM_CLR
170 if (ipc.ip_data & PSL_CM)
171 ipc.ip_data &= ~PSL_CM_CLR;
172#endif
173 goto ok;
174 }
175#if defined(hp300)
176#ifdef FPCOPROC
177 if (poff >= (int *)u.u_pcb.pcb_fpregs.fpf_regs &&
178 poff <= (int *)&u.u_pcb.pcb_fpregs.fpf_fpiar)
179 goto ok;
180#endif
181#endif
182 goto error;
183
184 ok:
185 *poff = ipc.ip_data;
186 break;
187
188 case PT_STEP: /* single step the child */
189 case PT_CONTINUE: /* continue the child */
190 if ((int)ipc.ip_addr != 1)
191 u.u_ar0[PC] = (int)ipc.ip_addr;
192 if ((unsigned)ipc.ip_data > NSIG)
193 goto error;
194 p->p_xstat = ipc.ip_data; /* see issig */
195 if (i == PT_STEP)
196 u.u_ar0[PS] |= PSL_T;
197 wakeup((caddr_t)&ipc);
198 return (1);
199
200 case PT_KILL: /* kill the child process */
201 wakeup((caddr_t)&ipc);
202 exit(p, (int)p->p_xstat);
203
204 default:
205 error:
206 ipc.ip_req = -1;
207 }
208 wakeup((caddr_t)&ipc);
209 return (0);
210}