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 * 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 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 * 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 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 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 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 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 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 * 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 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 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 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 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 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