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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1994-1999 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file contains interfaces that are wrappers over the basic 31 * /proc ioctls 32 */ 33 34 #include <unistd.h> 35 #include <string.h> 36 #include <errno.h> 37 #include <fcntl.h> 38 #include <stdlib.h> 39 #include <stdio.h> 40 #include <sys/uio.h> 41 #include <sys/types.h> 42 #include <sys/param.h> 43 #include <sys/fault.h> 44 #include <sys/procfs.h> 45 46 #include "prb_proc_int.h" 47 #include "dbg.h" 48 49 /* 50 * Declarations 51 */ 52 53 #define PROCFORMAT "/proc/%d" 54 55 static prb_status_t 56 prb_proc_open_general(pid_t pid, prb_proc_ctl_t **proc_pp, int oflg); 57 58 /* 59 * prb_proc_open_general() - function to open the process file 60 * system entry for the supplied process. Opens with different 61 * options based on the 'oflg'. 62 * Returns a pointer to an opaque structure that contains the fd 63 * needed for /proc control. 64 */ 65 66 prb_status_t 67 prb_proc_open_general(pid_t pid, prb_proc_ctl_t **proc_pp, int oflg) 68 { 69 prb_proc_ctl_t *proc_p; 70 char path[MAXPATHLEN]; 71 int retval; 72 73 (void) sprintf(path, PROCFORMAT, (int)pid); 74 75 DBG_TNF_PROBE_1(prb_proc_open_1, "libtnfctl", "sunw%verbosity 2", 76 tnf_string, opening_proc_on, path); 77 78 retval = open(path, oflg); 79 if (retval == -1) { 80 DBG((void) fprintf(stderr, 81 "proc_open: open of \"%s\" failed: %s\n", 82 path, strerror(errno))); 83 return (prb_status_map(errno)); 84 } 85 /* allocate proc_p and zero fill */ 86 proc_p = calloc(1, sizeof (*proc_p)); 87 if (proc_p == NULL) 88 return (PRB_STATUS_ALLOCFAIL); 89 proc_p->procfd = retval; 90 proc_p->pid = pid; 91 *proc_pp = proc_p; 92 return (PRB_STATUS_OK); 93 } 94 95 96 /* 97 * prb_proc_open() - a wrapper which opens the process file system 98 * entry for the supplied process. Returns a pointer to an opaque 99 * structure that contains the fd needed for /proc control. 100 */ 101 102 prb_status_t 103 prb_proc_open(pid_t pid, prb_proc_ctl_t **proc_pp) 104 { 105 106 return (prb_proc_open_general(pid, 107 proc_pp, O_RDWR | O_EXCL)); 108 109 } 110 111 /* 112 * prb_proc_reopen() - re-opens the process, mainly for setuid/setgid files. 113 * Read the last section of /proc man page for details. 114 * re-open should not use O_EXCL flag. 115 */ 116 117 prb_status_t 118 prb_proc_reopen(pid_t pid, prb_proc_ctl_t **proc_pp) 119 { 120 121 return (prb_proc_open_general(pid, 122 proc_pp, O_RDWR)); 123 124 } 125 126 /* 127 * prob_proc_close() - close the proc fd and free the memory taken up 128 * by proc_p 129 */ 130 prb_status_t 131 prb_proc_close(prb_proc_ctl_t *proc_p) 132 { 133 DBG_TNF_PROBE_0(prb_proc_close_1, "libtnfctl", "sunw%verbosity 2"); 134 135 if (proc_p == NULL) 136 return (PRB_STATUS_OK); 137 138 if (close(proc_p->procfd) == -1) { 139 DBG((void) fprintf(stderr, 140 "proc_close: close failed: %s\n", strerror(errno))); 141 return (prb_status_map(errno)); 142 } 143 free(proc_p); 144 return (PRB_STATUS_OK); 145 } 146 147 /* 148 * prb_proc_pid_get() - gets the pid of the proc 149 */ 150 pid_t 151 prb_proc_pid_get(prb_proc_ctl_t *proc_p) 152 { 153 return (proc_p->pid); 154 } 155 156 /* 157 * prb_proc_stop() - stops the target process 158 */ 159 prb_status_t 160 prb_proc_stop(prb_proc_ctl_t *proc_p) 161 { 162 int retval; 163 164 DBG_TNF_PROBE_0(prb_proc_stop_1, "libtnfctl", 165 "sunw%verbosity 2; sunw%debug 'stopping the target process'"); 166 167 again: 168 retval = ioctl(proc_p->procfd, PIOCSTOP, NULL); 169 if (retval == -1) { 170 if (errno == EINTR) 171 goto again; 172 DBG((void) fprintf(stderr, 173 "prb_proc_stop: PIOCSTOP failed: %s\n", 174 strerror(errno))); 175 return (prb_status_map(errno)); 176 } 177 return (PRB_STATUS_OK); 178 } 179 180 181 /* 182 * prb_proc_prstop() - runs and stops the process, used to clear a target 183 * process out of a system call state. 184 */ 185 prb_status_t 186 prb_proc_prstop(prb_proc_ctl_t *proc_p) 187 { 188 int procfd; 189 int retval; 190 prrun_t prrun; 191 prstatus_t prstat; 192 193 DBG_TNF_PROBE_0(prb_proc_prstop_1, "libtnfctl", 194 "sunw%verbosity 2; sunw%debug 'stepping the target process'"); 195 196 procfd = proc_p->procfd; 197 (void) memset((char *)&prrun, 0, sizeof (prrun)); 198 (void) memset((char *)&prstat, 0, sizeof (prstat)); 199 200 again1: 201 prrun.pr_flags = PRSTOP; 202 retval = ioctl(procfd, PIOCRUN, &prrun); 203 if (retval == -1) { 204 if (errno == EINTR) 205 goto again1; 206 DBG((void) fprintf(stderr, 207 "prb_proc_prstop: PIOCRUN failed: %s\n", 208 strerror(errno))); 209 return (prb_status_map(errno)); 210 } 211 again2: 212 retval = ioctl(procfd, PIOCWSTOP, &prstat); 213 if (retval == -1) { 214 if (errno == EINTR) 215 goto again2; 216 DBG((void) fprintf(stderr, 217 "prb_proc_prstop: PIOCWSTOP failed: %s\n", 218 strerror(errno))); 219 return (prb_status_map(errno)); 220 } 221 /* 222 * if we didn't stop because we requested it (eg. if there was a 223 * signal in the target ?), we might need to try again 224 */ 225 if (prstat.pr_why != PR_REQUESTED) 226 goto again1; 227 228 return (PRB_STATUS_OK); 229 } 230 231 232 /* 233 * prb_proc_state() - returns the status pf the process 234 */ 235 prb_status_t 236 prb_proc_state(prb_proc_ctl_t *proc_p, prb_proc_state_t *state_p) 237 { 238 int procfd; 239 int retval; 240 prstatus_t prstatus; 241 242 DBG_TNF_PROBE_0(prb_proc_state_1, "libtnfctl", 243 "sunw%verbosity 2; sunw%debug 'getting the status'"); 244 245 procfd = proc_p->procfd; 246 247 (void) memset(&prstatus, 0, sizeof (prstatus)); 248 249 again: 250 retval = ioctl(procfd, PIOCSTATUS, &prstatus); 251 if (retval == -1) { 252 if (errno == EINTR) 253 goto again; 254 DBG((void) fprintf(stderr, 255 "prb_proc_status: PIOCSTATUS failed: %s\n", 256 strerror(errno))); 257 return (prb_status_map(errno)); 258 } 259 state_p->ps_isbptfault = (prstatus.pr_flags & PR_FAULTED && 260 prstatus.pr_what == FLTBPT); 261 state_p->ps_isstopped = ((prstatus.pr_flags & PR_STOPPED) != 0); 262 state_p->ps_isinsys = ((prstatus.pr_flags & PR_ASLEEP) != 0); 263 state_p->ps_isrequested = ((prstatus.pr_why & PR_REQUESTED) != 0); 264 state_p->ps_issysexit = ((prstatus.pr_why & PR_SYSEXIT) != 0); 265 state_p->ps_issysentry = ((prstatus.pr_why & PR_SYSENTRY) != 0); 266 state_p->ps_syscallnum = prstatus.pr_what; 267 return (PRB_STATUS_OK); 268 } 269 270 271 /* 272 * prb_proc_wait() - waits for the target process to stop 273 */ 274 prb_status_t 275 prb_proc_wait(prb_proc_ctl_t *proc_p, boolean_t use_sigmask, sigset_t *oldmask) 276 { 277 int procfd; 278 int retval; 279 prstatus_t prstat; 280 sigset_t pendmask; 281 int i, mask_size; 282 boolean_t pending_signal = B_FALSE; 283 284 DBG_TNF_PROBE_0(prb_proc_wait_1, "libtnfctl", 285 "sunw%verbosity 2;" 286 "sunw%debug 'waiting for the target process to stop'"); 287 288 procfd = proc_p->procfd; 289 290 /* 291 * This one of the places where we do not resubmit the ioctl if 292 * if it is terminated by an EINTR (interrupted system call). In 293 * this case, the caller knows best ... 294 */ 295 (void) memset(&prstat, 0, sizeof (prstat)); 296 297 /* if we blocked signals... */ 298 if (use_sigmask) { 299 if (sigemptyset(&pendmask) == -1) 300 return (prb_status_map(errno)); 301 if (sigpending(&pendmask) == -1) 302 return (prb_status_map(errno)); 303 /* 304 * check if there were any signals pending - 305 * XXXX libc should provide this interface 306 */ 307 mask_size = sizeof (pendmask) / sizeof (pendmask.__sigbits[0]); 308 for (i = 0; i < mask_size; i++) { 309 if (pendmask.__sigbits[i] != 0) 310 pending_signal = B_TRUE; 311 } 312 313 /* return to original signal mask */ 314 if (sigprocmask(SIG_SETMASK, oldmask, NULL) == -1) 315 return (prb_status_map(errno)); 316 317 /* if there was a pending signal, don't call PIOCWSTOP ioctl */ 318 if (pending_signal) 319 return (prb_status_map(EINTR)); 320 321 /* 322 * XXXX - there is a a race between now and when we call 323 * the PIOCWSTOP ioctl. One solution, is for the user to 324 * call an interface in libtnfctl from their signal handler. 325 * This interface will do a longjmp such that it never 326 * calls the ioctl (the setjmp would be before we restore 327 * the signal mask above) 328 */ 329 } 330 331 retval = ioctl(procfd, PIOCWSTOP, &prstat); 332 333 DBG_TNF_PROBE_2(prb_proc_wait_2, "libtnfctl", "sunw%verbosity 2;", 334 tnf_opaque, pc, prstat.pr_reg[R_PC], 335 tnf_opaque, instr, prstat.pr_instr); 336 337 if (retval == -1) { 338 #ifdef DEBUG 339 if (errno != EINTR && errno != ENOENT) 340 (void) fprintf(stderr, 341 "prb_proc_wait: PIOCWSTOP failed: %s\n", 342 strerror(errno)); 343 344 #endif 345 return (prb_status_map(errno)); 346 } 347 348 return (PRB_STATUS_OK); 349 } 350 351 352 /* 353 * prb_proc_cont() - continues the target process 354 */ 355 prb_status_t 356 prb_proc_cont(prb_proc_ctl_t *proc_p) 357 { 358 int procfd; 359 int retval; 360 prrun_t prrun; 361 362 DBG_TNF_PROBE_0(prb_proc_cont_1, "libtnfctl", 363 "sunw%verbosity 2; sunw%debug 'starting the target process'"); 364 procfd = proc_p->procfd; 365 366 (void) memset((char *)&prrun, 0, sizeof (prrun)); 367 368 again: 369 prrun.pr_flags = PRCFAULT; 370 retval = ioctl(procfd, PIOCRUN, &prrun); 371 if (retval == -1) { 372 if (errno == EINTR) 373 goto again; 374 DBG((void) fprintf(stderr, 375 "prb_proc_cont: PIOCRUN failed: %s\n", 376 strerror(errno))); 377 return (prb_status_map(errno)); 378 } 379 return (PRB_STATUS_OK); 380 } 381 382 383 /* 384 * prb_proc_istepbpt() - step the target process one instruction 385 * 386 * CAUTION!!!! - this routine is specialized to only be able to single 387 * step over the breakpoint location. 388 */ 389 prb_status_t 390 prb_proc_istepbpt(prb_proc_ctl_t *proc_p) 391 { 392 int procfd; 393 int retval; 394 prrun_t run; 395 fltset_t faults; 396 prstatus_t prstat; 397 398 DBG_TNF_PROBE_0(prb_proc_istepbpt_1, "libtnfctl", 399 "sunw%verbosity 2; " 400 "sunw%debug 'single stepping over breakpoint'"); 401 402 procfd = proc_p->procfd; 403 404 (void) memset((char *)&run, 0, sizeof (run)); 405 406 /* add trace fault to the list of current traced faults */ 407 again1: 408 retval = ioctl(procfd, PIOCGFAULT, &faults); 409 if (retval == -1) { 410 if (errno == EINTR) 411 goto again1; 412 DBG((void) fprintf(stderr, 413 "prb_proc_istepbpt: PIOCGFAULT failed: %s\n", 414 strerror(errno))); 415 return (prb_status_map(errno)); 416 } 417 praddset(&faults, FLTTRACE); 418 419 /* issue the run command with the single-step option */ 420 run.pr_flags = PRCFAULT | PRSFAULT | PRSTEP; 421 run.pr_fault = faults; 422 423 /* load the location of the breakpoint */ 424 run.pr_vaddr = (caddr_t)proc_p->bptaddr; 425 run.pr_flags |= PRSVADDR; 426 427 again2: 428 retval = ioctl(procfd, PIOCRUN, &run); 429 if (retval == -1) { 430 if (errno == EINTR) 431 goto again2; 432 DBG((void) fprintf(stderr, 433 "prb_proc_istepbpt: PIOCRUN failed: %s\n", 434 strerror(errno))); 435 return (prb_status_map(errno)); 436 } 437 again3: 438 retval = ioctl(procfd, PIOCWSTOP, &prstat); 439 if (retval == -1) { 440 if (errno == EINTR) 441 goto again3; 442 DBG((void) fprintf(stderr, 443 "prb_proc_istepbpt: PIOCWSTOP failed: %s\n", 444 strerror(errno))); 445 return (prb_status_map(errno)); 446 } 447 448 DBG_TNF_PROBE_2(prb_proc_istepbpt_2, "libtnfctl", "sunw%verbosity 2;", 449 tnf_opaque, pc, prstat.pr_reg[R_PC], 450 tnf_opaque, instr, prstat.pr_instr); 451 452 453 /* clear any current faults */ 454 again4: 455 retval = ioctl(procfd, PIOCCFAULT, NULL); 456 if (retval == -1) { 457 if (errno == EINTR) 458 goto again4; 459 DBG((void) fprintf(stderr, 460 "prb_proc_clrbptflt: PIOCCFAULT failed: %s\n", 461 strerror(errno))); 462 return (prb_status_map(errno)); 463 } 464 /* remove the trace fault from the current traced faults */ 465 prdelset(&faults, FLTTRACE); 466 again5: 467 retval = ioctl(procfd, PIOCSFAULT, &faults); 468 if (retval == -1) { 469 if (errno == EINTR) 470 goto again5; 471 DBG((void) fprintf(stderr, 472 "prb_proc_istepbpt: PIOCSFAULT failed: %s\n", 473 strerror(errno))); 474 return (prb_status_map(errno)); 475 } 476 return (PRB_STATUS_OK); 477 } 478 479 480 /* 481 * prb_proc_clrbptflt() - clear an encountered breakpoint fault 482 */ 483 prb_status_t 484 prb_proc_clrbptflt(prb_proc_ctl_t *proc_p) 485 { 486 int retval; 487 int procfd; 488 489 DBG_TNF_PROBE_0(prb_proc_clrbptflt_1, "libtnfctl", "sunw%verbosity 2"); 490 491 procfd = proc_p->procfd; 492 493 /* clear any current faults */ 494 again: 495 retval = ioctl(procfd, PIOCCFAULT, NULL); 496 if (retval == -1) { 497 if (errno == EINTR) 498 goto again; 499 DBG((void) fprintf(stderr, 500 "prb_proc_clrbptflt: PIOCCFAULT failed: %s\n", 501 strerror(errno))); 502 return (prb_status_map(errno)); 503 } 504 return (PRB_STATUS_OK); 505 } 506 507 508 /* 509 * prb_proc_tracebpt() - sets the bpt tracing state. 510 */ 511 prb_status_t 512 prb_proc_tracebpt(prb_proc_ctl_t *proc_p, boolean_t bpt) 513 { 514 int procfd; 515 int retval; 516 fltset_t faults; 517 518 DBG_TNF_PROBE_1(prb_proc_tracebpt_1, "libtnfctl", "sunw%verbosity 2;", 519 tnf_string, bpt_state, (bpt) ? "enabled" : "disabled"); 520 521 procfd = proc_p->procfd; 522 /* get the current set of traced faults */ 523 again1: 524 retval = ioctl(procfd, PIOCGFAULT, &faults); 525 if (retval == -1) { 526 if (errno == EINTR) 527 goto again1; 528 DBG((void) fprintf(stderr, 529 "prb_proc_tracebpt: PIOCGFAULT failed: %s\n", 530 strerror(errno))); 531 return (prb_status_map(errno)); 532 } 533 /* set or clear the breakpoint flag */ 534 if (bpt) 535 praddset(&faults, FLTBPT); 536 else 537 prdelset(&faults, FLTBPT); 538 539 /* write the fault set back */ 540 again2: 541 retval = ioctl(procfd, PIOCSFAULT, &faults); 542 if (retval == -1) { 543 if (errno == EINTR) 544 goto again2; 545 DBG((void) fprintf(stderr, 546 "prb_proc_tracebpt: PIOCSFAULT failed: %s\n", 547 strerror(errno))); 548 return (prb_status_map(errno)); 549 } 550 return (PRB_STATUS_OK); 551 } 552 553 /* Note - the following 3 functions should be combined */ 554 555 /* 556 * prb_proc_setrlc() - sets or clears the run-on-last-close flag. 557 */ 558 prb_status_t 559 prb_proc_setrlc(prb_proc_ctl_t *proc_p, boolean_t rlc) 560 { 561 int procfd; 562 long mode; 563 int retval; 564 565 DBG_TNF_PROBE_1(prb_proc_setrlc_1, "libtnfctl", "sunw%verbosity 2;", 566 tnf_string, run_on_last_close, (rlc) ? "setting" : "clearing"); 567 568 procfd = proc_p->procfd; 569 mode = PR_RLC; 570 571 if (rlc) { 572 again1: 573 retval = ioctl(procfd, PIOCSET, &mode); 574 if (retval == -1) { 575 if (errno == EINTR) 576 goto again1; 577 DBG((void) fprintf(stderr, 578 "prb_proc_setrlc: PIOCSET failed: %s\n", 579 strerror(errno))); 580 return (prb_status_map(errno)); 581 } 582 } else { 583 again2: 584 retval = ioctl(procfd, PIOCRESET, &mode); 585 if (retval == -1) { 586 if (errno == EINTR) 587 goto again2; 588 DBG((void) fprintf(stderr, 589 "prb_proc_setrlc: PIOCRESET failed: %s\n", 590 strerror(errno))); 591 return (prb_status_map(errno)); 592 } 593 } 594 595 return (PRB_STATUS_OK); 596 597 598 } /* end prb_proc_setrlc */ 599 600 601 /* 602 * prb_proc_setklc() - sets or clears the kill-on-last-close flag. 603 */ 604 prb_status_t 605 prb_proc_setklc(prb_proc_ctl_t *proc_p, boolean_t klc) 606 { 607 int procfd; 608 long mode; 609 int retval; 610 611 DBG_TNF_PROBE_1(prb_proc_setklc_1, "libtnfctl", "sunw%verbosity 2;", 612 tnf_string, kill_on_last_close, (klc) ? "setting" : "clearing"); 613 614 procfd = proc_p->procfd; 615 mode = PR_KLC; 616 617 if (klc) { 618 again1: 619 retval = ioctl(procfd, PIOCSET, &mode); 620 if (retval == -1) { 621 if (errno == EINTR) 622 goto again1; 623 DBG((void) fprintf(stderr, 624 "prb_proc_setklc: PIOCSET failed: %s\n", 625 strerror(errno))); 626 return (prb_status_map(errno)); 627 } 628 } else { 629 again2: 630 retval = ioctl(procfd, PIOCRESET, &mode); 631 if (retval == -1) { 632 if (errno == EINTR) 633 goto again2; 634 DBG((void) fprintf(stderr, 635 "prb_proc_setklc: PIOCRESET failed: %s\n", 636 strerror(errno))); 637 return (prb_status_map(errno)); 638 } 639 } 640 641 return (PRB_STATUS_OK); 642 643 } /* end prb_proc_setklc */ 644 645 /* 646 * prb_proc_setfork() - sets or clears the inherit-on-fork flag 647 */ 648 prb_status_t 649 prb_proc_setfork(prb_proc_ctl_t *proc_p, boolean_t inhfork) 650 { 651 int procfd; 652 long mode; 653 int retval; 654 655 DBG_TNF_PROBE_1(prb_proc_setfork_1, "libtnfctl", "sunw%verbosity 2;", 656 tnf_string, kill_on_last_close, 657 (inhfork) ? "setting" : "clearing"); 658 659 procfd = proc_p->procfd; 660 mode = PR_FORK; 661 662 if (inhfork) { 663 again1: 664 retval = ioctl(procfd, PIOCSET, &mode); 665 if (retval == -1) { 666 if (errno == EINTR) 667 goto again1; 668 DBG((void) fprintf(stderr, 669 "prb_proc_setfork: PIOCSET failed: %s\n", 670 strerror(errno))); 671 return (prb_status_map(errno)); 672 } 673 } else { 674 again2: 675 retval = ioctl(procfd, PIOCRESET, &mode); 676 if (retval == -1) { 677 if (errno == EINTR) 678 goto again2; 679 DBG((void) fprintf(stderr, 680 "prb_proc_setfork: PIOCRESET failed: %s\n", 681 strerror(errno))); 682 return (prb_status_map(errno)); 683 } 684 } 685 686 return (PRB_STATUS_OK); 687 688 } /* end prb_proc_setfork */ 689 690 /* 691 * prb_proc_exit() - if op is PRB_SYS_ALL, sets up the target process to stop 692 * on exit from all system calls. If op is PRB_SYS_NONE, sets up the target 693 * process so that it will not stop on exit from any system call. 694 * PRB_SYS_ADD and PRB_SYS_DEL adds or deletes a particular system call from 695 * the mask of "interested" system calls respectively. This function can be 696 * called multiple times to build up the mask. 697 */ 698 prb_status_t 699 prb_proc_exit(prb_proc_ctl_t *proc_p, 700 uint_t syscall, 701 prb_syscall_op_t op) 702 { 703 int procfd; 704 int retval; 705 sysset_t sysmask; 706 707 DBG_TNF_PROBE_0(prb_proc_exit_1, "libtnfctl", 708 "sunw%verbosity 2; " 709 "sunw%debug 'setting up target to stop on exit of syscall'"); 710 711 procfd = proc_p->procfd; 712 713 switch (op) { 714 case PRB_SYS_ALL: 715 prfillset(&sysmask); 716 break; 717 case PRB_SYS_NONE: 718 premptyset(&sysmask); 719 break; 720 case PRB_SYS_ADD: 721 again1: 722 retval = ioctl(procfd, PIOCGEXIT, &sysmask); 723 if (retval == -1) { 724 if (errno == EINTR) 725 goto again1; 726 DBG((void) fprintf(stderr, 727 "prb_proc_exit: PIOCGEXIT failed: %s\n", 728 strerror(errno))); 729 return (prb_status_map(errno)); 730 } 731 praddset(&sysmask, syscall); 732 break; 733 case PRB_SYS_DEL: 734 again2: 735 retval = ioctl(procfd, PIOCGEXIT, &sysmask); 736 if (retval == -1) { 737 if (errno == EINTR) 738 goto again2; 739 DBG((void) fprintf(stderr, 740 "prb_proc_exit: PIOCGEXIT failed: %s\n", 741 strerror(errno))); 742 return (prb_status_map(errno)); 743 } 744 prdelset(&sysmask, syscall); 745 break; 746 default: 747 DBG((void) fprintf(stderr, "prb_proc_exit: bad input arg\n")); 748 return (PRB_STATUS_BADARG); 749 } 750 again3: 751 retval = ioctl(procfd, PIOCSEXIT, &sysmask); 752 if (retval == -1) { 753 if (errno == EINTR) 754 goto again3; 755 DBG((void) fprintf(stderr, 756 "prb_proc_exit: PIOCSEXIT failed: %s\n", 757 strerror(errno))); 758 return (prb_status_map(errno)); 759 } 760 return (PRB_STATUS_OK); 761 762 } /* end prb_proc_exit */ 763 764 /* 765 * prb_proc_entry() - if op is PRB_SYS_ALL, sets up the target process to 766 * stop on entry from all system calls. If op is PRB_SYS_NONE, sets up the 767 * target process so that it will not stop on entry from any system call. 768 * PRB_SYS_ADD and PRB_SYS_DEL adds or deletes a particular system call from 769 * the mask of "interested" system calls respectively. This function can be 770 * called multiple times to build up the mask. 771 */ 772 prb_status_t 773 prb_proc_entry(prb_proc_ctl_t *proc_p, 774 uint_t syscall, 775 prb_syscall_op_t op) 776 { 777 int procfd; 778 int retval; 779 sysset_t sysmask; 780 781 DBG_TNF_PROBE_0(prb_proc_entry_1, "libtnfctl", 782 "sunw%verbosity 2; " 783 "sunw%debug 'setting up target to stop on entry of syscall'"); 784 785 procfd = proc_p->procfd; 786 787 switch (op) { 788 case PRB_SYS_ALL: 789 prfillset(&sysmask); 790 break; 791 case PRB_SYS_NONE: 792 premptyset(&sysmask); 793 break; 794 case PRB_SYS_ADD: 795 again1: 796 retval = ioctl(procfd, PIOCGENTRY, &sysmask); 797 if (retval == -1) { 798 if (errno == EINTR) 799 goto again1; 800 DBG((void) fprintf(stderr, 801 "prb_proc_entry: PIOCGENTRY failed: %s\n", 802 strerror(errno))); 803 return (prb_status_map(errno)); 804 } 805 praddset(&sysmask, syscall); 806 break; 807 case PRB_SYS_DEL: 808 again2: 809 retval = ioctl(procfd, PIOCGENTRY, &sysmask); 810 if (retval == -1) { 811 if (errno == EINTR) 812 goto again2; 813 DBG((void) fprintf(stderr, 814 "prb_proc_entry: PIOCGENTRY failed: %s\n", 815 strerror(errno))); 816 return (prb_status_map(errno)); 817 } 818 prdelset(&sysmask, syscall); 819 break; 820 default: 821 DBG((void) fprintf(stderr, "prb_proc_entry: bad input arg\n")); 822 return (PRB_STATUS_BADARG); 823 } 824 again3: 825 retval = ioctl(procfd, PIOCSENTRY, &sysmask); 826 if (retval == -1) { 827 if (errno == EINTR) 828 goto again3; 829 DBG((void) fprintf(stderr, 830 "prb_proc_entry: PIOCSENTRY failed: %s\n", 831 strerror(errno))); 832 return (prb_status_map(errno)); 833 } 834 return (PRB_STATUS_OK); 835 } 836 837 /* 838 * prb_proc_read() - reads a block of memory from a processes address space. 839 */ 840 prb_status_t 841 prb_proc_read(prb_proc_ctl_t *proc_p, uintptr_t addr, void *buf, size_t size) 842 { 843 int procfd; 844 ssize_t sz; 845 off_t offset; 846 847 DBG_TNF_PROBE_2(prb_proc_read_1, "libtnfctl", "sunw%verbosity 3;", 848 tnf_long, num_bytes, size, 849 tnf_opaque, from_address, addr); 850 851 procfd = proc_p->procfd; 852 offset = lseek(procfd, (off_t)addr, SEEK_SET); 853 if (offset != (off_t)addr) { 854 DBG(perror("prb_proc_read: lseek failed")); 855 return (prb_status_map(errno)); 856 } 857 sz = read(procfd, buf, size); 858 if (sz != size) { 859 DBG(perror("prb_proc_read: read failed")); 860 return (prb_status_map(errno)); 861 } 862 return (PRB_STATUS_OK); 863 } 864 865 866 /* 867 * prb_proc_write() - writes a block of memory from a processes address 868 * space. 869 */ 870 prb_status_t 871 prb_proc_write(prb_proc_ctl_t *proc_p, uintptr_t addr, void *buf, size_t size) 872 { 873 int procfd; 874 ssize_t sz; 875 off_t offset; 876 877 DBG_TNF_PROBE_2(prb_proc_write_1, "libtnfctl", "sunw%verbosity 3;", 878 tnf_long, num_bytes, size, 879 tnf_opaque, to_address, addr); 880 881 procfd = proc_p->procfd; 882 offset = lseek(procfd, (off_t)addr, SEEK_SET); 883 if (offset != (off_t)addr) { 884 DBG(perror("prb_proc_write: lseek failed")); 885 return (prb_status_map(errno)); 886 } 887 sz = write(procfd, buf, size); 888 if (sz != size) { 889 DBG(perror("prb_proc_write: write failed")); 890 return (prb_status_map(errno)); 891 } 892 return (PRB_STATUS_OK); 893 } 894 895 896 /* 897 * prb_proc_readstr() - dereferences a string in the target 898 * NOTE: There is a similar routine called _tnfctl_readstr_targ() 899 * used by tnfctl layer. It would be better if there was only 900 * one of these functions defined. 901 */ 902 903 #define BUFSZ 256 904 905 prb_status_t 906 prb_proc_readstr(prb_proc_ctl_t *proc_p, uintptr_t addr, const char **outstr_pp) 907 { 908 prb_status_t prbstat; 909 int bufsz = BUFSZ; 910 char buffer[BUFSZ + 1]; 911 offset_t offset; 912 char *ptr, *orig_ptr; 913 914 *outstr_pp = NULL; 915 offset = 0; 916 917 /* allocate an inital return buffer */ 918 ptr = (char *)malloc(BUFSZ); 919 if (!ptr) { 920 DBG((void) fprintf(stderr, 921 "prb_proc_readstr: malloc failed\n")); 922 return (PRB_STATUS_ALLOCFAIL); 923 } 924 /*LINTED constant in conditional context*/ 925 while (1) { 926 int i; 927 928 /* read a chunk into our buffer */ 929 prbstat = prb_proc_read(proc_p, addr + offset, buffer, bufsz); 930 if (prbstat) { 931 932 /* 933 * if we get into trouble with a large read, try again 934 * with a single byte. Subsequent failure is real ... 935 */ 936 if (bufsz > 1) { 937 bufsz = 1; 938 continue; 939 } 940 941 DBG((void) fprintf(stderr, 942 "prb_proc_readstr: prb_proc_read failed: %s\n", 943 prb_status_str(prbstat))); 944 free(ptr); 945 return (prbstat); 946 } 947 /* copy the chracters into the return buffer */ 948 for (i = 0; i < bufsz; i++) { 949 char c = buffer[i]; 950 951 ptr[offset + i] = c; 952 if (c == '\0') { 953 /* hooray! we saw the end of the string */ 954 *outstr_pp = ptr; 955 return (PRB_STATUS_OK); 956 } 957 } 958 959 /* bummer, need to grab another bufsz characters */ 960 offset += bufsz; 961 orig_ptr = ptr; 962 ptr = (char *)realloc(ptr, offset + bufsz); 963 if (!ptr) { 964 free(orig_ptr); 965 DBG((void) fprintf(stderr, 966 "prb_proc_readstr: realloc failed\n")); 967 return (PRB_STATUS_ALLOCFAIL); 968 } 969 } 970 971 #if defined(lint) 972 return (PRB_STATUS_OK); 973 #endif 974 } 975 976 prb_status_t 977 prb_proc_get_r0_r1(prb_proc_ctl_t *proc_p, prgreg_t *r0, prgreg_t *r1) 978 { 979 int retval; 980 int procfd; 981 prstatus_t prstatus; 982 983 procfd = proc_p->procfd; 984 again: 985 retval = ioctl(procfd, PIOCSTATUS, &prstatus); 986 if (retval == -1) { 987 if (errno == EINTR) 988 goto again; 989 return (prb_status_map(errno)); 990 } 991 992 /* 993 * Use R_Rn register definitions for some uniformity 994 * sparc: define R_R0 R_O0 995 * define R_R1 R_O1 996 * x86: define R_R0 EAX 997 * define R_R1 EDX 998 */ 999 *r0 = prstatus.pr_reg[R_R0]; 1000 *r1 = prstatus.pr_reg[R_R1]; 1001 DBG((void) fprintf 1002 (stderr, "prb_proc_get_r0_r1: R_R0 = %d, R_R1 = %d\n", *r0, *r1)); 1003 return (PRB_STATUS_OK); 1004 } 1005