xref: /illumos-gate/usr/src/cmd/ptools/psig/psig.c (revision 21b85b87)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5004388ebScasper  * Common Development and Distribution License (the "License").
6004388ebScasper  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22004388ebScasper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
27004388ebScasper #include <stdio_ext.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <unistd.h>
307c478bd9Sstevel@tonic-gate #include <ctype.h>
317c478bd9Sstevel@tonic-gate #include <fcntl.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include <signal.h>
347c478bd9Sstevel@tonic-gate #include <stddef.h>
357c478bd9Sstevel@tonic-gate #include <sys/types.h>
367c478bd9Sstevel@tonic-gate #include <sys/stat.h>
377c478bd9Sstevel@tonic-gate #include <libproc.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /* evil knowledge of libc internals */
407c478bd9Sstevel@tonic-gate #include "../../../lib/libc/inc/thr_uberdata.h"
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #define	MAX_SYMNAMLEN	1024	/* Recommended max symbol name length */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate static	char	*sigflags(int, int);
457c478bd9Sstevel@tonic-gate static	int	look(char *);
467c478bd9Sstevel@tonic-gate static	void	perr(char *);
477c478bd9Sstevel@tonic-gate static	int	usage(void);
487c478bd9Sstevel@tonic-gate static	uintptr_t deinterpose(int, void *, psinfo_t *, struct sigaction *);
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate static	char	*command;
517c478bd9Sstevel@tonic-gate static	char	*procname;
527c478bd9Sstevel@tonic-gate static	int	all_flag = 0;
537c478bd9Sstevel@tonic-gate static	int	lookuphandlers_flag = 1;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)567c478bd9Sstevel@tonic-gate main(int argc, char **argv)
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate 	int rc = 0;
597c478bd9Sstevel@tonic-gate 	int c;
607c478bd9Sstevel@tonic-gate 	struct rlimit rlim;
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 	if ((command = strrchr(argv[0], '/')) != NULL)
637c478bd9Sstevel@tonic-gate 		command++;
647c478bd9Sstevel@tonic-gate 	else
657c478bd9Sstevel@tonic-gate 		command = argv[0];
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "an")) != EOF) {
687c478bd9Sstevel@tonic-gate 		switch (c) {
697c478bd9Sstevel@tonic-gate 		case 'a':
707c478bd9Sstevel@tonic-gate 			all_flag = 1;
717c478bd9Sstevel@tonic-gate 			break;
727c478bd9Sstevel@tonic-gate 		case 'n':
737c478bd9Sstevel@tonic-gate 			lookuphandlers_flag = 0;
747c478bd9Sstevel@tonic-gate 			break;
757c478bd9Sstevel@tonic-gate 		default:
767c478bd9Sstevel@tonic-gate 			return (usage());
777c478bd9Sstevel@tonic-gate 		}
787c478bd9Sstevel@tonic-gate 	}
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	if (argc - optind < 1) {
817c478bd9Sstevel@tonic-gate 		return (usage());
827c478bd9Sstevel@tonic-gate 	}
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	/*
857c478bd9Sstevel@tonic-gate 	 * Make sure we'll have enough file descriptors to handle a target
867c478bd9Sstevel@tonic-gate 	 * that has many many mappings.
877c478bd9Sstevel@tonic-gate 	 */
887c478bd9Sstevel@tonic-gate 	if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
897c478bd9Sstevel@tonic-gate 		rlim.rlim_cur = rlim.rlim_max;
907c478bd9Sstevel@tonic-gate 		(void) setrlimit(RLIMIT_NOFILE, &rlim);
91004388ebScasper 		(void) enable_extended_FILE_stdio(-1, -1);
927c478bd9Sstevel@tonic-gate 	}
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	for (; optind != argc; optind++) {
957c478bd9Sstevel@tonic-gate 		rc += look(argv[optind]);
967c478bd9Sstevel@tonic-gate 	}
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	return (rc);
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate static int
usage(void)1027c478bd9Sstevel@tonic-gate usage(void)
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "usage:\t%s [-n] pid ...\n", command);
1057c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "  (report process signal actions)\n");
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	return (2);
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate static uintptr_t
uberdata_addr(struct ps_prochandle * Pr,char dmodel)1117c478bd9Sstevel@tonic-gate uberdata_addr(struct ps_prochandle *Pr, char dmodel)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate 	GElf_Sym sym;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	if (Plookup_by_name(Pr, "libc.so", "_tdb_bootstrap", &sym) < 0)
116*21b85b87SToomas Soome 		return ((uintptr_t)NULL);
1177c478bd9Sstevel@tonic-gate #ifdef _LP64
1187c478bd9Sstevel@tonic-gate 	if (dmodel != PR_MODEL_NATIVE) {
1197c478bd9Sstevel@tonic-gate 		caddr32_t uaddr;
1207c478bd9Sstevel@tonic-gate 		caddr32_t addr;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 		if (Pread(Pr, &addr, sizeof (addr), sym.st_value)
1237c478bd9Sstevel@tonic-gate 		    == sizeof (addr) &&
1247c478bd9Sstevel@tonic-gate 		    addr != 0 &&
1257c478bd9Sstevel@tonic-gate 		    Pread(Pr, &uaddr, sizeof (uaddr), (uintptr_t)addr)
1267c478bd9Sstevel@tonic-gate 		    == sizeof (uaddr) &&
1277c478bd9Sstevel@tonic-gate 		    uaddr != 0)
1287c478bd9Sstevel@tonic-gate 			return ((uintptr_t)uaddr);
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate #endif
1317c478bd9Sstevel@tonic-gate 	if (dmodel == PR_MODEL_NATIVE) {
1327c478bd9Sstevel@tonic-gate 		uintptr_t uaddr;
1337c478bd9Sstevel@tonic-gate 		uintptr_t addr;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 		if (Pread(Pr, &addr, sizeof (addr), sym.st_value)
1367c478bd9Sstevel@tonic-gate 		    == sizeof (addr) &&
1377c478bd9Sstevel@tonic-gate 		    addr != 0 &&
1387c478bd9Sstevel@tonic-gate 		    Pread(Pr, &uaddr, sizeof (uaddr), addr)
1397c478bd9Sstevel@tonic-gate 		    == sizeof (uaddr) &&
1407c478bd9Sstevel@tonic-gate 		    uaddr != 0)
1417c478bd9Sstevel@tonic-gate 			return (uaddr);
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 	if (Plookup_by_name(Pr, "libc.so", "_uberdata", &sym) < 0)
144*21b85b87SToomas Soome 		return ((uintptr_t)NULL);
1457c478bd9Sstevel@tonic-gate 	return (sym.st_value);
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate /*
1497c478bd9Sstevel@tonic-gate  * Iterator function used to generate the process sigmask
1507c478bd9Sstevel@tonic-gate  * from the individual lwp sigmasks.
1517c478bd9Sstevel@tonic-gate  */
1527c478bd9Sstevel@tonic-gate static int
lwp_iter(void * cd,const lwpstatus_t * lwpstatus)1537c478bd9Sstevel@tonic-gate lwp_iter(void *cd, const lwpstatus_t *lwpstatus)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	sigset_t *ssp = cd;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	ssp->__sigbits[0] &= lwpstatus->pr_lwphold.__sigbits[0];
1587c478bd9Sstevel@tonic-gate 	ssp->__sigbits[1] &= lwpstatus->pr_lwphold.__sigbits[1];
1597c478bd9Sstevel@tonic-gate 	ssp->__sigbits[2] &= lwpstatus->pr_lwphold.__sigbits[2];
1607c478bd9Sstevel@tonic-gate 	ssp->__sigbits[3] &= lwpstatus->pr_lwphold.__sigbits[3];
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	/*
1637c478bd9Sstevel@tonic-gate 	 * Return non-zero to terminate the iteration
1647c478bd9Sstevel@tonic-gate 	 * if the sigmask has become all zeros.
1657c478bd9Sstevel@tonic-gate 	 */
1667c478bd9Sstevel@tonic-gate 	return ((ssp->__sigbits[0] | ssp->__sigbits[1] |
1677c478bd9Sstevel@tonic-gate 	    ssp->__sigbits[2] | ssp->__sigbits[3]) == 0);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate static int
look(char * arg)1717c478bd9Sstevel@tonic-gate look(char *arg)
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate 	char pathname[100];
1747c478bd9Sstevel@tonic-gate 	struct stat statb;
1757c478bd9Sstevel@tonic-gate 	int fd = -1;
1767c478bd9Sstevel@tonic-gate 	int sig, gcode;
1777c478bd9Sstevel@tonic-gate 	sigset_t holdmask;
1787c478bd9Sstevel@tonic-gate 	int maxsig;
1797c478bd9Sstevel@tonic-gate 	struct sigaction *action = NULL;
1807c478bd9Sstevel@tonic-gate 	psinfo_t psinfo;
1817c478bd9Sstevel@tonic-gate 	const psinfo_t *psinfop;
1827c478bd9Sstevel@tonic-gate 	struct ps_prochandle *Pr = NULL;
1837c478bd9Sstevel@tonic-gate 	uintptr_t uberaddr;
1847c478bd9Sstevel@tonic-gate 	uintptr_t aharraddr;
1857c478bd9Sstevel@tonic-gate 	uintptr_t intfnaddr;
1867c478bd9Sstevel@tonic-gate 	size_t aharrlen;
1877c478bd9Sstevel@tonic-gate 	void *aharr = NULL;
1887c478bd9Sstevel@tonic-gate 	int error = 1;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	procname = arg;		/* for perr() */
1917c478bd9Sstevel@tonic-gate 	if ((Pr = proc_arg_grab(arg, PR_ARG_PIDS, PGRAB_RDONLY|PGRAB_FORCE,
1927c478bd9Sstevel@tonic-gate 	    &gcode)) == NULL || (psinfop = Ppsinfo(Pr)) == NULL) {
1937c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: cannot examine %s: %s\n",
1947c478bd9Sstevel@tonic-gate 		    command, arg, Pgrab_error(gcode));
1957c478bd9Sstevel@tonic-gate 		goto look_error;
1967c478bd9Sstevel@tonic-gate 	}
1977c478bd9Sstevel@tonic-gate 	(void) memcpy(&psinfo, psinfop, sizeof (psinfo_t));
1987c478bd9Sstevel@tonic-gate 	proc_unctrl_psinfo(&psinfo);
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	(void) sprintf(pathname, "/proc/%d/sigact", (int)psinfo.pr_pid);
2017c478bd9Sstevel@tonic-gate 	if ((fd = open(pathname, O_RDONLY)) < 0) {
2027c478bd9Sstevel@tonic-gate 		perr("open sigact");
2037c478bd9Sstevel@tonic-gate 		goto look_error;
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	if (fstat(fd, &statb) != 0) {
2077c478bd9Sstevel@tonic-gate 		perr("fstat sigact");
2087c478bd9Sstevel@tonic-gate 		goto look_error;
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 	maxsig = statb.st_size / sizeof (struct sigaction);
2117c478bd9Sstevel@tonic-gate 	action = malloc(maxsig * sizeof (struct sigaction));
2127c478bd9Sstevel@tonic-gate 	if (action == NULL) {
2137c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
2147c478bd9Sstevel@tonic-gate 		"%s: cannot malloc() space for %d sigaction structures\n",
215*21b85b87SToomas Soome 		    command, maxsig);
2167c478bd9Sstevel@tonic-gate 		goto look_error;
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 	if (read(fd, (char *)action, maxsig * sizeof (struct sigaction)) !=
2197c478bd9Sstevel@tonic-gate 	    maxsig * sizeof (struct sigaction)) {
2207c478bd9Sstevel@tonic-gate 		perr("read sigact");
2217c478bd9Sstevel@tonic-gate 		goto look_error;
2227c478bd9Sstevel@tonic-gate 	}
2237c478bd9Sstevel@tonic-gate 	(void) close(fd);
2247c478bd9Sstevel@tonic-gate 	fd = -1;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	(void) printf("%d:\t%.70s\n", (int)psinfo.pr_pid, psinfo.pr_psargs);
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	(void) sigfillset(&holdmask);
2297c478bd9Sstevel@tonic-gate 	(void) Plwp_iter(Pr, lwp_iter, &holdmask);
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	if ((uberaddr = uberdata_addr(Pr, psinfo.pr_dmodel)) == 0) {
2327c478bd9Sstevel@tonic-gate 		aharraddr = 0;
2337c478bd9Sstevel@tonic-gate 		aharrlen = 0;
2347c478bd9Sstevel@tonic-gate 		intfnaddr = 0;
2357c478bd9Sstevel@tonic-gate 	} else {
2367c478bd9Sstevel@tonic-gate #ifdef _LP64
2377c478bd9Sstevel@tonic-gate 		if (psinfo.pr_dmodel != PR_MODEL_NATIVE) {
2387c478bd9Sstevel@tonic-gate 			caddr32_t addr;
2397c478bd9Sstevel@tonic-gate 			aharraddr = uberaddr +
240*21b85b87SToomas Soome 			    offsetof(uberdata32_t, siguaction);
2417c478bd9Sstevel@tonic-gate 			aharrlen = sizeof (siguaction32_t) * NSIG;
2427c478bd9Sstevel@tonic-gate 			(void) Pread(Pr, &addr, sizeof (addr),
2437c478bd9Sstevel@tonic-gate 			    uberaddr + offsetof(uberdata32_t, sigacthandler));
2447c478bd9Sstevel@tonic-gate 			intfnaddr = (uintptr_t)addr;
2457c478bd9Sstevel@tonic-gate 		} else
2467c478bd9Sstevel@tonic-gate #endif
2477c478bd9Sstevel@tonic-gate 		{
2487c478bd9Sstevel@tonic-gate 			aharraddr = uberaddr +
249*21b85b87SToomas Soome 			    offsetof(uberdata_t, siguaction);
2507c478bd9Sstevel@tonic-gate 			aharrlen = sizeof (siguaction_t) * NSIG;
2517c478bd9Sstevel@tonic-gate 			(void) Pread(Pr, &intfnaddr, sizeof (intfnaddr),
2527c478bd9Sstevel@tonic-gate 			    uberaddr + offsetof(uberdata_t, sigacthandler));
2537c478bd9Sstevel@tonic-gate 		}
2547c478bd9Sstevel@tonic-gate 	}
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	if (aharraddr) {
2577c478bd9Sstevel@tonic-gate 		aharr = malloc(aharrlen);
2587c478bd9Sstevel@tonic-gate 		if (aharr == NULL) {
2597c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
2607c478bd9Sstevel@tonic-gate 			"%s: cannot malloc() space for actual handler array\n",
2617c478bd9Sstevel@tonic-gate 			    command);
2627c478bd9Sstevel@tonic-gate 			goto look_error;
2637c478bd9Sstevel@tonic-gate 		}
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 		if (Pread(Pr, aharr, aharrlen, aharraddr) != aharrlen) {
2667c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
2677c478bd9Sstevel@tonic-gate 			    "%s: signal handler data at %p cannot be read.\n",
2687c478bd9Sstevel@tonic-gate 			    command, (void *)aharraddr);
2697c478bd9Sstevel@tonic-gate 			free(aharr);
2707c478bd9Sstevel@tonic-gate 			aharr = NULL;
2717c478bd9Sstevel@tonic-gate 		}
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	for (sig = 1; sig <= maxsig; sig++) {
2757c478bd9Sstevel@tonic-gate 		struct sigaction *sp = &action[sig - 1];
2767c478bd9Sstevel@tonic-gate 		int caught = 0;
2777c478bd9Sstevel@tonic-gate 		char buf[SIG2STR_MAX];
2787c478bd9Sstevel@tonic-gate 		char *s;
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 		/* proc_signame() returns "SIG..."; skip the "SIG" part */
2817c478bd9Sstevel@tonic-gate 		(void) printf("%s\t", proc_signame(sig, buf, sizeof (buf)) + 3);
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 		if (prismember(&holdmask, sig))
2847c478bd9Sstevel@tonic-gate 			(void) printf("blocked,");
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 		if (sp->sa_handler == SIG_DFL)
2877c478bd9Sstevel@tonic-gate 			(void) printf("default");
2887c478bd9Sstevel@tonic-gate 		else if (sp->sa_handler == SIG_IGN)
2897c478bd9Sstevel@tonic-gate 			(void) printf("ignored");
2907c478bd9Sstevel@tonic-gate 		else
2917c478bd9Sstevel@tonic-gate 			caught = 1;
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 		if (caught || all_flag) {
2947c478bd9Sstevel@tonic-gate 			uintptr_t haddr;
2957c478bd9Sstevel@tonic-gate 			GElf_Sym hsym;
2967c478bd9Sstevel@tonic-gate 			char hname[MAX_SYMNAMLEN];
2977c478bd9Sstevel@tonic-gate 			char buf[PRSIGBUFSZ];
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 			haddr = (uintptr_t)sp->sa_handler;
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 			if (aharr && intfnaddr && haddr == intfnaddr)
3027c478bd9Sstevel@tonic-gate 				haddr = deinterpose(sig, aharr, &psinfo, sp);
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 			if (haddr == (uintptr_t)SIG_DFL) {
3057c478bd9Sstevel@tonic-gate 				if (caught)
3067c478bd9Sstevel@tonic-gate 					(void) printf("default");
3077c478bd9Sstevel@tonic-gate 				caught = 0;
3087c478bd9Sstevel@tonic-gate 			} else if (haddr == (uintptr_t)SIG_IGN) {
3097c478bd9Sstevel@tonic-gate 				if (caught)
3107c478bd9Sstevel@tonic-gate 					(void) printf("ignored");
3117c478bd9Sstevel@tonic-gate 				caught = 0;
3127c478bd9Sstevel@tonic-gate 			} else {
3137c478bd9Sstevel@tonic-gate 				if (caught)
3147c478bd9Sstevel@tonic-gate 					(void) printf("caught");
3157c478bd9Sstevel@tonic-gate 			}
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 			if (caught || all_flag) {
3187c478bd9Sstevel@tonic-gate 				if (lookuphandlers_flag && haddr > 1 &&
3197c478bd9Sstevel@tonic-gate 				    Plookup_by_addr(Pr, haddr, hname,
3207c478bd9Sstevel@tonic-gate 				    sizeof (hname), &hsym) == 0)
3217c478bd9Sstevel@tonic-gate 					(void) printf("\t%-8s", hname);
3227c478bd9Sstevel@tonic-gate 				else
3237c478bd9Sstevel@tonic-gate 					(void) printf("\t0x%-8lx",
324*21b85b87SToomas Soome 					    (ulong_t)haddr);
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 				s = sigflags(sig, sp->sa_flags);
3277c478bd9Sstevel@tonic-gate 				(void) printf("%s", (*s != '\0')? s : "\t0");
3287c478bd9Sstevel@tonic-gate 				(void) proc_sigset2str(&sp->sa_mask, ",", 1,
3297c478bd9Sstevel@tonic-gate 				    buf, sizeof (buf));
3307c478bd9Sstevel@tonic-gate 				if (buf[0] != '\0')
3317c478bd9Sstevel@tonic-gate 					(void) printf("\t%s", buf);
3327c478bd9Sstevel@tonic-gate 			}
3337c478bd9Sstevel@tonic-gate 		} else if (sig == SIGCLD) {
3347c478bd9Sstevel@tonic-gate 			s = sigflags(sig,
335*21b85b87SToomas Soome 			    sp->sa_flags & (SA_NOCLDWAIT | SA_NOCLDSTOP));
3367c478bd9Sstevel@tonic-gate 			if (*s != '\0')
3377c478bd9Sstevel@tonic-gate 				(void) printf("\t\t%s", s);
3387c478bd9Sstevel@tonic-gate 		}
3397c478bd9Sstevel@tonic-gate 		(void) printf("\n");
3407c478bd9Sstevel@tonic-gate 	}
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	error = 0;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate look_error:
3457c478bd9Sstevel@tonic-gate 	if (fd >= 0)
3467c478bd9Sstevel@tonic-gate 		(void) close(fd);
3477c478bd9Sstevel@tonic-gate 	if (aharr)
3487c478bd9Sstevel@tonic-gate 		free(aharr);
3497c478bd9Sstevel@tonic-gate 	if (action)
3507c478bd9Sstevel@tonic-gate 		free(action);
3517c478bd9Sstevel@tonic-gate 	if (Pr)
3527c478bd9Sstevel@tonic-gate 		Prelease(Pr, 0);
3537c478bd9Sstevel@tonic-gate 	return (error);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate static void
perr(char * s)3577c478bd9Sstevel@tonic-gate perr(char *s)
3587c478bd9Sstevel@tonic-gate {
3597c478bd9Sstevel@tonic-gate 	if (s)
3607c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: ", procname);
3617c478bd9Sstevel@tonic-gate 	else
3627c478bd9Sstevel@tonic-gate 		s = procname;
3637c478bd9Sstevel@tonic-gate 	perror(s);
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate static char *
sigflags(int sig,int flags)3677c478bd9Sstevel@tonic-gate sigflags(int sig, int flags)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate 	static char code_buf[100];
3707c478bd9Sstevel@tonic-gate 	char *str = code_buf;
3717c478bd9Sstevel@tonic-gate 	int flagmask =
372*21b85b87SToomas Soome 	    (SA_ONSTACK | SA_RESETHAND | SA_RESTART | SA_SIGINFO | SA_NODEFER);
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	if (sig == SIGCLD)
375*21b85b87SToomas Soome 		flagmask |= (SA_NOCLDSTOP | SA_NOCLDWAIT);
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	*str = '\0';
3787c478bd9Sstevel@tonic-gate 	if (flags & ~flagmask)
3797c478bd9Sstevel@tonic-gate 		(void) sprintf(str, ",0x%x,", flags & ~flagmask);
3807c478bd9Sstevel@tonic-gate 	else if (flags == 0)
3817c478bd9Sstevel@tonic-gate 		return (str);
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	if (flags & SA_RESTART)
3847c478bd9Sstevel@tonic-gate 		(void) strcat(str, ",RESTART");
3857c478bd9Sstevel@tonic-gate 	if (flags & SA_RESETHAND)
3867c478bd9Sstevel@tonic-gate 		(void) strcat(str, ",RESETHAND");
3877c478bd9Sstevel@tonic-gate 	if (flags & SA_ONSTACK)
3887c478bd9Sstevel@tonic-gate 		(void) strcat(str, ",ONSTACK");
3897c478bd9Sstevel@tonic-gate 	if (flags & SA_SIGINFO)
3907c478bd9Sstevel@tonic-gate 		(void) strcat(str, ",SIGINFO");
3917c478bd9Sstevel@tonic-gate 	if (flags & SA_NODEFER)
3927c478bd9Sstevel@tonic-gate 		(void) strcat(str, ",NODEFER");
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 	if (sig == SIGCLD) {
3957c478bd9Sstevel@tonic-gate 		if (flags & SA_NOCLDWAIT)
3967c478bd9Sstevel@tonic-gate 			(void) strcat(str, ",NOCLDWAIT");
3977c478bd9Sstevel@tonic-gate 		if (flags & SA_NOCLDSTOP)
3987c478bd9Sstevel@tonic-gate 			(void) strcat(str, ",NOCLDSTOP");
3997c478bd9Sstevel@tonic-gate 	}
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	*str = '\t';
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	return (str);
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate /*ARGSUSED2*/
4077c478bd9Sstevel@tonic-gate static uintptr_t
deinterpose(int sig,void * aharr,psinfo_t * psinfo,struct sigaction * sp)4087c478bd9Sstevel@tonic-gate deinterpose(int sig, void *aharr, psinfo_t *psinfo, struct sigaction *sp)
4097c478bd9Sstevel@tonic-gate {
4107c478bd9Sstevel@tonic-gate 	if (sp->sa_handler == SIG_DFL || sp->sa_handler == SIG_IGN)
4117c478bd9Sstevel@tonic-gate 		return ((uintptr_t)sp->sa_handler);
4127c478bd9Sstevel@tonic-gate #ifdef _LP64
4137c478bd9Sstevel@tonic-gate 	if (psinfo->pr_dmodel != PR_MODEL_NATIVE) {
4147c478bd9Sstevel@tonic-gate 		struct sigaction32 *sa32 = (struct sigaction32 *)
415*21b85b87SToomas Soome 		    ((uintptr_t)aharr + sig * sizeof (siguaction32_t) +
416*21b85b87SToomas Soome 		    offsetof(siguaction32_t, sig_uaction));
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 		sp->sa_flags = sa32->sa_flags;
4197c478bd9Sstevel@tonic-gate 		sp->sa_handler = (void (*)())(uintptr_t)sa32->sa_handler;
4207c478bd9Sstevel@tonic-gate 		(void) memcpy(&sp->sa_mask, &sa32->sa_mask,
421*21b85b87SToomas Soome 		    sizeof (sp->sa_mask));
4227c478bd9Sstevel@tonic-gate 	} else
4237c478bd9Sstevel@tonic-gate #endif
4247c478bd9Sstevel@tonic-gate 	{
4257c478bd9Sstevel@tonic-gate 		struct sigaction *sa = (struct sigaction *)
426*21b85b87SToomas Soome 		    ((uintptr_t)aharr + sig * sizeof (siguaction_t) +
427*21b85b87SToomas Soome 		    offsetof(siguaction_t, sig_uaction));
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 		sp->sa_flags = sa->sa_flags;
4307c478bd9Sstevel@tonic-gate 		sp->sa_handler = sa->sa_handler;
4317c478bd9Sstevel@tonic-gate 		sp->sa_mask = sa->sa_mask;
4327c478bd9Sstevel@tonic-gate 	}
4337c478bd9Sstevel@tonic-gate 	return ((uintptr_t)sp->sa_handler);
4347c478bd9Sstevel@tonic-gate }
435