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