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 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #pragma weak _ptrace = ptrace 34 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> 52 /* 53 * mtlib.h must precede thread.h 54 */ 55 #include <mtlib.h> 56 #include <thread.h> 57 #include <synch.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 * 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 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 if (pwrite(cp->asfd, (char *)&data, sizeof (data), (off_t)addr) 268 == sizeof (data)) { 269 (void) mutex_unlock(&pt_lock); 270 return (data); 271 } 272 goto eio; 273 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); 289 } 290 goto eio; 291 292 case 7: /* PTRACE_CONT */ 293 case 9: /* PTRACE_SINGLESTEP */ 294 { 295 long runctl[3]; 296 297 if (cp->flags & CS_SETREGS) { 298 long cmd; 299 iovec_t iov[2]; 300 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; 327 } 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; 335 } 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; 346 } 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); 360 } 361 goto tryagain; 362 } 363 (void) memset((char *)ps, 0, sizeof (pstatus_t)); 364 cp->flags = 0; 365 (void) mutex_unlock(&pt_lock); 366 return (data); 367 } 368 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); 380 381 default: 382 goto eio; 383 } 384 385 tryagain: 386 if (errno == EAGAIN) { 387 if (OpenProc(cp) == 0) 388 goto again; 389 ReleaseProc(cp); 390 } 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); 399 } 400 401 /* 402 * Find the cstatus structure corresponding to pid. 403 */ 404 static cstatus_t * 405 FindProc(pid_t pid) 406 { 407 cstatus_t *cp; 408 409 for (cp = childp; cp != NULLCP; cp = cp->next) 410 if (cp->pid == pid) 411 break; 412 413 return (cp); 414 } 415 416 /* 417 * Check every proc for existence, release those that are gone. 418 * Be careful about the linked list; ReleaseProc() changes it. 419 */ 420 static void 421 CheckAllProcs() 422 { 423 cstatus_t *cp = childp; 424 425 while (cp != NULLCP) { 426 cstatus_t *next = cp->next; 427 428 if (ProcUpdate(cp) != 0) 429 ReleaseProc(cp); 430 cp = next; 431 } 432 } 433 434 /* 435 * Utility for OpenProc(). 436 */ 437 static int 438 Dupfd(int fd, int dfd) 439 { 440 /* 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. 443 */ 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; 453 } 454 } 455 /* 456 * Mark filedescriptor close-on-exec. 457 * Should also be close-on-return-from-fork-in-child. 458 */ 459 (void) fcntl(fd, F_SETFD, (intptr_t)1); 460 return (fd); 461 } 462 463 /* 464 * Construct the /proc directory name: "/proc/<pid>" 465 * The name buffer passed by the caller must be large enough. 466 */ 467 static void 468 MakeProcName(char *procname, pid_t pid) 469 { 470 (void) sprintf(procname, "/proc/%d", pid); 471 } 472 473 /* 474 * Open/reopen the /proc/<pid> files. 475 */ 476 static int 477 OpenProc(cstatus_t *cp) 478 { 479 char procname[64]; /* /proc/nnnnn/fname */ 480 char *fname; 481 int fd; 482 int omode; 483 484 MakeProcName(procname, cp->pid); 485 fname = procname + strlen(procname); 486 487 /* 488 * Use exclusive-open only if this is the first open. 489 */ 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; 495 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; 500 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; 505 506 return (0); 507 508 err: 509 CloseProc(cp); 510 return (-1); 511 } 512 513 /* 514 * Close the /proc/<pid> files. 515 */ 516 static void 517 CloseProc(cstatus_t *cp) 518 { 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; 528 } 529 530 /* 531 * Take control of a child process. 532 */ 533 static cstatus_t * 534 GrabProc(pid_t pid) 535 { 536 cstatus_t *cp; 537 long ctl[2]; 538 pid_t ppid; 539 540 if (pid <= 0) 541 return (NULLCP); 542 543 if ((cp = FindProc(pid)) != NULLCP) /* already grabbed */ 544 return (cp); 545 546 CheckAllProcs(); /* clean up before grabbing new process */ 547 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; 553 554 ppid = getpid(); 555 while (OpenProc(cp) == 0) { 556 ctl[0] = PCSET; 557 ctl[1] = PR_RLC; 558 errno = 0; 559 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); 570 } 571 572 if (errno != EAGAIN) 573 break; 574 } 575 576 free((char *)cp); 577 return (NULLCP); 578 } 579 580 /* 581 * Close the /proc/<pid> file, if open. 582 * Deallocate the memory used by the cstatus_t structure. 583 */ 584 static void 585 ReleaseProc(cstatus_t *cp) 586 { 587 CloseProc(cp); 588 589 if (childp == cp) 590 childp = cp->next; 591 else { 592 cstatus_t *pcp; 593 594 for (pcp = childp; pcp != NULLCP; pcp = pcp->next) { 595 if (pcp->next == cp) { 596 pcp->next = cp->next; 597 break; 598 } 599 } 600 } 601 602 free((char *)cp); 603 } 604 605 /* 606 * Update process information from /proc. 607 * Return 0 on success, -1 on failure. 608 */ 609 static int 610 ProcUpdate(cstatus_t *cp) 611 { 612 pstatus_t *ps = &cp->pstatus; 613 614 if (cp->flags & CS_SETREGS) { 615 long cmd; 616 iovec_t iov[2]; 617 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; 644 } 645 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); 651 } 652 653 if (ps->pr_flags & PR_ISTOP) 654 MakeUser(cp); 655 else 656 (void) memset((char *)ps, 0, sizeof (pstatus_t)); 657 658 return (0); 659 } 660 661 /* 662 * Manufacture the contents of the fake u-block. 663 */ 664 static void 665 MakeUser(cstatus_t *cp) 666 { 667 pstatus_t *ps = &cp->pstatus; 668 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); 692 } 693 694 /* 695 * Fetch the contents of u_psargs[]. 696 */ 697 static void 698 GetPsargs(cstatus_t *cp) 699 { 700 char procname[64]; /* /proc/<pid>/psinfo */ 701 int fd; 702 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; 708 } 709 (void) pread(fd, cp->user.u_psargs, PSARGSZ, 710 (off_t)((psinfo_t *)0)->pr_psargs); 711 (void) close(fd); 712 713 cp->flags |= CS_PSARGS; 714 } 715 716 /* 717 * Fetch the contents of u_signal[]. 718 */ 719 static void 720 GetSignal(cstatus_t *cp) 721 { 722 char procname[64]; /* /proc/<pid>/sigact */ 723 int fd; 724 struct sigaction action[MAXSIG]; 725 int i; 726 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); 733 } 734 for (i = 0; i < MAXSIG; i++) 735 cp->user.u_signal[i] = action[i].sa_handler; 736 cp->flags |= CS_SIGNAL; 737 } 738