1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * ptrace(2) interface built on top of proc(4).
29 */
30
31
32 #pragma weak _ptrace = ptrace
33
34 #include "lint.h"
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <memory.h>
39 #include <string.h>
40 #include <fcntl.h>
41 #include <errno.h>
42 #include <sys/types.h>
43 #include <sys/uio.h>
44 #include <signal.h>
45 #include <sys/siginfo.h>
46 #include <sys/fault.h>
47 #include <sys/syscall.h>
48 #include <procfs.h>
49 #include <sys/psw.h>
50 #include <sys/user.h>
51 /*
52 * mtlib.h must precede thread.h
53 */
54 #include <mtlib.h>
55 #include <thread.h>
56 #include <synch.h>
57 #include <unistd.h>
58
59 static mutex_t pt_lock = DEFAULTMUTEX;
60
61 #define TRUE 1
62 #define FALSE 0
63
64 /*
65 * All my children...
66 */
67 typedef struct cstatus {
68 struct cstatus *next; /* linked list */
69 pid_t pid; /* process-id */
70 int asfd; /* /proc/<pid>/as */
71 int ctlfd; /* /proc/<pid>/ctl */
72 int statusfd; /* /proc/<pid>/status */
73 int flags; /* see below */
74 pstatus_t pstatus; /* from /proc/<pid>/status */
75 user_t user; /* manufactured u-block */
76 } cstatus_t;
77
78 /* flags */
79 #define CS_SETREGS 0x01 /* set registers on run */
80 #define CS_PSARGS 0x02 /* u_psargs[] has been fetched */
81 #define CS_SIGNAL 0x04 /* u_signal[] has been fetched */
82
83 #define NULLCP ((cstatus_t *)0)
84
85 static cstatus_t *childp = NULLCP;
86
87 /* fake u-block offsets */
88 #define UP ((user_t *)NULL)
89 #define U_REG ((int)(&UP->u_reg[0]))
90 #define U_AR0 ((int)(&UP->u_ar0))
91 #define U_PSARGS ((int)(&UP->u_psargs[0]))
92 #define U_SIGNAL ((int)(&UP->u_signal[0]))
93 #define U_CODE ((int)(&UP->u_code))
94 #define U_ADDR ((int)(&UP->u_addr))
95 #define U_END ((int)sizeof (user_t))
96 #define REGADDR 0xffff0000 /* arbitrary kernel address for u_ar0 */
97
98 /* external routines defined in this module */
99 extern int ptrace(int, pid_t, int, int);
100 /* static routines defined in this module */
101 static cstatus_t *FindProc(pid_t);
102 static void CheckAllProcs(void);
103 static int Dupfd(int, int);
104 static void MakeProcName(char *, pid_t);
105 static int OpenProc(cstatus_t *);
106 static void CloseProc(cstatus_t *);
107 static cstatus_t *GrabProc(pid_t);
108 static void ReleaseProc(cstatus_t *);
109 static int ProcUpdate(cstatus_t *);
110 static void MakeUser(cstatus_t *);
111 static void GetPsargs(cstatus_t *);
112 static void GetSignal(cstatus_t *);
113
114 #if PTRACE_DEBUG
115 /* for debugging */
116 static char *
map(int request)117 map(int request)
118 {
119 static char name[20];
120
121 switch (request) {
122 case 0: return ("PTRACE_TRACEME");
123 case 1: return ("PTRACE_PEEKTEXT");
124 case 2: return ("PTRACE_PEEKDATA");
125 case 3: return ("PTRACE_PEEKUSER");
126 case 4: return ("PTRACE_POKETEXT");
127 case 5: return ("PTRACE_POKEDATA");
128 case 6: return ("PTRACE_POKEUSER");
129 case 7: return ("PTRACE_CONT");
130 case 8: return ("PTRACE_KILL");
131 case 9: return ("PTRACE_SINGLESTEP");
132 }
133 (void) sprintf(name, "%d", request);
134 return (name);
135 }
136 #endif
137
138 int
ptrace(int request,pid_t pid,int addr,int data)139 ptrace(int request, pid_t pid, int addr, int data)
140 {
141 pstatus_t *ps;
142 cstatus_t *cp;
143 unsigned xaddr;
144 struct {
145 long cmd;
146 union {
147 long flags;
148 sigset_t signals;
149 fltset_t faults;
150 sysset_t syscalls;
151 siginfo_t siginfo;
152 } arg;
153 } ctl;
154
155 #if PTRACE_DEBUG
156 fprintf(stderr, " ptrace(%s, 0x%X, 0x%X, 0x%X)\n",
157 map(request), pid, addr, data);
158 #endif
159
160 (void) mutex_lock(&pt_lock);
161
162 if (request == 0) { /* PTRACE_TRACEME, executed by traced process */
163 /*
164 * Set stop-on-all-signals and nothing else.
165 * Turn off inherit-on-fork flag (grandchildren run away).
166 * Set ptrace-compatible flag.
167 */
168 char procname[64]; /* /proc/<pid>/ctl */
169 int fd;
170
171 MakeProcName(procname, getpid());
172 (void) strcat(procname, "/ctl");
173 if ((fd = open(procname, O_WRONLY, 0)) < 0)
174 exit(255);
175 ctl.cmd = PCSTRACE;
176 prfillset(&ctl.arg.signals);
177 if (write(fd, (char *)&ctl, sizeof (long)+sizeof (sigset_t))
178 != sizeof (long)+sizeof (sigset_t))
179 exit(255);
180 ctl.cmd = PCSFAULT;
181 premptyset(&ctl.arg.faults);
182 if (write(fd, (char *)&ctl, sizeof (long)+sizeof (fltset_t))
183 != sizeof (long)+sizeof (fltset_t))
184 exit(255);
185 ctl.cmd = PCSENTRY;
186 premptyset(&ctl.arg.syscalls);
187 if (write(fd, (char *)&ctl, sizeof (long)+sizeof (sysset_t))
188 != sizeof (long)+sizeof (sysset_t))
189 exit(255);
190 ctl.cmd = PCSEXIT;
191 premptyset(&ctl.arg.syscalls);
192 if (write(fd, (char *)&ctl, sizeof (long)+sizeof (sysset_t))
193 != sizeof (long)+sizeof (sysset_t))
194 exit(255);
195 ctl.cmd = PCUNSET;
196 ctl.arg.flags = PR_FORK;
197 if (write(fd, (char *)&ctl, sizeof (long)+sizeof (long))
198 != sizeof (long)+sizeof (long))
199 exit(255);
200 ctl.cmd = PCSET;
201 ctl.arg.flags = PR_PTRACE;
202 if (write(fd, (char *)&ctl, sizeof (long)+sizeof (long))
203 != sizeof (long)+sizeof (long))
204 exit(255);
205 if (close(fd) != 0)
206 exit(255);
207
208 (void) mutex_unlock(&pt_lock);
209 return (0);
210 }
211
212 again:
213 errno = 0;
214
215 /* find the cstatus structure corresponding to pid */
216 if ((cp = GrabProc(pid)) == NULLCP)
217 goto esrch;
218
219 ps = &cp->pstatus;
220 if (!(ps->pr_flags & PR_ISTOP)) {
221 if (ProcUpdate(cp) != 0) {
222 ReleaseProc(cp);
223 goto esrch;
224 }
225 if (!(ps->pr_flags & PR_ISTOP))
226 goto esrch;
227 }
228
229 /*
230 * Process the request.
231 */
232 errno = 0;
233 switch (request) {
234 case 1: /* PTRACE_PEEKTEXT */
235 case 2: /* PTRACE_PEEKDATA */
236 if (addr & 03)
237 goto eio;
238 if (pread(cp->asfd, (char *)&data, sizeof (data), (off_t)addr)
239 == sizeof (data)) {
240 (void) mutex_unlock(&pt_lock);
241 return (data);
242 }
243 goto eio;
244
245 case 3: /* PTRACE_PEEKUSER */
246 if (addr & 03)
247 goto eio;
248 xaddr = addr;
249 if (xaddr >= REGADDR && xaddr < REGADDR+sizeof (gregset_t))
250 xaddr -= REGADDR-U_REG;
251 if (xaddr >= U_PSARGS && xaddr < U_PSARGS+sizeof (UP->u_psargs))
252 GetPsargs(cp);
253 if (xaddr >= U_SIGNAL && xaddr < U_SIGNAL+sizeof (UP->u_signal))
254 GetSignal(cp);
255 if ((int)xaddr >= 0 && xaddr < U_END) {
256 /* LINTED pointer alignment */
257 data = *((int *)((caddr_t)(&cp->user) + xaddr));
258 (void) mutex_unlock(&pt_lock);
259 return (data);
260 }
261 goto eio;
262
263 case 4: /* PTRACE_POKETEXT */
264 case 5: /* PTRACE_POKEDATA */
265 if (addr & 03)
266 goto eio;
267 xaddr = addr;
268 if (xaddr >= (unsigned)cp->user.u_reg[REG_SP] &&
269 xaddr < (unsigned)cp->user.u_reg[REG_SP]+16*sizeof (int))
270 cp->flags |= CS_SETREGS;
271 if (pwrite(cp->asfd, (char *)&data, sizeof (data), (off_t)addr)
272 == sizeof (data)) {
273 (void) mutex_unlock(&pt_lock);
274 return (data);
275 }
276 goto eio;
277
278 case 6: /* PTRACE_POKEUSER */
279 if (addr & 03)
280 goto eio;
281 xaddr = addr;
282 if (xaddr >= REGADDR && xaddr < REGADDR+sizeof (gregset_t))
283 xaddr -= REGADDR-U_REG;
284 if ((int)xaddr >= U_REG && xaddr < U_REG+sizeof (gregset_t)) {
285 int rx = (xaddr-U_REG)/sizeof (greg_t);
286 if (rx == REG_PS)
287 data = (cp->user.u_reg[REG_PS] &
288 ~PSL_USERMASK) | (data & PSL_USERMASK);
289 else if (rx == REG_SP || rx == REG_PC || rx == REG_nPC)
290 data &= ~03;
291 cp->user.u_reg[rx] = data;
292 cp->flags |= CS_SETREGS;
293 (void) mutex_unlock(&pt_lock);
294 return (data);
295 }
296 goto eio;
297
298 case 7: /* PTRACE_CONT */
299 case 9: /* PTRACE_SINGLESTEP */
300 {
301 long runctl[3];
302
303 if (cp->flags & CS_SETREGS) {
304 long cmd;
305 iovec_t iov[2];
306
307 ps->pr_lwp.pr_reg[R_PSR] = cp->user.u_reg[REG_PSR];
308 ps->pr_lwp.pr_reg[R_PC] = cp->user.u_reg[REG_PC];
309 ps->pr_lwp.pr_reg[R_nPC] = cp->user.u_reg[REG_nPC];
310 ps->pr_lwp.pr_reg[R_Y] = cp->user.u_reg[REG_Y];
311 ps->pr_lwp.pr_reg[R_G1] = cp->user.u_reg[REG_G1];
312 ps->pr_lwp.pr_reg[R_G2] = cp->user.u_reg[REG_G2];
313 ps->pr_lwp.pr_reg[R_G3] = cp->user.u_reg[REG_G3];
314 ps->pr_lwp.pr_reg[R_G4] = cp->user.u_reg[REG_G4];
315 ps->pr_lwp.pr_reg[R_G5] = cp->user.u_reg[REG_G5];
316 ps->pr_lwp.pr_reg[R_G6] = cp->user.u_reg[REG_G6];
317 ps->pr_lwp.pr_reg[R_G7] = cp->user.u_reg[REG_G7];
318 ps->pr_lwp.pr_reg[R_O0] = cp->user.u_reg[REG_O0];
319 ps->pr_lwp.pr_reg[R_O1] = cp->user.u_reg[REG_O1];
320 ps->pr_lwp.pr_reg[R_O2] = cp->user.u_reg[REG_O2];
321 ps->pr_lwp.pr_reg[R_O3] = cp->user.u_reg[REG_O3];
322 ps->pr_lwp.pr_reg[R_O4] = cp->user.u_reg[REG_O4];
323 ps->pr_lwp.pr_reg[R_O5] = cp->user.u_reg[REG_O5];
324 ps->pr_lwp.pr_reg[R_O6] = cp->user.u_reg[REG_O6];
325 ps->pr_lwp.pr_reg[R_O7] = cp->user.u_reg[REG_O7];
326 (void) pread(cp->asfd, (char *)&ps->pr_lwp.pr_reg[R_L0],
327 16*sizeof (int), (off_t)cp->user.u_reg[REG_SP]);
328 cmd = PCSREG;
329 iov[0].iov_base = (caddr_t)&cmd;
330 iov[0].iov_len = sizeof (long);
331 iov[1].iov_base = (caddr_t)&ps->pr_lwp.pr_reg[0];
332 iov[1].iov_len = sizeof (ps->pr_lwp.pr_reg);
333 if (writev(cp->ctlfd, iov, 2) < 0)
334 goto tryagain;
335 }
336 if (addr != 1 && /* new virtual address */
337 (addr & ~03) != cp->user.u_reg[REG_PC]) {
338 runctl[0] = PCSVADDR;
339 runctl[1] = (addr & ~03);
340 if (write(cp->ctlfd, (char *)runctl, 2*sizeof (long))
341 != 2*sizeof (long))
342 goto tryagain;
343 }
344 /* make data the current signal */
345 if (data != 0 && data != ps->pr_lwp.pr_cursig) {
346 (void) memset((char *)&ctl.arg.siginfo, 0,
347 sizeof (siginfo_t));
348 ctl.arg.siginfo.si_signo = data;
349 ctl.cmd = PCSSIG;
350 if (write(cp->ctlfd, (char *)&ctl,
351 sizeof (long)+sizeof (siginfo_t))
352 != sizeof (long)+sizeof (siginfo_t))
353 goto tryagain;
354 }
355 if (data == 0)
356 runctl[0] = PCCSIG;
357 else
358 runctl[0] = PCNULL;
359 runctl[1] = PCRUN;
360 runctl[2] = (request == 9)? PRSTEP : 0;
361 if (write(cp->ctlfd, (char *)runctl, 3*sizeof (long))
362 != 3*sizeof (long)) {
363 if (errno == ENOENT) {
364 /* current signal must have killed it */
365 ReleaseProc(cp);
366 (void) mutex_unlock(&pt_lock);
367 return (data);
368 }
369 goto tryagain;
370 }
371 (void) memset((char *)ps, 0, sizeof (pstatus_t));
372 cp->flags = 0;
373 (void) mutex_unlock(&pt_lock);
374 return (data);
375 }
376
377 case 8: /* PTRACE_KILL */
378 /* overkill? */
379 (void) memset((char *)&ctl.arg.siginfo, 0, sizeof (siginfo_t));
380 ctl.arg.siginfo.si_signo = SIGKILL;
381 ctl.cmd = PCSSIG;
382 (void) write(cp->ctlfd, (char *)&ctl,
383 sizeof (long)+sizeof (siginfo_t));
384 (void) kill(pid, SIGKILL);
385 ReleaseProc(cp);
386 (void) mutex_unlock(&pt_lock);
387 return (0);
388
389 default:
390 goto eio;
391 }
392
393 tryagain:
394 if (errno == EAGAIN) {
395 if (OpenProc(cp) == 0)
396 goto again;
397 ReleaseProc(cp);
398 }
399 eio:
400 errno = EIO;
401 (void) mutex_unlock(&pt_lock);
402 return (-1);
403 esrch:
404 errno = ESRCH;
405 (void) mutex_unlock(&pt_lock);
406 return (-1);
407 }
408
409 /*
410 * Find the cstatus structure corresponding to pid.
411 */
412 static cstatus_t *
FindProc(pid_t pid)413 FindProc(pid_t pid)
414 {
415 cstatus_t *cp;
416
417 for (cp = childp; cp != NULLCP; cp = cp->next)
418 if (cp->pid == pid)
419 break;
420
421 return (cp);
422 }
423
424 /*
425 * Check every proc for existence, release those that are gone.
426 * Be careful about the linked list; ReleaseProc() changes it.
427 */
428 static void
CheckAllProcs()429 CheckAllProcs()
430 {
431 cstatus_t *cp = childp;
432
433 while (cp != NULLCP) {
434 cstatus_t *next = cp->next;
435
436 if (ProcUpdate(cp) != 0)
437 ReleaseProc(cp);
438 cp = next;
439 }
440 }
441
442 /*
443 * Utility for OpenProc().
444 */
445 static int
Dupfd(int fd,int dfd)446 Dupfd(int fd, int dfd)
447 {
448 /*
449 * Make sure fd not one of 0, 1, or 2 to avoid stdio interference.
450 * Also, if dfd is greater than 2, dup fd to be exactly dfd.
451 */
452 if (dfd > 2 || (0 <= fd && fd <= 2)) {
453 if (dfd > 2 && fd != dfd)
454 (void) close(dfd);
455 else
456 dfd = 3;
457 if (fd != dfd) {
458 dfd = fcntl(fd, F_DUPFD, (intptr_t)dfd);
459 (void) close(fd);
460 fd = dfd;
461 }
462 }
463 /*
464 * Mark filedescriptor close-on-exec.
465 * Should also be close-on-return-from-fork-in-child.
466 */
467 (void) fcntl(fd, F_SETFD, (intptr_t)1);
468 return (fd);
469 }
470
471 /*
472 * Construct the /proc directory name: "/proc/<pid>"
473 * The name buffer passed by the caller must be large enough.
474 */
475 static void
MakeProcName(char * procname,pid_t pid)476 MakeProcName(char *procname, pid_t pid)
477 {
478 (void) sprintf(procname, "/proc/%d", (int)pid);
479 }
480
481 /*
482 * Open/reopen the /proc/<pid> files.
483 */
484 static int
OpenProc(cstatus_t * cp)485 OpenProc(cstatus_t *cp)
486 {
487 char procname[64]; /* /proc/nnnnn/fname */
488 char *fname;
489 int fd;
490 int omode;
491
492 MakeProcName(procname, cp->pid);
493 fname = procname + strlen(procname);
494
495 /*
496 * Use exclusive-open only if this is the first open.
497 */
498 omode = (cp->asfd > 0)? O_RDWR : (O_RDWR|O_EXCL);
499 (void) strcpy(fname, "/as");
500 if ((fd = open(procname, omode, 0)) < 0 ||
501 (cp->asfd = Dupfd(fd, cp->asfd)) < 0)
502 goto err;
503
504 (void) strcpy(fname, "/ctl");
505 if ((fd = open(procname, O_WRONLY, 0)) < 0 ||
506 (cp->ctlfd = Dupfd(fd, cp->ctlfd)) < 0)
507 goto err;
508
509 (void) strcpy(fname, "/status");
510 if ((fd = open(procname, O_RDONLY, 0)) < 0 ||
511 (cp->statusfd = Dupfd(fd, cp->statusfd)) < 0)
512 goto err;
513
514 return (0);
515
516 err:
517 CloseProc(cp);
518 return (-1);
519 }
520
521 /*
522 * Close the /proc/<pid> files.
523 */
524 static void
CloseProc(cstatus_t * cp)525 CloseProc(cstatus_t *cp)
526 {
527 if (cp->asfd > 0)
528 (void) close(cp->asfd);
529 if (cp->ctlfd > 0)
530 (void) close(cp->ctlfd);
531 if (cp->statusfd > 0)
532 (void) close(cp->statusfd);
533 cp->asfd = 0;
534 cp->ctlfd = 0;
535 cp->statusfd = 0;
536 }
537
538 /*
539 * Take control of a child process.
540 */
541 static cstatus_t *
GrabProc(pid_t pid)542 GrabProc(pid_t pid)
543 {
544 cstatus_t *cp;
545 long ctl[2];
546 pid_t ppid;
547
548 if (pid <= 0)
549 return (NULLCP);
550
551 if ((cp = FindProc(pid)) != NULLCP) /* already grabbed */
552 return (cp);
553
554 CheckAllProcs(); /* clean up before grabbing new process */
555
556 cp = (cstatus_t *)malloc(sizeof (cstatus_t));
557 if (cp == NULLCP)
558 return (NULLCP);
559 (void) memset((char *)cp, 0, sizeof (cstatus_t));
560 cp->pid = pid;
561
562 ppid = getpid();
563 while (OpenProc(cp) == 0) {
564 ctl[0] = PCSET;
565 ctl[1] = PR_RLC;
566 errno = 0;
567
568 if (pread(cp->statusfd, (char *)&cp->pstatus,
569 sizeof (cp->pstatus), (off_t)0) == sizeof (cp->pstatus) &&
570 cp->pstatus.pr_ppid == ppid &&
571 (cp->pstatus.pr_flags & PR_PTRACE) &&
572 write(cp->ctlfd, (char *)ctl, 2*sizeof (long))
573 == 2*sizeof (long)) {
574 cp->next = childp;
575 childp = cp;
576 MakeUser(cp);
577 return (cp);
578 }
579
580 if (errno != EAGAIN)
581 break;
582 }
583
584 free((char *)cp);
585 return (NULLCP);
586 }
587
588 /*
589 * Close the /proc/<pid> file, if open.
590 * Deallocate the memory used by the cstatus_t structure.
591 */
592 static void
ReleaseProc(cstatus_t * cp)593 ReleaseProc(cstatus_t *cp)
594 {
595 CloseProc(cp);
596
597 if (childp == cp)
598 childp = cp->next;
599 else {
600 cstatus_t *pcp;
601
602 for (pcp = childp; pcp != NULLCP; pcp = pcp->next) {
603 if (pcp->next == cp) {
604 pcp->next = cp->next;
605 break;
606 }
607 }
608 }
609
610 free((char *)cp);
611 }
612
613 /*
614 * Update process information from /proc.
615 * Return 0 on success, -1 on failure.
616 */
617 static int
ProcUpdate(cstatus_t * cp)618 ProcUpdate(cstatus_t *cp)
619 {
620 pstatus_t *ps = &cp->pstatus;
621
622 if (cp->flags & CS_SETREGS) {
623 long cmd;
624 iovec_t iov[2];
625
626 ps->pr_lwp.pr_reg[R_PSR] = cp->user.u_reg[REG_PSR];
627 ps->pr_lwp.pr_reg[R_PC] = cp->user.u_reg[REG_PC];
628 ps->pr_lwp.pr_reg[R_nPC] = cp->user.u_reg[REG_nPC];
629 ps->pr_lwp.pr_reg[R_Y] = cp->user.u_reg[REG_Y];
630 ps->pr_lwp.pr_reg[R_G1] = cp->user.u_reg[REG_G1];
631 ps->pr_lwp.pr_reg[R_G2] = cp->user.u_reg[REG_G2];
632 ps->pr_lwp.pr_reg[R_G3] = cp->user.u_reg[REG_G3];
633 ps->pr_lwp.pr_reg[R_G4] = cp->user.u_reg[REG_G4];
634 ps->pr_lwp.pr_reg[R_G5] = cp->user.u_reg[REG_G5];
635 ps->pr_lwp.pr_reg[R_G6] = cp->user.u_reg[REG_G6];
636 ps->pr_lwp.pr_reg[R_G7] = cp->user.u_reg[REG_G7];
637 ps->pr_lwp.pr_reg[R_O0] = cp->user.u_reg[REG_O0];
638 ps->pr_lwp.pr_reg[R_O1] = cp->user.u_reg[REG_O1];
639 ps->pr_lwp.pr_reg[R_O2] = cp->user.u_reg[REG_O2];
640 ps->pr_lwp.pr_reg[R_O3] = cp->user.u_reg[REG_O3];
641 ps->pr_lwp.pr_reg[R_O4] = cp->user.u_reg[REG_O4];
642 ps->pr_lwp.pr_reg[R_O5] = cp->user.u_reg[REG_O5];
643 ps->pr_lwp.pr_reg[R_O6] = cp->user.u_reg[REG_O6];
644 ps->pr_lwp.pr_reg[R_O7] = cp->user.u_reg[REG_O7];
645 (void) pread(cp->asfd, (char *)&ps->pr_lwp.pr_reg[R_L0],
646 16*sizeof (int), (off_t)cp->user.u_reg[REG_SP]);
647 cmd = PCSREG;
648 iov[0].iov_base = (caddr_t)&cmd;
649 iov[0].iov_len = sizeof (long);
650 iov[1].iov_base = (caddr_t)&ps->pr_lwp.pr_reg[0];
651 iov[1].iov_len = sizeof (ps->pr_lwp.pr_reg);
652 (void) writev(cp->ctlfd, iov, 2);
653 cp->flags &= ~CS_SETREGS;
654 }
655
656 while (pread(cp->statusfd, (char *)ps, sizeof (*ps), (off_t)0) < 0) {
657 /* attempt to regain control */
658 if (errno != EINTR &&
659 !(errno == EAGAIN && OpenProc(cp) == 0))
660 return (-1);
661 }
662
663 if (ps->pr_flags & PR_ISTOP)
664 MakeUser(cp);
665 else
666 (void) memset((char *)ps, 0, sizeof (pstatus_t));
667
668 return (0);
669 }
670
671 /*
672 * Manufacture the contents of the fake u-block.
673 */
674 static void
MakeUser(cstatus_t * cp)675 MakeUser(cstatus_t *cp)
676 {
677 pstatus_t *ps = &cp->pstatus;
678
679 cp->user.u_reg[REG_PSR] = ps->pr_lwp.pr_reg[R_PSR];
680 cp->user.u_reg[REG_PC] = ps->pr_lwp.pr_reg[R_PC];
681 cp->user.u_reg[REG_nPC] = ps->pr_lwp.pr_reg[R_nPC];
682 cp->user.u_reg[REG_Y] = ps->pr_lwp.pr_reg[R_Y];
683 cp->user.u_reg[REG_G1] = ps->pr_lwp.pr_reg[R_G1];
684 cp->user.u_reg[REG_G2] = ps->pr_lwp.pr_reg[R_G2];
685 cp->user.u_reg[REG_G3] = ps->pr_lwp.pr_reg[R_G3];
686 cp->user.u_reg[REG_G4] = ps->pr_lwp.pr_reg[R_G4];
687 cp->user.u_reg[REG_G5] = ps->pr_lwp.pr_reg[R_G5];
688 cp->user.u_reg[REG_G6] = ps->pr_lwp.pr_reg[R_G6];
689 cp->user.u_reg[REG_G7] = ps->pr_lwp.pr_reg[R_G7];
690 cp->user.u_reg[REG_O0] = ps->pr_lwp.pr_reg[R_O0];
691 cp->user.u_reg[REG_O1] = ps->pr_lwp.pr_reg[R_O1];
692 cp->user.u_reg[REG_O2] = ps->pr_lwp.pr_reg[R_O2];
693 cp->user.u_reg[REG_O3] = ps->pr_lwp.pr_reg[R_O3];
694 cp->user.u_reg[REG_O4] = ps->pr_lwp.pr_reg[R_O4];
695 cp->user.u_reg[REG_O5] = ps->pr_lwp.pr_reg[R_O5];
696 cp->user.u_reg[REG_O6] = ps->pr_lwp.pr_reg[R_O6];
697 cp->user.u_reg[REG_O7] = ps->pr_lwp.pr_reg[R_O7];
698 cp->user.u_ar0 = (greg_t *)REGADDR;
699 cp->user.u_code = ps->pr_lwp.pr_info.si_code;
700 cp->user.u_addr = ps->pr_lwp.pr_info.si_addr;
701 cp->flags &= ~(CS_PSARGS|CS_SIGNAL);
702 }
703
704 /*
705 * Fetch the contents of u_psargs[].
706 */
707 static void
GetPsargs(cstatus_t * cp)708 GetPsargs(cstatus_t *cp)
709 {
710 char procname[64]; /* /proc/<pid>/psinfo */
711 int fd;
712
713 MakeProcName(procname, cp->pid);
714 (void) strcat(procname, "/psinfo");
715 if ((fd = open(procname, O_RDONLY, 0)) < 0) {
716 (void) memset(cp->user.u_psargs, 0, PSARGSZ);
717 return;
718 }
719 (void) pread(fd, cp->user.u_psargs, PSARGSZ,
720 (off_t)((psinfo_t *)0)->pr_psargs);
721 (void) close(fd);
722
723 cp->flags |= CS_PSARGS;
724 }
725
726 /*
727 * Fetch the contents of u_signal[].
728 */
729 static void
GetSignal(cstatus_t * cp)730 GetSignal(cstatus_t *cp)
731 {
732 char procname[64]; /* /proc/<pid>/sigact */
733 int fd;
734 struct sigaction action[MAXSIG];
735 int i;
736
737 MakeProcName(procname, cp->pid);
738 (void) strcat(procname, "/sigact");
739 (void) memset((char *)action, 0, sizeof (action));
740 if ((fd = open(procname, O_RDONLY, 0)) >= 0) {
741 (void) read(fd, (char *)action, sizeof (action));
742 (void) close(fd);
743 }
744 for (i = 0; i < MAXSIG; i++)
745 cp->user.u_signal[i] = action[i].sa_handler;
746 cp->flags |= CS_SIGNAL;
747 }
748