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