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 2006 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 (fork1()) { 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 691 /* for I/O buffer dumps, force tracing of read()s and write()s */ 692 if (!isemptyset(&readfd)) { 693 praddset(&traceeven, SYS_read); 694 praddset(&traceeven, SYS_readv); 695 praddset(&traceeven, SYS_pread); 696 praddset(&traceeven, SYS_pread64); 697 praddset(&traceeven, SYS_recv); 698 praddset(&traceeven, SYS_recvfrom); 699 praddset(&traceeven, SYS_recvmsg); 700 } 701 if (!isemptyset(&writefd)) { 702 praddset(&traceeven, SYS_write); 703 praddset(&traceeven, SYS_writev); 704 praddset(&traceeven, SYS_pwrite); 705 praddset(&traceeven, SYS_pwrite64); 706 praddset(&traceeven, SYS_send); 707 praddset(&traceeven, SYS_sendto); 708 praddset(&traceeven, SYS_sendmsg); 709 } 710 711 if (cflag || Eflag) { 712 Psetsysentry(Proc, &traceeven); 713 } 714 Psetsysexit(Proc, &traceeven); 715 716 /* special case -- cannot trace sysexit because context is changed */ 717 if (prismember(&trace, SYS_context)) { 718 (void) Psysentry(Proc, SYS_context, TRUE); 719 (void) Psysexit(Proc, SYS_context, FALSE); 720 prdelset(&traceeven, SYS_context); 721 } 722 723 /* special case -- sysexit not traced by OS */ 724 if (prismember(&trace, SYS_evtrapret)) { 725 (void) Psysentry(Proc, SYS_evtrapret, TRUE); 726 (void) Psysexit(Proc, SYS_evtrapret, FALSE); 727 prdelset(&traceeven, SYS_evtrapret); 728 } 729 730 /* special case -- trace exec() on entry to get the args */ 731 (void) Psysentry(Proc, SYS_exec, TRUE); 732 (void) Psysentry(Proc, SYS_execve, TRUE); 733 734 /* special case -- sysexit never reached */ 735 (void) Psysentry(Proc, SYS_exit, TRUE); 736 (void) Psysentry(Proc, SYS_lwp_exit, TRUE); 737 (void) Psysexit(Proc, SYS_exit, FALSE); 738 (void) Psysexit(Proc, SYS_lwp_exit, FALSE); 739 740 Psetsignal(Proc, &signals); /* trace these signals */ 741 Psetfault(Proc, &faults); /* trace these faults */ 742 743 /* for function call tracing */ 744 if (Dynpat != NULL) { 745 /* trace these regardless, to deal with function calls */ 746 (void) Pfault(Proc, FLTBPT, TRUE); 747 (void) Pfault(Proc, FLTTRACE, TRUE); 748 749 /* needed for x86 */ 750 (void) Psetflags(Proc, PR_BPTADJ); 751 752 /* 753 * Find functions and set breakpoints on grabbed process. 754 * A process stopped on exec() gets its breakpoints set below. 755 */ 756 if ((Lsp->pr_why != PR_SYSENTRY && 757 Lsp->pr_why != PR_SYSEXIT) || 758 (Lsp->pr_what != SYS_exec && 759 Lsp->pr_what != SYS_execve)) { 760 establish_breakpoints(); 761 establish_stacks(); 762 } 763 } 764 765 /* 766 * Use asynchronous-stop for multithreaded truss. 767 * truss runs one lwp for each lwp in the target process. 768 */ 769 (void) Psetflags(Proc, PR_ASYNC); 770 771 /* flush out all tracing flags now. */ 772 Psync(Proc); 773 774 /* 775 * If we grabbed a running process, set it running again. 776 * Since we are tracing lwp_create() and lwp_exit(), the 777 * lwps will not change in the process until we create all 778 * of the truss worker threads. 779 * We leave a created process stopped so its exec() can be reported. 780 */ 781 first = created? FALSE : TRUE; 782 if (!created && 783 ((Pstate(Proc) == PS_STOP && Lsp->pr_why == PR_REQUESTED) || 784 (Lsp->pr_flags & PR_DSTOP))) 785 first = FALSE; 786 787 main_thread(first); 788 return (0); 789 } 790 791 /* 792 * Called from main() and from control() after fork1(). 793 */ 794 void 795 main_thread(int first) 796 { 797 private_t *pri = get_private(); 798 struct tms tms; 799 int flags; 800 int retc; 801 int i; 802 int count; 803 804 /* 805 * Block all signals in the main thread. 806 * Some worker thread will receive signals. 807 */ 808 (void) thr_sigsetmask(SIG_SETMASK, &fillset, NULL); 809 810 /* 811 * If we are dealing with a previously hung process, 812 * arrange not to leave it hung on the same system call. 813 */ 814 primary_lwp = (first && Pstate(Proc) == PS_STOP)? 815 Pstatus(Proc)->pr_lwp.pr_lwpid : 0; 816 817 /* 818 * Create worker threads to match the lwps in the target process. 819 */ 820 truss_nlwp = 0; 821 truss_maxlwp = 1; 822 truss_lwpid = my_realloc(truss_lwpid, sizeof (lwpid_t), NULL); 823 truss_lwpid[0] = 0; 824 count = 0; 825 (void) Plwp_iter(Proc, create_thread, &count); 826 827 if (count == 0) { 828 (void) printf("(Warning: no matching active LWPs found, " 829 "waiting)\n"); 830 Flush(); 831 } 832 833 /* 834 * Set all of the truss worker threads running now. 835 */ 836 (void) mutex_lock(&truss_lock); 837 for (i = 0; i < truss_maxlwp; i++) { 838 if (truss_lwpid[i]) 839 (void) thr_continue(truss_lwpid[i]); 840 } 841 (void) mutex_unlock(&truss_lock); 842 843 /* 844 * Wait until all worker threads terminate. 845 */ 846 while (thr_join(0, NULL, NULL) == 0) 847 continue; 848 849 (void) Punsetflags(Proc, PR_ASYNC); 850 Psync(Proc); 851 if (sigusr1) 852 letgo(pri); 853 flags = PRELEASE_CLEAR; 854 if (leave_hung) 855 flags |= PRELEASE_HANG; 856 Prelease(Proc, flags); 857 858 procdel(); 859 retc = (leave_hung? 0 : wait4all()); 860 861 if (!descendent) { 862 interrupt = 0; /* another interrupt kills the report */ 863 if (cflag) { 864 if (fflag) 865 file_to_parent(); 866 report(pri, times(&tms) - starttime); 867 } 868 } else if (cflag && fflag) { 869 child_to_file(); 870 } 871 872 exit(retc); /* exit with exit status of created process, else 0 */ 873 } 874 875 void * 876 worker_thread(void *arg) 877 { 878 struct ps_lwphandle *Lwp = (struct ps_lwphandle *)arg; 879 const pstatus_t *Psp = Pstatus(Proc); 880 const lwpstatus_t *Lsp = Lstatus(Lwp); 881 struct syscount *scp; 882 lwpid_t who = Lsp->pr_lwpid; 883 int first = (who == primary_lwp); 884 private_t *pri = get_private(); 885 int req_flag = 0; 886 int leave_it_hung = FALSE; 887 int reset_traps = FALSE; 888 int gcode; 889 int what; 890 int ow_in_effect = 0; 891 long ow_syscall = 0; 892 long ow_subcode = 0; 893 char *ow_string = NULL; 894 sysset_t full_set; 895 sysset_t running_set; 896 int dotrace = lwptrace(Psp->pr_pid, Lsp->pr_lwpid); 897 898 pri->Lwp = Lwp; 899 pri->lwpstat = Lsp; 900 pri->syslast = Lsp->pr_stime; 901 pri->usrlast = Lsp->pr_utime; 902 make_pname(pri, 0); 903 904 prfillset(&full_set); 905 906 /* we were created with all signals blocked; unblock them */ 907 (void) thr_sigsetmask(SIG_SETMASK, &emptyset, NULL); 908 909 /* 910 * Run this loop until the victim lwp terminates or we receive 911 * a termination condition (leave_hung | interrupt | sigusr1). 912 */ 913 for (;;) { 914 if (interrupt | sigusr1) { 915 (void) Lstop(Lwp, MILLISEC); 916 if (Lstate(Lwp) == PS_RUN) 917 break; 918 } 919 if (Lstate(Lwp) == PS_RUN) { 920 /* millisecond timeout is for sleeping syscalls */ 921 uint_t tout = (iflag || req_flag)? 0 : MILLISEC; 922 923 /* 924 * If we are to leave this lwp stopped in sympathy 925 * with another lwp that has been left hung, or if 926 * we have been interrupted or instructed to release 927 * our victim process, and this lwp is stopped but 928 * not on an event of interest to /proc, then just 929 * leave it in that state. 930 */ 931 if ((leave_hung | interrupt | sigusr1) && 932 (Lsp->pr_flags & (PR_STOPPED|PR_ISTOP)) 933 == PR_STOPPED) 934 break; 935 936 (void) Lwait(Lwp, tout); 937 if (Lstate(Lwp) == PS_RUN && 938 tout != 0 && !(interrupt | sigusr1)) { 939 (void) mutex_lock(&truss_lock); 940 if ((Lsp->pr_flags & PR_STOPPED) && 941 Lsp->pr_why == PR_JOBCONTROL) 942 req_flag = jobcontrol(pri, dotrace); 943 else 944 req_flag = requested(pri, req_flag, 945 dotrace); 946 (void) mutex_unlock(&truss_lock); 947 } 948 continue; 949 } 950 data_model = Psp->pr_dmodel; 951 if (Lstate(Lwp) == PS_UNDEAD) 952 break; 953 if (Lstate(Lwp) == PS_LOST) { /* we lost control */ 954 /* 955 * After exec(), only one LWP remains in the process. 956 * /proc makes the thread following that LWP receive 957 * EAGAIN (PS_LOST) if the program being exec()ed 958 * is a set-id program. Every other controlling 959 * thread receives ENOENT (because its LWP vanished). 960 * We are the controlling thread for the exec()ing LWP. 961 * We must wait until all of our siblings terminate 962 * before attempting to reopen the process. 963 */ 964 (void) mutex_lock(&truss_lock); 965 while (truss_nlwp > 1) 966 (void) cond_wait(&truss_cv, &truss_lock); 967 if (Preopen(Proc) == 0) { /* we got control back */ 968 /* 969 * We have to free and re-grab the LWP. 970 * The process is guaranteed to be at exit 971 * from exec() or execve() and have only 972 * one LWP, namely this one, and the LWP 973 * is guaranteed to have lwpid == 1. 974 * This "cannot fail". 975 */ 976 who = 1; 977 Lfree(Lwp); 978 pri->Lwp = Lwp = 979 Lgrab(Proc, who, &gcode); 980 if (Lwp == NULL) 981 abend("Lgrab error: ", 982 Lgrab_error(gcode)); 983 pri->lwpstat = Lsp = Lstatus(Lwp); 984 (void) mutex_unlock(&truss_lock); 985 continue; 986 } 987 988 /* we really lost it */ 989 if (pri->exec_string && *pri->exec_string) { 990 if (pri->exec_pname[0] != '\0') 991 (void) fputs(pri->exec_pname, stdout); 992 timestamp(pri); 993 (void) fputs(pri->exec_string, stdout); 994 (void) fputc('\n', stdout); 995 } else if (pri->length) { 996 (void) fputc('\n', stdout); 997 } 998 if (pri->sys_valid) 999 (void) printf( 1000 "%s\t*** cannot trace across exec() of %s ***\n", 1001 pri->pname, pri->sys_path); 1002 else 1003 (void) printf( 1004 "%s\t*** lost control of process ***\n", 1005 pri->pname); 1006 pri->length = 0; 1007 Flush(); 1008 (void) mutex_unlock(&truss_lock); 1009 break; 1010 } 1011 if (Lstate(Lwp) != PS_STOP) { 1012 (void) fprintf(stderr, 1013 "%s: state = %d\n", command, Lstate(Lwp)); 1014 abend(pri->pname, "uncaught status of subject lwp"); 1015 } 1016 1017 make_pname(pri, 0); 1018 1019 (void) mutex_lock(&truss_lock); 1020 1021 what = Lsp->pr_what; 1022 req_flag = 0; 1023 1024 switch (Lsp->pr_why) { 1025 case PR_REQUESTED: 1026 break; 1027 case PR_SIGNALLED: 1028 req_flag = signalled(pri, req_flag, dotrace); 1029 if (Sflag && !first && prismember(&sighang, what)) 1030 leave_it_hung = TRUE; 1031 break; 1032 case PR_FAULTED: 1033 if (what == FLTBPT) { 1034 int rval; 1035 1036 (void) Pstop(Proc, 0); 1037 rval = function_trace(pri, first, 0, dotrace); 1038 if (rval == 1) 1039 leave_it_hung = TRUE; 1040 if (rval >= 0) 1041 break; 1042 } 1043 if (faulted(pri, dotrace) && 1044 Mflag && !first && prismember(&flthang, what)) 1045 leave_it_hung = TRUE; 1046 break; 1047 case PR_JOBCONTROL: /* can't happen except first time */ 1048 req_flag = jobcontrol(pri, dotrace); 1049 break; 1050 case PR_SYSENTRY: 1051 /* protect ourself from operating system error */ 1052 if (what <= 0 || what > PRMAXSYS) 1053 what = PRMAXSYS; 1054 pri->length = 0; 1055 /* 1056 * ow_in_effect checks to see whether or not we 1057 * are attempting to quantify the time spent in 1058 * a one way system call. This is necessary as 1059 * some system calls never return, yet it is desireable 1060 * to determine how much time the traced process 1061 * spends in these calls. To do this, a one way 1062 * flag is set on SYSENTRY when the call is recieved. 1063 * After this, the call mask for the SYSENTRY events 1064 * is filled so that the traced process will stop 1065 * on the entry to the very next system call. 1066 * This appears to the the best way to determine 1067 * system time elapsed between a one way system call. 1068 * Once the next call occurs, values that have been 1069 * stashed are used to record the correct syscall 1070 * and time, and the SYSENTRY event mask is restored 1071 * so that the traced process may continue. 1072 */ 1073 if (dotrace && ow_in_effect) { 1074 if (cflag) { 1075 (void) mutex_lock(&count_lock); 1076 scp = Cp->syscount[ow_syscall]; 1077 if (ow_subcode != -1) 1078 scp += ow_subcode; 1079 scp->count++; 1080 accumulate(&scp->stime, 1081 &Lsp->pr_stime, &pri->syslast); 1082 accumulate(&Cp->usrtotal, 1083 &Lsp->pr_utime, &pri->usrlast); 1084 pri->syslast = Lsp->pr_stime; 1085 pri->usrlast = Lsp->pr_utime; 1086 (void) mutex_unlock(&count_lock); 1087 } else if (Eflag) { 1088 putpname(pri); 1089 timestamp(pri); 1090 (void) printf("%s\n", ow_string); 1091 free(ow_string); 1092 ow_string = NULL; 1093 pri->syslast = Lsp->pr_stime; 1094 } 1095 ow_in_effect = 0; 1096 Psetsysentry(Proc, &running_set); 1097 } 1098 1099 /* 1100 * Special cases. Most syscalls are traced on exit. 1101 */ 1102 switch (what) { 1103 case SYS_exit: /* exit() */ 1104 case SYS_lwp_exit: /* lwp_exit() */ 1105 case SYS_context: /* [get|set]context() */ 1106 case SYS_evtrapret: /* evtrapret() */ 1107 if (dotrace && cflag && 1108 prismember(&trace, what)) { 1109 ow_in_effect = 1; 1110 ow_syscall = what; 1111 ow_subcode = getsubcode(pri); 1112 pri->syslast = Lsp->pr_stime; 1113 running_set = 1114 (Pstatus(Proc))->pr_sysentry; 1115 Psetsysentry(Proc, &full_set); 1116 } else if (dotrace && Eflag && 1117 prismember(&trace, what)) { 1118 (void) sysentry(pri, dotrace); 1119 ow_in_effect = 1; 1120 ow_string = my_malloc( 1121 strlen(pri->sys_string) + 1, NULL); 1122 (void) strcpy(ow_string, 1123 pri->sys_string); 1124 running_set = 1125 (Pstatus(Proc))->pr_sysentry; 1126 Psetsysentry(Proc, &full_set); 1127 pri->syslast = Lsp->pr_stime; 1128 } else if (dotrace && 1129 prismember(&trace, what)) { 1130 (void) sysentry(pri, dotrace); 1131 putpname(pri); 1132 timestamp(pri); 1133 pri->length += 1134 printf("%s\n", pri->sys_string); 1135 Flush(); 1136 } 1137 pri->sys_leng = 0; 1138 *pri->sys_string = '\0'; 1139 1140 if (what == SYS_exit) 1141 exit_called = TRUE; 1142 break; 1143 case SYS_exec: 1144 case SYS_execve: 1145 (void) sysentry(pri, dotrace); 1146 if (dotrace && !cflag && 1147 prismember(&trace, what)) { 1148 pri->exec_string = 1149 my_realloc(pri->exec_string, 1150 strlen(pri->sys_string) + 1, 1151 NULL); 1152 (void) strcpy(pri->exec_pname, 1153 pri->pname); 1154 (void) strcpy(pri->exec_string, 1155 pri->sys_string); 1156 pri->length += strlen(pri->sys_string); 1157 pri->exec_lwpid = Lsp->pr_lwpid; 1158 } 1159 pri->sys_leng = 0; 1160 *pri->sys_string = '\0'; 1161 break; 1162 default: 1163 if (dotrace && (cflag || Eflag) && 1164 prismember(&trace, what)) { 1165 pri->syslast = Lsp->pr_stime; 1166 } 1167 break; 1168 } 1169 if (dotrace && Tflag && !first && 1170 (prismember(&syshang, what) || 1171 (exit_called && prismember(&syshang, SYS_exit)))) 1172 leave_it_hung = TRUE; 1173 break; 1174 case PR_SYSEXIT: 1175 /* check for write open of a /proc file */ 1176 if ((what == SYS_open || what == SYS_open64)) { 1177 (void) sysentry(pri, dotrace); 1178 pri->Errno = Lsp->pr_errno; 1179 pri->ErrPriv = Lsp->pr_errpriv; 1180 if ((pri->Errno == 0 || pri->Errno == EBUSY) && 1181 pri->sys_valid && 1182 (pri->sys_nargs > 1 && 1183 (pri->sys_args[1]&0x3) != O_RDONLY)) { 1184 int rv = checkproc(pri); 1185 if (rv == 1 && Fflag != PGRAB_FORCE) { 1186 /* 1187 * The process opened itself 1188 * and no -F flag was specified. 1189 * Just print the open() call 1190 * and let go of the process. 1191 */ 1192 if (dotrace && !cflag && 1193 prismember(&trace, what)) { 1194 putpname(pri); 1195 timestamp(pri); 1196 (void) printf("%s\n", 1197 pri->sys_string); 1198 Flush(); 1199 } 1200 sigusr1 = TRUE; 1201 (void) mutex_unlock( 1202 &truss_lock); 1203 goto out; 1204 } 1205 if (rv == 2) { 1206 /* 1207 * Process opened someone else. 1208 * The open is being reissued. 1209 * Don't report this one. 1210 */ 1211 pri->sys_leng = 0; 1212 *pri->sys_string = '\0'; 1213 pri->sys_nargs = 0; 1214 break; 1215 } 1216 } 1217 } 1218 if ((what == SYS_exec || what == SYS_execve) && 1219 pri->Errno == 0) { 1220 /* 1221 * Refresh the data model on exec() in case it 1222 * is different from the parent. Lwait() 1223 * doesn't update process-wide status, so we 1224 * have to explicitly call Pstopstatus() to get 1225 * the new state. 1226 */ 1227 (void) Pstopstatus(Proc, PCNULL, 0); 1228 data_model = Psp->pr_dmodel; 1229 } 1230 if (sysexit(pri, dotrace)) 1231 Flush(); 1232 if (what == SYS_lwp_create && pri->Rval1 != 0) { 1233 struct ps_lwphandle *new_Lwp; 1234 lwpid_t lwpid; 1235 1236 if ((new_Lwp = grab_lwp(pri->Rval1)) != NULL) { 1237 (void) thr_sigsetmask(SIG_SETMASK, 1238 &fillset, NULL); 1239 if (thr_create(NULL, 0, worker_thread, 1240 new_Lwp, THR_BOUND | THR_SUSPENDED, 1241 &lwpid) != 0) 1242 abend("cannot create lwp ", 1243 "to follow child lwp"); 1244 insert_lwpid(lwpid); 1245 (void) thr_continue(lwpid); 1246 (void) thr_sigsetmask(SIG_SETMASK, 1247 &emptyset, NULL); 1248 } 1249 } 1250 pri->sys_nargs = 0; 1251 if (dotrace && Tflag && !first && 1252 prismember(&syshang, what)) 1253 leave_it_hung = TRUE; 1254 if ((what == SYS_exec || what == SYS_execve) && 1255 pri->Errno == 0) { 1256 is_vfork_child = FALSE; 1257 reset_breakpoints(); 1258 /* 1259 * exec() resets the calling LWP's lwpid to 1. 1260 * If the LWP has changed its lwpid, then 1261 * we have to free and re-grab the LWP 1262 * in order to keep libproc consistent. 1263 * This "cannot fail". 1264 */ 1265 if (who != Lsp->pr_lwpid) { 1266 /* 1267 * We must wait for all of our 1268 * siblings to terminate. 1269 */ 1270 while (truss_nlwp > 1) 1271 (void) cond_wait(&truss_cv, 1272 &truss_lock); 1273 who = Lsp->pr_lwpid; 1274 Lfree(Lwp); 1275 pri->Lwp = Lwp = 1276 Lgrab(Proc, who, &gcode); 1277 if (Lwp == NULL) 1278 abend("Lgrab error: ", 1279 Lgrab_error(gcode)); 1280 pri->lwpstat = Lsp = Lstatus(Lwp); 1281 } 1282 } 1283 break; 1284 default: 1285 req_flag = 0; 1286 (void) fprintf(stderr, 1287 "unknown reason for stopping: %d/%d\n", 1288 Lsp->pr_why, what); 1289 abend(NULL, NULL); 1290 } 1291 1292 if (pri->child) { /* controlled process fork()ed */ 1293 if (fflag || Dynpat != NULL) { 1294 if (Lsp->pr_why == PR_SYSEXIT && 1295 Lsp->pr_what == SYS_vfork) 1296 is_vfork_child = TRUE; 1297 if (control(pri, pri->child)) { 1298 (void) mutex_unlock(&truss_lock); 1299 pri->child = 0; 1300 if (!fflag) { 1301 /* 1302 * If this is vfork(), then 1303 * this clears the breakpoints 1304 * in the parent's address space 1305 * as well as in the child's. 1306 */ 1307 clear_breakpoints(); 1308 Prelease(Proc, PRELEASE_CLEAR); 1309 _exit(0); 1310 } 1311 main_thread(FALSE); 1312 /* NOTREACHED */ 1313 } 1314 1315 /* 1316 * Here, we are still the parent truss. 1317 * If the child messed with the breakpoints and 1318 * this is vfork(), we have to set them again. 1319 */ 1320 if (Dynpat != NULL && is_vfork_child) 1321 reset_traps = TRUE; 1322 is_vfork_child = FALSE; 1323 } 1324 pri->child = 0; 1325 } 1326 1327 if (leave_it_hung) { 1328 (void) mutex_unlock(&truss_lock); 1329 break; 1330 } 1331 1332 if (reset_traps) { 1333 /* 1334 * To recover from vfork, we must catch the lwp 1335 * that issued the vfork() when it returns to user 1336 * level, with all other lwps remaining stopped. 1337 * For this purpose, we direct all lwps to stop 1338 * and set the vfork()ing lwp running with the 1339 * PRSTEP flag. We expect to capture it when 1340 * it stops again showing PR_FAULTED/FLTTRACE. 1341 * We are holding truss_lock, so no other threads 1342 * in truss will set any other lwps in the victim 1343 * process running. 1344 */ 1345 reset_traps = FALSE; 1346 (void) Pstop(Proc, 0); 1347 (void) Lsetrun(Lwp, 0, PRSTEP); 1348 do { 1349 (void) Lwait(Lwp, 0); 1350 } while (Lstate(Lwp) == PS_RUN); 1351 if (Lstate(Lwp) == PS_STOP && 1352 Lsp->pr_why == PR_FAULTED && 1353 Lsp->pr_what == FLTTRACE) { 1354 reestablish_traps(); 1355 (void) Lsetrun(Lwp, 0, PRCFAULT|PRSTOP); 1356 } else { 1357 (void) printf("%s\t*** Expected PR_FAULTED/" 1358 "FLTTRACE stop following vfork()\n", 1359 pri->pname); 1360 } 1361 } 1362 1363 if (Lstate(Lwp) == PS_STOP) { 1364 int flags = 0; 1365 1366 if (interrupt | sigusr1) { 1367 (void) mutex_unlock(&truss_lock); 1368 break; 1369 } 1370 /* 1371 * If we must leave this lwp hung is sympathy with 1372 * another lwp that is being left hung on purpose, 1373 * then push the state onward toward PR_REQUESTED. 1374 */ 1375 if (leave_hung) { 1376 if (Lsp->pr_why == PR_REQUESTED) { 1377 (void) mutex_unlock(&truss_lock); 1378 break; 1379 } 1380 flags |= PRSTOP; 1381 } 1382 if (Lsetrun(Lwp, 0, flags) != 0 && 1383 Lstate(Lwp) != PS_LOST && 1384 Lstate(Lwp) != PS_UNDEAD) { 1385 (void) mutex_unlock(&truss_lock); 1386 perror("Lsetrun"); 1387 abend("cannot start subject lwp", NULL); 1388 /* NOTREACHED */ 1389 } 1390 } 1391 first = FALSE; 1392 1393 (void) mutex_unlock(&truss_lock); 1394 } 1395 1396 out: 1397 /* block all signals in preparation for exiting */ 1398 (void) thr_sigsetmask(SIG_SETMASK, &fillset, NULL); 1399 1400 if (Lstate(Lwp) == PS_UNDEAD || Lstate(Lwp) == PS_LOST) 1401 (void) mutex_lock(&truss_lock); 1402 else { 1403 (void) Lstop(Lwp, MILLISEC); 1404 (void) mutex_lock(&truss_lock); 1405 if (Lstate(Lwp) == PS_STOP && 1406 Lsp->pr_why == PR_FAULTED && 1407 Lsp->pr_what == FLTBPT) 1408 (void) function_trace(pri, 0, 1, dotrace); 1409 } 1410 1411 if (dotrace && ow_in_effect) { 1412 if (cflag) { 1413 (void) mutex_lock(&count_lock); 1414 scp = Cp->syscount[ow_syscall]; 1415 if (ow_subcode != -1) 1416 scp += ow_subcode; 1417 scp->count++; 1418 accumulate(&scp->stime, 1419 &Lsp->pr_stime, &pri->syslast); 1420 accumulate(&Cp->usrtotal, 1421 &Lsp->pr_utime, &pri->usrlast); 1422 pri->syslast = Lsp->pr_stime; 1423 pri->usrlast = Lsp->pr_utime; 1424 (void) mutex_unlock(&count_lock); 1425 } else if (Eflag) { 1426 putpname(pri); 1427 timestamp(pri); 1428 (void) printf("%s\n", ow_string); 1429 free(ow_string); 1430 ow_string = NULL; 1431 pri->syslast = Lsp->pr_stime; 1432 } 1433 ow_in_effect = 0; 1434 Psetsysentry(Proc, &running_set); 1435 } 1436 1437 if (Lstate(Lwp) == PS_UNDEAD || Lstate(Lwp) == PS_LOST) { 1438 /* 1439 * The victim thread has exited or we lost control of 1440 * the process. Remove ourself from the list of all 1441 * truss threads and notify everyone waiting for this. 1442 */ 1443 lwpid_t my_id = thr_self(); 1444 int i; 1445 1446 for (i = 0; i < truss_maxlwp; i++) { 1447 if (truss_lwpid[i] == my_id) { 1448 truss_lwpid[i] = 0; 1449 break; 1450 } 1451 } 1452 if (--truss_nlwp != 0) { 1453 (void) cond_broadcast(&truss_cv); 1454 } else { 1455 /* 1456 * The last truss worker thread is terminating. 1457 * The address space is gone (UNDEAD) or is 1458 * inaccessible (LOST) so we cannot clear the 1459 * breakpoints. Just report the htable stats. 1460 */ 1461 report_htable_stats(); 1462 } 1463 } else { 1464 /* 1465 * The victim thread is not a zombie thread, and we have not 1466 * lost control of the process. We must have gotten here due 1467 * to (leave_hung || leave_it_hung || interrupt || sigusr1). 1468 * In these cases, we must carefully uninstrument the process 1469 * and either set it running or leave it stopped and abandoned. 1470 */ 1471 static int nstopped = 0; 1472 static int cleared = 0; 1473 1474 if (leave_it_hung) 1475 leave_hung = TRUE; 1476 if ((leave_hung | interrupt | sigusr1) == 0) 1477 abend("(leave_hung | interrupt | sigusr1) == 0", NULL); 1478 1479 /* 1480 * The first truss thread through here needs to instruct all 1481 * application threads to stop -- they're not necessarily 1482 * going to stop on their own. 1483 */ 1484 if (nstopped++ == 0) 1485 (void) Pdstop(Proc); 1486 1487 /* 1488 * Notify all other worker threads about the reason 1489 * for being here (leave_hung || interrupt || sigusr1). 1490 */ 1491 broadcast_signals(); 1492 1493 /* 1494 * Once the last thread has reached this point, then and 1495 * only then is it safe to remove breakpoints and other 1496 * instrumentation. Since breakpoints are executed without 1497 * truss_lock held, a monitor thread can't exit until all 1498 * breakpoints have been removed, and we can't be sure the 1499 * procedure to execute a breakpoint won't temporarily 1500 * reinstall a breakpont. Accordingly, we need to wait 1501 * until all threads are in a known state. 1502 */ 1503 while (nstopped != truss_nlwp) 1504 (void) cond_wait(&truss_cv, &truss_lock); 1505 1506 /* 1507 * All truss threads have reached this point. 1508 * One of them clears the breakpoints and 1509 * wakes up everybody else to finish up. 1510 */ 1511 if (cleared++ == 0) { 1512 /* 1513 * All threads should already be stopped, 1514 * but just to be safe... 1515 */ 1516 (void) Pstop(Proc, MILLISEC); 1517 clear_breakpoints(); 1518 (void) Psysexit(Proc, SYS_forkall, FALSE); 1519 (void) Psysexit(Proc, SYS_vfork, FALSE); 1520 (void) Psysexit(Proc, SYS_fork1, FALSE); 1521 (void) Punsetflags(Proc, PR_FORK); 1522 Psync(Proc); 1523 fflag = 0; 1524 (void) cond_broadcast(&truss_cv); 1525 } 1526 1527 if (!leave_hung && Lstate(Lwp) == PS_STOP) 1528 (void) Lsetrun(Lwp, 0, 0); 1529 } 1530 1531 (void) Lfree(Lwp); 1532 (void) mutex_unlock(&truss_lock); 1533 return (NULL); 1534 } 1535 1536 /* 1537 * Give a base date for time stamps, adjusted to the 1538 * stop time of the selected (first or created) process. 1539 */ 1540 void 1541 setup_basetime(hrtime_t basehrtime, struct timeval *basedate) 1542 { 1543 const pstatus_t *Psp = Pstatus(Proc); 1544 (void) mutex_lock(&count_lock); 1545 Cp->basetime = Psp->pr_lwp.pr_tstamp; 1546 (void) mutex_unlock(&count_lock); 1547 1548 if ((dflag|Dflag) && !cflag) { 1549 const struct tm *ptm; 1550 const char *ptime; 1551 const char *pdst; 1552 hrtime_t delta = basehrtime - 1553 ((hrtime_t)Cp->basetime.tv_sec * NANOSEC + 1554 Cp->basetime.tv_nsec); 1555 1556 if (delta > 0) { 1557 basedate->tv_sec -= (time_t)(delta / NANOSEC); 1558 basedate->tv_usec -= (delta % NANOSEC) / 1000; 1559 if (basedate->tv_usec < 0) { 1560 basedate->tv_sec--; 1561 basedate->tv_usec += MICROSEC; 1562 } 1563 } 1564 ptm = localtime(&basedate->tv_sec); 1565 ptime = asctime(ptm); 1566 if ((pdst = tzname[ptm->tm_isdst ? 1 : 0]) == NULL) 1567 pdst = "???"; 1568 if (dflag) { 1569 (void) printf( 1570 "Base time stamp: %ld.%4.4ld [ %.20s%s %.4s ]\n", 1571 basedate->tv_sec, basedate->tv_usec / 100, 1572 ptime, pdst, ptime + 20); 1573 Flush(); 1574 } 1575 } 1576 } 1577 1578 /* 1579 * Performs per-process initializations. If truss is following a victim 1580 * process it will fork additional truss processes to follow new processes 1581 * created. Here is where each new truss process gets its per-process data 1582 * initialized. 1583 */ 1584 1585 void 1586 per_proc_init() 1587 { 1588 void *pmem; 1589 struct timeval basedate; 1590 hrtime_t basehrtime; 1591 struct syscount *scp; 1592 int i; 1593 timestruc_t c_basetime; 1594 1595 /* Make sure we only configure the basetime for the first truss proc */ 1596 1597 if (Cp == NULL) { 1598 pmem = my_malloc(sizeof (struct counts) + maxsyscalls() * 1599 sizeof (struct syscount), NULL); 1600 Cp = (struct counts *)pmem; 1601 basehrtime = gethrtime(); 1602 (void) gettimeofday(&basedate, NULL); 1603 setup_basetime(basehrtime, &basedate); 1604 } 1605 1606 c_basetime = Cp->basetime; 1607 1608 (void) memset(Cp, 0, sizeof (struct counts) + maxsyscalls() * 1609 sizeof (struct syscount)); 1610 1611 Cp->basetime = c_basetime; 1612 1613 if (fcall_tbl != NULL) 1614 destroy_hash(fcall_tbl); 1615 fcall_tbl = init_hash(4096); 1616 1617 (void) mutex_lock(&count_lock); 1618 scp = (struct syscount *)(Cp + 1); 1619 for (i = 0; i <= PRMAXSYS; i++) { 1620 Cp->syscount[i] = scp; 1621 scp += nsubcodes(i); 1622 } 1623 (void) mutex_unlock(&count_lock); 1624 } 1625 1626 1627 /* 1628 * Writes child state to a tempfile where it can be read and 1629 * accumulated by the parent process. The file descriptor is shared 1630 * among the processes. Ordering of writes does not matter, it is, however, 1631 * necessary to ensure that all writes are atomic. 1632 */ 1633 1634 void 1635 child_to_file() 1636 { 1637 hiter_t *itr; 1638 hentry_t *ntry; 1639 hdntry_t fentry; 1640 char *s = NULL; 1641 char *t = NULL; 1642 unsigned char *buf = NULL; 1643 size_t bufsz = 0; 1644 size_t i = 0; 1645 size_t j = 0; 1646 1647 /* ensure that we are in fact a child process */ 1648 if (!descendent) 1649 return; 1650 1651 /* enumerate fcall_tbl (tbl locked until freed) */ 1652 if (Dynpat != NULL) { 1653 itr = iterate_hash(fcall_tbl); 1654 1655 ntry = iter_next(itr); 1656 while (ntry != NULL) { 1657 fentry.type = HD_hashntry; 1658 fentry.count = ntry->count; 1659 s = ntry->key; 1660 t = ntry->lib; 1661 i = strlen(s) + 1; 1662 j = strlen(t) + 1; 1663 fentry.sz_key = i; 1664 fentry.sz_lib = j; 1665 if (i + sizeof (fentry) > bufsz) { 1666 buf = my_realloc(buf, i + j + sizeof (fentry), 1667 NULL); 1668 bufsz = i + j + sizeof (fentry); 1669 } 1670 (void) memcpy(buf, &fentry, sizeof (fentry)); 1671 (void) strlcpy((char *)(buf + sizeof (fentry)), t, j); 1672 (void) strlcpy((char *)(buf + sizeof (fentry) + j), 1673 s, i); 1674 if (write(sfd, buf, sizeof (fentry) + i + j) == -1) 1675 abend("Error writing to tmp file", NULL); 1676 ntry = iter_next(itr); 1677 } 1678 iter_free(itr); 1679 } 1680 1681 /* Now write the count/syscount structs down */ 1682 bufsz = sizeof (fentry) + (sizeof (struct counts) + maxsyscalls() * 1683 sizeof (struct syscount)); 1684 buf = my_realloc(buf, bufsz, NULL); 1685 fentry.type = HD_cts_syscts; 1686 fentry.count = 0; /* undefined, really */ 1687 fentry.sz_key = bufsz - sizeof (fentry); 1688 fentry.sz_lib = 0; /* also undefined */ 1689 (void) memcpy(buf, &fentry, sizeof (fentry)); 1690 (void) memcpy((char *)(buf + sizeof (fentry)), Cp, 1691 bufsz - sizeof (fentry)); 1692 if (write(sfd, buf, bufsz) == -1) 1693 abend("Error writing cts/syscts to tmpfile", NULL); 1694 1695 free(buf); 1696 } 1697 1698 /* 1699 * The following reads entries from the tempfile back to the parent 1700 * so that information can be collected and summed for overall statistics. 1701 * This reads records out of the tempfile. If they are hash table entries, 1702 * the record is merged with the hash table kept by the parent process. 1703 * If the information is a struct count/struct syscount pair, they are 1704 * copied and added into the count/syscount array kept by the parent. 1705 */ 1706 1707 void 1708 file_to_parent() 1709 { 1710 hdntry_t ntry; 1711 char *s = NULL; 1712 char *t = NULL; 1713 size_t c_offset = 0; 1714 size_t filesz; 1715 size_t t_strsz = 0; 1716 size_t s_strsz = 0; 1717 struct stat fsi; 1718 1719 if (descendent) 1720 return; 1721 1722 if (fstat(sfd, &fsi) == -1) 1723 abend("Error stat-ing tempfile", NULL); 1724 filesz = fsi.st_size; 1725 1726 while (c_offset < filesz) { 1727 /* first get hdntry */ 1728 if (pread(sfd, &ntry, sizeof (hdntry_t), c_offset) != 1729 sizeof (hdntry_t)) 1730 abend("Unable to perform full read of hdntry", NULL); 1731 c_offset += sizeof (hdntry_t); 1732 1733 switch (ntry.type) { 1734 case HD_hashntry: 1735 1736 /* first get lib string */ 1737 if (ntry.sz_lib > t_strsz) { 1738 t = my_realloc(t, ntry.sz_lib, NULL); 1739 t_strsz = ntry.sz_lib; 1740 } 1741 1742 (void) memset(t, 0, t_strsz); 1743 1744 /* now actually get the string */ 1745 if (pread(sfd, t, ntry.sz_lib, c_offset) != ntry.sz_lib) 1746 abend("Unable to perform full read of lib str", 1747 NULL); 1748 c_offset += ntry.sz_lib; 1749 1750 /* now get key string */ 1751 1752 if (ntry.sz_key > s_strsz) { 1753 s = my_realloc(s, ntry.sz_key, NULL); 1754 s_strsz = ntry.sz_key; 1755 } 1756 (void) memset(s, 0, s_strsz); 1757 if (pread(sfd, s, ntry.sz_key, c_offset) != ntry.sz_key) 1758 abend("Unable to perform full read of key str", 1759 NULL); 1760 c_offset += ntry.sz_key; 1761 1762 add_fcall(fcall_tbl, t, s, ntry.count); 1763 break; 1764 1765 case HD_cts_syscts: 1766 { 1767 struct counts *ncp; 1768 size_t bfsz = sizeof (struct counts) + maxsyscalls() 1769 * sizeof (struct syscount); 1770 int i; 1771 struct syscount *sscp; 1772 1773 if (ntry.sz_key != bfsz) 1774 abend("cts/syscts size does not sanity check", 1775 NULL); 1776 ncp = my_malloc(ntry.sz_key, NULL); 1777 1778 if (pread(sfd, ncp, ntry.sz_key, c_offset) != 1779 ntry.sz_key) 1780 abend("Unable to perform full read of cts", 1781 NULL); 1782 c_offset += ntry.sz_key; 1783 1784 sscp = (struct syscount *)(ncp + 1); 1785 1786 (void) mutex_lock(&count_lock); 1787 1788 Cp->usrtotal.tv_sec += ncp->usrtotal.tv_sec; 1789 Cp->usrtotal.tv_nsec += ncp->usrtotal.tv_nsec; 1790 if (Cp->usrtotal.tv_nsec >= NANOSEC) { 1791 Cp->usrtotal.tv_nsec -= NANOSEC; 1792 Cp->usrtotal.tv_sec++; 1793 } 1794 for (i = 0; i <= PRMAXSYS; i++) { 1795 ncp->syscount[i] = sscp; 1796 sscp += nsubcodes(i); 1797 } 1798 1799 for (i = 0; i <= PRMAXFAULT; i++) { 1800 Cp->fltcount[i] += ncp->fltcount[i]; 1801 } 1802 1803 for (i = 0; i <= PRMAXSIG; i++) { 1804 Cp->sigcount[i] += ncp->sigcount[i]; 1805 } 1806 1807 for (i = 0; i <= PRMAXSYS; i++) { 1808 struct syscount *scp = Cp->syscount[i]; 1809 struct syscount *nscp = ncp->syscount[i]; 1810 int n = nsubcodes(i); 1811 int subcode; 1812 1813 for (subcode = 0; subcode < n; subcode++, 1814 scp++, nscp++) { 1815 scp->count += nscp->count; 1816 scp->error += nscp->error; 1817 scp->stime.tv_sec += nscp->stime.tv_sec; 1818 scp->stime.tv_nsec += 1819 nscp->stime.tv_nsec; 1820 if (scp->stime.tv_nsec >= NANOSEC) { 1821 scp->stime.tv_nsec -= NANOSEC; 1822 scp->stime.tv_sec++; 1823 } 1824 } 1825 } 1826 (void) mutex_unlock(&count_lock); 1827 free(ncp); 1828 break; 1829 } 1830 default: 1831 1832 abend("Unknown file entry type encountered", NULL); 1833 break; 1834 1835 } 1836 1837 if (fstat(sfd, &fsi) == -1) 1838 abend("Error stat-ing tempfile", NULL); 1839 filesz = fsi.st_size; 1840 } 1841 if (s != NULL) 1842 free(s); 1843 if (t != NULL) 1844 free(t); 1845 } 1846 1847 void 1848 make_pname(private_t *pri, id_t tid) 1849 { 1850 if (!cflag) { 1851 int ff = (fflag || ngrab > 1); 1852 int lf = (lflag | tid | (Thr_agent != NULL) | (truss_nlwp > 1)); 1853 pid_t pid = Pstatus(Proc)->pr_pid; 1854 id_t lwpid = pri->lwpstat->pr_lwpid; 1855 1856 if (ff != pri->pparam.ff || 1857 lf != pri->pparam.lf || 1858 pid != pri->pparam.pid || 1859 lwpid != pri->pparam.lwpid || 1860 tid != pri->pparam.tid) { 1861 char *s = pri->pname; 1862 1863 if (ff) 1864 s += sprintf(s, "%d", (int)pid); 1865 if (lf) 1866 s += sprintf(s, "/%d", (int)lwpid); 1867 if (tid) 1868 s += sprintf(s, "@%d", (int)tid); 1869 if (ff || lf) 1870 *s++ = ':', *s++ = '\t'; 1871 if (ff && lf && s < pri->pname + 9) 1872 *s++ = '\t'; 1873 *s = '\0'; 1874 pri->pparam.ff = ff; 1875 pri->pparam.lf = lf; 1876 pri->pparam.pid = pid; 1877 pri->pparam.lwpid = lwpid; 1878 pri->pparam.tid = tid; 1879 } 1880 } 1881 } 1882 1883 /* 1884 * Print the pri->pname[] string, if any. 1885 */ 1886 void 1887 putpname(private_t *pri) 1888 { 1889 if (pri->pname[0]) 1890 (void) fputs(pri->pname, stdout); 1891 } 1892 1893 /* 1894 * Print the timestamp, if requested (-d, -D, or -E). 1895 */ 1896 void 1897 timestamp(private_t *pri) 1898 { 1899 const lwpstatus_t *Lsp = pri->lwpstat; 1900 int seconds; 1901 int fraction; 1902 1903 if (!(dflag|Dflag|Eflag) || !(Lsp->pr_flags & PR_STOPPED)) 1904 return; 1905 1906 seconds = Lsp->pr_tstamp.tv_sec - Cp->basetime.tv_sec; 1907 fraction = Lsp->pr_tstamp.tv_nsec - Cp->basetime.tv_nsec; 1908 if (fraction < 0) { 1909 seconds--; 1910 fraction += NANOSEC; 1911 } 1912 /* fraction in 1/10 milliseconds, rounded up */ 1913 fraction = (fraction + 50000) / 100000; 1914 if (fraction >= (MILLISEC * 10)) { 1915 seconds++; 1916 fraction -= (MILLISEC * 10); 1917 } 1918 1919 if (dflag) /* time stamp */ 1920 (void) printf("%2d.%4.4d\t", seconds, fraction); 1921 1922 if (Dflag) { /* time delta */ 1923 int oseconds = pri->seconds; 1924 int ofraction = pri->fraction; 1925 1926 pri->seconds = seconds; 1927 pri->fraction = fraction; 1928 seconds -= oseconds; 1929 fraction -= ofraction; 1930 if (fraction < 0) { 1931 seconds--; 1932 fraction += (MILLISEC * 10); 1933 } 1934 (void) printf("%2d.%4.4d\t", seconds, fraction); 1935 } 1936 1937 if (Eflag) { 1938 seconds = Lsp->pr_stime.tv_sec - pri->syslast.tv_sec; 1939 fraction = Lsp->pr_stime.tv_nsec - pri->syslast.tv_nsec; 1940 1941 if (fraction < 0) { 1942 seconds--; 1943 fraction += NANOSEC; 1944 } 1945 /* fraction in 1/10 milliseconds, rounded up */ 1946 fraction = (fraction + 50000) / 100000; 1947 if (fraction >= (MILLISEC * 10)) { 1948 seconds++; 1949 fraction -= (MILLISEC * 10); 1950 } 1951 (void) printf("%2d.%4.4d\t", seconds, fraction); 1952 } 1953 } 1954 1955 /* 1956 * Create output file, being careful about 1957 * suid/sgid and file descriptor 0, 1, 2 issues. 1958 */ 1959 int 1960 xcreat(char *path) 1961 { 1962 int fd; 1963 int mode = 0666; 1964 1965 if (Euid == Ruid && Egid == Rgid) /* not set-id */ 1966 fd = creat(path, mode); 1967 else if (access(path, F_OK) != 0) { /* file doesn't exist */ 1968 /* if directory permissions OK, create file & set ownership */ 1969 1970 char *dir; 1971 char *p; 1972 char dot[4]; 1973 1974 /* generate path for directory containing file */ 1975 if ((p = strrchr(path, '/')) == NULL) { /* no '/' */ 1976 p = dir = dot; 1977 *p++ = '.'; /* current directory */ 1978 *p = '\0'; 1979 } else if (p == path) { /* leading '/' */ 1980 p = dir = dot; 1981 *p++ = '/'; /* root directory */ 1982 *p = '\0'; 1983 } else { /* embedded '/' */ 1984 dir = path; /* directory path */ 1985 *p = '\0'; 1986 } 1987 1988 if (access(dir, W_OK|X_OK) != 0) { 1989 /* not writeable/searchable */ 1990 *p = '/'; 1991 fd = -1; 1992 } else { /* create file and set ownership correctly */ 1993 *p = '/'; 1994 if ((fd = creat(path, mode)) >= 0) 1995 (void) chown(path, (int)Ruid, (int)Rgid); 1996 } 1997 } else if (access(path, W_OK) != 0) /* file not writeable */ 1998 fd = -1; 1999 else 2000 fd = creat(path, mode); 2001 2002 /* 2003 * Make sure it's not one of 0, 1, or 2. 2004 * This allows truss to work when spawned by init(1m). 2005 */ 2006 if (0 <= fd && fd <= 2) { 2007 int dfd = fcntl(fd, F_DUPFD, 3); 2008 (void) close(fd); 2009 fd = dfd; 2010 } 2011 2012 /* 2013 * Mark it close-on-exec so created processes don't inherit it. 2014 */ 2015 if (fd >= 0) 2016 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 2017 2018 return (fd); 2019 } 2020 2021 void 2022 setoutput(int ofd) 2023 { 2024 if (ofd < 0) { 2025 (void) close(1); 2026 (void) fcntl(2, F_DUPFD, 1); 2027 } else if (ofd != 1) { 2028 (void) close(1); 2029 (void) fcntl(ofd, F_DUPFD, 1); 2030 (void) close(ofd); 2031 /* if no stderr, make it the same file */ 2032 if ((ofd = dup(2)) < 0) 2033 (void) fcntl(1, F_DUPFD, 2); 2034 else 2035 (void) close(ofd); 2036 } 2037 } 2038 2039 /* 2040 * Accumulate time differencies: a += e - s; 2041 */ 2042 void 2043 accumulate(timestruc_t *ap, const timestruc_t *ep, const timestruc_t *sp) 2044 { 2045 ap->tv_sec += ep->tv_sec - sp->tv_sec; 2046 ap->tv_nsec += ep->tv_nsec - sp->tv_nsec; 2047 if (ap->tv_nsec >= NANOSEC) { 2048 ap->tv_nsec -= NANOSEC; 2049 ap->tv_sec++; 2050 } else if (ap->tv_nsec < 0) { 2051 ap->tv_nsec += NANOSEC; 2052 ap->tv_sec--; 2053 } 2054 } 2055 2056 int 2057 lib_sort(const void *p1, const void *p2) 2058 { 2059 int cmpr = 0; 2060 long i; 2061 long j; 2062 2063 hentry_t *t1 = (hentry_t *)p1; 2064 hentry_t *t2 = (hentry_t *)p2; 2065 2066 char *p = t1->lib; 2067 char *q = t2->lib; 2068 2069 if ((cmpr = strcmp(p, q)) == 0) { 2070 i = t1->count; 2071 j = t2->count; 2072 if (i > j) 2073 return (-1); 2074 else if (i < j) 2075 return (1); 2076 else { 2077 p = t1->key; 2078 q = t2->key; 2079 return (strcmp(p, q)); 2080 } 2081 } else 2082 return (cmpr); 2083 } 2084 2085 void 2086 report(private_t *pri, time_t lapse) /* elapsed time, clock ticks */ 2087 { 2088 int i; 2089 long count; 2090 const char *name; 2091 long error; 2092 long total; 2093 long errtot; 2094 timestruc_t tickzero; 2095 timestruc_t ticks; 2096 timestruc_t ticktot; 2097 2098 if (descendent) 2099 return; 2100 2101 for (i = 0, total = 0; i <= PRMAXFAULT && !interrupt; i++) { 2102 if ((count = Cp->fltcount[i]) != 0) { 2103 if (total == 0) /* produce header */ 2104 (void) printf("faults -------------\n"); 2105 2106 name = proc_fltname(i, pri->flt_name, 2107 sizeof (pri->flt_name)); 2108 2109 (void) printf("%s%s\t%4ld\n", name, 2110 (((int)strlen(name) < 8)? 2111 (const char *)"\t" : (const char *)""), 2112 count); 2113 total += count; 2114 } 2115 } 2116 if (total && !interrupt) 2117 (void) printf("total:\t\t%4ld\n\n", total); 2118 2119 for (i = 0, total = 0; i <= PRMAXSIG && !interrupt; i++) { 2120 if ((count = Cp->sigcount[i]) != 0) { 2121 if (total == 0) /* produce header */ 2122 (void) printf("signals ------------\n"); 2123 name = signame(pri, i); 2124 (void) printf("%s%s\t%4ld\n", name, 2125 (((int)strlen(name) < 8)? 2126 (const char *)"\t" : (const char *)""), 2127 count); 2128 total += count; 2129 } 2130 } 2131 if (total && !interrupt) 2132 (void) printf("total:\t\t%4ld\n\n", total); 2133 2134 if ((Dynpat != NULL) && !interrupt) { 2135 size_t elem = elements_in_table(fcall_tbl); 2136 hiter_t *itr = iterate_hash(fcall_tbl); 2137 hentry_t *tmp = iter_next(itr); 2138 hentry_t *stbl = my_malloc(elem * sizeof (hentry_t), NULL); 2139 i = 0; 2140 while ((tmp != NULL) && (i < elem)) { 2141 stbl[i].prev = tmp->prev; 2142 stbl[i].next = tmp->next; 2143 stbl[i].lib = tmp->lib; 2144 stbl[i].key = tmp->key; 2145 stbl[i].count = tmp->count; 2146 tmp = iter_next(itr); 2147 i++; 2148 } 2149 qsort((void *)stbl, elem, sizeof (hentry_t), 2150 lib_sort); 2151 (void) printf( 2152 "\n%-20s %-40s %s\n", "Library:", "Function", "calls"); 2153 for (i = 0; i < elem; i++) { 2154 (void) printf("%-20s %-40s %ld\n", stbl[i].lib, 2155 stbl[i].key, stbl[i].count); 2156 } 2157 iter_free(itr); 2158 free(stbl); 2159 itr = NULL; 2160 } 2161 2162 if (!interrupt) 2163 (void) printf( 2164 "\nsyscall seconds calls errors\n"); 2165 2166 total = errtot = 0; 2167 tickzero.tv_sec = ticks.tv_sec = ticktot.tv_sec = 0; 2168 tickzero.tv_nsec = ticks.tv_nsec = ticktot.tv_nsec = 0; 2169 for (i = 0; i <= PRMAXSYS && !interrupt; i++) { 2170 struct syscount *scp = Cp->syscount[i]; 2171 int n = nsubcodes(i); 2172 int subcode; 2173 2174 for (subcode = 0; subcode < n; subcode++, scp++) { 2175 if ((count = scp->count) != 0 || scp->error) { 2176 (void) printf("%-19.19s ", 2177 sysname(pri, i, subcode)); 2178 2179 ticks = scp->stime; 2180 accumulate(&ticktot, &ticks, &tickzero); 2181 prtim(&ticks); 2182 2183 (void) printf(" %7ld", count); 2184 if ((error = scp->error) != 0) 2185 (void) printf(" %7ld", error); 2186 (void) fputc('\n', stdout); 2187 total += count; 2188 errtot += error; 2189 } 2190 } 2191 } 2192 2193 if (!interrupt) { 2194 (void) printf( 2195 " -------- ------ ----\n"); 2196 (void) printf("sys totals: "); 2197 prtim(&ticktot); 2198 (void) printf(" %7ld %6ld\n", total, errtot); 2199 } 2200 2201 if (!interrupt) { 2202 (void) printf("usr time: "); 2203 prtim(&Cp->usrtotal); 2204 (void) fputc('\n', stdout); 2205 } 2206 2207 if (!interrupt) { 2208 int hz = (int)sysconf(_SC_CLK_TCK); 2209 2210 ticks.tv_sec = lapse / hz; 2211 ticks.tv_nsec = (lapse % hz) * (1000000000 / hz); 2212 (void) printf("elapsed: "); 2213 prtim(&ticks); 2214 (void) fputc('\n', stdout); 2215 } 2216 } 2217 2218 void 2219 prtim(timestruc_t *tp) 2220 { 2221 time_t sec; 2222 2223 if ((sec = tp->tv_sec) != 0) /* whole seconds */ 2224 (void) printf("%5lu", sec); 2225 else 2226 (void) printf(" "); 2227 2228 (void) printf(".%3.3ld", tp->tv_nsec/1000000); /* fraction */ 2229 } 2230 2231 /* 2232 * Gather process id's. 2233 * Return 0 on success, != 0 on failure. 2234 */ 2235 void 2236 pids(char *arg, proc_set_t *grab) 2237 { 2238 pid_t pid = -1; 2239 int i; 2240 const char *lwps = NULL; 2241 2242 if ((pid = proc_arg_xpsinfo(arg, PR_ARG_PIDS, NULL, &i, &lwps)) < 0) { 2243 (void) fprintf(stderr, "%s: cannot trace '%s': %s\n", 2244 command, arg, Pgrab_error(i)); 2245 return; 2246 } 2247 2248 for (i = 0; i < ngrab; i++) 2249 if (grab[i].pid == pid) /* duplicate */ 2250 break; 2251 2252 if (i == ngrab) { 2253 grab[ngrab].pid = pid; 2254 grab[ngrab].lwps = lwps; 2255 ngrab++; 2256 } else { 2257 (void) fprintf(stderr, "%s: duplicate process-id ignored: %d\n", 2258 command, (int)pid); 2259 } 2260 } 2261 2262 /* 2263 * Report psargs string. 2264 */ 2265 void 2266 psargs(private_t *pri) 2267 { 2268 pid_t pid = Pstatus(Proc)->pr_pid; 2269 psinfo_t psinfo; 2270 2271 if (proc_get_psinfo(pid, &psinfo) == 0) 2272 (void) printf("%spsargs: %.64s\n", 2273 pri->pname, psinfo.pr_psargs); 2274 else { 2275 perror("psargs()"); 2276 (void) printf("%s\t*** Cannot read psinfo file for pid %d\n", 2277 pri->pname, (int)pid); 2278 } 2279 } 2280 2281 char * 2282 fetchstring(private_t *pri, long addr, int maxleng) 2283 { 2284 int nbyte; 2285 int leng = 0; 2286 char string[41]; 2287 2288 string[40] = '\0'; 2289 if (pri->str_bsize == 0) /* initial allocation of string buffer */ 2290 pri->str_buffer = 2291 my_malloc(pri->str_bsize = 16, "string buffer"); 2292 *pri->str_buffer = '\0'; 2293 2294 for (nbyte = 40; nbyte == 40 && leng < maxleng; addr += 40) { 2295 if ((nbyte = Pread(Proc, string, 40, addr)) <= 0) 2296 return (leng? pri->str_buffer : NULL); 2297 if (nbyte > 0 && 2298 (nbyte = strlen(string)) > 0) { 2299 while (leng + nbyte >= pri->str_bsize) 2300 pri->str_buffer = 2301 my_realloc(pri->str_buffer, 2302 pri->str_bsize *= 2, "string buffer"); 2303 (void) strcpy(pri->str_buffer+leng, string); 2304 leng += nbyte; 2305 } 2306 } 2307 2308 if (leng > maxleng) 2309 leng = maxleng; 2310 pri->str_buffer[leng] = '\0'; 2311 2312 return (pri->str_buffer); 2313 } 2314 2315 void 2316 show_cred(private_t *pri, int new) 2317 { 2318 prcred_t cred; 2319 2320 if (proc_get_cred(Pstatus(Proc)->pr_pid, &cred, 0) < 0) { 2321 perror("show_cred()"); 2322 (void) printf("%s\t*** Cannot get credentials\n", pri->pname); 2323 return; 2324 } 2325 2326 if (!cflag && prismember(&trace, SYS_exec)) { 2327 if (new) 2328 credentials = cred; 2329 if ((new && cred.pr_ruid != cred.pr_suid) || 2330 cred.pr_ruid != credentials.pr_ruid || 2331 cred.pr_suid != credentials.pr_suid) 2332 (void) printf( 2333 "%s *** SUID: ruid/euid/suid = %d / %d / %d ***\n", 2334 pri->pname, 2335 (int)cred.pr_ruid, 2336 (int)cred.pr_euid, 2337 (int)cred.pr_suid); 2338 if ((new && cred.pr_rgid != cred.pr_sgid) || 2339 cred.pr_rgid != credentials.pr_rgid || 2340 cred.pr_sgid != credentials.pr_sgid) 2341 (void) printf( 2342 "%s *** SGID: rgid/egid/sgid = %d / %d / %d ***\n", 2343 pri->pname, 2344 (int)cred.pr_rgid, 2345 (int)cred.pr_egid, 2346 (int)cred.pr_sgid); 2347 } 2348 2349 credentials = cred; 2350 } 2351 2352 /* 2353 * Take control of a child process. 2354 * We come here with truss_lock held. 2355 */ 2356 int 2357 control(private_t *pri, pid_t pid) 2358 { 2359 const pstatus_t *Psp; 2360 const lwpstatus_t *Lsp; 2361 pid_t childpid = 0; 2362 long flags; 2363 int rc; 2364 2365 (void) mutex_lock(&gps->fork_lock); 2366 while (gps->fork_pid != 0) 2367 (void) cond_wait(&gps->fork_cv, &gps->fork_lock); 2368 gps->fork_pid = getpid(); /* parent pid */ 2369 if ((childpid = fork1()) == -1) { 2370 (void) printf("%s\t*** Cannot fork() to control process #%d\n", 2371 pri->pname, (int)pid); 2372 Flush(); 2373 gps->fork_pid = 0; 2374 (void) cond_broadcast(&gps->fork_cv); 2375 (void) mutex_unlock(&gps->fork_lock); 2376 release(pri, pid); 2377 return (FALSE); 2378 } 2379 2380 if (childpid != 0) { 2381 /* 2382 * The parent carries on, after a brief pause. 2383 * The parent must wait until the child executes procadd(pid). 2384 */ 2385 while (gps->fork_pid != childpid) 2386 (void) cond_wait(&gps->fork_cv, &gps->fork_lock); 2387 gps->fork_pid = 0; 2388 (void) cond_broadcast(&gps->fork_cv); 2389 (void) mutex_unlock(&gps->fork_lock); 2390 return (FALSE); 2391 } 2392 2393 childpid = getpid(); 2394 descendent = TRUE; 2395 exit_called = FALSE; 2396 Pfree(Proc); /* forget old process */ 2397 2398 /* 2399 * The parent process owns the shared gps->fork_lock. 2400 * The child must grab it again. 2401 */ 2402 (void) mutex_lock(&gps->fork_lock); 2403 2404 /* 2405 * Child grabs the process and retains the tracing flags. 2406 */ 2407 if ((Proc = Pgrab(pid, PGRAB_RETAIN, &rc)) == NULL) { 2408 (void) fprintf(stderr, 2409 "%s: cannot control child process, pid# %d: %s\n", 2410 command, (int)pid, Pgrab_error(rc)); 2411 gps->fork_pid = childpid; 2412 (void) cond_broadcast(&gps->fork_cv); 2413 (void) mutex_unlock(&gps->fork_lock); 2414 exit(2); 2415 } 2416 2417 per_proc_init(); 2418 /* 2419 * Add ourself to the set of truss processes 2420 * and notify the parent to carry on. 2421 */ 2422 procadd(pid, NULL); 2423 gps->fork_pid = childpid; 2424 (void) cond_broadcast(&gps->fork_cv); 2425 (void) mutex_unlock(&gps->fork_lock); 2426 2427 /* 2428 * We may have grabbed the child before it is fully stopped on exit 2429 * from fork. Wait one second (at most) for it to settle down. 2430 */ 2431 (void) Pwait(Proc, MILLISEC); 2432 if (Rdb_agent != NULL) 2433 Rdb_agent = Prd_agent(Proc); 2434 2435 Psp = Pstatus(Proc); 2436 Lsp = &Psp->pr_lwp; 2437 pri->lwpstat = Lsp; 2438 data_model = Psp->pr_dmodel; 2439 2440 make_pname(pri, 0); 2441 2442 if (Lsp->pr_why != PR_SYSEXIT || 2443 (Lsp->pr_what != SYS_forkall && 2444 Lsp->pr_what != SYS_vfork && 2445 Lsp->pr_what != SYS_fork1)) 2446 (void) printf("%s\t*** Expected SYSEXIT, fork1,forkall,vfork\n", 2447 pri->pname); 2448 2449 pri->syslast = Psp->pr_stime; 2450 pri->usrlast = Psp->pr_utime; 2451 2452 flags = PR_FORK | PR_ASYNC; 2453 if (Dynpat != NULL) 2454 flags |= PR_BPTADJ; /* needed for x86 */ 2455 (void) Psetflags(Proc, flags); 2456 2457 return (TRUE); 2458 } 2459 2460 /* 2461 * Take control of an existing process. 2462 */ 2463 int 2464 grabit(private_t *pri, proc_set_t *set) 2465 { 2466 const pstatus_t *Psp; 2467 const lwpstatus_t *Lsp; 2468 int gcode; 2469 2470 /* 2471 * Don't force the takeover unless the -F option was specified. 2472 */ 2473 if ((Proc = Pgrab(set->pid, Fflag, &gcode)) == NULL) { 2474 (void) fprintf(stderr, "%s: %s: %d\n", 2475 command, Pgrab_error(gcode), (int)set->pid); 2476 pri->lwpstat = NULL; 2477 return (FALSE); 2478 } 2479 Psp = Pstatus(Proc); 2480 Lsp = &Psp->pr_lwp; 2481 pri->lwpstat = Lsp; 2482 2483 make_pname(pri, 0); 2484 2485 data_model = Psp->pr_dmodel; 2486 pri->syslast = Psp->pr_stime; 2487 pri->usrlast = Psp->pr_utime; 2488 2489 if (fflag || Dynpat != NULL) 2490 (void) Psetflags(Proc, PR_FORK); 2491 else 2492 (void) Punsetflags(Proc, PR_FORK); 2493 procadd(set->pid, set->lwps); 2494 show_cred(pri, TRUE); 2495 return (TRUE); 2496 } 2497 2498 /* 2499 * Release process from control. 2500 */ 2501 void 2502 release(private_t *pri, pid_t pid) 2503 { 2504 /* 2505 * The process in question is the child of a traced process. 2506 * We are here to turn off the inherited tracing flags. 2507 */ 2508 int fd; 2509 char ctlname[100]; 2510 long ctl[2]; 2511 2512 ctl[0] = PCSET; 2513 ctl[1] = PR_RLC; 2514 2515 /* process is freshly forked, no need for exclusive open */ 2516 (void) sprintf(ctlname, "/proc/%d/ctl", (int)pid); 2517 if ((fd = open(ctlname, O_WRONLY)) < 0 || 2518 write(fd, (char *)ctl, sizeof (ctl)) < 0) { 2519 perror("release()"); 2520 (void) printf( 2521 "%s\t*** Cannot release child process, pid# %d\n", 2522 pri->pname, (int)pid); 2523 Flush(); 2524 } 2525 if (fd >= 0) /* run-on-last-close sets the process running */ 2526 (void) close(fd); 2527 } 2528 2529 void 2530 intr(int sig) 2531 { 2532 /* 2533 * SIGUSR1 is special. It is used by one truss process to tell 2534 * another truss process to release its controlled process. 2535 * SIGUSR2 is also special. It is used to wake up threads waiting 2536 * for a victim lwp to stop after an event that will leave the 2537 * process hung (stopped and abandoned) has occurred. 2538 */ 2539 if (sig == SIGUSR1) { 2540 sigusr1 = TRUE; 2541 } else if (sig == SIGUSR2) { 2542 void *value; 2543 private_t *pri; 2544 struct ps_lwphandle *Lwp; 2545 2546 if (thr_getspecific(private_key, &value) == 0 && 2547 (pri = value) != NULL && 2548 (Lwp = pri->Lwp) != NULL) 2549 (void) Lstop(Lwp, MILLISEC / 10); 2550 } else { 2551 interrupt = sig; 2552 } 2553 } 2554 2555 void 2556 errmsg(const char *s, const char *q) 2557 { 2558 char msg[512]; 2559 2560 if (s || q) { 2561 msg[0] = '\0'; 2562 if (command) { 2563 (void) strcpy(msg, command); 2564 (void) strcat(msg, ": "); 2565 } 2566 if (s) 2567 (void) strcat(msg, s); 2568 if (q) 2569 (void) strcat(msg, q); 2570 (void) strcat(msg, "\n"); 2571 (void) write(2, msg, (size_t)strlen(msg)); 2572 } 2573 } 2574 2575 void 2576 abend(const char *s, const char *q) 2577 { 2578 (void) thr_sigsetmask(SIG_SETMASK, &fillset, NULL); 2579 if (Proc) { 2580 Flush(); 2581 errmsg(s, q); 2582 clear_breakpoints(); 2583 (void) Punsetflags(Proc, PR_ASYNC); 2584 Prelease(Proc, created? PRELEASE_KILL : PRELEASE_CLEAR); 2585 procdel(); 2586 (void) wait4all(); 2587 } else { 2588 errmsg(s, q); 2589 } 2590 exit(2); 2591 } 2592 2593 /* 2594 * Allocate memory. 2595 * If allocation fails then print a message and abort. 2596 */ 2597 void * 2598 my_realloc(void *buf, size_t size, const char *msg) 2599 { 2600 if ((buf = realloc(buf, size)) == NULL) { 2601 if (msg != NULL) 2602 abend("cannot allocate ", msg); 2603 else 2604 abend("memory allocation failure", NULL); 2605 } 2606 2607 return (buf); 2608 } 2609 2610 void * 2611 my_calloc(size_t nelem, size_t elsize, const char *msg) 2612 { 2613 void *buf = NULL; 2614 2615 if ((buf = calloc(nelem, elsize)) == NULL) { 2616 if (msg != NULL) 2617 abend("cannot allocate ", msg); 2618 else 2619 abend("memory allocation failure", NULL); 2620 } 2621 2622 return (buf); 2623 } 2624 2625 void * 2626 my_malloc(size_t size, const char *msg) 2627 { 2628 return (my_realloc(NULL, size, msg)); 2629 } 2630 2631 int 2632 wait4all() 2633 { 2634 int i; 2635 pid_t pid; 2636 int rc = 0; 2637 int status; 2638 2639 for (i = 0; i < 10; i++) { 2640 while ((pid = wait(&status)) != -1) { 2641 /* return exit() code of the created process */ 2642 if (pid == created) { 2643 if (WIFEXITED(status)) 2644 rc = WEXITSTATUS(status); 2645 else 2646 rc |= 0x80; /* +128 to indicate sig */ 2647 } 2648 } 2649 if (errno != EINTR && errno != ERESTART) 2650 break; 2651 } 2652 2653 if (i >= 10) /* repeated interrupts */ 2654 rc = 2; 2655 2656 return (rc); 2657 } 2658 2659 void 2660 letgo(private_t *pri) 2661 { 2662 (void) printf("%s\t*** process otherwise traced, releasing ...\n", 2663 pri->pname); 2664 } 2665 2666 /* 2667 * Test for empty set. 2668 * support routine used by isemptyset() macro. 2669 */ 2670 int 2671 is_empty(const uint32_t *sp, /* pointer to set (array of int32's) */ 2672 size_t n) /* number of int32's in set */ 2673 { 2674 if (n) { 2675 do { 2676 if (*sp++) 2677 return (FALSE); 2678 } while (--n); 2679 } 2680 2681 return (TRUE); 2682 } 2683 2684 /* 2685 * OR the second set into the first. 2686 * The sets must be the same size. 2687 */ 2688 void 2689 or_set(uint32_t *sp1, const uint32_t *sp2, size_t n) 2690 { 2691 if (n) { 2692 do { 2693 *sp1++ |= *sp2++; 2694 } while (--n); 2695 } 2696 } 2697