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