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