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