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