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