feature_tests.h: always use largefile interfaces
[unleashed/lotheac.git] / usr / src / lib / libc / i386 / sys / ptrace.c
blob5ca6bcceba634fa45e6b57a45db3b8d525cc2ed6
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * ptrace(2) interface built on top of proc(4).
31 #pragma ident "%Z%%M% %I% %E% SMI"
33 #pragma weak _ptrace = ptrace
35 #include "lint.h"
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <memory.h>
40 #include <string.h>
41 #include <fcntl.h>
42 #include <errno.h>
43 #include <sys/types.h>
44 #include <sys/uio.h>
45 #include <signal.h>
46 #include <sys/siginfo.h>
47 #include <sys/fault.h>
48 #include <sys/syscall.h>
49 #include <procfs.h>
50 #include <sys/psw.h>
51 #include <sys/user.h>
53 * mtlib.h must precede thread.h
55 #include <mtlib.h>
56 #include <thread.h>
57 #include <synch.h>
59 static mutex_t pt_lock = DEFAULTMUTEX;
61 #define TRUE 1
62 #define FALSE 0
65 * All my children...
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;
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 */
83 #define NULLCP ((cstatus_t *)0)
85 static cstatus_t *childp = NULLCP;
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 */
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 *);
114 #if PTRACE_DEBUG
115 /* for debugging */
116 static char *
117 map(int request)
119 static char name[20];
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");
133 (void) sprintf(name, "%d", request);
134 return (name);
136 #endif
139 ptrace(int request, pid_t pid, int addr, int data)
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;
155 #if PTRACE_DEBUG
156 fprintf(stderr, " ptrace(%s, 0x%X, 0x%X, 0x%X)\n",
157 map(request), pid, addr, data);
158 #endif
160 (void) mutex_lock(&pt_lock);
162 if (request == 0) { /* PTRACE_TRACEME, executed by traced process */
164 * Set stop-on-all-signals and nothing else.
165 * Turn off inherit-on-fork flag (grandchildren run away).
166 * Set ptrace-compatible flag.
168 char procname[64]; /* /proc/<pid>/ctl */
169 int fd;
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);
208 (void) mutex_unlock(&pt_lock);
209 return (0);
212 again:
213 errno = 0;
215 /* find the cstatus structure corresponding to pid */
216 if ((cp = GrabProc(pid)) == NULLCP)
217 goto esrch;
219 ps = &cp->pstatus;
220 if (!(ps->pr_flags & PR_ISTOP)) {
221 if (ProcUpdate(cp) != 0) {
222 ReleaseProc(cp);
223 goto esrch;
225 if (!(ps->pr_flags & PR_ISTOP))
226 goto esrch;
230 * Process the request.
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);
243 goto eio;
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);
261 goto eio;
263 case 4: /* PTRACE_POKETEXT */
264 case 5: /* PTRACE_POKEDATA */
265 if (addr & 03)
266 goto eio;
267 if (pwrite(cp->asfd, (char *)&data, sizeof (data), (off_t)addr)
268 == sizeof (data)) {
269 (void) mutex_unlock(&pt_lock);
270 return (data);
272 goto eio;
274 case 6: /* PTRACE_POKEUSER */
275 if (addr & 03)
276 goto eio;
277 xaddr = addr;
278 if (xaddr >= REGADDR && xaddr < REGADDR+sizeof (gregset_t))
279 xaddr -= REGADDR-U_REG;
280 if ((int)xaddr >= U_REG && xaddr < U_REG+sizeof (gregset_t)) {
281 int rx = (xaddr-U_REG)/sizeof (greg_t);
282 if (rx == EFL)
283 data = (cp->user.u_reg[EFL] & ~PSL_USERMASK) |
284 (data & PSL_USERMASK);
285 cp->user.u_reg[rx] = data;
286 cp->flags |= CS_SETREGS;
287 (void) mutex_unlock(&pt_lock);
288 return (data);
290 goto eio;
292 case 7: /* PTRACE_CONT */
293 case 9: /* PTRACE_SINGLESTEP */
295 long runctl[3];
297 if (cp->flags & CS_SETREGS) {
298 long cmd;
299 iovec_t iov[2];
301 ps->pr_lwp.pr_reg[GS] = cp->user.u_reg[GS];
302 ps->pr_lwp.pr_reg[FS] = cp->user.u_reg[FS];
303 ps->pr_lwp.pr_reg[ES] = cp->user.u_reg[ES];
304 ps->pr_lwp.pr_reg[DS] = cp->user.u_reg[DS];
305 ps->pr_lwp.pr_reg[EDI] = cp->user.u_reg[EDI];
306 ps->pr_lwp.pr_reg[ESI] = cp->user.u_reg[ESI];
307 ps->pr_lwp.pr_reg[EBP] = cp->user.u_reg[EBP];
308 ps->pr_lwp.pr_reg[ESP] = cp->user.u_reg[ESP];
309 ps->pr_lwp.pr_reg[EBX] = cp->user.u_reg[EBX];
310 ps->pr_lwp.pr_reg[EDX] = cp->user.u_reg[EDX];
311 ps->pr_lwp.pr_reg[ECX] = cp->user.u_reg[ECX];
312 ps->pr_lwp.pr_reg[EAX] = cp->user.u_reg[EAX];
313 ps->pr_lwp.pr_reg[TRAPNO] = cp->user.u_reg[TRAPNO];
314 ps->pr_lwp.pr_reg[ERR] = cp->user.u_reg[ERR];
315 ps->pr_lwp.pr_reg[EIP] = cp->user.u_reg[EIP];
316 ps->pr_lwp.pr_reg[CS] = cp->user.u_reg[CS];
317 ps->pr_lwp.pr_reg[EFL] = cp->user.u_reg[EFL];
318 ps->pr_lwp.pr_reg[UESP] = cp->user.u_reg[UESP];
319 ps->pr_lwp.pr_reg[SS] = cp->user.u_reg[SS];
320 cmd = PCSREG;
321 iov[0].iov_base = (caddr_t)&cmd;
322 iov[0].iov_len = sizeof (long);
323 iov[1].iov_base = (caddr_t)&ps->pr_lwp.pr_reg[0];
324 iov[1].iov_len = sizeof (ps->pr_lwp.pr_reg);
325 if (writev(cp->ctlfd, iov, 2) < 0)
326 goto tryagain;
328 if (addr != 1 && /* new virtual address */
329 addr != cp->user.u_reg[EIP]) {
330 runctl[0] = PCSVADDR;
331 runctl[1] = addr;
332 if (write(cp->ctlfd, (char *)runctl, 2*sizeof (long))
333 != 2*sizeof (long))
334 goto tryagain;
336 /* make data the current signal */
337 if (data != 0 && data != ps->pr_lwp.pr_cursig) {
338 (void) memset((char *)&ctl.arg.siginfo, 0,
339 sizeof (siginfo_t));
340 ctl.arg.siginfo.si_signo = data;
341 ctl.cmd = PCSSIG;
342 if (write(cp->ctlfd, (char *)&ctl,
343 sizeof (long)+sizeof (siginfo_t))
344 != sizeof (long)+sizeof (siginfo_t))
345 goto tryagain;
347 if (data == 0)
348 runctl[0] = PCCSIG;
349 else
350 runctl[0] = PCNULL;
351 runctl[1] = PCRUN;
352 runctl[2] = (request == 9)? PRSTEP : 0;
353 if (write(cp->ctlfd, (char *)runctl, 3*sizeof (long))
354 != 3*sizeof (long)) {
355 if (errno == ENOENT) {
356 /* current signal must have killed it */
357 ReleaseProc(cp);
358 (void) mutex_unlock(&pt_lock);
359 return (data);
361 goto tryagain;
363 (void) memset((char *)ps, 0, sizeof (pstatus_t));
364 cp->flags = 0;
365 (void) mutex_unlock(&pt_lock);
366 return (data);
369 case 8: /* PTRACE_KILL */
370 /* overkill? */
371 (void) memset((char *)&ctl.arg.siginfo, 0, sizeof (siginfo_t));
372 ctl.arg.siginfo.si_signo = SIGKILL;
373 ctl.cmd = PCSSIG;
374 (void) write(cp->ctlfd, (char *)&ctl,
375 sizeof (long)+sizeof (siginfo_t));
376 (void) kill(pid, SIGKILL);
377 ReleaseProc(cp);
378 (void) mutex_unlock(&pt_lock);
379 return (0);
381 default:
382 goto eio;
385 tryagain:
386 if (errno == EAGAIN) {
387 if (OpenProc(cp) == 0)
388 goto again;
389 ReleaseProc(cp);
391 eio:
392 errno = EIO;
393 (void) mutex_unlock(&pt_lock);
394 return (-1);
395 esrch:
396 errno = ESRCH;
397 (void) mutex_unlock(&pt_lock);
398 return (-1);
402 * Find the cstatus structure corresponding to pid.
404 static cstatus_t *
405 FindProc(pid_t pid)
407 cstatus_t *cp;
409 for (cp = childp; cp != NULLCP; cp = cp->next)
410 if (cp->pid == pid)
411 break;
413 return (cp);
417 * Check every proc for existence, release those that are gone.
418 * Be careful about the linked list; ReleaseProc() changes it.
420 static void
421 CheckAllProcs()
423 cstatus_t *cp = childp;
425 while (cp != NULLCP) {
426 cstatus_t *next = cp->next;
428 if (ProcUpdate(cp) != 0)
429 ReleaseProc(cp);
430 cp = next;
435 * Utility for OpenProc().
437 static int
438 Dupfd(int fd, int dfd)
441 * Make sure fd not one of 0, 1, or 2 to avoid stdio interference.
442 * Also, if dfd is greater than 2, dup fd to be exactly dfd.
444 if (dfd > 2 || (0 <= fd && fd <= 2)) {
445 if (dfd > 2 && fd != dfd)
446 (void) close(dfd);
447 else
448 dfd = 3;
449 if (fd != dfd) {
450 dfd = fcntl(fd, F_DUPFD, (intptr_t)dfd);
451 (void) close(fd);
452 fd = dfd;
456 * Mark filedescriptor close-on-exec.
457 * Should also be close-on-return-from-fork-in-child.
459 (void) fcntl(fd, F_SETFD, (intptr_t)1);
460 return (fd);
464 * Construct the /proc directory name: "/proc/<pid>"
465 * The name buffer passed by the caller must be large enough.
467 static void
468 MakeProcName(char *procname, pid_t pid)
470 (void) sprintf(procname, "/proc/%ld", pid);
474 * Open/reopen the /proc/<pid> files.
476 static int
477 OpenProc(cstatus_t *cp)
479 char procname[64]; /* /proc/nnnnn/fname */
480 char *fname;
481 int fd;
482 int omode;
484 MakeProcName(procname, cp->pid);
485 fname = procname + strlen(procname);
488 * Use exclusive-open only if this is the first open.
490 omode = (cp->asfd > 0)? O_RDWR : (O_RDWR|O_EXCL);
491 (void) strcpy(fname, "/as");
492 if ((fd = open(procname, omode, 0)) < 0 ||
493 (cp->asfd = Dupfd(fd, cp->asfd)) < 0)
494 goto err;
496 (void) strcpy(fname, "/ctl");
497 if ((fd = open(procname, O_WRONLY, 0)) < 0 ||
498 (cp->ctlfd = Dupfd(fd, cp->ctlfd)) < 0)
499 goto err;
501 (void) strcpy(fname, "/status");
502 if ((fd = open(procname, O_RDONLY, 0)) < 0 ||
503 (cp->statusfd = Dupfd(fd, cp->statusfd)) < 0)
504 goto err;
506 return (0);
508 err:
509 CloseProc(cp);
510 return (-1);
514 * Close the /proc/<pid> files.
516 static void
517 CloseProc(cstatus_t *cp)
519 if (cp->asfd > 0)
520 (void) close(cp->asfd);
521 if (cp->ctlfd > 0)
522 (void) close(cp->ctlfd);
523 if (cp->statusfd > 0)
524 (void) close(cp->statusfd);
525 cp->asfd = 0;
526 cp->ctlfd = 0;
527 cp->statusfd = 0;
531 * Take control of a child process.
533 static cstatus_t *
534 GrabProc(pid_t pid)
536 cstatus_t *cp;
537 long ctl[2];
538 pid_t ppid;
540 if (pid <= 0)
541 return (NULLCP);
543 if ((cp = FindProc(pid)) != NULLCP) /* already grabbed */
544 return (cp);
546 CheckAllProcs(); /* clean up before grabbing new process */
548 cp = (cstatus_t *)malloc(sizeof (cstatus_t));
549 if (cp == NULLCP)
550 return (NULLCP);
551 (void) memset((char *)cp, 0, sizeof (cstatus_t));
552 cp->pid = pid;
554 ppid = getpid();
555 while (OpenProc(cp) == 0) {
556 ctl[0] = PCSET;
557 ctl[1] = PR_RLC;
558 errno = 0;
560 if (pread(cp->statusfd, (char *)&cp->pstatus,
561 sizeof (cp->pstatus), (off_t)0) == sizeof (cp->pstatus) &&
562 cp->pstatus.pr_ppid == ppid &&
563 (cp->pstatus.pr_flags & PR_PTRACE) &&
564 write(cp->ctlfd, (char *)ctl, 2*sizeof (long))
565 == 2*sizeof (long)) {
566 cp->next = childp;
567 childp = cp;
568 MakeUser(cp);
569 return (cp);
572 if (errno != EAGAIN)
573 break;
576 free((char *)cp);
577 return (NULLCP);
581 * Close the /proc/<pid> file, if open.
582 * Deallocate the memory used by the cstatus_t structure.
584 static void
585 ReleaseProc(cstatus_t *cp)
587 CloseProc(cp);
589 if (childp == cp)
590 childp = cp->next;
591 else {
592 cstatus_t *pcp;
594 for (pcp = childp; pcp != NULLCP; pcp = pcp->next) {
595 if (pcp->next == cp) {
596 pcp->next = cp->next;
597 break;
602 free((char *)cp);
606 * Update process information from /proc.
607 * Return 0 on success, -1 on failure.
609 static int
610 ProcUpdate(cstatus_t *cp)
612 pstatus_t *ps = &cp->pstatus;
614 if (cp->flags & CS_SETREGS) {
615 long cmd;
616 iovec_t iov[2];
618 ps->pr_lwp.pr_reg[GS] = cp->user.u_reg[GS];
619 ps->pr_lwp.pr_reg[FS] = cp->user.u_reg[FS];
620 ps->pr_lwp.pr_reg[ES] = cp->user.u_reg[ES];
621 ps->pr_lwp.pr_reg[DS] = cp->user.u_reg[DS];
622 ps->pr_lwp.pr_reg[EDI] = cp->user.u_reg[EDI];
623 ps->pr_lwp.pr_reg[ESI] = cp->user.u_reg[ESI];
624 ps->pr_lwp.pr_reg[EBP] = cp->user.u_reg[EBP];
625 ps->pr_lwp.pr_reg[ESP] = cp->user.u_reg[ESP];
626 ps->pr_lwp.pr_reg[EBX] = cp->user.u_reg[EBX];
627 ps->pr_lwp.pr_reg[EDX] = cp->user.u_reg[EDX];
628 ps->pr_lwp.pr_reg[ECX] = cp->user.u_reg[ECX];
629 ps->pr_lwp.pr_reg[EAX] = cp->user.u_reg[EAX];
630 ps->pr_lwp.pr_reg[TRAPNO] = cp->user.u_reg[TRAPNO];
631 ps->pr_lwp.pr_reg[ERR] = cp->user.u_reg[ERR];
632 ps->pr_lwp.pr_reg[EIP] = cp->user.u_reg[EIP];
633 ps->pr_lwp.pr_reg[CS] = cp->user.u_reg[CS];
634 ps->pr_lwp.pr_reg[EFL] = cp->user.u_reg[EFL];
635 ps->pr_lwp.pr_reg[UESP] = cp->user.u_reg[UESP];
636 ps->pr_lwp.pr_reg[SS] = cp->user.u_reg[SS];
637 cmd = PCSREG;
638 iov[0].iov_base = (caddr_t)&cmd;
639 iov[0].iov_len = sizeof (long);
640 iov[1].iov_base = (caddr_t)&ps->pr_lwp.pr_reg[0];
641 iov[1].iov_len = sizeof (ps->pr_lwp.pr_reg);
642 (void) writev(cp->ctlfd, iov, 2);
643 cp->flags &= ~CS_SETREGS;
646 while (pread(cp->statusfd, (char *)ps, sizeof (*ps), (off_t)0) < 0) {
647 /* attempt to regain control */
648 if (errno != EINTR &&
649 !(errno == EAGAIN && OpenProc(cp) == 0))
650 return (-1);
653 if (ps->pr_flags & PR_ISTOP)
654 MakeUser(cp);
655 else
656 (void) memset((char *)ps, 0, sizeof (pstatus_t));
658 return (0);
662 * Manufacture the contents of the fake u-block.
664 static void
665 MakeUser(cstatus_t *cp)
667 pstatus_t *ps = &cp->pstatus;
669 cp->user.u_reg[GS] = ps->pr_lwp.pr_reg[GS];
670 cp->user.u_reg[FS] = ps->pr_lwp.pr_reg[FS];
671 cp->user.u_reg[ES] = ps->pr_lwp.pr_reg[ES];
672 cp->user.u_reg[DS] = ps->pr_lwp.pr_reg[DS];
673 cp->user.u_reg[EDI] = ps->pr_lwp.pr_reg[EDI];
674 cp->user.u_reg[ESI] = ps->pr_lwp.pr_reg[ESI];
675 cp->user.u_reg[EBP] = ps->pr_lwp.pr_reg[EBP];
676 cp->user.u_reg[ESP] = ps->pr_lwp.pr_reg[ESP];
677 cp->user.u_reg[EBX] = ps->pr_lwp.pr_reg[EBX];
678 cp->user.u_reg[EDX] = ps->pr_lwp.pr_reg[EDX];
679 cp->user.u_reg[ECX] = ps->pr_lwp.pr_reg[ECX];
680 cp->user.u_reg[EAX] = ps->pr_lwp.pr_reg[EAX];
681 cp->user.u_reg[TRAPNO] = ps->pr_lwp.pr_reg[TRAPNO];
682 cp->user.u_reg[ERR] = ps->pr_lwp.pr_reg[ERR];
683 cp->user.u_reg[EIP] = ps->pr_lwp.pr_reg[EIP];
684 cp->user.u_reg[CS] = ps->pr_lwp.pr_reg[CS];
685 cp->user.u_reg[EFL] = ps->pr_lwp.pr_reg[EFL];
686 cp->user.u_reg[UESP] = ps->pr_lwp.pr_reg[UESP];
687 cp->user.u_reg[SS] = ps->pr_lwp.pr_reg[SS];
688 cp->user.u_ar0 = (greg_t *)REGADDR;
689 cp->user.u_code = ps->pr_lwp.pr_info.si_code;
690 cp->user.u_addr = ps->pr_lwp.pr_info.si_addr;
691 cp->flags &= ~(CS_PSARGS|CS_SIGNAL);
695 * Fetch the contents of u_psargs[].
697 static void
698 GetPsargs(cstatus_t *cp)
700 char procname[64]; /* /proc/<pid>/psinfo */
701 int fd;
703 MakeProcName(procname, cp->pid);
704 (void) strcat(procname, "/psinfo");
705 if ((fd = open(procname, O_RDONLY, 0)) < 0) {
706 (void) memset(cp->user.u_psargs, 0, PSARGSZ);
707 return;
709 (void) pread(fd, cp->user.u_psargs, PSARGSZ,
710 (intptr_t)((psinfo_t *)0)->pr_psargs);
711 (void) close(fd);
713 cp->flags |= CS_PSARGS;
717 * Fetch the contents of u_signal[].
719 static void
720 GetSignal(cstatus_t *cp)
722 char procname[64]; /* /proc/<pid>/sigact */
723 int fd;
724 struct sigaction action[MAXSIG];
725 int i;
727 MakeProcName(procname, cp->pid);
728 (void) strcat(procname, "/sigact");
729 (void) memset((char *)action, 0, sizeof (action));
730 if ((fd = open(procname, O_RDONLY, 0)) >= 0) {
731 (void) read(fd, (char *)action, sizeof (action));
732 (void) close(fd);
734 for (i = 0; i < MAXSIG; i++)
735 cp->user.u_signal[i] = action[i].sa_handler;
736 cp->flags |= CS_SIGNAL;