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