Blame


1 a84cbb2a 2004-04-19 devnull /*
2 a84cbb2a 2004-04-19 devnull * process interface for Linux.
3 a84cbb2a 2004-04-19 devnull *
4 a84cbb2a 2004-04-19 devnull * Uses ptrace for registers and data,
5 a84cbb2a 2004-04-19 devnull * /proc for some process status.
6 a84cbb2a 2004-04-19 devnull * There's not much point to worrying about
7 a84cbb2a 2004-04-19 devnull * byte order here -- using ptrace means
8 a84cbb2a 2004-04-19 devnull * we're running on the architecture we're debugging,
9 a84cbb2a 2004-04-19 devnull * unless truly weird stuff is going on.
10 a84cbb2a 2004-04-19 devnull *
11 a84cbb2a 2004-04-19 devnull * It is tempting to use /proc/%d/mem along with
12 a84cbb2a 2004-04-19 devnull * the sp and pc in the stat file to get a stack trace
13 a84cbb2a 2004-04-19 devnull * without attaching to the program, but unfortunately
14 a84cbb2a 2004-04-19 devnull * you can't read the mem file unless you've attached.
15 a84cbb2a 2004-04-19 devnull */
16 a84cbb2a 2004-04-19 devnull
17 a84cbb2a 2004-04-19 devnull #include <u.h>
18 a84cbb2a 2004-04-19 devnull #include <sys/ptrace.h>
19 a84cbb2a 2004-04-19 devnull #include <sys/types.h>
20 a84cbb2a 2004-04-19 devnull #include <sys/wait.h>
21 1cc215aa 2004-12-25 devnull #include <sys/procfs.h>
22 a84cbb2a 2004-04-19 devnull #include <signal.h>
23 a84cbb2a 2004-04-19 devnull #include <errno.h>
24 a84cbb2a 2004-04-19 devnull #include <libc.h>
25 a84cbb2a 2004-04-19 devnull #include <mach.h>
26 1cc215aa 2004-12-25 devnull #include <elf.h>
27 a84cbb2a 2004-04-19 devnull #include "ureg386.h"
28 a84cbb2a 2004-04-19 devnull
29 a84cbb2a 2004-04-19 devnull Mach *machcpu = &mach386;
30 a84cbb2a 2004-04-19 devnull
31 a84cbb2a 2004-04-19 devnull typedef struct PtraceRegs PtraceRegs;
32 a84cbb2a 2004-04-19 devnull
33 a84cbb2a 2004-04-19 devnull struct PtraceRegs
34 a84cbb2a 2004-04-19 devnull {
35 a84cbb2a 2004-04-19 devnull Regs r;
36 a84cbb2a 2004-04-19 devnull int pid;
37 a84cbb2a 2004-04-19 devnull };
38 a84cbb2a 2004-04-19 devnull
39 1cc215aa 2004-12-25 devnull static int ptracesegrw(Map*, Seg*, ulong, void*, uint, int);
40 4f0073fe 2004-06-11 devnull static int ptraceregrw(Regs*, char*, ulong*, int);
41 a84cbb2a 2004-04-19 devnull
42 2e965b33 2004-05-05 devnull static int attachedpids[1000];
43 2e965b33 2004-05-05 devnull static int nattached;
44 2e965b33 2004-05-05 devnull
45 39dbe6e7 2005-01-07 devnull static int
46 1cc215aa 2004-12-25 devnull ptraceattach(int pid)
47 a84cbb2a 2004-04-19 devnull {
48 2e965b33 2004-05-05 devnull int i;
49 a84cbb2a 2004-04-19 devnull
50 1cc215aa 2004-12-25 devnull /*
51 2e965b33 2004-05-05 devnull if(nattached==1 && attachedpids[0] == pid)
52 2e965b33 2004-05-05 devnull goto already;
53 2e965b33 2004-05-05 devnull if(nattached)
54 2e965b33 2004-05-05 devnull detachproc(attachedpids[0]);
55 1cc215aa 2004-12-25 devnull */
56 1cc215aa 2004-12-25 devnull
57 2e965b33 2004-05-05 devnull for(i=0; i<nattached; i++)
58 2e965b33 2004-05-05 devnull if(attachedpids[i]==pid)
59 1cc215aa 2004-12-25 devnull return 0;
60 2e965b33 2004-05-05 devnull if(nattached == nelem(attachedpids)){
61 2e965b33 2004-05-05 devnull werrstr("attached to too many processes");
62 2e965b33 2004-05-05 devnull return -1;
63 2e965b33 2004-05-05 devnull }
64 2e965b33 2004-05-05 devnull
65 a84cbb2a 2004-04-19 devnull if(ptrace(PTRACE_ATTACH, pid, 0, 0) < 0){
66 a84cbb2a 2004-04-19 devnull werrstr("ptrace attach %d: %r", pid);
67 a84cbb2a 2004-04-19 devnull return -1;
68 a84cbb2a 2004-04-19 devnull }
69 2e965b33 2004-05-05 devnull
70 a84cbb2a 2004-04-19 devnull if(ctlproc(pid, "waitstop") < 0){
71 2e965b33 2004-05-05 devnull fprint(2, "waitstop: %r");
72 a84cbb2a 2004-04-19 devnull ptrace(PTRACE_DETACH, pid, 0, 0);
73 a84cbb2a 2004-04-19 devnull return -1;
74 a84cbb2a 2004-04-19 devnull }
75 2e965b33 2004-05-05 devnull attachedpids[nattached++] = pid;
76 1cc215aa 2004-12-25 devnull return 0;
77 1cc215aa 2004-12-25 devnull }
78 a84cbb2a 2004-04-19 devnull
79 1cc215aa 2004-12-25 devnull void
80 1cc215aa 2004-12-25 devnull unmapproc(Map *map)
81 1cc215aa 2004-12-25 devnull {
82 1cc215aa 2004-12-25 devnull int i;
83 1cc215aa 2004-12-25 devnull
84 1cc215aa 2004-12-25 devnull if(map == nil)
85 1cc215aa 2004-12-25 devnull return;
86 1cc215aa 2004-12-25 devnull for(i=0; i<map->nseg; i++)
87 1cc215aa 2004-12-25 devnull while(i<map->nseg && map->seg[i].pid){
88 1cc215aa 2004-12-25 devnull map->nseg--;
89 1cc215aa 2004-12-25 devnull memmove(&map->seg[i], &map->seg[i+1],
90 1cc215aa 2004-12-25 devnull (map->nseg-i)*sizeof(map->seg[0]));
91 1cc215aa 2004-12-25 devnull }
92 1cc215aa 2004-12-25 devnull }
93 1cc215aa 2004-12-25 devnull
94 1cc215aa 2004-12-25 devnull int
95 1cc215aa 2004-12-25 devnull mapproc(int pid, Map *map, Regs **rp)
96 1cc215aa 2004-12-25 devnull {
97 1cc215aa 2004-12-25 devnull Seg s;
98 1cc215aa 2004-12-25 devnull PtraceRegs *r;
99 1cc215aa 2004-12-25 devnull
100 1cc215aa 2004-12-25 devnull if(ptraceattach(pid) < 0)
101 1cc215aa 2004-12-25 devnull return -1;
102 1cc215aa 2004-12-25 devnull
103 a84cbb2a 2004-04-19 devnull memset(&s, 0, sizeof s);
104 a84cbb2a 2004-04-19 devnull s.base = 0;
105 a84cbb2a 2004-04-19 devnull s.size = 0xFFFFFFFF;
106 a84cbb2a 2004-04-19 devnull s.offset = 0;
107 a84cbb2a 2004-04-19 devnull s.name = "data";
108 a84cbb2a 2004-04-19 devnull s.file = nil;
109 1cc215aa 2004-12-25 devnull s.rw = ptracesegrw;
110 a84cbb2a 2004-04-19 devnull s.pid = pid;
111 2e965b33 2004-05-05 devnull if(addseg(map, s) < 0){
112 2e965b33 2004-05-05 devnull fprint(2, "addseg: %r\n");
113 a84cbb2a 2004-04-19 devnull return -1;
114 2e965b33 2004-05-05 devnull }
115 a84cbb2a 2004-04-19 devnull
116 2e965b33 2004-05-05 devnull if((r = mallocz(sizeof(PtraceRegs), 1)) == nil){
117 2e965b33 2004-05-05 devnull fprint(2, "mallocz: %r\n");
118 a84cbb2a 2004-04-19 devnull return -1;
119 2e965b33 2004-05-05 devnull }
120 a84cbb2a 2004-04-19 devnull r->r.rw = ptraceregrw;
121 a84cbb2a 2004-04-19 devnull r->pid = pid;
122 a84cbb2a 2004-04-19 devnull *rp = (Regs*)r;
123 a84cbb2a 2004-04-19 devnull return 0;
124 a84cbb2a 2004-04-19 devnull }
125 a84cbb2a 2004-04-19 devnull
126 a84cbb2a 2004-04-19 devnull int
127 a84cbb2a 2004-04-19 devnull detachproc(int pid)
128 a84cbb2a 2004-04-19 devnull {
129 2e965b33 2004-05-05 devnull int i;
130 2e965b33 2004-05-05 devnull
131 2e965b33 2004-05-05 devnull for(i=0; i<nattached; i++){
132 2e965b33 2004-05-05 devnull if(attachedpids[i] == pid){
133 2e965b33 2004-05-05 devnull attachedpids[i] = attachedpids[--nattached];
134 2e965b33 2004-05-05 devnull break;
135 2e965b33 2004-05-05 devnull }
136 2e965b33 2004-05-05 devnull }
137 a84cbb2a 2004-04-19 devnull return ptrace(PTRACE_DETACH, pid, 0, 0);
138 a84cbb2a 2004-04-19 devnull }
139 a84cbb2a 2004-04-19 devnull
140 a84cbb2a 2004-04-19 devnull static int
141 1cc215aa 2004-12-25 devnull ptracerw(int type, int xtype, int isr, int pid, ulong addr, void *v, uint n)
142 a84cbb2a 2004-04-19 devnull {
143 a84cbb2a 2004-04-19 devnull int i;
144 a84cbb2a 2004-04-19 devnull u32int u;
145 a84cbb2a 2004-04-19 devnull uchar buf[4];
146 a84cbb2a 2004-04-19 devnull
147 a84cbb2a 2004-04-19 devnull for(i=0; i<n; i+=4){
148 a84cbb2a 2004-04-19 devnull if(isr){
149 a84cbb2a 2004-04-19 devnull errno = 0;
150 1cc215aa 2004-12-25 devnull u = ptrace(type, pid, addr+i, 0);
151 a84cbb2a 2004-04-19 devnull if(errno)
152 a84cbb2a 2004-04-19 devnull goto ptraceerr;
153 a84cbb2a 2004-04-19 devnull if(n-i >= 4)
154 a84cbb2a 2004-04-19 devnull *(u32int*)((char*)v+i) = u;
155 a84cbb2a 2004-04-19 devnull else{
156 a84cbb2a 2004-04-19 devnull *(u32int*)buf = u;
157 a84cbb2a 2004-04-19 devnull memmove((char*)v+i, buf, n-i);
158 a84cbb2a 2004-04-19 devnull }
159 a84cbb2a 2004-04-19 devnull }else{
160 a84cbb2a 2004-04-19 devnull if(n-i >= 4)
161 a84cbb2a 2004-04-19 devnull u = *(u32int*)((char*)v+i);
162 a84cbb2a 2004-04-19 devnull else{
163 a84cbb2a 2004-04-19 devnull errno = 0;
164 1cc215aa 2004-12-25 devnull u = ptrace(xtype, pid, addr+i, 0);
165 a84cbb2a 2004-04-19 devnull if(errno)
166 a84cbb2a 2004-04-19 devnull return -1;
167 a84cbb2a 2004-04-19 devnull *(u32int*)buf = u;
168 a84cbb2a 2004-04-19 devnull memmove(buf, (char*)v+i, n-i);
169 a84cbb2a 2004-04-19 devnull u = *(u32int*)buf;
170 a84cbb2a 2004-04-19 devnull }
171 1cc215aa 2004-12-25 devnull if(ptrace(type, pid, addr+i, &u) < 0)
172 a84cbb2a 2004-04-19 devnull goto ptraceerr;
173 a84cbb2a 2004-04-19 devnull }
174 a84cbb2a 2004-04-19 devnull }
175 a84cbb2a 2004-04-19 devnull return 0;
176 a84cbb2a 2004-04-19 devnull
177 a84cbb2a 2004-04-19 devnull ptraceerr:
178 a84cbb2a 2004-04-19 devnull werrstr("ptrace: %r");
179 a84cbb2a 2004-04-19 devnull return -1;
180 1cc215aa 2004-12-25 devnull }
181 1cc215aa 2004-12-25 devnull
182 1cc215aa 2004-12-25 devnull static int
183 1cc215aa 2004-12-25 devnull ptracesegrw(Map *map, Seg *seg, ulong addr, void *v, uint n, int isr)
184 1cc215aa 2004-12-25 devnull {
185 1cc215aa 2004-12-25 devnull addr += seg->base;
186 1cc215aa 2004-12-25 devnull return ptracerw(isr ? PTRACE_PEEKDATA : PTRACE_POKEDATA, PTRACE_PEEKDATA,
187 1cc215aa 2004-12-25 devnull isr, seg->pid, addr, v, n);
188 a84cbb2a 2004-04-19 devnull }
189 a84cbb2a 2004-04-19 devnull
190 a84cbb2a 2004-04-19 devnull static char* linuxregs[] = {
191 a84cbb2a 2004-04-19 devnull "BX",
192 a84cbb2a 2004-04-19 devnull "CX",
193 a84cbb2a 2004-04-19 devnull "DX",
194 a84cbb2a 2004-04-19 devnull "SI",
195 a84cbb2a 2004-04-19 devnull "DI",
196 a84cbb2a 2004-04-19 devnull "BP",
197 a84cbb2a 2004-04-19 devnull "AX",
198 a84cbb2a 2004-04-19 devnull "DS",
199 a84cbb2a 2004-04-19 devnull "ES",
200 a84cbb2a 2004-04-19 devnull "FS",
201 a84cbb2a 2004-04-19 devnull "GS",
202 a84cbb2a 2004-04-19 devnull "OAX",
203 a84cbb2a 2004-04-19 devnull "PC",
204 a84cbb2a 2004-04-19 devnull "CS",
205 a84cbb2a 2004-04-19 devnull "EFLAGS",
206 a84cbb2a 2004-04-19 devnull "SP",
207 a84cbb2a 2004-04-19 devnull "SS",
208 a84cbb2a 2004-04-19 devnull };
209 a84cbb2a 2004-04-19 devnull
210 a84cbb2a 2004-04-19 devnull static ulong
211 a84cbb2a 2004-04-19 devnull reg2linux(char *reg)
212 a84cbb2a 2004-04-19 devnull {
213 a84cbb2a 2004-04-19 devnull int i;
214 a84cbb2a 2004-04-19 devnull
215 a84cbb2a 2004-04-19 devnull for(i=0; i<nelem(linuxregs); i++)
216 a84cbb2a 2004-04-19 devnull if(strcmp(linuxregs[i], reg) == 0)
217 a84cbb2a 2004-04-19 devnull return 4*i;
218 a84cbb2a 2004-04-19 devnull return ~(ulong)0;
219 a84cbb2a 2004-04-19 devnull }
220 a84cbb2a 2004-04-19 devnull
221 a84cbb2a 2004-04-19 devnull static int
222 4f0073fe 2004-06-11 devnull ptraceregrw(Regs *regs, char *name, ulong *val, int isr)
223 a84cbb2a 2004-04-19 devnull {
224 a84cbb2a 2004-04-19 devnull int pid;
225 a84cbb2a 2004-04-19 devnull ulong addr;
226 a84cbb2a 2004-04-19 devnull u32int u;
227 a84cbb2a 2004-04-19 devnull
228 a84cbb2a 2004-04-19 devnull pid = ((PtraceRegs*)regs)->pid;
229 a84cbb2a 2004-04-19 devnull addr = reg2linux(name);
230 a84cbb2a 2004-04-19 devnull if(~addr == 0){
231 a84cbb2a 2004-04-19 devnull if(isr){
232 4f0073fe 2004-06-11 devnull *val = ~(ulong)0;
233 a84cbb2a 2004-04-19 devnull return 0;
234 a84cbb2a 2004-04-19 devnull }
235 a84cbb2a 2004-04-19 devnull werrstr("register not available");
236 a84cbb2a 2004-04-19 devnull return -1;
237 a84cbb2a 2004-04-19 devnull }
238 a84cbb2a 2004-04-19 devnull if(isr){
239 a84cbb2a 2004-04-19 devnull errno = 0;
240 a84cbb2a 2004-04-19 devnull u = ptrace(PTRACE_PEEKUSER, pid, addr, 0);
241 a84cbb2a 2004-04-19 devnull if(errno)
242 a84cbb2a 2004-04-19 devnull goto ptraceerr;
243 a84cbb2a 2004-04-19 devnull *val = u;
244 a84cbb2a 2004-04-19 devnull }else{
245 a84cbb2a 2004-04-19 devnull u = *val;
246 a84cbb2a 2004-04-19 devnull if(ptrace(PTRACE_POKEUSER, pid, addr, &u) < 0)
247 a84cbb2a 2004-04-19 devnull goto ptraceerr;
248 a84cbb2a 2004-04-19 devnull }
249 a84cbb2a 2004-04-19 devnull return 0;
250 a84cbb2a 2004-04-19 devnull
251 a84cbb2a 2004-04-19 devnull ptraceerr:
252 a84cbb2a 2004-04-19 devnull werrstr("ptrace: %r");
253 a84cbb2a 2004-04-19 devnull return -1;
254 a84cbb2a 2004-04-19 devnull }
255 a84cbb2a 2004-04-19 devnull
256 a84cbb2a 2004-04-19 devnull static int
257 a84cbb2a 2004-04-19 devnull isstopped(int pid)
258 a84cbb2a 2004-04-19 devnull {
259 a84cbb2a 2004-04-19 devnull char buf[1024];
260 a84cbb2a 2004-04-19 devnull int fd, n;
261 a84cbb2a 2004-04-19 devnull char *p;
262 a84cbb2a 2004-04-19 devnull
263 a84cbb2a 2004-04-19 devnull snprint(buf, sizeof buf, "/proc/%d/stat", pid);
264 a84cbb2a 2004-04-19 devnull if((fd = open(buf, OREAD)) < 0)
265 a84cbb2a 2004-04-19 devnull return 0;
266 a84cbb2a 2004-04-19 devnull n = read(fd, buf, sizeof buf-1);
267 a84cbb2a 2004-04-19 devnull close(fd);
268 a84cbb2a 2004-04-19 devnull if(n <= 0)
269 a84cbb2a 2004-04-19 devnull return 0;
270 a84cbb2a 2004-04-19 devnull buf[n] = 0;
271 a84cbb2a 2004-04-19 devnull
272 a84cbb2a 2004-04-19 devnull /* command name is in parens, no parens afterward */
273 a84cbb2a 2004-04-19 devnull p = strrchr(buf, ')');
274 a84cbb2a 2004-04-19 devnull if(p == nil || *++p != ' ')
275 a84cbb2a 2004-04-19 devnull return 0;
276 a84cbb2a 2004-04-19 devnull ++p;
277 a84cbb2a 2004-04-19 devnull
278 a84cbb2a 2004-04-19 devnull /* next is state - T is stopped for tracing */
279 a84cbb2a 2004-04-19 devnull return *p == 'T';
280 a84cbb2a 2004-04-19 devnull }
281 a84cbb2a 2004-04-19 devnull
282 a84cbb2a 2004-04-19 devnull /* /proc/pid/stat contains
283 a84cbb2a 2004-04-19 devnull pid
284 a84cbb2a 2004-04-19 devnull command in parens
285 a84cbb2a 2004-04-19 devnull 0. state
286 a84cbb2a 2004-04-19 devnull 1. ppid
287 a84cbb2a 2004-04-19 devnull 2. pgrp
288 a84cbb2a 2004-04-19 devnull 3. session
289 a84cbb2a 2004-04-19 devnull 4. tty_nr
290 a84cbb2a 2004-04-19 devnull 5. tpgid
291 a84cbb2a 2004-04-19 devnull 6. flags (math=4, traced=10)
292 a84cbb2a 2004-04-19 devnull 7. minflt
293 a84cbb2a 2004-04-19 devnull 8. cminflt
294 a84cbb2a 2004-04-19 devnull 9. majflt
295 a84cbb2a 2004-04-19 devnull 10. cmajflt
296 a84cbb2a 2004-04-19 devnull 11. utime
297 a84cbb2a 2004-04-19 devnull 12. stime
298 a84cbb2a 2004-04-19 devnull 13. cutime
299 a84cbb2a 2004-04-19 devnull 14. cstime
300 a84cbb2a 2004-04-19 devnull 15. priority
301 a84cbb2a 2004-04-19 devnull 16. nice
302 a84cbb2a 2004-04-19 devnull 17. 0
303 a84cbb2a 2004-04-19 devnull 18. itrealvalue
304 a84cbb2a 2004-04-19 devnull 19. starttime
305 a84cbb2a 2004-04-19 devnull 20. vsize
306 a84cbb2a 2004-04-19 devnull 21. rss
307 a84cbb2a 2004-04-19 devnull 22. rlim
308 a84cbb2a 2004-04-19 devnull 23. startcode
309 a84cbb2a 2004-04-19 devnull 24. endcode
310 a84cbb2a 2004-04-19 devnull 25. startstack
311 a84cbb2a 2004-04-19 devnull 26. kstkesp
312 a84cbb2a 2004-04-19 devnull 27. kstkeip
313 a84cbb2a 2004-04-19 devnull 28. pending signal bitmap
314 a84cbb2a 2004-04-19 devnull 29. blocked signal bitmap
315 a84cbb2a 2004-04-19 devnull 30. ignored signal bitmap
316 a84cbb2a 2004-04-19 devnull 31. caught signal bitmap
317 a84cbb2a 2004-04-19 devnull 32. wchan
318 a84cbb2a 2004-04-19 devnull 33. nswap
319 a84cbb2a 2004-04-19 devnull 34. cnswap
320 a84cbb2a 2004-04-19 devnull 35. exit_signal
321 a84cbb2a 2004-04-19 devnull 36. processor
322 a84cbb2a 2004-04-19 devnull */
323 a84cbb2a 2004-04-19 devnull
324 a84cbb2a 2004-04-19 devnull
325 a84cbb2a 2004-04-19 devnull int
326 a84cbb2a 2004-04-19 devnull procnotes(int pid, char ***pnotes)
327 a84cbb2a 2004-04-19 devnull {
328 a84cbb2a 2004-04-19 devnull char buf[1024], *f[40];
329 a84cbb2a 2004-04-19 devnull int fd, i, n, nf;
330 a84cbb2a 2004-04-19 devnull char *p, *s, **notes;
331 a84cbb2a 2004-04-19 devnull ulong sigs;
332 a84cbb2a 2004-04-19 devnull extern char *_p9sigstr(int, char*);
333 a84cbb2a 2004-04-19 devnull
334 a84cbb2a 2004-04-19 devnull *pnotes = nil;
335 a84cbb2a 2004-04-19 devnull snprint(buf, sizeof buf, "/proc/%d/stat", pid);
336 a84cbb2a 2004-04-19 devnull if((fd = open(buf, OREAD)) < 0){
337 a84cbb2a 2004-04-19 devnull fprint(2, "open %s: %r\n", buf);
338 a84cbb2a 2004-04-19 devnull return -1;
339 a84cbb2a 2004-04-19 devnull }
340 a84cbb2a 2004-04-19 devnull n = read(fd, buf, sizeof buf-1);
341 a84cbb2a 2004-04-19 devnull close(fd);
342 a84cbb2a 2004-04-19 devnull if(n <= 0){
343 a84cbb2a 2004-04-19 devnull fprint(2, "read %s: %r\n", buf);
344 a84cbb2a 2004-04-19 devnull return -1;
345 a84cbb2a 2004-04-19 devnull }
346 a84cbb2a 2004-04-19 devnull buf[n] = 0;
347 a84cbb2a 2004-04-19 devnull
348 a84cbb2a 2004-04-19 devnull /* command name is in parens, no parens afterward */
349 a84cbb2a 2004-04-19 devnull p = strrchr(buf, ')');
350 a84cbb2a 2004-04-19 devnull if(p == nil || *++p != ' '){
351 a84cbb2a 2004-04-19 devnull fprint(2, "bad format in /proc/%d/stat\n", pid);
352 a84cbb2a 2004-04-19 devnull return -1;
353 a84cbb2a 2004-04-19 devnull }
354 a84cbb2a 2004-04-19 devnull ++p;
355 a84cbb2a 2004-04-19 devnull
356 a84cbb2a 2004-04-19 devnull nf = tokenize(p, f, nelem(f));
357 a84cbb2a 2004-04-19 devnull if(0) print("code 0x%lux-0x%lux stack 0x%lux kstk 0x%lux keip 0x%lux pending 0x%lux\n",
358 a84cbb2a 2004-04-19 devnull strtoul(f[23], 0, 0), strtoul(f[24], 0, 0), strtoul(f[25], 0, 0),
359 a84cbb2a 2004-04-19 devnull strtoul(f[26], 0, 0), strtoul(f[27], 0, 0), strtoul(f[28], 0, 0));
360 a84cbb2a 2004-04-19 devnull if(nf <= 28)
361 a84cbb2a 2004-04-19 devnull return -1;
362 a84cbb2a 2004-04-19 devnull
363 a84cbb2a 2004-04-19 devnull sigs = strtoul(f[28], 0, 0) & ~(1<<SIGCONT);
364 a84cbb2a 2004-04-19 devnull if(sigs == 0){
365 a84cbb2a 2004-04-19 devnull *pnotes = nil;
366 a84cbb2a 2004-04-19 devnull return 0;
367 a84cbb2a 2004-04-19 devnull }
368 a84cbb2a 2004-04-19 devnull
369 a84cbb2a 2004-04-19 devnull notes = mallocz(32*sizeof(char*), 0);
370 a84cbb2a 2004-04-19 devnull if(notes == nil)
371 a84cbb2a 2004-04-19 devnull return -1;
372 a84cbb2a 2004-04-19 devnull n = 0;
373 a84cbb2a 2004-04-19 devnull for(i=0; i<32; i++){
374 a84cbb2a 2004-04-19 devnull if((sigs&(1<<i)) == 0)
375 a84cbb2a 2004-04-19 devnull continue;
376 a84cbb2a 2004-04-19 devnull if((s = _p9sigstr(i, nil)) == nil)
377 a84cbb2a 2004-04-19 devnull continue;
378 a84cbb2a 2004-04-19 devnull notes[n++] = s;
379 a84cbb2a 2004-04-19 devnull }
380 a84cbb2a 2004-04-19 devnull *pnotes = notes;
381 a84cbb2a 2004-04-19 devnull return n;
382 a84cbb2a 2004-04-19 devnull }
383 a84cbb2a 2004-04-19 devnull
384 a84cbb2a 2004-04-19 devnull #undef waitpid
385 a84cbb2a 2004-04-19 devnull
386 a84cbb2a 2004-04-19 devnull int
387 a84cbb2a 2004-04-19 devnull ctlproc(int pid, char *msg)
388 a84cbb2a 2004-04-19 devnull {
389 a84cbb2a 2004-04-19 devnull int p, status;
390 a84cbb2a 2004-04-19 devnull
391 a84cbb2a 2004-04-19 devnull if(strcmp(msg, "hang") == 0){
392 a84cbb2a 2004-04-19 devnull if(pid == getpid())
393 a84cbb2a 2004-04-19 devnull return ptrace(PTRACE_TRACEME, 0, 0, 0);
394 a84cbb2a 2004-04-19 devnull werrstr("can only hang self");
395 a84cbb2a 2004-04-19 devnull return -1;
396 a84cbb2a 2004-04-19 devnull }
397 a84cbb2a 2004-04-19 devnull if(strcmp(msg, "kill") == 0)
398 a84cbb2a 2004-04-19 devnull return ptrace(PTRACE_KILL, pid, 0, 0);
399 a84cbb2a 2004-04-19 devnull if(strcmp(msg, "startstop") == 0){
400 a84cbb2a 2004-04-19 devnull if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
401 a84cbb2a 2004-04-19 devnull return -1;
402 a84cbb2a 2004-04-19 devnull goto waitstop;
403 a84cbb2a 2004-04-19 devnull }
404 a84cbb2a 2004-04-19 devnull if(strcmp(msg, "sysstop") == 0){
405 a84cbb2a 2004-04-19 devnull if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
406 a84cbb2a 2004-04-19 devnull return -1;
407 a84cbb2a 2004-04-19 devnull goto waitstop;
408 a84cbb2a 2004-04-19 devnull }
409 a84cbb2a 2004-04-19 devnull if(strcmp(msg, "stop") == 0){
410 a84cbb2a 2004-04-19 devnull if(kill(pid, SIGSTOP) < 0)
411 a84cbb2a 2004-04-19 devnull return -1;
412 a84cbb2a 2004-04-19 devnull goto waitstop;
413 a84cbb2a 2004-04-19 devnull }
414 a84cbb2a 2004-04-19 devnull if(strcmp(msg, "waitstop") == 0){
415 a84cbb2a 2004-04-19 devnull waitstop:
416 a84cbb2a 2004-04-19 devnull if(isstopped(pid))
417 a84cbb2a 2004-04-19 devnull return 0;
418 a84cbb2a 2004-04-19 devnull for(;;){
419 2e965b33 2004-05-05 devnull p = waitpid(pid, &status, WUNTRACED|__WALL);
420 2e965b33 2004-05-05 devnull if(p <= 0){
421 2e965b33 2004-05-05 devnull if(errno == ECHILD){
422 2e965b33 2004-05-05 devnull if(isstopped(pid))
423 2e965b33 2004-05-05 devnull return 0;
424 2e965b33 2004-05-05 devnull }
425 a84cbb2a 2004-04-19 devnull return -1;
426 2e965b33 2004-05-05 devnull }
427 a84cbb2a 2004-04-19 devnull if(WIFEXITED(status) || WIFSTOPPED(status))
428 a84cbb2a 2004-04-19 devnull return 0;
429 a84cbb2a 2004-04-19 devnull }
430 a84cbb2a 2004-04-19 devnull }
431 a84cbb2a 2004-04-19 devnull if(strcmp(msg, "start") == 0)
432 a84cbb2a 2004-04-19 devnull return ptrace(PTRACE_CONT, pid, 0, 0);
433 a84cbb2a 2004-04-19 devnull werrstr("unknown control message '%s'", msg);
434 a84cbb2a 2004-04-19 devnull return -1;
435 a84cbb2a 2004-04-19 devnull }
436 a84cbb2a 2004-04-19 devnull
437 a84cbb2a 2004-04-19 devnull char*
438 a84cbb2a 2004-04-19 devnull proctextfile(int pid)
439 a84cbb2a 2004-04-19 devnull {
440 a84cbb2a 2004-04-19 devnull static char buf[1024], pbuf[128];
441 a84cbb2a 2004-04-19 devnull
442 a84cbb2a 2004-04-19 devnull snprint(pbuf, sizeof pbuf, "/proc/%d/exe", pid);
443 a84cbb2a 2004-04-19 devnull if(readlink(pbuf, buf, sizeof buf) >= 0)
444 a84cbb2a 2004-04-19 devnull return buf;
445 a84cbb2a 2004-04-19 devnull if(access(pbuf, AEXIST) >= 0)
446 a84cbb2a 2004-04-19 devnull return pbuf;
447 a84cbb2a 2004-04-19 devnull return nil;
448 a84cbb2a 2004-04-19 devnull }
449 a84cbb2a 2004-04-19 devnull
450 a84cbb2a 2004-04-19 devnull
451 a84cbb2a 2004-04-19 devnull #if 0
452 a84cbb2a 2004-04-19 devnull snprint(buf, sizeof buf, "/proc/%d/maps", pid);
453 a84cbb2a 2004-04-19 devnull if((b = Bopen(buf, OREAD)) == nil){
454 a84cbb2a 2004-04-19 devnull werrstr("open %s: %r", buf);
455 a84cbb2a 2004-04-19 devnull return -1;
456 a84cbb2a 2004-04-19 devnull }
457 a84cbb2a 2004-04-19 devnull
458 a84cbb2a 2004-04-19 devnull /*
459 a84cbb2a 2004-04-19 devnull 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
460 a84cbb2a 2004-04-19 devnull 08056000-08058000 rw-p 0000d000 03:0c 64593 /usr/sbin/gpm
461 a84cbb2a 2004-04-19 devnull 08058000-0805b000 rwxp 00000000 00:00 0
462 a84cbb2a 2004-04-19 devnull 40000000-40013000 r-xp 00000000 03:0c 4165 /lib/ld-2.2.4.so
463 a84cbb2a 2004-04-19 devnull 40013000-40015000 rw-p 00012000 03:0c 4165 /lib/ld-2.2.4.so
464 a84cbb2a 2004-04-19 devnull 4001f000-40135000 r-xp 00000000 03:0c 45494 /lib/libc-2.2.4.so
465 a84cbb2a 2004-04-19 devnull 40135000-4013e000 rw-p 00115000 03:0c 45494 /lib/libc-2.2.4.so
466 a84cbb2a 2004-04-19 devnull 4013e000-40142000 rw-p 00000000 00:00 0
467 a84cbb2a 2004-04-19 devnull bffff000-c0000000 rwxp 00000000 00:00 0
468 a84cbb2a 2004-04-19 devnull */
469 a84cbb2a 2004-04-19 devnull
470 a84cbb2a 2004-04-19 devnull file = nil;
471 a84cbb2a 2004-04-19 devnull while((p = Brdline(b, '\n')) != nil){
472 a84cbb2a 2004-04-19 devnull p[Blinelen(b)-1] = 0;
473 a84cbb2a 2004-04-19 devnull memset(f, 0, sizeof f);
474 a84cbb2a 2004-04-19 devnull if((nf = getfields(p, f, 6, 1, " ")) < 5)
475 a84cbb2a 2004-04-19 devnull continue;
476 a84cbb2a 2004-04-19 devnull base = strtoul(f[0], &p, 16);
477 a84cbb2a 2004-04-19 devnull if(*p != '-')
478 a84cbb2a 2004-04-19 devnull continue;
479 a84cbb2a 2004-04-19 devnull end = strtoul(p+1, &p, 16);
480 a84cbb2a 2004-04-19 devnull if(*p != 0)
481 a84cbb2a 2004-04-19 devnull continue;
482 a84cbb2a 2004-04-19 devnull offset = strtoul(f[2], &p, 16);
483 a84cbb2a 2004-04-19 devnull if(*p != 0)
484 a84cbb2a 2004-04-19 devnull continue;
485 a84cbb2a 2004-04-19 devnull if(nf == 6)
486 a84cbb2a 2004-04-19 devnull file = f[5];
487 a84cbb2a 2004-04-19 devnull zero = atoi(f[4]) == 0;
488 a84cbb2a 2004-04-19 devnull print("%lux-%lux %lux %s %s\n", base, end, offset, zero ? "data" : "text", file ? file : "");
489 a84cbb2a 2004-04-19 devnull s.base = base;
490 a84cbb2a 2004-04-19 devnull s.size = end - base;
491 a84cbb2a 2004-04-19 devnull s.offset = offset;
492 a84cbb2a 2004-04-19 devnull s.name = zero ? "data" : "text";
493 a84cbb2a 2004-04-19 devnull s.file = strdup(file);
494 a84cbb2a 2004-04-19 devnull s.rw = ptracerw;
495 a84cbb2a 2004-04-19 devnull s.pid = pid;
496 a84cbb2a 2004-04-19 devnull if(addseg(map, s) < 0){
497 a84cbb2a 2004-04-19 devnull Bterm(b);
498 a84cbb2a 2004-04-19 devnull ptrace(PTRACE_DETACH, pid, 0, 0);
499 a84cbb2a 2004-04-19 devnull return -1;
500 a84cbb2a 2004-04-19 devnull }
501 a84cbb2a 2004-04-19 devnull }
502 a84cbb2a 2004-04-19 devnull Bterm(b);
503 a84cbb2a 2004-04-19 devnull #endif
504 1cc215aa 2004-12-25 devnull
505 1cc215aa 2004-12-25 devnull /*
506 1cc215aa 2004-12-25 devnull * bottom-end functions for libthread_db to call
507 1cc215aa 2004-12-25 devnull */
508 1cc215aa 2004-12-25 devnull enum
509 1cc215aa 2004-12-25 devnull {
510 1cc215aa 2004-12-25 devnull PS_OK,
511 1cc215aa 2004-12-25 devnull PS_ERR,
512 1cc215aa 2004-12-25 devnull PS_BADPID,
513 1cc215aa 2004-12-25 devnull PS_BADLWPID,
514 1cc215aa 2004-12-25 devnull PS_BADADDR,
515 1cc215aa 2004-12-25 devnull PS_NOSYM,
516 1cc215aa 2004-12-25 devnull PS_NOFPREGS,
517 1cc215aa 2004-12-25 devnull };
518 a84cbb2a 2004-04-19 devnull
519 1cc215aa 2004-12-25 devnull pid_t
520 1cc215aa 2004-12-25 devnull ps_getpid(struct ps_prochandle *ph)
521 1cc215aa 2004-12-25 devnull {
522 1cc215aa 2004-12-25 devnull return ph->pid;
523 1cc215aa 2004-12-25 devnull }
524 1cc215aa 2004-12-25 devnull
525 1cc215aa 2004-12-25 devnull int
526 1cc215aa 2004-12-25 devnull ps_pstop(const struct ps_prochandle *ph)
527 1cc215aa 2004-12-25 devnull {
528 1cc215aa 2004-12-25 devnull return PS_ERR;
529 1cc215aa 2004-12-25 devnull }
530 1cc215aa 2004-12-25 devnull
531 1cc215aa 2004-12-25 devnull int
532 1cc215aa 2004-12-25 devnull ps_pcontinue(const struct ps_prochandle *ph)
533 1cc215aa 2004-12-25 devnull {
534 1cc215aa 2004-12-25 devnull return PS_ERR;
535 1cc215aa 2004-12-25 devnull }
536 1cc215aa 2004-12-25 devnull
537 1cc215aa 2004-12-25 devnull int
538 1cc215aa 2004-12-25 devnull ps_lstop(const struct ps_prochandle *ph)
539 1cc215aa 2004-12-25 devnull {
540 1cc215aa 2004-12-25 devnull return PS_ERR;
541 1cc215aa 2004-12-25 devnull }
542 1cc215aa 2004-12-25 devnull
543 1cc215aa 2004-12-25 devnull int
544 1cc215aa 2004-12-25 devnull ps_lcontinue(const struct ps_prochandle *ph)
545 1cc215aa 2004-12-25 devnull {
546 1cc215aa 2004-12-25 devnull return PS_ERR;
547 1cc215aa 2004-12-25 devnull }
548 1cc215aa 2004-12-25 devnull
549 1cc215aa 2004-12-25 devnull /* read/write data or text memory */
550 1cc215aa 2004-12-25 devnull int
551 1cc215aa 2004-12-25 devnull ps_pdread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
552 1cc215aa 2004-12-25 devnull {
553 1cc215aa 2004-12-25 devnull //print("read %d %p %d\n", ph->pid, addr, sz);
554 1cc215aa 2004-12-25 devnull if(ptracerw(PTRACE_PEEKDATA, 0, 1, ph->pid, (ulong)addr, v, sz) < 0)
555 1cc215aa 2004-12-25 devnull return PS_ERR;
556 1cc215aa 2004-12-25 devnull //print(" => 0x%lux\n", *(ulong*)v);
557 1cc215aa 2004-12-25 devnull return PS_OK;
558 1cc215aa 2004-12-25 devnull }
559 1cc215aa 2004-12-25 devnull
560 1cc215aa 2004-12-25 devnull int
561 1cc215aa 2004-12-25 devnull ps_pdwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
562 1cc215aa 2004-12-25 devnull {
563 1cc215aa 2004-12-25 devnull //print("write %d %p\n", ph->pid, addr);
564 1cc215aa 2004-12-25 devnull if(ptracerw(PTRACE_POKEDATA, PTRACE_PEEKDATA, 0, ph->pid, (ulong)addr, v, sz) < 0)
565 1cc215aa 2004-12-25 devnull return PS_ERR;
566 1cc215aa 2004-12-25 devnull return PS_OK;
567 1cc215aa 2004-12-25 devnull }
568 1cc215aa 2004-12-25 devnull
569 1cc215aa 2004-12-25 devnull int
570 1cc215aa 2004-12-25 devnull ps_ptread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
571 1cc215aa 2004-12-25 devnull {
572 1cc215aa 2004-12-25 devnull //print("read %d %p\n", ph->pid, addr);
573 1cc215aa 2004-12-25 devnull if(ptracerw(PTRACE_PEEKTEXT, 0, 1, ph->pid, (ulong)addr, v, sz) < 0)
574 1cc215aa 2004-12-25 devnull return PS_ERR;
575 1cc215aa 2004-12-25 devnull return PS_OK;
576 1cc215aa 2004-12-25 devnull }
577 1cc215aa 2004-12-25 devnull
578 1cc215aa 2004-12-25 devnull int
579 1cc215aa 2004-12-25 devnull ps_ptwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
580 1cc215aa 2004-12-25 devnull {
581 1cc215aa 2004-12-25 devnull //print("write %d %p\n", ph->pid, addr);
582 1cc215aa 2004-12-25 devnull if(ptracerw(PTRACE_POKETEXT, PTRACE_PEEKTEXT, 0, ph->pid, (ulong)addr, v, sz) < 0)
583 1cc215aa 2004-12-25 devnull return PS_ERR;
584 1cc215aa 2004-12-25 devnull return PS_OK;
585 1cc215aa 2004-12-25 devnull }
586 1cc215aa 2004-12-25 devnull
587 1cc215aa 2004-12-25 devnull int
588 1cc215aa 2004-12-25 devnull ps_lgetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs)
589 1cc215aa 2004-12-25 devnull {
590 1cc215aa 2004-12-25 devnull if(lwp == 0){
591 1cc215aa 2004-12-25 devnull memset(regs, 0xfe, sizeof(regs[0])*nelem(linuxregs));
592 1cc215aa 2004-12-25 devnull return PS_OK;
593 1cc215aa 2004-12-25 devnull }
594 1cc215aa 2004-12-25 devnull //print("getregs %d %p (%d)\n", lwp, regs, sizeof(regs[0])*nelem(linuxregs));
595 1cc215aa 2004-12-25 devnull
596 1cc215aa 2004-12-25 devnull if(ptraceattach(lwp) < 0){
597 1cc215aa 2004-12-25 devnull fprint(2, "ptrace attach: %r\n");
598 1cc215aa 2004-12-25 devnull return PS_ERR;
599 1cc215aa 2004-12-25 devnull }
600 1cc215aa 2004-12-25 devnull
601 1cc215aa 2004-12-25 devnull if(ptracerw(PTRACE_PEEKUSER, 0, 1, lwp, 0, regs, sizeof(regs[0])*nelem(linuxregs)) < 0){
602 1cc215aa 2004-12-25 devnull fprint(2, "ptrace: %r\n");
603 1cc215aa 2004-12-25 devnull return PS_ERR;
604 1cc215aa 2004-12-25 devnull }
605 1cc215aa 2004-12-25 devnull return PS_OK;
606 1cc215aa 2004-12-25 devnull }
607 1cc215aa 2004-12-25 devnull
608 1cc215aa 2004-12-25 devnull int
609 1cc215aa 2004-12-25 devnull ps_lsetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs)
610 1cc215aa 2004-12-25 devnull {
611 1cc215aa 2004-12-25 devnull print("setregs %d\n", lwp);
612 1cc215aa 2004-12-25 devnull if(ptracerw(PTRACE_POKEUSER, PTRACE_PEEKUSER, 1, lwp, 0, regs, sizeof(regs[0])*nelem(linuxregs)) < 0)
613 1cc215aa 2004-12-25 devnull return PS_ERR;
614 1cc215aa 2004-12-25 devnull return PS_OK;
615 1cc215aa 2004-12-25 devnull }
616 1cc215aa 2004-12-25 devnull
617 1cc215aa 2004-12-25 devnull int
618 1cc215aa 2004-12-25 devnull ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs)
619 1cc215aa 2004-12-25 devnull {
620 1cc215aa 2004-12-25 devnull if(ptracerw(PTRACE_PEEKUSER, 0, 1, lwp, 18*4, fpregs, sizeof *fpregs) < 0)
621 1cc215aa 2004-12-25 devnull return PS_ERR;
622 1cc215aa 2004-12-25 devnull return PS_OK;
623 1cc215aa 2004-12-25 devnull }
624 1cc215aa 2004-12-25 devnull
625 1cc215aa 2004-12-25 devnull int
626 1cc215aa 2004-12-25 devnull ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs)
627 1cc215aa 2004-12-25 devnull {
628 1cc215aa 2004-12-25 devnull if(ptracerw(PTRACE_POKEUSER, PTRACE_PEEKUSER, 1, lwp, 18*4, fpregs, sizeof *fpregs) < 0)
629 1cc215aa 2004-12-25 devnull return PS_ERR;
630 1cc215aa 2004-12-25 devnull return PS_OK;
631 1cc215aa 2004-12-25 devnull }
632 1cc215aa 2004-12-25 devnull
633 1cc215aa 2004-12-25 devnull /* Fetch the special per-thread address associated with the given LWP.
634 1cc215aa 2004-12-25 devnull This call is only used on a few platforms (most use a normal register).
635 1cc215aa 2004-12-25 devnull The meaning of the `int' parameter is machine-dependent. */
636 1cc215aa 2004-12-25 devnull int
637 1cc215aa 2004-12-25 devnull ps_get_thread_area(struct ps_prochandle *ph, lwpid_t lwp, int xxx, psaddr_t *addr)
638 1cc215aa 2004-12-25 devnull {
639 1cc215aa 2004-12-25 devnull return PS_NOSYM;
640 1cc215aa 2004-12-25 devnull }
641 1cc215aa 2004-12-25 devnull
642 1cc215aa 2004-12-25 devnull /* Look up the named symbol in the named DSO in the symbol tables
643 1cc215aa 2004-12-25 devnull associated with the process being debugged, filling in *SYM_ADDR
644 1cc215aa 2004-12-25 devnull with the corresponding run-time address. */
645 1cc215aa 2004-12-25 devnull int
646 1cc215aa 2004-12-25 devnull ps_pglobal_lookup(struct ps_prochandle *ph, char *object_name, char *sym_name, psaddr_t *sym_addr)
647 1cc215aa 2004-12-25 devnull {
648 1cc215aa 2004-12-25 devnull Fhdr *fp;
649 1cc215aa 2004-12-25 devnull ulong addr;
650 1cc215aa 2004-12-25 devnull
651 1cc215aa 2004-12-25 devnull if((fp = findhdr(object_name)) == nil){
652 1cc215aa 2004-12-25 devnull print("lookup %d %s %s => no such hdr\n", ph->pid, object_name, sym_name);
653 1cc215aa 2004-12-25 devnull return PS_NOSYM;
654 1cc215aa 2004-12-25 devnull }
655 1cc215aa 2004-12-25 devnull if(elfsymlookup(fp->elf, sym_name, &addr) < 0){
656 1cc215aa 2004-12-25 devnull print("lookup %d %s %s => name not found\n", ph->pid, object_name, sym_name);
657 1cc215aa 2004-12-25 devnull return PS_NOSYM;
658 1cc215aa 2004-12-25 devnull }
659 1cc215aa 2004-12-25 devnull print("lookup %d %s %s => 0x%lux\n", ph->pid, object_name, sym_name, addr);
660 1cc215aa 2004-12-25 devnull *sym_addr = (void*)(addr+fp->base);
661 1cc215aa 2004-12-25 devnull return PS_OK;
662 1cc215aa 2004-12-25 devnull }
663 1cc215aa 2004-12-25 devnull
664 1cc215aa 2004-12-25 devnull Ureg*
665 1cc215aa 2004-12-25 devnull _linux2ureg386(UregLinux386 *l)
666 1cc215aa 2004-12-25 devnull {
667 1cc215aa 2004-12-25 devnull Ureg *u;
668 1cc215aa 2004-12-25 devnull
669 1cc215aa 2004-12-25 devnull u = malloc(sizeof(Ureg));
670 1cc215aa 2004-12-25 devnull if(u == nil)
671 1cc215aa 2004-12-25 devnull return nil;
672 1cc215aa 2004-12-25 devnull u->di = l->edi;
673 1cc215aa 2004-12-25 devnull u->si = l->esi;
674 1cc215aa 2004-12-25 devnull u->bp = l->ebp;
675 1cc215aa 2004-12-25 devnull u->nsp = l->esp;
676 1cc215aa 2004-12-25 devnull u->bx = l->ebx;
677 1cc215aa 2004-12-25 devnull u->dx = l->edx;
678 1cc215aa 2004-12-25 devnull u->cx = l->ecx;
679 1cc215aa 2004-12-25 devnull u->ax = l->eax;
680 1cc215aa 2004-12-25 devnull u->gs = l->xgs;
681 1cc215aa 2004-12-25 devnull u->fs = l->xfs;
682 1cc215aa 2004-12-25 devnull u->es = l->xes;
683 1cc215aa 2004-12-25 devnull u->ds = l->xds;
684 1cc215aa 2004-12-25 devnull u->trap = ~0; // l->trapno;
685 1cc215aa 2004-12-25 devnull u->ecode = ~0; // l->err;
686 1cc215aa 2004-12-25 devnull u->pc = l->eip;
687 1cc215aa 2004-12-25 devnull u->cs = l->xcs;
688 1cc215aa 2004-12-25 devnull u->flags = l->eflags;
689 1cc215aa 2004-12-25 devnull u->sp = l->esp;
690 1cc215aa 2004-12-25 devnull u->ss = l->xss;
691 1cc215aa 2004-12-25 devnull return u;
692 1cc215aa 2004-12-25 devnull }