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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 29 #include <stdio.h> 30 #include <stdio_ext.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <fcntl.h> 34 #include <ctype.h> 35 #include <string.h> 36 #include <memory.h> 37 #include <signal.h> 38 #include <wait.h> 39 #include <limits.h> 40 #include <errno.h> 41 #include <sys/types.h> 42 #include <sys/time.h> 43 #include <sys/times.h> 44 #include <sys/fstyp.h> 45 #include <sys/fsid.h> 46 #include <sys/stat.h> 47 #include <sys/mman.h> 48 #include <sys/resource.h> 49 #include <libproc.h> 50 #include "ramdata.h" 51 #include "proto.h" 52 #include "htbl.h" 53 54 /* 55 * The user can trace individual threads by using the 'pid/1,3-6,8-' syntax. 56 * This structure keeps track of pid/lwp specifications. If there are no LWPs 57 * specified, then 'lwps' will be NULL. 58 */ 59 typedef struct proc_set { 60 pid_t pid; 61 const char *lwps; 62 } proc_set_t; 63 64 /* 65 * Function prototypes for static routines in this file. 66 */ 67 void setup_basetime(hrtime_t, struct timeval *); 68 int xcreat(char *); 69 void setoutput(int); 70 void report(private_t *, time_t); 71 void prtim(timestruc_t *); 72 void pids(char *, proc_set_t *); 73 void psargs(private_t *); 74 int control(private_t *, pid_t); 75 int grabit(private_t *, proc_set_t *); 76 void release(private_t *, pid_t); 77 void intr(int); 78 int wait4all(void); 79 void letgo(private_t *); 80 void child_to_file(); 81 void file_to_parent(); 82 void per_proc_init(); 83 int lib_sort(const void *, const void *); 84 int key_sort(const void *, const void *); 85 86 void *worker_thread(void *); 87 void main_thread(int); 88 89 /* 90 * Test for empty set. 91 * is_empty() should not be called directly. 92 */ 93 int is_empty(const uint32_t *, size_t); 94 #define isemptyset(sp) \ 95 is_empty((uint32_t *)(sp), sizeof (*(sp)) / sizeof (uint32_t)) 96 97 /* 98 * OR the second set into the first set. 99 * or_set() should not be called directly. 100 */ 101 void or_set(uint32_t *, const uint32_t *, size_t); 102 #define prorset(sp1, sp2) \ 103 or_set((uint32_t *)(sp1), (uint32_t *)(sp2), \ 104 sizeof (*(sp1)) / sizeof (uint32_t)) 105 106 /* fetch or allocate thread-private data */ 107 private_t * 108 get_private() 109 { 110 void *value; 111 private_t *pri = NULL; 112 113 if (thr_getspecific(private_key, &value) == 0) 114 pri = value; 115 if (pri == NULL) { 116 pri = my_malloc(sizeof (*pri), NULL); 117 (void) memset(pri, 0, sizeof (*pri)); 118 pri->sys_path = my_malloc(pri->sys_psize = 16, NULL); 119 pri->sys_string = my_malloc(pri->sys_ssize = 32, NULL); 120 if (thr_setspecific(private_key, pri) == ENOMEM) 121 abend("memory allocation failure", NULL); 122 } 123 return (pri); 124 } 125 126 /* destructor function for thread-private data */ 127 void 128 free_private(void *value) 129 { 130 private_t *pri = value; 131 132 if (pri->sys_path) 133 free(pri->sys_path); 134 if (pri->sys_string) 135 free(pri->sys_string); 136 if (pri->exec_string) 137 free(pri->exec_string); 138 if (pri->str_buffer) 139 free(pri->str_buffer); 140 free(pri); 141 } 142 143 /* 144 * This is called by the main thread (via create_thread()) 145 * and is also called from other threads in worker_thread() 146 * while holding truss_lock. No further locking is required. 147 */ 148 void 149 insert_lwpid(lwpid_t lwpid) 150 { 151 int i; 152 153 truss_nlwp++; 154 for (i = 0; i < truss_maxlwp; i++) { 155 if (truss_lwpid[i] == 0) 156 break; 157 } 158 if (i == truss_maxlwp) { 159 /* double the size of the array */ 160 truss_lwpid = my_realloc(truss_lwpid, 161 truss_maxlwp * 2 * sizeof (lwpid_t), NULL); 162 (void) memset(&truss_lwpid[truss_maxlwp], 0, 163 truss_maxlwp * sizeof (lwpid_t)); 164 truss_maxlwp *= 2; 165 } 166 truss_lwpid[i] = lwpid; 167 } 168 169 /* 170 * This is called from the first worker thread to encounter one of 171 * (leave_hung || interrupt || sigusr1). It must notify all other 172 * worker threads of the same condition. truss_lock is held. 173 */ 174 void 175 broadcast_signals(void) 176 { 177 static int int_notified = FALSE; 178 static int usr1_notified = FALSE; 179 static int usr2_notified = FALSE; 180 lwpid_t my_id = thr_self(); 181 lwpid_t lwpid; 182 int i; 183 184 if (interrupt && !int_notified) { 185 int_notified = TRUE; 186 for (i = 0; i < truss_maxlwp; i++) { 187 if ((lwpid = truss_lwpid[i]) != 0 && lwpid != my_id) 188 (void) thr_kill(lwpid, interrupt); 189 } 190 } 191 if (sigusr1 && !usr1_notified) { 192 usr1_notified = TRUE; 193 for (i = 0; i < truss_maxlwp; i++) { 194 if ((lwpid = truss_lwpid[i]) != 0 && lwpid != my_id) 195 (void) thr_kill(lwpid, SIGUSR1); 196 } 197 } 198 if (leave_hung && !usr2_notified) { 199 usr2_notified = TRUE; 200 for (i = 0; i < truss_maxlwp; i++) { 201 if ((lwpid = truss_lwpid[i]) != 0 && lwpid != my_id) 202 (void) thr_kill(lwpid, SIGUSR2); 203 } 204 } 205 } 206 207 static struct ps_lwphandle * 208 grab_lwp(lwpid_t who) 209 { 210 struct ps_lwphandle *Lwp; 211 int gcode; 212 213 if ((Lwp = Lgrab(Proc, who, &gcode)) == NULL) { 214 if (gcode != G_NOPROC) { 215 (void) fprintf(stderr, 216 "%s: cannot grab LWP %u in process %d," 217 " reason: %s\n", 218 command, who, (int)Pstatus(Proc)->pr_pid, 219 Lgrab_error(gcode)); 220 interrupt = SIGTERM; /* post an interrupt */ 221 } 222 } 223 return (Lwp); 224 } 225 226 /* 227 * Iteration function called for each initial lwp in the controlled process. 228 */ 229 /* ARGSUSED */ 230 int 231 create_thread(void *arg, const lwpstatus_t *Lsp) 232 { 233 struct ps_lwphandle *new_Lwp; 234 lwpid_t lwpid; 235 int *count = arg; 236 237 if (lwptrace(Pstatus(Proc)->pr_pid, Lsp->pr_lwpid)) 238 *count += 1; 239 240 if ((new_Lwp = grab_lwp(Lsp->pr_lwpid)) != NULL) { 241 if (thr_create(NULL, 0, worker_thread, new_Lwp, 242 THR_BOUND | THR_SUSPENDED, &lwpid) != 0) 243 abend("cannot create lwp to follow child lwp", NULL); 244 insert_lwpid(lwpid); 245 } 246 return (0); 247 } 248 249 int 250 main(int argc, char *argv[]) 251 { 252 private_t *pri; 253 struct tms tms; 254 struct rlimit rlim; 255 int ofd = -1; 256 int opt; 257 int i; 258 int first; 259 int errflg = FALSE; 260 int badname = FALSE; 261 proc_set_t *grab = NULL; 262 const pstatus_t *Psp; 263 const lwpstatus_t *Lsp; 264 int sharedmem; 265 266 /* a few of these need to be initialized to NULL */ 267 Cp = NULL; 268 fcall_tbl = NULL; 269 270 /* 271 * Make sure fd's 0, 1, and 2 are allocated, 272 * just in case truss was invoked from init. 273 */ 274 while ((i = open("/dev/null", O_RDWR)) >= 0 && i < 2) 275 ; 276 if (i > 2) 277 (void) close(i); 278 279 starttime = times(&tms); /* for elapsed timing */ 280 281 /* this should be per-traced-process */ 282 pagesize = sysconf(_SC_PAGESIZE); 283 284 /* command name (e.g., "truss") */ 285 if ((command = strrchr(argv[0], '/')) != NULL) 286 command++; 287 else 288 command = argv[0]; 289 290 /* set up the initial private data */ 291 (void) mutex_init(&truss_lock, USYNC_THREAD, NULL); 292 (void) mutex_init(&count_lock, USYNC_THREAD, NULL); 293 (void) cond_init(&truss_cv, USYNC_THREAD, NULL); 294 if (thr_keycreate(&private_key, free_private) == ENOMEM) 295 abend("memory allocation failure", NULL); 296 pri = get_private(); 297 298 Euid = geteuid(); 299 Egid = getegid(); 300 Ruid = getuid(); 301 Rgid = getgid(); 302 ancestor = getpid(); 303 304 prfillset(&trace); /* default: trace all system calls */ 305 premptyset(&verbose); /* default: no syscall verbosity */ 306 premptyset(&rawout); /* default: no raw syscall interpretation */ 307 308 prfillset(&signals); /* default: trace all signals */ 309 310 prfillset(&faults); /* default: trace all faults */ 311 prdelset(&faults, FLTPAGE); /* except this one */ 312 313 premptyset(&readfd); /* default: dump no buffers */ 314 premptyset(&writefd); 315 316 premptyset(&syshang); /* default: hang on no system calls */ 317 premptyset(&sighang); /* default: hang on no signals */ 318 premptyset(&flthang); /* default: hang on no faults */ 319 320 (void) sigemptyset(&emptyset); /* for unblocking all signals */ 321 (void) sigfillset(&fillset); /* for blocking all signals */ 322 323 #define OPTIONS "FpfcaeildDEht:T:v:x:s:S:m:M:u:U:r:w:o:" 324 while ((opt = getopt(argc, argv, OPTIONS)) != EOF) { 325 switch (opt) { 326 case 'F': /* force grabbing (no O_EXCL) */ 327 Fflag = PGRAB_FORCE; 328 break; 329 case 'p': /* grab processes */ 330 pflag = TRUE; 331 break; 332 case 'f': /* follow children */ 333 fflag = TRUE; 334 break; 335 case 'c': /* don't trace, just count */ 336 cflag = TRUE; 337 iflag = TRUE; /* implies no interruptable syscalls */ 338 break; 339 case 'a': /* display argument lists */ 340 aflag = TRUE; 341 break; 342 case 'e': /* display environments */ 343 eflag = TRUE; 344 break; 345 case 'i': /* don't show interruptable syscalls */ 346 iflag = TRUE; 347 break; 348 case 'l': /* show lwp id for each syscall */ 349 lflag = TRUE; 350 break; 351 case 'h': /* debugging: report hash stats */ 352 hflag = TRUE; 353 break; 354 case 'd': /* show time stamps */ 355 dflag = TRUE; 356 break; 357 case 'D': /* show time deltas */ 358 Dflag = TRUE; 359 break; 360 case 'E': 361 Eflag = TRUE; /* show syscall times */ 362 break; 363 case 't': /* system calls to trace */ 364 if (syslist(optarg, &trace, &tflag)) 365 badname = TRUE; 366 break; 367 case 'T': /* system calls to hang process */ 368 if (syslist(optarg, &syshang, &Tflag)) 369 badname = TRUE; 370 break; 371 case 'v': /* verbose interpretation of syscalls */ 372 if (syslist(optarg, &verbose, &vflag)) 373 badname = TRUE; 374 break; 375 case 'x': /* raw interpretation of syscalls */ 376 if (syslist(optarg, &rawout, &xflag)) 377 badname = TRUE; 378 break; 379 case 's': /* signals to trace */ 380 if (siglist(pri, optarg, &signals, &sflag)) 381 badname = TRUE; 382 break; 383 case 'S': /* signals to hang process */ 384 if (siglist(pri, optarg, &sighang, &Sflag)) 385 badname = TRUE; 386 break; 387 case 'm': /* machine faults to trace */ 388 if (fltlist(optarg, &faults, &mflag)) 389 badname = TRUE; 390 break; 391 case 'M': /* machine faults to hang process */ 392 if (fltlist(optarg, &flthang, &Mflag)) 393 badname = TRUE; 394 break; 395 case 'u': /* user library functions to trace */ 396 if (liblist(optarg, 0)) 397 badname = TRUE; 398 break; 399 case 'U': /* user library functions to hang */ 400 if (liblist(optarg, 1)) 401 badname = TRUE; 402 break; 403 case 'r': /* show contents of read(fd) */ 404 if (fdlist(optarg, &readfd)) 405 badname = TRUE; 406 break; 407 case 'w': /* show contents of write(fd) */ 408 if (fdlist(optarg, &writefd)) 409 badname = TRUE; 410 break; 411 case 'o': /* output file for trace */ 412 oflag = TRUE; 413 if (ofd >= 0) 414 (void) close(ofd); 415 if ((ofd = xcreat(optarg)) < 0) { 416 perror(optarg); 417 badname = TRUE; 418 } 419 break; 420 default: 421 errflg = TRUE; 422 break; 423 } 424 } 425 426 if (badname) 427 exit(2); 428 429 /* if -a or -e was specified, force tracing of exec() */ 430 if (aflag || eflag) 431 praddset(&trace, SYS_execve); 432 433 /* 434 * Make sure that all system calls, signals, and machine faults 435 * that hang the process are added to their trace sets. 436 */ 437 prorset(&trace, &syshang); 438 prorset(&signals, &sighang); 439 prorset(&faults, &flthang); 440 441 argc -= optind; 442 argv += optind; 443 444 /* collect the specified process ids */ 445 if (pflag && argc > 0) { 446 grab = my_malloc(argc * sizeof (proc_set_t), 447 "memory for process-ids"); 448 while (argc-- > 0) 449 pids(*argv++, grab); 450 } 451 452 if (errflg || (argc <= 0 && ngrab <= 0)) { 453 (void) fprintf(stderr, 454 "usage:\t%s [-fcaeildDEF] [-[tTvx] [!]syscalls] [-[sS] [!]signals]\\\n", 455 command); 456 (void) fprintf(stderr, 457 "\t[-[mM] [!]faults] [-[rw] [!]fds] [-[uU] [!]libs:[:][!]funcs]\\\n"); 458 (void) fprintf(stderr, 459 "\t[-o outfile] command | -p pid[/lwps] ...\n"); 460 exit(2); 461 } 462 463 if (argc > 0) { /* create the controlled process */ 464 int err; 465 char path[PATH_MAX]; 466 467 Proc = Pcreate(argv[0], &argv[0], &err, path, sizeof (path)); 468 if (Proc == NULL) { 469 switch (err) { 470 case C_PERM: 471 (void) fprintf(stderr, 472 "%s: cannot trace set-id or " 473 "unreadable object file: %s\n", 474 command, path); 475 break; 476 case C_LP64: 477 (void) fprintf(stderr, 478 "%s: cannot control _LP64 " 479 "program: %s\n", 480 command, path); 481 break; 482 case C_NOEXEC: 483 (void) fprintf(stderr, 484 "%s: cannot execute program: %s\n", 485 command, argv[0]); 486 break; 487 case C_NOENT: 488 (void) fprintf(stderr, 489 "%s: cannot find program: %s\n", 490 command, argv[0]); 491 break; 492 case C_STRANGE: 493 break; 494 default: 495 (void) fprintf(stderr, "%s: %s\n", 496 command, Pcreate_error(err)); 497 break; 498 } 499 exit(2); 500 } 501 if (fflag || Dynpat != NULL) 502 (void) Psetflags(Proc, PR_FORK); 503 else 504 (void) Punsetflags(Proc, PR_FORK); 505 Psp = Pstatus(Proc); 506 Lsp = &Psp->pr_lwp; 507 pri->lwpstat = Lsp; 508 data_model = Psp->pr_dmodel; 509 created = Psp->pr_pid; 510 make_pname(pri, 0); 511 (void) sysentry(pri, 1); 512 pri->length = 0; 513 if (!cflag && prismember(&trace, SYS_execve)) { 514 pri->exec_string = my_realloc(pri->exec_string, 515 strlen(pri->sys_string) + 1, NULL); 516 (void) strcpy(pri->exec_pname, pri->pname); 517 (void) strcpy(pri->exec_string, pri->sys_string); 518 pri->length += strlen(pri->sys_string); 519 pri->exec_lwpid = pri->lwpstat->pr_lwpid; 520 pri->sys_leng = 0; 521 *pri->sys_string = '\0'; 522 } 523 pri->syslast = Psp->pr_stime; 524 pri->usrlast = Psp->pr_utime; 525 } 526 527 /* 528 * Now that we have created the victim process, 529 * give ourself a million file descriptors. 530 * This is enough to deal with a multithreaded 531 * victim process that has half a million lwps. 532 */ 533 rlim.rlim_cur = 1024 * 1024; 534 rlim.rlim_max = 1024 * 1024; 535 if ((Euid != 0 || setrlimit(RLIMIT_NOFILE, &rlim) != 0) && 536 getrlimit(RLIMIT_NOFILE, &rlim) == 0) { 537 /* 538 * Failing the million, give ourself as many 539 * file descriptors as we can get. 540 */ 541 rlim.rlim_cur = rlim.rlim_max; 542 (void) setrlimit(RLIMIT_NOFILE, &rlim); 543 } 544 (void) enable_extended_FILE_stdio(-1, -1); 545 546 setoutput(ofd); /* establish truss output */ 547 istty = isatty(1); 548 549 if (setvbuf(stdout, (char *)NULL, _IOFBF, MYBUFSIZ) != 0) 550 abend("setvbuf() failure", NULL); 551 552 /* 553 * Set up signal dispositions. 554 */ 555 if (created && (oflag || !istty)) { /* ignore interrupts */ 556 (void) sigset(SIGHUP, SIG_IGN); 557 (void) sigset(SIGINT, SIG_IGN); 558 (void) sigset(SIGQUIT, SIG_IGN); 559 } else { /* receive interrupts */ 560 if (sigset(SIGHUP, SIG_IGN) == SIG_DFL) 561 (void) sigset(SIGHUP, intr); 562 if (sigset(SIGINT, SIG_IGN) == SIG_DFL) 563 (void) sigset(SIGINT, intr); 564 if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL) 565 (void) sigset(SIGQUIT, intr); 566 } 567 (void) sigset(SIGTERM, intr); 568 (void) sigset(SIGUSR1, intr); 569 (void) sigset(SIGUSR2, intr); 570 (void) sigset(SIGPIPE, intr); 571 572 /* don't accumulate zombie children */ 573 (void) sigset(SIGCLD, SIG_IGN); 574 575 /* create shared mem space for global mutexes */ 576 577 sharedmem = (fflag || Dynpat != NULL || ngrab > 1); 578 gps = (void *)mmap(NULL, sizeof (struct global_psinfo), 579 PROT_READ|PROT_WRITE, 580 MAP_ANON | (sharedmem? MAP_SHARED : MAP_PRIVATE), 581 -1, (off_t)0); 582 if (gps == MAP_FAILED) 583 abend("cannot allocate ", "memory for counts"); 584 i = sharedmem? USYNC_PROCESS : USYNC_THREAD; 585 (void) mutex_init(&gps->ps_mutex0, i, NULL); 586 (void) mutex_init(&gps->ps_mutex1, i, NULL); 587 (void) mutex_init(&gps->fork_lock, i, NULL); 588 (void) cond_init(&gps->fork_cv, i, NULL); 589 590 591 /* config tmp file if counting and following */ 592 if (fflag && cflag) { 593 char *tmps = tempnam("/var/tmp", "truss"); 594 sfd = open(tmps, O_CREAT|O_APPEND|O_EXCL|O_RDWR, 0600); 595 if (sfd == -1) 596 abend("Error creating tmpfile", NULL); 597 if (unlink(tmps) == -1) 598 abend("Error unlinking tmpfile", NULL); 599 free(tmps); 600 tmps = NULL; 601 } 602 603 if (created) { 604 per_proc_init(); 605 procadd(created, NULL); 606 show_cred(pri, TRUE); 607 } else { /* grab the specified processes */ 608 int gotone = FALSE; 609 610 i = 0; 611 while (i < ngrab) { /* grab first process */ 612 if (grabit(pri, &grab[i++])) { 613 Psp = Pstatus(Proc); 614 Lsp = &Psp->pr_lwp; 615 gotone = TRUE; 616 break; 617 } 618 } 619 if (!gotone) 620 abend(NULL, NULL); 621 per_proc_init(); 622 while (i < ngrab) { /* grab the remainder */ 623 proc_set_t *set = &grab[i++]; 624 625 (void) mutex_lock(&truss_lock); 626 switch (fork()) { 627 case -1: 628 (void) fprintf(stderr, 629 "%s: cannot fork to control process, pid# %d\n", 630 command, (int)set->pid); 631 /* FALLTHROUGH */ 632 default: 633 (void) mutex_unlock(&truss_lock); 634 continue; /* parent carries on */ 635 636 case 0: /* child grabs process */ 637 (void) mutex_unlock(&truss_lock); 638 Pfree(Proc); 639 descendent = TRUE; 640 if (grabit(pri, set)) { 641 Psp = Pstatus(Proc); 642 Lsp = &Psp->pr_lwp; 643 per_proc_init(); 644 break; 645 } 646 exit(2); 647 } 648 break; 649 } 650 free(grab); 651 } 652 653 654 /* 655 * If running setuid-root, become root for real to avoid 656 * affecting the per-user limitation on the maximum number 657 * of processes (one benefit of running setuid-root). 658 */ 659 if (Rgid != Egid) 660 (void) setgid(Egid); 661 if (Ruid != Euid) 662 (void) setuid(Euid); 663 664 if (!created && aflag && prismember(&trace, SYS_execve)) { 665 psargs(pri); 666 Flush(); 667 } 668 669 if (created && Pstate(Proc) != PS_STOP) /* assertion */ 670 if (!(interrupt | sigusr1)) 671 abend("ASSERT error: process is not stopped", NULL); 672 673 traceeven = trace; /* trace these system calls */ 674 675 /* trace these regardless, even if we don't report results */ 676 praddset(&traceeven, SYS_exit); 677 praddset(&traceeven, SYS_lwp_create); 678 praddset(&traceeven, SYS_lwp_exit); 679 praddset(&traceeven, SYS_execve); 680 praddset(&traceeven, SYS_openat); 681 praddset(&traceeven, SYS_openat64); 682 praddset(&traceeven, SYS_open); 683 praddset(&traceeven, SYS_open64); 684 praddset(&traceeven, SYS_vfork); 685 praddset(&traceeven, SYS_forksys); 686 687 /* for I/O buffer dumps, force tracing of read()s and write()s */ 688 if (!isemptyset(&readfd)) { 689 praddset(&traceeven, SYS_read); 690 praddset(&traceeven, SYS_readv); 691 praddset(&traceeven, SYS_pread); 692 praddset(&traceeven, SYS_pread64); 693 praddset(&traceeven, SYS_recv); 694 praddset(&traceeven, SYS_recvfrom); 695 praddset(&traceeven, SYS_recvmsg); 696 } 697 if (!isemptyset(&writefd)) { 698 praddset(&traceeven, SYS_write); 699 praddset(&traceeven, SYS_writev); 700 praddset(&traceeven, SYS_pwrite); 701 praddset(&traceeven, SYS_pwrite64); 702 praddset(&traceeven, SYS_send); 703 praddset(&traceeven, SYS_sendto); 704 praddset(&traceeven, SYS_sendmsg); 705 } 706 707 if (cflag || Eflag) { 708 Psetsysentry(Proc, &traceeven); 709 } 710 Psetsysexit(Proc, &traceeven); 711 712 /* special case -- cannot trace sysexit because context is changed */ 713 if (prismember(&trace, SYS_context)) { 714 (void) Psysentry(Proc, SYS_context, TRUE); 715 (void) Psysexit(Proc, SYS_context, FALSE); 716 prdelset(&traceeven, SYS_context); 717 } 718 719 /* special case -- trace exec() on entry to get the args */ 720 (void) Psysentry(Proc, SYS_execve, TRUE); 721 722 /* special case -- sysexit never reached */ 723 (void) Psysentry(Proc, SYS_exit, TRUE); 724 (void) Psysentry(Proc, SYS_lwp_exit, TRUE); 725 (void) Psysexit(Proc, SYS_exit, FALSE); 726 (void) Psysexit(Proc, SYS_lwp_exit, FALSE); 727 728 Psetsignal(Proc, &signals); /* trace these signals */ 729 Psetfault(Proc, &faults); /* trace these faults */ 730 731 /* for function call tracing */ 732 if (Dynpat != NULL) { 733 /* trace these regardless, to deal with function calls */ 734 (void) Pfault(Proc, FLTBPT, TRUE); 735 (void) Pfault(Proc, FLTTRACE, TRUE); 736 737 /* needed for x86 */ 738 (void) Psetflags(Proc, PR_BPTADJ); 739 740 /* 741 * Find functions and set breakpoints on grabbed process. 742 * A process stopped on exec() gets its breakpoints set below. 743 */ 744 if ((Lsp->pr_why != PR_SYSENTRY && 745 Lsp->pr_why != PR_SYSEXIT) || 746 Lsp->pr_what != SYS_execve) { 747 establish_breakpoints(); 748 establish_stacks(); 749 } 750 } 751 752 /* 753 * Use asynchronous-stop for multithreaded truss. 754 * truss runs one lwp for each lwp in the target process. 755 */ 756 (void) Psetflags(Proc, PR_ASYNC); 757 758 /* flush out all tracing flags now. */ 759 Psync(Proc); 760 761 /* 762 * If we grabbed a running process, set it running again. 763 * Since we are tracing lwp_create() and lwp_exit(), the 764 * lwps will not change in the process until we create all 765 * of the truss worker threads. 766 * We leave a created process stopped so its exec() can be reported. 767 */ 768 first = created? FALSE : TRUE; 769 if (!created && 770 ((Pstate(Proc) == PS_STOP && Lsp->pr_why == PR_REQUESTED) || 771 (Lsp->pr_flags & PR_DSTOP))) 772 first = FALSE; 773 774 main_thread(first); 775 return (0); 776 } 777 778 /* 779 * Called from main() and from control() after fork(). 780 */ 781 void 782 main_thread(int first) 783 { 784 private_t *pri = get_private(); 785 struct tms tms; 786 int flags; 787 int retc; 788 int i; 789 int count; 790 791 /* 792 * Block all signals in the main thread. 793 * Some worker thread will receive signals. 794 */ 795 (void) thr_sigsetmask(SIG_SETMASK, &fillset, NULL); 796 797 /* 798 * If we are dealing with a previously hung process, 799 * arrange not to leave it hung on the same system call. 800 */ 801 primary_lwp = (first && Pstate(Proc) == PS_STOP)? 802 Pstatus(Proc)->pr_lwp.pr_lwpid : 0; 803 804 /* 805 * Create worker threads to match the lwps in the target process. 806 */ 807 truss_nlwp = 0; 808 truss_maxlwp = 1; 809 truss_lwpid = my_realloc(truss_lwpid, sizeof (lwpid_t), NULL); 810 truss_lwpid[0] = 0; 811 count = 0; 812 (void) Plwp_iter(Proc, create_thread, &count); 813 814 if (count == 0) { 815 (void) printf("(Warning: no matching active LWPs found, " 816 "waiting)\n"); 817 Flush(); 818 } 819 820 /* 821 * Set all of the truss worker threads running now. 822 */ 823 (void) mutex_lock(&truss_lock); 824 for (i = 0; i < truss_maxlwp; i++) { 825 if (truss_lwpid[i]) 826 (void) thr_continue(truss_lwpid[i]); 827 } 828 (void) mutex_unlock(&truss_lock); 829 830 /* 831 * Wait until all worker threads terminate. 832 */ 833 while (thr_join(0, NULL, NULL) == 0) 834 continue; 835 836 (void) Punsetflags(Proc, PR_ASYNC); 837 Psync(Proc); 838 if (sigusr1) 839 letgo(pri); 840 flags = PRELEASE_CLEAR; 841 if (leave_hung) 842 flags |= PRELEASE_HANG; 843 Prelease(Proc, flags); 844 845 procdel(); 846 retc = (leave_hung? 0 : wait4all()); 847 848 if (!descendent) { 849 interrupt = 0; /* another interrupt kills the report */ 850 if (cflag) { 851 if (fflag) 852 file_to_parent(); 853 report(pri, times(&tms) - starttime); 854 } 855 } else if (cflag && fflag) { 856 child_to_file(); 857 } 858 859 exit(retc); /* exit with exit status of created process, else 0 */ 860 } 861 862 void * 863 worker_thread(void *arg) 864 { 865 struct ps_lwphandle *Lwp = (struct ps_lwphandle *)arg; 866 const pstatus_t *Psp = Pstatus(Proc); 867 const lwpstatus_t *Lsp = Lstatus(Lwp); 868 struct syscount *scp; 869 lwpid_t who = Lsp->pr_lwpid; 870 int first = (who == primary_lwp); 871 private_t *pri = get_private(); 872 int req_flag = 0; 873 int leave_it_hung = FALSE; 874 int reset_traps = FALSE; 875 int gcode; 876 int what; 877 int ow_in_effect = 0; 878 long ow_syscall = 0; 879 long ow_subcode = 0; 880 char *ow_string = NULL; 881 sysset_t full_set; 882 sysset_t running_set; 883 int dotrace = lwptrace(Psp->pr_pid, Lsp->pr_lwpid); 884 885 pri->Lwp = Lwp; 886 pri->lwpstat = Lsp; 887 pri->syslast = Lsp->pr_stime; 888 pri->usrlast = Lsp->pr_utime; 889 make_pname(pri, 0); 890 891 prfillset(&full_set); 892 893 /* we were created with all signals blocked; unblock them */ 894 (void) thr_sigsetmask(SIG_SETMASK, &emptyset, NULL); 895 896 /* 897 * Run this loop until the victim lwp terminates or we receive 898 * a termination condition (leave_hung | interrupt | sigusr1). 899 */ 900 for (;;) { 901 if (interrupt | sigusr1) { 902 (void) Lstop(Lwp, MILLISEC); 903 if (Lstate(Lwp) == PS_RUN) 904 break; 905 } 906 if (Lstate(Lwp) == PS_RUN) { 907 /* millisecond timeout is for sleeping syscalls */ 908 uint_t tout = (iflag || req_flag)? 0 : MILLISEC; 909 910 /* 911 * If we are to leave this lwp stopped in sympathy 912 * with another lwp that has been left hung, or if 913 * we have been interrupted or instructed to release 914 * our victim process, and this lwp is stopped but 915 * not on an event of interest to /proc, then just 916 * leave it in that state. 917 */ 918 if ((leave_hung | interrupt | sigusr1) && 919 (Lsp->pr_flags & (PR_STOPPED|PR_ISTOP)) 920 == PR_STOPPED) 921 break; 922 923 (void) Lwait(Lwp, tout); 924 if (Lstate(Lwp) == PS_RUN && 925 tout != 0 && !(interrupt | sigusr1)) { 926 (void) mutex_lock(&truss_lock); 927 if ((Lsp->pr_flags & PR_STOPPED) && 928 Lsp->pr_why == PR_JOBCONTROL) 929 req_flag = jobcontrol(pri, dotrace); 930 else 931 req_flag = requested(pri, req_flag, 932 dotrace); 933 (void) mutex_unlock(&truss_lock); 934 } 935 continue; 936 } 937 data_model = Psp->pr_dmodel; 938 if (Lstate(Lwp) == PS_UNDEAD) 939 break; 940 if (Lstate(Lwp) == PS_LOST) { /* we lost control */ 941 /* 942 * After exec(), only one LWP remains in the process. 943 * /proc makes the thread following that LWP receive 944 * EAGAIN (PS_LOST) if the program being exec()ed 945 * is a set-id program. Every other controlling 946 * thread receives ENOENT (because its LWP vanished). 947 * We are the controlling thread for the exec()ing LWP. 948 * We must wait until all of our siblings terminate 949 * before attempting to reopen the process. 950 */ 951 (void) mutex_lock(&truss_lock); 952 while (truss_nlwp > 1) 953 (void) cond_wait(&truss_cv, &truss_lock); 954 if (Preopen(Proc) == 0) { /* we got control back */ 955 /* 956 * We have to free and re-grab the LWP. 957 * The process is guaranteed to be at exit 958 * from exec() or execve() and have only 959 * one LWP, namely this one, and the LWP 960 * is guaranteed to have lwpid == 1. 961 * This "cannot fail". 962 */ 963 who = 1; 964 Lfree(Lwp); 965 pri->Lwp = Lwp = 966 Lgrab(Proc, who, &gcode); 967 if (Lwp == NULL) 968 abend("Lgrab error: ", 969 Lgrab_error(gcode)); 970 pri->lwpstat = Lsp = Lstatus(Lwp); 971 (void) mutex_unlock(&truss_lock); 972 continue; 973 } 974 975 /* we really lost it */ 976 if (pri->exec_string && *pri->exec_string) { 977 if (pri->exec_pname[0] != '\0') 978 (void) fputs(pri->exec_pname, stdout); 979 timestamp(pri); 980 (void) fputs(pri->exec_string, stdout); 981 (void) fputc('\n', stdout); 982 } else if (pri->length) { 983 (void) fputc('\n', stdout); 984 } 985 if (pri->sys_valid) 986 (void) printf( 987 "%s\t*** cannot trace across exec() of %s ***\n", 988 pri->pname, pri->sys_path); 989 else 990 (void) printf( 991 "%s\t*** lost control of process ***\n", 992 pri->pname); 993 pri->length = 0; 994 Flush(); 995 (void) mutex_unlock(&truss_lock); 996 break; 997 } 998 if (Lstate(Lwp) != PS_STOP) { 999 (void) fprintf(stderr, 1000 "%s: state = %d\n", command, Lstate(Lwp)); 1001 abend(pri->pname, "uncaught status of subject lwp"); 1002 } 1003 1004 make_pname(pri, 0); 1005 1006 (void) mutex_lock(&truss_lock); 1007 1008 what = Lsp->pr_what; 1009 req_flag = 0; 1010 1011 switch (Lsp->pr_why) { 1012 case PR_REQUESTED: 1013 break; 1014 case PR_SIGNALLED: 1015 req_flag = signalled(pri, req_flag, dotrace); 1016 if (Sflag && !first && prismember(&sighang, what)) 1017 leave_it_hung = TRUE; 1018 break; 1019 case PR_FAULTED: 1020 if (what == FLTBPT) { 1021 int rval; 1022 1023 (void) Pstop(Proc, 0); 1024 rval = function_trace(pri, first, 0, dotrace); 1025 if (rval == 1) 1026 leave_it_hung = TRUE; 1027 if (rval >= 0) 1028 break; 1029 } 1030 if (faulted(pri, dotrace) && 1031 Mflag && !first && prismember(&flthang, what)) 1032 leave_it_hung = TRUE; 1033 break; 1034 case PR_JOBCONTROL: /* can't happen except first time */ 1035 req_flag = jobcontrol(pri, dotrace); 1036 break; 1037 case PR_SYSENTRY: 1038 /* protect ourself from operating system error */ 1039 if (what <= 0 || what > PRMAXSYS) 1040 what = PRMAXSYS; 1041 pri->length = 0; 1042 /* 1043 * ow_in_effect checks to see whether or not we 1044 * are attempting to quantify the time spent in 1045 * a one way system call. This is necessary as 1046 * some system calls never return, yet it is desireable 1047 * to determine how much time the traced process 1048 * spends in these calls. To do this, a one way 1049 * flag is set on SYSENTRY when the call is recieved. 1050 * After this, the call mask for the SYSENTRY events 1051 * is filled so that the traced process will stop 1052 * on the entry to the very next system call. 1053 * This appears to the the best way to determine 1054 * system time elapsed between a one way system call. 1055 * Once the next call occurs, values that have been 1056 * stashed are used to record the correct syscall 1057 * and time, and the SYSENTRY event mask is restored 1058 * so that the traced process may continue. 1059 */ 1060 if (dotrace && ow_in_effect) { 1061 if (cflag) { 1062 (void) mutex_lock(&count_lock); 1063 scp = Cp->syscount[ow_syscall]; 1064 if (ow_subcode != -1) 1065 scp += ow_subcode; 1066 scp->count++; 1067 accumulate(&scp->stime, 1068 &Lsp->pr_stime, &pri->syslast); 1069 accumulate(&Cp->usrtotal, 1070 &Lsp->pr_utime, &pri->usrlast); 1071 pri->syslast = Lsp->pr_stime; 1072 pri->usrlast = Lsp->pr_utime; 1073 (void) mutex_unlock(&count_lock); 1074 } else if (Eflag) { 1075 putpname(pri); 1076 timestamp(pri); 1077 (void) printf("%s\n", ow_string); 1078 free(ow_string); 1079 ow_string = NULL; 1080 pri->syslast = Lsp->pr_stime; 1081 } 1082 ow_in_effect = 0; 1083 Psetsysentry(Proc, &running_set); 1084 } 1085 1086 /* 1087 * Special cases. Most syscalls are traced on exit. 1088 */ 1089 switch (what) { 1090 case SYS_exit: /* exit() */ 1091 case SYS_lwp_exit: /* lwp_exit() */ 1092 case SYS_context: /* [get|set]context() */ 1093 if (dotrace && cflag && 1094 prismember(&trace, what)) { 1095 ow_in_effect = 1; 1096 ow_syscall = what; 1097 ow_subcode = getsubcode(pri); 1098 pri->syslast = Lsp->pr_stime; 1099 running_set = 1100 (Pstatus(Proc))->pr_sysentry; 1101 Psetsysentry(Proc, &full_set); 1102 } else if (dotrace && Eflag && 1103 prismember(&trace, what)) { 1104 (void) sysentry(pri, dotrace); 1105 ow_in_effect = 1; 1106 ow_string = my_malloc( 1107 strlen(pri->sys_string) + 1, NULL); 1108 (void) strcpy(ow_string, 1109 pri->sys_string); 1110 running_set = 1111 (Pstatus(Proc))->pr_sysentry; 1112 Psetsysentry(Proc, &full_set); 1113 pri->syslast = Lsp->pr_stime; 1114 } else if (dotrace && 1115 prismember(&trace, what)) { 1116 (void) sysentry(pri, dotrace); 1117 putpname(pri); 1118 timestamp(pri); 1119 pri->length += 1120 printf("%s\n", pri->sys_string); 1121 Flush(); 1122 } 1123 pri->sys_leng = 0; 1124 *pri->sys_string = '\0'; 1125 1126 if (what == SYS_exit) 1127 exit_called = TRUE; 1128 break; 1129 case SYS_execve: 1130 (void) sysentry(pri, dotrace); 1131 if (dotrace && !cflag && 1132 prismember(&trace, what)) { 1133 pri->exec_string = 1134 my_realloc(pri->exec_string, 1135 strlen(pri->sys_string) + 1, 1136 NULL); 1137 (void) strcpy(pri->exec_pname, 1138 pri->pname); 1139 (void) strcpy(pri->exec_string, 1140 pri->sys_string); 1141 pri->length += strlen(pri->sys_string); 1142 pri->exec_lwpid = Lsp->pr_lwpid; 1143 } 1144 pri->sys_leng = 0; 1145 *pri->sys_string = '\0'; 1146 break; 1147 default: 1148 if (dotrace && (cflag || Eflag) && 1149 prismember(&trace, what)) { 1150 pri->syslast = Lsp->pr_stime; 1151 } 1152 break; 1153 } 1154 if (dotrace && Tflag && !first && 1155 (prismember(&syshang, what) || 1156 (exit_called && prismember(&syshang, SYS_exit)))) 1157 leave_it_hung = TRUE; 1158 break; 1159 case PR_SYSEXIT: 1160 /* check for write open of a /proc file */ 1161 if (what == SYS_openat || what == SYS_openat64 || 1162 what == SYS_open || what == SYS_open64) { 1163 int readonly; 1164 1165 (void) sysentry(pri, dotrace); 1166 pri->Errno = Lsp->pr_errno; 1167 pri->ErrPriv = Lsp->pr_errpriv; 1168 readonly = 1169 ((what == SYS_openat || 1170 what == SYS_openat64) && 1171 pri->sys_nargs > 2 && 1172 (pri->sys_args[2]&0x3) == O_RDONLY) || 1173 ((what == SYS_open || 1174 what == SYS_open64) && 1175 pri->sys_nargs > 1 && 1176 (pri->sys_args[1]&0x3) == O_RDONLY); 1177 if ((pri->Errno == 0 || pri->Errno == EBUSY) && 1178 pri->sys_valid && !readonly) { 1179 int rv = checkproc(pri); 1180 if (rv == 1 && Fflag != PGRAB_FORCE) { 1181 /* 1182 * The process opened itself 1183 * and no -F flag was specified. 1184 * Just print the open() call 1185 * and let go of the process. 1186 */ 1187 if (dotrace && !cflag && 1188 prismember(&trace, what)) { 1189 putpname(pri); 1190 timestamp(pri); 1191 (void) printf("%s\n", 1192 pri->sys_string); 1193 Flush(); 1194 } 1195 sigusr1 = TRUE; 1196 (void) mutex_unlock( 1197 &truss_lock); 1198 goto out; 1199 } 1200 if (rv == 2) { 1201 /* 1202 * Process opened someone else. 1203 * The open is being reissued. 1204 * Don't report this one. 1205 */ 1206 pri->sys_leng = 0; 1207 *pri->sys_string = '\0'; 1208 pri->sys_nargs = 0; 1209 break; 1210 } 1211 } 1212 } 1213 if (what == SYS_execve && pri->Errno == 0) { 1214 /* 1215 * Refresh the data model on exec() in case it 1216 * is different from the parent. Lwait() 1217 * doesn't update process-wide status, so we 1218 * have to explicitly call Pstopstatus() to get 1219 * the new state. 1220 */ 1221 (void) Pstopstatus(Proc, PCNULL, 0); 1222 data_model = Psp->pr_dmodel; 1223 } 1224 if (sysexit(pri, dotrace)) 1225 Flush(); 1226 if (what == SYS_lwp_create && pri->Rval1 != 0) { 1227 struct ps_lwphandle *new_Lwp; 1228 lwpid_t lwpid; 1229 1230 if ((new_Lwp = grab_lwp(pri->Rval1)) != NULL) { 1231 (void) thr_sigsetmask(SIG_SETMASK, 1232 &fillset, NULL); 1233 if (thr_create(NULL, 0, worker_thread, 1234 new_Lwp, THR_BOUND | THR_SUSPENDED, 1235 &lwpid) != 0) 1236 abend("cannot create lwp ", 1237 "to follow child lwp"); 1238 insert_lwpid(lwpid); 1239 (void) thr_continue(lwpid); 1240 (void) thr_sigsetmask(SIG_SETMASK, 1241 &emptyset, NULL); 1242 } 1243 } 1244 pri->sys_nargs = 0; 1245 if (dotrace && Tflag && !first && 1246 prismember(&syshang, what)) 1247 leave_it_hung = TRUE; 1248 if (what == SYS_execve && pri->Errno == 0) { 1249 is_vfork_child = FALSE; 1250 reset_breakpoints(); 1251 /* 1252 * exec() resets the calling LWP's lwpid to 1. 1253 * If the LWP has changed its lwpid, then 1254 * we have to free and re-grab the LWP 1255 * in order to keep libproc consistent. 1256 * This "cannot fail". 1257 */ 1258 if (who != Lsp->pr_lwpid) { 1259 /* 1260 * We must wait for all of our 1261 * siblings to terminate. 1262 */ 1263 while (truss_nlwp > 1) 1264 (void) cond_wait(&truss_cv, 1265 &truss_lock); 1266 who = Lsp->pr_lwpid; 1267 Lfree(Lwp); 1268 pri->Lwp = Lwp = 1269 Lgrab(Proc, who, &gcode); 1270 if (Lwp == NULL) 1271 abend("Lgrab error: ", 1272 Lgrab_error(gcode)); 1273 pri->lwpstat = Lsp = Lstatus(Lwp); 1274 } 1275 } 1276 break; 1277 default: 1278 req_flag = 0; 1279 (void) fprintf(stderr, 1280 "unknown reason for stopping: %d/%d\n", 1281 Lsp->pr_why, what); 1282 abend(NULL, NULL); 1283 } 1284 1285 if (pri->child) { /* controlled process fork()ed */ 1286 if (fflag || Dynpat != NULL) { 1287 if (Lsp->pr_why == PR_SYSEXIT && 1288 (Lsp->pr_what == SYS_vfork || 1289 (Lsp->pr_what == SYS_forksys && 1290 Lsp->pr_sysarg[0] == 2))) { 1291 is_vfork_child = TRUE; 1292 (void) Pstop(Proc, 0); 1293 } 1294 if (control(pri, pri->child)) { 1295 (void) mutex_unlock(&truss_lock); 1296 pri->child = 0; 1297 if (!fflag) { 1298 /* 1299 * If this is vfork(), then 1300 * this clears the breakpoints 1301 * in the parent's address space 1302 * as well as in the child's. 1303 */ 1304 clear_breakpoints(); 1305 Prelease(Proc, PRELEASE_CLEAR); 1306 _exit(0); 1307 } 1308 main_thread(FALSE); 1309 /* NOTREACHED */ 1310 } 1311 1312 /* 1313 * Here, we are still the parent truss. 1314 * If the child messes with the breakpoints and 1315 * this is vfork(), we have to set them again. 1316 */ 1317 if (Dynpat != NULL && is_vfork_child && !fflag) 1318 reset_traps = TRUE; 1319 is_vfork_child = FALSE; 1320 } 1321 pri->child = 0; 1322 } 1323 1324 if (leave_it_hung) { 1325 (void) mutex_unlock(&truss_lock); 1326 break; 1327 } 1328 1329 if (reset_traps) { 1330 /* 1331 * To recover from vfork, we must catch the lwp 1332 * that issued the vfork() when it returns to user 1333 * level, with all other lwps remaining stopped. 1334 * For this purpose, we have directed all lwps to 1335 * stop and we now set the vfork()ing lwp running 1336 * with the PRSTEP flag. We expect to capture it 1337 * when it stops again showing PR_FAULTED/FLTTRACE. 1338 * We are holding truss_lock, so no other threads 1339 * in truss will set any other lwps in the victim 1340 * process running. 1341 */ 1342 reset_traps = FALSE; 1343 (void) Lsetrun(Lwp, 0, PRSTEP); 1344 do { 1345 (void) Lwait(Lwp, 0); 1346 } while (Lstate(Lwp) == PS_RUN); 1347 if (Lstate(Lwp) == PS_STOP && 1348 Lsp->pr_why == PR_FAULTED && 1349 Lsp->pr_what == FLTTRACE) { 1350 reestablish_traps(); 1351 (void) Lsetrun(Lwp, 0, PRCFAULT|PRSTOP); 1352 } else { 1353 (void) printf("%s\t*** Expected PR_FAULTED/" 1354 "FLTTRACE stop following vfork()\n", 1355 pri->pname); 1356 } 1357 } 1358 1359 if (Lstate(Lwp) == PS_STOP) { 1360 int flags = 0; 1361 1362 if (interrupt | sigusr1) { 1363 (void) mutex_unlock(&truss_lock); 1364 break; 1365 } 1366 /* 1367 * If we must leave this lwp hung is sympathy with 1368 * another lwp that is being left hung on purpose, 1369 * then push the state onward toward PR_REQUESTED. 1370 */ 1371 if (leave_hung) { 1372 if (Lsp->pr_why == PR_REQUESTED) { 1373 (void) mutex_unlock(&truss_lock); 1374 break; 1375 } 1376 flags |= PRSTOP; 1377 } 1378 if (Lsetrun(Lwp, 0, flags) != 0 && 1379 Lstate(Lwp) != PS_LOST && 1380 Lstate(Lwp) != PS_UNDEAD) { 1381 (void) mutex_unlock(&truss_lock); 1382 perror("Lsetrun"); 1383 abend("cannot start subject lwp", NULL); 1384 /* NOTREACHED */ 1385 } 1386 } 1387 first = FALSE; 1388 1389 (void) mutex_unlock(&truss_lock); 1390 } 1391 1392 out: 1393 /* block all signals in preparation for exiting */ 1394 (void) thr_sigsetmask(SIG_SETMASK, &fillset, NULL); 1395 1396 if (Lstate(Lwp) == PS_UNDEAD || Lstate(Lwp) == PS_LOST) 1397 (void) mutex_lock(&truss_lock); 1398 else { 1399 (void) Lstop(Lwp, MILLISEC); 1400 (void) mutex_lock(&truss_lock); 1401 if (Lstate(Lwp) == PS_STOP && 1402 Lsp->pr_why == PR_FAULTED && 1403 Lsp->pr_what == FLTBPT) 1404 (void) function_trace(pri, 0, 1, dotrace); 1405 } 1406 1407 if (dotrace && ow_in_effect) { 1408 if (cflag) { 1409 (void) mutex_lock(&count_lock); 1410 scp = Cp->syscount[ow_syscall]; 1411 if (ow_subcode != -1) 1412 scp += ow_subcode; 1413 scp->count++; 1414 accumulate(&scp->stime, 1415 &Lsp->pr_stime, &pri->syslast); 1416 accumulate(&Cp->usrtotal, 1417 &Lsp->pr_utime, &pri->usrlast); 1418 pri->syslast = Lsp->pr_stime; 1419 pri->usrlast = Lsp->pr_utime; 1420 (void) mutex_unlock(&count_lock); 1421 } else if (Eflag) { 1422 putpname(pri); 1423 timestamp(pri); 1424 (void) printf("%s\n", ow_string); 1425 free(ow_string); 1426 ow_string = NULL; 1427 pri->syslast = Lsp->pr_stime; 1428 } 1429 ow_in_effect = 0; 1430 Psetsysentry(Proc, &running_set); 1431 } 1432 1433 if (Lstate(Lwp) == PS_UNDEAD || Lstate(Lwp) == PS_LOST) { 1434 /* 1435 * The victim thread has exited or we lost control of 1436 * the process. Remove ourself from the list of all 1437 * truss threads and notify everyone waiting for this. 1438 */ 1439 lwpid_t my_id = thr_self(); 1440 int i; 1441 1442 for (i = 0; i < truss_maxlwp; i++) { 1443 if (truss_lwpid[i] == my_id) { 1444 truss_lwpid[i] = 0; 1445 break; 1446 } 1447 } 1448 if (--truss_nlwp != 0) { 1449 (void) cond_broadcast(&truss_cv); 1450 } else { 1451 /* 1452 * The last truss worker thread is terminating. 1453 * The address space is gone (UNDEAD) or is 1454 * inaccessible (LOST) so we cannot clear the 1455 * breakpoints. Just report the htable stats. 1456 */ 1457 report_htable_stats(); 1458 } 1459 } else { 1460 /* 1461 * The victim thread is not a zombie thread, and we have not 1462 * lost control of the process. We must have gotten here due 1463 * to (leave_hung || leave_it_hung || interrupt || sigusr1). 1464 * In these cases, we must carefully uninstrument the process 1465 * and either set it running or leave it stopped and abandoned. 1466 */ 1467 static int nstopped = 0; 1468 static int cleared = 0; 1469 1470 if (leave_it_hung) 1471 leave_hung = TRUE; 1472 if ((leave_hung | interrupt | sigusr1) == 0) 1473 abend("(leave_hung | interrupt | sigusr1) == 0", NULL); 1474 1475 /* 1476 * The first truss thread through here needs to instruct all 1477 * application threads to stop -- they're not necessarily 1478 * going to stop on their own. 1479 */ 1480 if (nstopped++ == 0) 1481 (void) Pdstop(Proc); 1482 1483 /* 1484 * Notify all other worker threads about the reason 1485 * for being here (leave_hung || interrupt || sigusr1). 1486 */ 1487 broadcast_signals(); 1488 1489 /* 1490 * Once the last thread has reached this point, then and 1491 * only then is it safe to remove breakpoints and other 1492 * instrumentation. Since breakpoints are executed without 1493 * truss_lock held, a monitor thread can't exit until all 1494 * breakpoints have been removed, and we can't be sure the 1495 * procedure to execute a breakpoint won't temporarily 1496 * reinstall a breakpont. Accordingly, we need to wait 1497 * until all threads are in a known state. 1498 */ 1499 while (nstopped != truss_nlwp) 1500 (void) cond_wait(&truss_cv, &truss_lock); 1501 1502 /* 1503 * All truss threads have reached this point. 1504 * One of them clears the breakpoints and 1505 * wakes up everybody else to finish up. 1506 */ 1507 if (cleared++ == 0) { 1508 /* 1509 * All threads should already be stopped, 1510 * but just to be safe... 1511 */ 1512 (void) Pstop(Proc, MILLISEC); 1513 clear_breakpoints(); 1514 (void) Psysexit(Proc, SYS_vfork, FALSE); 1515 (void) Psysexit(Proc, SYS_forksys, FALSE); 1516 (void) Punsetflags(Proc, PR_FORK); 1517 Psync(Proc); 1518 fflag = 0; 1519 (void) cond_broadcast(&truss_cv); 1520 } 1521 1522 if (!leave_hung && Lstate(Lwp) == PS_STOP) 1523 (void) Lsetrun(Lwp, 0, 0); 1524 } 1525 1526 (void) Lfree(Lwp); 1527 (void) mutex_unlock(&truss_lock); 1528 return (NULL); 1529 } 1530 1531 /* 1532 * Give a base date for time stamps, adjusted to the 1533 * stop time of the selected (first or created) process. 1534 */ 1535 void 1536 setup_basetime(hrtime_t basehrtime, struct timeval *basedate) 1537 { 1538 const pstatus_t *Psp = Pstatus(Proc); 1539 (void) mutex_lock(&count_lock); 1540 Cp->basetime = Psp->pr_lwp.pr_tstamp; 1541 (void) mutex_unlock(&count_lock); 1542 1543 if ((dflag|Dflag) && !cflag) { 1544 const struct tm *ptm; 1545 const char *ptime; 1546 const char *pdst; 1547 hrtime_t delta = basehrtime - 1548 ((hrtime_t)Cp->basetime.tv_sec * NANOSEC + 1549 Cp->basetime.tv_nsec); 1550 1551 if (delta > 0) { 1552 basedate->tv_sec -= (time_t)(delta / NANOSEC); 1553 basedate->tv_usec -= (delta % NANOSEC) / 1000; 1554 if (basedate->tv_usec < 0) { 1555 basedate->tv_sec--; 1556 basedate->tv_usec += MICROSEC; 1557 } 1558 } 1559 ptm = localtime(&basedate->tv_sec); 1560 ptime = asctime(ptm); 1561 if ((pdst = tzname[ptm->tm_isdst ? 1 : 0]) == NULL) 1562 pdst = "???"; 1563 if (dflag) { 1564 (void) printf( 1565 "Base time stamp: %ld.%4.4ld [ %.20s%s %.4s ]\n", 1566 basedate->tv_sec, basedate->tv_usec / 100, 1567 ptime, pdst, ptime + 20); 1568 Flush(); 1569 } 1570 } 1571 } 1572 1573 /* 1574 * Performs per-process initializations. If truss is following a victim 1575 * process it will fork additional truss processes to follow new processes 1576 * created. Here is where each new truss process gets its per-process data 1577 * initialized. 1578 */ 1579 1580 void 1581 per_proc_init() 1582 { 1583 void *pmem; 1584 struct timeval basedate; 1585 hrtime_t basehrtime; 1586 struct syscount *scp; 1587 int i; 1588 timestruc_t c_basetime; 1589 1590 /* Make sure we only configure the basetime for the first truss proc */ 1591 1592 if (Cp == NULL) { 1593 pmem = my_malloc(sizeof (struct counts) + maxsyscalls() * 1594 sizeof (struct syscount), NULL); 1595 Cp = (struct counts *)pmem; 1596 basehrtime = gethrtime(); 1597 (void) gettimeofday(&basedate, NULL); 1598 setup_basetime(basehrtime, &basedate); 1599 } 1600 1601 c_basetime = Cp->basetime; 1602 1603 (void) memset(Cp, 0, sizeof (struct counts) + maxsyscalls() * 1604 sizeof (struct syscount)); 1605 1606 Cp->basetime = c_basetime; 1607 1608 if (fcall_tbl != NULL) 1609 destroy_hash(fcall_tbl); 1610 fcall_tbl = init_hash(4096); 1611 1612 (void) mutex_lock(&count_lock); 1613 scp = (struct syscount *)(Cp + 1); 1614 for (i = 0; i <= PRMAXSYS; i++) { 1615 Cp->syscount[i] = scp; 1616 scp += nsubcodes(i); 1617 } 1618 (void) mutex_unlock(&count_lock); 1619 } 1620 1621 1622 /* 1623 * Writes child state to a tempfile where it can be read and 1624 * accumulated by the parent process. The file descriptor is shared 1625 * among the processes. Ordering of writes does not matter, it is, however, 1626 * necessary to ensure that all writes are atomic. 1627 */ 1628 1629 void 1630 child_to_file() 1631 { 1632 hiter_t *itr; 1633 hentry_t *ntry; 1634 hdntry_t fentry; 1635 char *s = NULL; 1636 char *t = NULL; 1637 unsigned char *buf = NULL; 1638 size_t bufsz = 0; 1639 size_t i = 0; 1640 size_t j = 0; 1641 1642 /* ensure that we are in fact a child process */ 1643 if (!descendent) 1644 return; 1645 1646 /* enumerate fcall_tbl (tbl locked until freed) */ 1647 if (Dynpat != NULL) { 1648 itr = iterate_hash(fcall_tbl); 1649 1650 ntry = iter_next(itr); 1651 while (ntry != NULL) { 1652 fentry.type = HD_hashntry; 1653 fentry.count = ntry->count; 1654 s = ntry->key; 1655 t = ntry->lib; 1656 i = strlen(s) + 1; 1657 j = strlen(t) + 1; 1658 fentry.sz_key = i; 1659 fentry.sz_lib = j; 1660 if (i + sizeof (fentry) > bufsz) { 1661 buf = my_realloc(buf, i + j + sizeof (fentry), 1662 NULL); 1663 bufsz = i + j + sizeof (fentry); 1664 } 1665 (void) memcpy(buf, &fentry, sizeof (fentry)); 1666 (void) strlcpy((char *)(buf + sizeof (fentry)), t, j); 1667 (void) strlcpy((char *)(buf + sizeof (fentry) + j), 1668 s, i); 1669 if (write(sfd, buf, sizeof (fentry) + i + j) == -1) 1670 abend("Error writing to tmp file", NULL); 1671 ntry = iter_next(itr); 1672 } 1673 iter_free(itr); 1674 } 1675 1676 /* Now write the count/syscount structs down */ 1677 bufsz = sizeof (fentry) + (sizeof (struct counts) + maxsyscalls() * 1678 sizeof (struct syscount)); 1679 buf = my_realloc(buf, bufsz, NULL); 1680 fentry.type = HD_cts_syscts; 1681 fentry.count = 0; /* undefined, really */ 1682 fentry.sz_key = bufsz - sizeof (fentry); 1683 fentry.sz_lib = 0; /* also undefined */ 1684 (void) memcpy(buf, &fentry, sizeof (fentry)); 1685 (void) memcpy((char *)(buf + sizeof (fentry)), Cp, 1686 bufsz - sizeof (fentry)); 1687 if (write(sfd, buf, bufsz) == -1) 1688 abend("Error writing cts/syscts to tmpfile", NULL); 1689 1690 free(buf); 1691 } 1692 1693 /* 1694 * The following reads entries from the tempfile back to the parent 1695 * so that information can be collected and summed for overall statistics. 1696 * This reads records out of the tempfile. If they are hash table entries, 1697 * the record is merged with the hash table kept by the parent process. 1698 * If the information is a struct count/struct syscount pair, they are 1699 * copied and added into the count/syscount array kept by the parent. 1700 */ 1701 1702 void 1703 file_to_parent() 1704 { 1705 hdntry_t ntry; 1706 char *s = NULL; 1707 char *t = NULL; 1708 size_t c_offset = 0; 1709 size_t filesz; 1710 size_t t_strsz = 0; 1711 size_t s_strsz = 0; 1712 struct stat fsi; 1713 1714 if (descendent) 1715 return; 1716 1717 if (fstat(sfd, &fsi) == -1) 1718 abend("Error stat-ing tempfile", NULL); 1719 filesz = fsi.st_size; 1720 1721 while (c_offset < filesz) { 1722 /* first get hdntry */ 1723 if (pread(sfd, &ntry, sizeof (hdntry_t), c_offset) != 1724 sizeof (hdntry_t)) 1725 abend("Unable to perform full read of hdntry", NULL); 1726 c_offset += sizeof (hdntry_t); 1727 1728 switch (ntry.type) { 1729 case HD_hashntry: 1730 1731 /* first get lib string */ 1732 if (ntry.sz_lib > t_strsz) { 1733 t = my_realloc(t, ntry.sz_lib, NULL); 1734 t_strsz = ntry.sz_lib; 1735 } 1736 1737 (void) memset(t, 0, t_strsz); 1738 1739 /* now actually get the string */ 1740 if (pread(sfd, t, ntry.sz_lib, c_offset) != ntry.sz_lib) 1741 abend("Unable to perform full read of lib str", 1742 NULL); 1743 c_offset += ntry.sz_lib; 1744 1745 /* now get key string */ 1746 1747 if (ntry.sz_key > s_strsz) { 1748 s = my_realloc(s, ntry.sz_key, NULL); 1749 s_strsz = ntry.sz_key; 1750 } 1751 (void) memset(s, 0, s_strsz); 1752 if (pread(sfd, s, ntry.sz_key, c_offset) != ntry.sz_key) 1753 abend("Unable to perform full read of key str", 1754 NULL); 1755 c_offset += ntry.sz_key; 1756 1757 add_fcall(fcall_tbl, t, s, ntry.count); 1758 break; 1759 1760 case HD_cts_syscts: 1761 { 1762 struct counts *ncp; 1763 size_t bfsz = sizeof (struct counts) + maxsyscalls() 1764 * sizeof (struct syscount); 1765 int i; 1766 struct syscount *sscp; 1767 1768 if (ntry.sz_key != bfsz) 1769 abend("cts/syscts size does not sanity check", 1770 NULL); 1771 ncp = my_malloc(ntry.sz_key, NULL); 1772 1773 if (pread(sfd, ncp, ntry.sz_key, c_offset) != 1774 ntry.sz_key) 1775 abend("Unable to perform full read of cts", 1776 NULL); 1777 c_offset += ntry.sz_key; 1778 1779 sscp = (struct syscount *)(ncp + 1); 1780 1781 (void) mutex_lock(&count_lock); 1782 1783 Cp->usrtotal.tv_sec += ncp->usrtotal.tv_sec; 1784 Cp->usrtotal.tv_nsec += ncp->usrtotal.tv_nsec; 1785 if (Cp->usrtotal.tv_nsec >= NANOSEC) { 1786 Cp->usrtotal.tv_nsec -= NANOSEC; 1787 Cp->usrtotal.tv_sec++; 1788 } 1789 for (i = 0; i <= PRMAXSYS; i++) { 1790 ncp->syscount[i] = sscp; 1791 sscp += nsubcodes(i); 1792 } 1793 1794 for (i = 0; i <= PRMAXFAULT; i++) { 1795 Cp->fltcount[i] += ncp->fltcount[i]; 1796 } 1797 1798 for (i = 0; i <= PRMAXSIG; i++) { 1799 Cp->sigcount[i] += ncp->sigcount[i]; 1800 } 1801 1802 for (i = 0; i <= PRMAXSYS; i++) { 1803 struct syscount *scp = Cp->syscount[i]; 1804 struct syscount *nscp = ncp->syscount[i]; 1805 int n = nsubcodes(i); 1806 int subcode; 1807 1808 for (subcode = 0; subcode < n; subcode++, 1809 scp++, nscp++) { 1810 scp->count += nscp->count; 1811 scp->error += nscp->error; 1812 scp->stime.tv_sec += nscp->stime.tv_sec; 1813 scp->stime.tv_nsec += 1814 nscp->stime.tv_nsec; 1815 if (scp->stime.tv_nsec >= NANOSEC) { 1816 scp->stime.tv_nsec -= NANOSEC; 1817 scp->stime.tv_sec++; 1818 } 1819 } 1820 } 1821 (void) mutex_unlock(&count_lock); 1822 free(ncp); 1823 break; 1824 } 1825 default: 1826 1827 abend("Unknown file entry type encountered", NULL); 1828 break; 1829 1830 } 1831 1832 if (fstat(sfd, &fsi) == -1) 1833 abend("Error stat-ing tempfile", NULL); 1834 filesz = fsi.st_size; 1835 } 1836 if (s != NULL) 1837 free(s); 1838 if (t != NULL) 1839 free(t); 1840 } 1841 1842 void 1843 make_pname(private_t *pri, id_t tid) 1844 { 1845 if (!cflag) { 1846 int ff = (fflag || ngrab > 1); 1847 int lf = (lflag | tid | (Thr_agent != NULL) | (truss_nlwp > 1)); 1848 pid_t pid = Pstatus(Proc)->pr_pid; 1849 id_t lwpid = pri->lwpstat->pr_lwpid; 1850 1851 if (ff != pri->pparam.ff || 1852 lf != pri->pparam.lf || 1853 pid != pri->pparam.pid || 1854 lwpid != pri->pparam.lwpid || 1855 tid != pri->pparam.tid) { 1856 char *s = pri->pname; 1857 1858 if (ff) 1859 s += sprintf(s, "%d", (int)pid); 1860 if (lf) 1861 s += sprintf(s, "/%d", (int)lwpid); 1862 if (tid) 1863 s += sprintf(s, "@%d", (int)tid); 1864 if (ff || lf) 1865 *s++ = ':', *s++ = '\t'; 1866 if (ff && lf && s < pri->pname + 9) 1867 *s++ = '\t'; 1868 *s = '\0'; 1869 pri->pparam.ff = ff; 1870 pri->pparam.lf = lf; 1871 pri->pparam.pid = pid; 1872 pri->pparam.lwpid = lwpid; 1873 pri->pparam.tid = tid; 1874 } 1875 } 1876 } 1877 1878 /* 1879 * Print the pri->pname[] string, if any. 1880 */ 1881 void 1882 putpname(private_t *pri) 1883 { 1884 if (pri->pname[0]) 1885 (void) fputs(pri->pname, stdout); 1886 } 1887 1888 /* 1889 * Print the timestamp, if requested (-d, -D, or -E). 1890 */ 1891 void 1892 timestamp(private_t *pri) 1893 { 1894 const lwpstatus_t *Lsp = pri->lwpstat; 1895 int seconds; 1896 int fraction; 1897 1898 if (!(dflag|Dflag|Eflag) || !(Lsp->pr_flags & PR_STOPPED)) 1899 return; 1900 1901 seconds = Lsp->pr_tstamp.tv_sec - Cp->basetime.tv_sec; 1902 fraction = Lsp->pr_tstamp.tv_nsec - Cp->basetime.tv_nsec; 1903 if (fraction < 0) { 1904 seconds--; 1905 fraction += NANOSEC; 1906 } 1907 /* fraction in 1/10 milliseconds, rounded up */ 1908 fraction = (fraction + 50000) / 100000; 1909 if (fraction >= (MILLISEC * 10)) { 1910 seconds++; 1911 fraction -= (MILLISEC * 10); 1912 } 1913 1914 if (dflag) /* time stamp */ 1915 (void) printf("%2d.%4.4d\t", seconds, fraction); 1916 1917 if (Dflag) { /* time delta */ 1918 int oseconds = pri->seconds; 1919 int ofraction = pri->fraction; 1920 1921 pri->seconds = seconds; 1922 pri->fraction = fraction; 1923 seconds -= oseconds; 1924 fraction -= ofraction; 1925 if (fraction < 0) { 1926 seconds--; 1927 fraction += (MILLISEC * 10); 1928 } 1929 (void) printf("%2d.%4.4d\t", seconds, fraction); 1930 } 1931 1932 if (Eflag) { 1933 seconds = Lsp->pr_stime.tv_sec - pri->syslast.tv_sec; 1934 fraction = Lsp->pr_stime.tv_nsec - pri->syslast.tv_nsec; 1935 1936 if (fraction < 0) { 1937 seconds--; 1938 fraction += NANOSEC; 1939 } 1940 /* fraction in 1/10 milliseconds, rounded up */ 1941 fraction = (fraction + 50000) / 100000; 1942 if (fraction >= (MILLISEC * 10)) { 1943 seconds++; 1944 fraction -= (MILLISEC * 10); 1945 } 1946 (void) printf("%2d.%4.4d\t", seconds, fraction); 1947 } 1948 } 1949 1950 /* 1951 * Create output file, being careful about 1952 * suid/sgid and file descriptor 0, 1, 2 issues. 1953 */ 1954 int 1955 xcreat(char *path) 1956 { 1957 int fd; 1958 int mode = 0666; 1959 1960 if (Euid == Ruid && Egid == Rgid) /* not set-id */ 1961 fd = creat(path, mode); 1962 else if (access(path, F_OK) != 0) { /* file doesn't exist */ 1963 /* if directory permissions OK, create file & set ownership */ 1964 1965 char *dir; 1966 char *p; 1967 char dot[4]; 1968 1969 /* generate path for directory containing file */ 1970 if ((p = strrchr(path, '/')) == NULL) { /* no '/' */ 1971 p = dir = dot; 1972 *p++ = '.'; /* current directory */ 1973 *p = '\0'; 1974 } else if (p == path) { /* leading '/' */ 1975 p = dir = dot; 1976 *p++ = '/'; /* root directory */ 1977 *p = '\0'; 1978 } else { /* embedded '/' */ 1979 dir = path; /* directory path */ 1980 *p = '\0'; 1981 } 1982 1983 if (access(dir, W_OK|X_OK) != 0) { 1984 /* not writeable/searchable */ 1985 *p = '/'; 1986 fd = -1; 1987 } else { /* create file and set ownership correctly */ 1988 *p = '/'; 1989 if ((fd = creat(path, mode)) >= 0) 1990 (void) chown(path, (int)Ruid, (int)Rgid); 1991 } 1992 } else if (access(path, W_OK) != 0) /* file not writeable */ 1993 fd = -1; 1994 else 1995 fd = creat(path, mode); 1996 1997 /* 1998 * Make sure it's not one of 0, 1, or 2. 1999 * This allows truss to work when spawned by init(1m). 2000 */ 2001 if (0 <= fd && fd <= 2) { 2002 int dfd = fcntl(fd, F_DUPFD, 3); 2003 (void) close(fd); 2004 fd = dfd; 2005 } 2006 2007 /* 2008 * Mark it close-on-exec so created processes don't inherit it. 2009 */ 2010 if (fd >= 0) 2011 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 2012 2013 return (fd); 2014 } 2015 2016 void 2017 setoutput(int ofd) 2018 { 2019 if (ofd < 0) { 2020 (void) close(1); 2021 (void) fcntl(2, F_DUPFD, 1); 2022 } else if (ofd != 1) { 2023 (void) close(1); 2024 (void) fcntl(ofd, F_DUPFD, 1); 2025 (void) close(ofd); 2026 /* if no stderr, make it the same file */ 2027 if ((ofd = dup(2)) < 0) 2028 (void) fcntl(1, F_DUPFD, 2); 2029 else 2030 (void) close(ofd); 2031 } 2032 } 2033 2034 /* 2035 * Accumulate time differencies: a += e - s; 2036 */ 2037 void 2038 accumulate(timestruc_t *ap, const timestruc_t *ep, const timestruc_t *sp) 2039 { 2040 ap->tv_sec += ep->tv_sec - sp->tv_sec; 2041 ap->tv_nsec += ep->tv_nsec - sp->tv_nsec; 2042 if (ap->tv_nsec >= NANOSEC) { 2043 ap->tv_nsec -= NANOSEC; 2044 ap->tv_sec++; 2045 } else if (ap->tv_nsec < 0) { 2046 ap->tv_nsec += NANOSEC; 2047 ap->tv_sec--; 2048 } 2049 } 2050 2051 int 2052 lib_sort(const void *p1, const void *p2) 2053 { 2054 int cmpr = 0; 2055 long i; 2056 long j; 2057 2058 hentry_t *t1 = (hentry_t *)p1; 2059 hentry_t *t2 = (hentry_t *)p2; 2060 2061 char *p = t1->lib; 2062 char *q = t2->lib; 2063 2064 if ((cmpr = strcmp(p, q)) == 0) { 2065 i = t1->count; 2066 j = t2->count; 2067 if (i > j) 2068 return (-1); 2069 else if (i < j) 2070 return (1); 2071 else { 2072 p = t1->key; 2073 q = t2->key; 2074 return (strcmp(p, q)); 2075 } 2076 } else 2077 return (cmpr); 2078 } 2079 2080 void 2081 report(private_t *pri, time_t lapse) /* elapsed time, clock ticks */ 2082 { 2083 int i; 2084 long count; 2085 const char *name; 2086 long error; 2087 long total; 2088 long errtot; 2089 timestruc_t tickzero; 2090 timestruc_t ticks; 2091 timestruc_t ticktot; 2092 2093 if (descendent) 2094 return; 2095 2096 for (i = 0, total = 0; i <= PRMAXFAULT && !interrupt; i++) { 2097 if ((count = Cp->fltcount[i]) != 0) { 2098 if (total == 0) /* produce header */ 2099 (void) printf("faults -------------\n"); 2100 2101 name = proc_fltname(i, pri->flt_name, 2102 sizeof (pri->flt_name)); 2103 2104 (void) printf("%s%s\t%4ld\n", name, 2105 (((int)strlen(name) < 8)? 2106 (const char *)"\t" : (const char *)""), 2107 count); 2108 total += count; 2109 } 2110 } 2111 if (total && !interrupt) 2112 (void) printf("total:\t\t%4ld\n\n", total); 2113 2114 for (i = 0, total = 0; i <= PRMAXSIG && !interrupt; i++) { 2115 if ((count = Cp->sigcount[i]) != 0) { 2116 if (total == 0) /* produce header */ 2117 (void) printf("signals ------------\n"); 2118 name = signame(pri, i); 2119 (void) printf("%s%s\t%4ld\n", name, 2120 (((int)strlen(name) < 8)? 2121 (const char *)"\t" : (const char *)""), 2122 count); 2123 total += count; 2124 } 2125 } 2126 if (total && !interrupt) 2127 (void) printf("total:\t\t%4ld\n\n", total); 2128 2129 if ((Dynpat != NULL) && !interrupt) { 2130 size_t elem = elements_in_table(fcall_tbl); 2131 hiter_t *itr = iterate_hash(fcall_tbl); 2132 hentry_t *tmp = iter_next(itr); 2133 hentry_t *stbl = my_malloc(elem * sizeof (hentry_t), NULL); 2134 i = 0; 2135 while ((tmp != NULL) && (i < elem)) { 2136 stbl[i].prev = tmp->prev; 2137 stbl[i].next = tmp->next; 2138 stbl[i].lib = tmp->lib; 2139 stbl[i].key = tmp->key; 2140 stbl[i].count = tmp->count; 2141 tmp = iter_next(itr); 2142 i++; 2143 } 2144 qsort((void *)stbl, elem, sizeof (hentry_t), 2145 lib_sort); 2146 (void) printf( 2147 "\n%-20s %-40s %s\n", "Library:", "Function", "calls"); 2148 for (i = 0; i < elem; i++) { 2149 (void) printf("%-20s %-40s %ld\n", stbl[i].lib, 2150 stbl[i].key, stbl[i].count); 2151 } 2152 iter_free(itr); 2153 free(stbl); 2154 itr = NULL; 2155 } 2156 2157 if (!interrupt) 2158 (void) printf( 2159 "\nsyscall seconds calls errors\n"); 2160 2161 total = errtot = 0; 2162 tickzero.tv_sec = ticks.tv_sec = ticktot.tv_sec = 0; 2163 tickzero.tv_nsec = ticks.tv_nsec = ticktot.tv_nsec = 0; 2164 for (i = 0; i <= PRMAXSYS && !interrupt; i++) { 2165 struct syscount *scp = Cp->syscount[i]; 2166 int n = nsubcodes(i); 2167 int subcode; 2168 2169 for (subcode = 0; subcode < n; subcode++, scp++) { 2170 if ((count = scp->count) != 0 || scp->error) { 2171 (void) printf("%-19.19s ", 2172 sysname(pri, i, subcode)); 2173 2174 ticks = scp->stime; 2175 accumulate(&ticktot, &ticks, &tickzero); 2176 prtim(&ticks); 2177 2178 (void) printf(" %7ld", count); 2179 if ((error = scp->error) != 0) 2180 (void) printf(" %7ld", error); 2181 (void) fputc('\n', stdout); 2182 total += count; 2183 errtot += error; 2184 } 2185 } 2186 } 2187 2188 if (!interrupt) { 2189 (void) printf( 2190 " -------- ------ ----\n"); 2191 (void) printf("sys totals: "); 2192 prtim(&ticktot); 2193 (void) printf(" %7ld %6ld\n", total, errtot); 2194 } 2195 2196 if (!interrupt) { 2197 (void) printf("usr time: "); 2198 prtim(&Cp->usrtotal); 2199 (void) fputc('\n', stdout); 2200 } 2201 2202 if (!interrupt) { 2203 int hz = (int)sysconf(_SC_CLK_TCK); 2204 2205 ticks.tv_sec = lapse / hz; 2206 ticks.tv_nsec = (lapse % hz) * (1000000000 / hz); 2207 (void) printf("elapsed: "); 2208 prtim(&ticks); 2209 (void) fputc('\n', stdout); 2210 } 2211 } 2212 2213 void 2214 prtim(timestruc_t *tp) 2215 { 2216 time_t sec; 2217 2218 if ((sec = tp->tv_sec) != 0) /* whole seconds */ 2219 (void) printf("%5lu", sec); 2220 else 2221 (void) printf(" "); 2222 2223 (void) printf(".%3.3ld", tp->tv_nsec/1000000); /* fraction */ 2224 } 2225 2226 /* 2227 * Gather process id's. 2228 * Return 0 on success, != 0 on failure. 2229 */ 2230 void 2231 pids(char *arg, proc_set_t *grab) 2232 { 2233 pid_t pid = -1; 2234 int i; 2235 const char *lwps = NULL; 2236 2237 if ((pid = proc_arg_xpsinfo(arg, PR_ARG_PIDS, NULL, &i, &lwps)) < 0) { 2238 (void) fprintf(stderr, "%s: cannot trace '%s': %s\n", 2239 command, arg, Pgrab_error(i)); 2240 return; 2241 } 2242 2243 for (i = 0; i < ngrab; i++) 2244 if (grab[i].pid == pid) /* duplicate */ 2245 break; 2246 2247 if (i == ngrab) { 2248 grab[ngrab].pid = pid; 2249 grab[ngrab].lwps = lwps; 2250 ngrab++; 2251 } else { 2252 (void) fprintf(stderr, "%s: duplicate process-id ignored: %d\n", 2253 command, (int)pid); 2254 } 2255 } 2256 2257 /* 2258 * Report psargs string. 2259 */ 2260 void 2261 psargs(private_t *pri) 2262 { 2263 pid_t pid = Pstatus(Proc)->pr_pid; 2264 psinfo_t psinfo; 2265 2266 if (proc_get_psinfo(pid, &psinfo) == 0) 2267 (void) printf("%spsargs: %.64s\n", 2268 pri->pname, psinfo.pr_psargs); 2269 else { 2270 perror("psargs()"); 2271 (void) printf("%s\t*** Cannot read psinfo file for pid %d\n", 2272 pri->pname, (int)pid); 2273 } 2274 } 2275 2276 char * 2277 fetchstring(private_t *pri, long addr, int maxleng) 2278 { 2279 int nbyte; 2280 int leng = 0; 2281 char string[41]; 2282 2283 string[40] = '\0'; 2284 if (pri->str_bsize == 0) /* initial allocation of string buffer */ 2285 pri->str_buffer = 2286 my_malloc(pri->str_bsize = 16, "string buffer"); 2287 *pri->str_buffer = '\0'; 2288 2289 for (nbyte = 40; nbyte == 40 && leng < maxleng; addr += 40) { 2290 if ((nbyte = Pread(Proc, string, 40, addr)) <= 0) 2291 return (leng? pri->str_buffer : NULL); 2292 if (nbyte > 0 && 2293 (nbyte = strlen(string)) > 0) { 2294 while (leng + nbyte >= pri->str_bsize) 2295 pri->str_buffer = 2296 my_realloc(pri->str_buffer, 2297 pri->str_bsize *= 2, "string buffer"); 2298 (void) strcpy(pri->str_buffer+leng, string); 2299 leng += nbyte; 2300 } 2301 } 2302 2303 if (leng > maxleng) 2304 leng = maxleng; 2305 pri->str_buffer[leng] = '\0'; 2306 2307 return (pri->str_buffer); 2308 } 2309 2310 void 2311 show_cred(private_t *pri, int new) 2312 { 2313 prcred_t cred; 2314 2315 if (proc_get_cred(Pstatus(Proc)->pr_pid, &cred, 0) < 0) { 2316 perror("show_cred()"); 2317 (void) printf("%s\t*** Cannot get credentials\n", pri->pname); 2318 return; 2319 } 2320 2321 if (!cflag && prismember(&trace, SYS_execve)) { 2322 if (new) 2323 credentials = cred; 2324 if ((new && cred.pr_ruid != cred.pr_suid) || 2325 cred.pr_ruid != credentials.pr_ruid || 2326 cred.pr_suid != credentials.pr_suid) 2327 (void) printf( 2328 "%s *** SUID: ruid/euid/suid = %d / %d / %d ***\n", 2329 pri->pname, 2330 (int)cred.pr_ruid, 2331 (int)cred.pr_euid, 2332 (int)cred.pr_suid); 2333 if ((new && cred.pr_rgid != cred.pr_sgid) || 2334 cred.pr_rgid != credentials.pr_rgid || 2335 cred.pr_sgid != credentials.pr_sgid) 2336 (void) printf( 2337 "%s *** SGID: rgid/egid/sgid = %d / %d / %d ***\n", 2338 pri->pname, 2339 (int)cred.pr_rgid, 2340 (int)cred.pr_egid, 2341 (int)cred.pr_sgid); 2342 } 2343 2344 credentials = cred; 2345 } 2346 2347 /* 2348 * Take control of a child process. 2349 * We come here with truss_lock held. 2350 */ 2351 int 2352 control(private_t *pri, pid_t pid) 2353 { 2354 const pstatus_t *Psp; 2355 const lwpstatus_t *Lsp; 2356 pid_t childpid = 0; 2357 long flags; 2358 int rc; 2359 2360 (void) mutex_lock(&gps->fork_lock); 2361 while (gps->fork_pid != 0) 2362 (void) cond_wait(&gps->fork_cv, &gps->fork_lock); 2363 gps->fork_pid = getpid(); /* parent pid */ 2364 if ((childpid = fork()) == -1) { 2365 (void) printf("%s\t*** Cannot fork() to control process #%d\n", 2366 pri->pname, (int)pid); 2367 Flush(); 2368 gps->fork_pid = 0; 2369 (void) cond_broadcast(&gps->fork_cv); 2370 (void) mutex_unlock(&gps->fork_lock); 2371 release(pri, pid); 2372 return (FALSE); 2373 } 2374 2375 if (childpid != 0) { 2376 /* 2377 * The parent carries on, after a brief pause. 2378 * The parent must wait until the child executes procadd(pid). 2379 */ 2380 while (gps->fork_pid != childpid) 2381 (void) cond_wait(&gps->fork_cv, &gps->fork_lock); 2382 gps->fork_pid = 0; 2383 (void) cond_broadcast(&gps->fork_cv); 2384 (void) mutex_unlock(&gps->fork_lock); 2385 return (FALSE); 2386 } 2387 2388 childpid = getpid(); 2389 descendent = TRUE; 2390 exit_called = FALSE; 2391 Pfree(Proc); /* forget old process */ 2392 2393 /* 2394 * The parent process owns the shared gps->fork_lock. 2395 * The child must grab it again. 2396 */ 2397 (void) mutex_lock(&gps->fork_lock); 2398 2399 /* 2400 * Child grabs the process and retains the tracing flags. 2401 */ 2402 if ((Proc = Pgrab(pid, PGRAB_RETAIN, &rc)) == NULL) { 2403 (void) fprintf(stderr, 2404 "%s: cannot control child process, pid# %d: %s\n", 2405 command, (int)pid, Pgrab_error(rc)); 2406 gps->fork_pid = childpid; 2407 (void) cond_broadcast(&gps->fork_cv); 2408 (void) mutex_unlock(&gps->fork_lock); 2409 exit(2); 2410 } 2411 2412 per_proc_init(); 2413 /* 2414 * Add ourself to the set of truss processes 2415 * and notify the parent to carry on. 2416 */ 2417 procadd(pid, NULL); 2418 gps->fork_pid = childpid; 2419 (void) cond_broadcast(&gps->fork_cv); 2420 (void) mutex_unlock(&gps->fork_lock); 2421 2422 /* 2423 * We may have grabbed the child before it is fully stopped on exit 2424 * from fork. Wait one second (at most) for it to settle down. 2425 */ 2426 (void) Pwait(Proc, MILLISEC); 2427 if (Rdb_agent != NULL) 2428 Rdb_agent = Prd_agent(Proc); 2429 2430 Psp = Pstatus(Proc); 2431 Lsp = &Psp->pr_lwp; 2432 pri->lwpstat = Lsp; 2433 data_model = Psp->pr_dmodel; 2434 2435 make_pname(pri, 0); 2436 2437 pri->syslast = Psp->pr_stime; 2438 pri->usrlast = Psp->pr_utime; 2439 2440 flags = PR_FORK | PR_ASYNC; 2441 if (Dynpat != NULL) 2442 flags |= PR_BPTADJ; /* needed for x86 */ 2443 (void) Psetflags(Proc, flags); 2444 2445 return (TRUE); 2446 } 2447 2448 /* 2449 * Take control of an existing process. 2450 */ 2451 int 2452 grabit(private_t *pri, proc_set_t *set) 2453 { 2454 const pstatus_t *Psp; 2455 const lwpstatus_t *Lsp; 2456 int gcode; 2457 2458 /* 2459 * Don't force the takeover unless the -F option was specified. 2460 */ 2461 if ((Proc = Pgrab(set->pid, Fflag, &gcode)) == NULL) { 2462 (void) fprintf(stderr, "%s: %s: %d\n", 2463 command, Pgrab_error(gcode), (int)set->pid); 2464 pri->lwpstat = NULL; 2465 return (FALSE); 2466 } 2467 Psp = Pstatus(Proc); 2468 Lsp = &Psp->pr_lwp; 2469 pri->lwpstat = Lsp; 2470 2471 make_pname(pri, 0); 2472 2473 data_model = Psp->pr_dmodel; 2474 pri->syslast = Psp->pr_stime; 2475 pri->usrlast = Psp->pr_utime; 2476 2477 if (fflag || Dynpat != NULL) 2478 (void) Psetflags(Proc, PR_FORK); 2479 else 2480 (void) Punsetflags(Proc, PR_FORK); 2481 procadd(set->pid, set->lwps); 2482 show_cred(pri, TRUE); 2483 return (TRUE); 2484 } 2485 2486 /* 2487 * Release process from control. 2488 */ 2489 void 2490 release(private_t *pri, pid_t pid) 2491 { 2492 /* 2493 * The process in question is the child of a traced process. 2494 * We are here to turn off the inherited tracing flags. 2495 */ 2496 int fd; 2497 char ctlname[100]; 2498 long ctl[2]; 2499 2500 ctl[0] = PCSET; 2501 ctl[1] = PR_RLC; 2502 2503 /* process is freshly forked, no need for exclusive open */ 2504 (void) sprintf(ctlname, "/proc/%d/ctl", (int)pid); 2505 if ((fd = open(ctlname, O_WRONLY)) < 0 || 2506 write(fd, (char *)ctl, sizeof (ctl)) < 0) { 2507 perror("release()"); 2508 (void) printf( 2509 "%s\t*** Cannot release child process, pid# %d\n", 2510 pri->pname, (int)pid); 2511 Flush(); 2512 } 2513 if (fd >= 0) /* run-on-last-close sets the process running */ 2514 (void) close(fd); 2515 } 2516 2517 void 2518 intr(int sig) 2519 { 2520 /* 2521 * SIGUSR1 is special. It is used by one truss process to tell 2522 * another truss process to release its controlled process. 2523 * SIGUSR2 is also special. It is used to wake up threads waiting 2524 * for a victim lwp to stop after an event that will leave the 2525 * process hung (stopped and abandoned) has occurred. 2526 */ 2527 if (sig == SIGUSR1) { 2528 sigusr1 = TRUE; 2529 } else if (sig == SIGUSR2) { 2530 void *value; 2531 private_t *pri; 2532 struct ps_lwphandle *Lwp; 2533 2534 if (thr_getspecific(private_key, &value) == 0 && 2535 (pri = value) != NULL && 2536 (Lwp = pri->Lwp) != NULL) 2537 (void) Lstop(Lwp, MILLISEC / 10); 2538 } else { 2539 interrupt = sig; 2540 } 2541 } 2542 2543 void 2544 errmsg(const char *s, const char *q) 2545 { 2546 char msg[512]; 2547 2548 if (s || q) { 2549 msg[0] = '\0'; 2550 if (command) { 2551 (void) strcpy(msg, command); 2552 (void) strcat(msg, ": "); 2553 } 2554 if (s) 2555 (void) strcat(msg, s); 2556 if (q) 2557 (void) strcat(msg, q); 2558 (void) strcat(msg, "\n"); 2559 (void) write(2, msg, (size_t)strlen(msg)); 2560 } 2561 } 2562 2563 void 2564 abend(const char *s, const char *q) 2565 { 2566 (void) thr_sigsetmask(SIG_SETMASK, &fillset, NULL); 2567 if (Proc) { 2568 Flush(); 2569 errmsg(s, q); 2570 clear_breakpoints(); 2571 (void) Punsetflags(Proc, PR_ASYNC); 2572 Prelease(Proc, created? PRELEASE_KILL : PRELEASE_CLEAR); 2573 procdel(); 2574 (void) wait4all(); 2575 } else { 2576 errmsg(s, q); 2577 } 2578 exit(2); 2579 } 2580 2581 /* 2582 * Allocate memory. 2583 * If allocation fails then print a message and abort. 2584 */ 2585 void * 2586 my_realloc(void *buf, size_t size, const char *msg) 2587 { 2588 if ((buf = realloc(buf, size)) == NULL) { 2589 if (msg != NULL) 2590 abend("cannot allocate ", msg); 2591 else 2592 abend("memory allocation failure", NULL); 2593 } 2594 2595 return (buf); 2596 } 2597 2598 void * 2599 my_calloc(size_t nelem, size_t elsize, const char *msg) 2600 { 2601 void *buf = NULL; 2602 2603 if ((buf = calloc(nelem, elsize)) == NULL) { 2604 if (msg != NULL) 2605 abend("cannot allocate ", msg); 2606 else 2607 abend("memory allocation failure", NULL); 2608 } 2609 2610 return (buf); 2611 } 2612 2613 void * 2614 my_malloc(size_t size, const char *msg) 2615 { 2616 return (my_realloc(NULL, size, msg)); 2617 } 2618 2619 int 2620 wait4all() 2621 { 2622 int i; 2623 pid_t pid; 2624 int rc = 0; 2625 int status; 2626 2627 for (i = 0; i < 10; i++) { 2628 while ((pid = wait(&status)) != -1) { 2629 /* return exit() code of the created process */ 2630 if (pid == created) { 2631 if (WIFEXITED(status)) 2632 rc = WEXITSTATUS(status); 2633 else 2634 rc |= 0x80; /* +128 to indicate sig */ 2635 } 2636 } 2637 if (errno != EINTR && errno != ERESTART) 2638 break; 2639 } 2640 2641 if (i >= 10) /* repeated interrupts */ 2642 rc = 2; 2643 2644 return (rc); 2645 } 2646 2647 void 2648 letgo(private_t *pri) 2649 { 2650 (void) printf("%s\t*** process otherwise traced, releasing ...\n", 2651 pri->pname); 2652 } 2653 2654 /* 2655 * Test for empty set. 2656 * support routine used by isemptyset() macro. 2657 */ 2658 int 2659 is_empty(const uint32_t *sp, /* pointer to set (array of int32's) */ 2660 size_t n) /* number of int32's in set */ 2661 { 2662 if (n) { 2663 do { 2664 if (*sp++) 2665 return (FALSE); 2666 } while (--n); 2667 } 2668 2669 return (TRUE); 2670 } 2671 2672 /* 2673 * OR the second set into the first. 2674 * The sets must be the same size. 2675 */ 2676 void 2677 or_set(uint32_t *sp1, const uint32_t *sp2, size_t n) 2678 { 2679 if (n) { 2680 do { 2681 *sp1++ |= *sp2++; 2682 } while (--n); 2683 } 2684 } 2685