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