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 *
get_private()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
free_private(void * value)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
insert_lwpid(lwpid_t lwpid)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
broadcast_signals(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 *
grab_lwp(lwpid_t who)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
create_thread(void * arg,const lwpstatus_t * Lsp)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
main(int argc,char * argv[])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
main_thread(int first)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 *
worker_thread(void * arg)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
setup_basetime(hrtime_t basehrtime,struct timeval * basedate)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
per_proc_init()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
child_to_file()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
file_to_parent()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
make_pname(private_t * pri,id_t tid)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
putpname(private_t * pri)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
timestamp(private_t * pri)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
xcreat(char * path)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
setoutput(int ofd)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
accumulate(timestruc_t * ap,const timestruc_t * ep,const timestruc_t * sp)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
lib_sort(const void * p1,const void * p2)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
report(private_t * pri,time_t lapse)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
prtim(timestruc_t * tp)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
pids(char * arg,proc_set_t * grab)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
psargs(private_t * pri)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 *
fetchstring(private_t * pri,long addr,int maxleng)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 *
getset(prpriv_t * p,priv_ptype_t set)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
show_cred(private_t * pri,int new,int loadonly)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
control(private_t * pri,pid_t pid)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
grabit(private_t * pri,proc_set_t * set)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
release(private_t * pri,pid_t pid)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
intr(int sig)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
errmsg(const char * s,const char * q)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
abend(const char * s,const char * q)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 *
my_realloc(void * buf,size_t size,const char * msg)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 *
my_calloc(size_t nelem,size_t elsize,const char * msg)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 *
my_malloc(size_t size,const char * msg)2654 my_malloc(size_t size, const char *msg)
2655 {
2656 return (my_realloc(NULL, size, msg));
2657 }
2658
2659 int
wait4all()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
letgo(private_t * pri)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
is_empty(const uint32_t * sp,size_t n)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
or_set(uint32_t * sp1,const uint32_t * sp2,size_t n)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