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