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