Home | History | Annotate | Download | only in psig
      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     0  stevel /*
     22  1914  casper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     23     0  stevel  * Use is subject to license terms.
     24     0  stevel  */
     25     0  stevel 
     26     0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27     0  stevel 
     28     0  stevel #include <stdio.h>
     29  1914  casper #include <stdio_ext.h>
     30     0  stevel #include <stdlib.h>
     31     0  stevel #include <unistd.h>
     32     0  stevel #include <ctype.h>
     33     0  stevel #include <fcntl.h>
     34     0  stevel #include <string.h>
     35     0  stevel #include <signal.h>
     36     0  stevel #include <stddef.h>
     37     0  stevel #include <sys/types.h>
     38     0  stevel #include <sys/stat.h>
     39     0  stevel #include <libproc.h>
     40     0  stevel 
     41     0  stevel /* evil knowledge of libc internals */
     42     0  stevel #include "../../../lib/libc/inc/thr_uberdata.h"
     43     0  stevel 
     44     0  stevel #define	MAX_SYMNAMLEN	1024	/* Recommended max symbol name length */
     45     0  stevel 
     46     0  stevel static	char	*sigflags(int, int);
     47     0  stevel static	int	look(char *);
     48     0  stevel static	void	perr(char *);
     49     0  stevel static	int	usage(void);
     50     0  stevel static	uintptr_t deinterpose(int, void *, psinfo_t *, struct sigaction *);
     51     0  stevel 
     52     0  stevel static	char	*command;
     53     0  stevel static	char	*procname;
     54     0  stevel static	int	all_flag = 0;
     55     0  stevel static	int	lookuphandlers_flag = 1;
     56     0  stevel 
     57     0  stevel int
     58     0  stevel main(int argc, char **argv)
     59     0  stevel {
     60     0  stevel 	int rc = 0;
     61     0  stevel 	int c;
     62     0  stevel 	struct rlimit rlim;
     63     0  stevel 
     64     0  stevel 	if ((command = strrchr(argv[0], '/')) != NULL)
     65     0  stevel 		command++;
     66     0  stevel 	else
     67     0  stevel 		command = argv[0];
     68     0  stevel 
     69     0  stevel 	while ((c = getopt(argc, argv, "an")) != EOF) {
     70     0  stevel 		switch (c) {
     71     0  stevel 		case 'a':
     72     0  stevel 			all_flag = 1;
     73     0  stevel 			break;
     74     0  stevel 		case 'n':
     75     0  stevel 			lookuphandlers_flag = 0;
     76     0  stevel 			break;
     77     0  stevel 		default:
     78     0  stevel 			return (usage());
     79     0  stevel 		}
     80     0  stevel 	}
     81     0  stevel 
     82     0  stevel 	if (argc - optind < 1) {
     83     0  stevel 		return (usage());
     84     0  stevel 	}
     85     0  stevel 
     86     0  stevel 	/*
     87     0  stevel 	 * Make sure we'll have enough file descriptors to handle a target
     88     0  stevel 	 * that has many many mappings.
     89     0  stevel 	 */
     90     0  stevel 	if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
     91     0  stevel 		rlim.rlim_cur = rlim.rlim_max;
     92     0  stevel 		(void) setrlimit(RLIMIT_NOFILE, &rlim);
     93  1914  casper 		(void) enable_extended_FILE_stdio(-1, -1);
     94     0  stevel 	}
     95     0  stevel 
     96     0  stevel 	for (; optind != argc; optind++) {
     97     0  stevel 		rc += look(argv[optind]);
     98     0  stevel 	}
     99     0  stevel 
    100     0  stevel 	return (rc);
    101     0  stevel }
    102     0  stevel 
    103     0  stevel static int
    104     0  stevel usage(void)
    105     0  stevel {
    106     0  stevel 	(void) fprintf(stderr, "usage:\t%s [-n] pid ...\n", command);
    107     0  stevel 	(void) fprintf(stderr, "  (report process signal actions)\n");
    108     0  stevel 
    109     0  stevel 	return (2);
    110     0  stevel }
    111     0  stevel 
    112     0  stevel static uintptr_t
    113     0  stevel uberdata_addr(struct ps_prochandle *Pr, char dmodel)
    114     0  stevel {
    115     0  stevel 	GElf_Sym sym;
    116     0  stevel 
    117     0  stevel 	if (Plookup_by_name(Pr, "libc.so", "_tdb_bootstrap", &sym) < 0)
    118     0  stevel 		return (NULL);
    119     0  stevel #ifdef _LP64
    120     0  stevel 	if (dmodel != PR_MODEL_NATIVE) {
    121     0  stevel 		caddr32_t uaddr;
    122     0  stevel 		caddr32_t addr;
    123     0  stevel 
    124     0  stevel 		if (Pread(Pr, &addr, sizeof (addr), sym.st_value)
    125     0  stevel 		    == sizeof (addr) &&
    126     0  stevel 		    addr != 0 &&
    127     0  stevel 		    Pread(Pr, &uaddr, sizeof (uaddr), (uintptr_t)addr)
    128     0  stevel 		    == sizeof (uaddr) &&
    129     0  stevel 		    uaddr != 0)
    130     0  stevel 			return ((uintptr_t)uaddr);
    131     0  stevel 	}
    132     0  stevel #endif
    133     0  stevel 	if (dmodel == PR_MODEL_NATIVE) {
    134     0  stevel 		uintptr_t uaddr;
    135     0  stevel 		uintptr_t addr;
    136     0  stevel 
    137     0  stevel 		if (Pread(Pr, &addr, sizeof (addr), sym.st_value)
    138     0  stevel 		    == sizeof (addr) &&
    139     0  stevel 		    addr != 0 &&
    140     0  stevel 		    Pread(Pr, &uaddr, sizeof (uaddr), addr)
    141     0  stevel 		    == sizeof (uaddr) &&
    142     0  stevel 		    uaddr != 0)
    143     0  stevel 			return (uaddr);
    144     0  stevel 	}
    145     0  stevel 	if (Plookup_by_name(Pr, "libc.so", "_uberdata", &sym) < 0)
    146     0  stevel 		return (0);
    147     0  stevel 	return (sym.st_value);
    148     0  stevel }
    149     0  stevel 
    150     0  stevel /*
    151     0  stevel  * Iterator function used to generate the process sigmask
    152     0  stevel  * from the individual lwp sigmasks.
    153     0  stevel  */
    154     0  stevel static int
    155     0  stevel lwp_iter(void *cd, const lwpstatus_t *lwpstatus)
    156     0  stevel {
    157     0  stevel 	sigset_t *ssp = cd;
    158     0  stevel 
    159     0  stevel 	ssp->__sigbits[0] &= lwpstatus->pr_lwphold.__sigbits[0];
    160     0  stevel 	ssp->__sigbits[1] &= lwpstatus->pr_lwphold.__sigbits[1];
    161     0  stevel 	ssp->__sigbits[2] &= lwpstatus->pr_lwphold.__sigbits[2];
    162     0  stevel 	ssp->__sigbits[3] &= lwpstatus->pr_lwphold.__sigbits[3];
    163     0  stevel 
    164     0  stevel 	/*
    165     0  stevel 	 * Return non-zero to terminate the iteration
    166     0  stevel 	 * if the sigmask has become all zeros.
    167     0  stevel 	 */
    168     0  stevel 	return ((ssp->__sigbits[0] | ssp->__sigbits[1] |
    169     0  stevel 	    ssp->__sigbits[2] | ssp->__sigbits[3]) == 0);
    170     0  stevel }
    171     0  stevel 
    172     0  stevel static int
    173     0  stevel look(char *arg)
    174     0  stevel {
    175     0  stevel 	char pathname[100];
    176     0  stevel 	struct stat statb;
    177     0  stevel 	int fd = -1;
    178     0  stevel 	int sig, gcode;
    179     0  stevel 	sigset_t holdmask;
    180     0  stevel 	int maxsig;
    181     0  stevel 	struct sigaction *action = NULL;
    182     0  stevel 	psinfo_t psinfo;
    183     0  stevel 	const psinfo_t *psinfop;
    184     0  stevel 	struct ps_prochandle *Pr = NULL;
    185     0  stevel 	uintptr_t uberaddr;
    186     0  stevel 	uintptr_t aharraddr;
    187     0  stevel 	uintptr_t intfnaddr;
    188     0  stevel 	size_t aharrlen;
    189     0  stevel 	void *aharr = NULL;
    190     0  stevel 	int error = 1;
    191     0  stevel 
    192     0  stevel 	procname = arg;		/* for perr() */
    193     0  stevel 	if ((Pr = proc_arg_grab(arg, PR_ARG_PIDS, PGRAB_RDONLY|PGRAB_FORCE,
    194     0  stevel 	    &gcode)) == NULL || (psinfop = Ppsinfo(Pr)) == NULL) {
    195     0  stevel 		(void) fprintf(stderr, "%s: cannot examine %s: %s\n",
    196     0  stevel 		    command, arg, Pgrab_error(gcode));
    197     0  stevel 		goto look_error;
    198     0  stevel 	}
    199     0  stevel 	(void) memcpy(&psinfo, psinfop, sizeof (psinfo_t));
    200     0  stevel 	proc_unctrl_psinfo(&psinfo);
    201     0  stevel 
    202     0  stevel 	(void) sprintf(pathname, "/proc/%d/sigact", (int)psinfo.pr_pid);
    203     0  stevel 	if ((fd = open(pathname, O_RDONLY)) < 0) {
    204     0  stevel 		perr("open sigact");
    205     0  stevel 		goto look_error;
    206     0  stevel 	}
    207     0  stevel 
    208     0  stevel 	if (fstat(fd, &statb) != 0) {
    209     0  stevel 		perr("fstat sigact");
    210     0  stevel 		goto look_error;
    211     0  stevel 	}
    212     0  stevel 	maxsig = statb.st_size / sizeof (struct sigaction);
    213     0  stevel 	action = malloc(maxsig * sizeof (struct sigaction));
    214     0  stevel 	if (action == NULL) {
    215     0  stevel 		(void) fprintf(stderr,
    216     0  stevel 		"%s: cannot malloc() space for %d sigaction structures\n",
    217     0  stevel 			command, maxsig);
    218     0  stevel 		goto look_error;
    219     0  stevel 	}
    220     0  stevel 	if (read(fd, (char *)action, maxsig * sizeof (struct sigaction)) !=
    221     0  stevel 	    maxsig * sizeof (struct sigaction)) {
    222     0  stevel 		perr("read sigact");
    223     0  stevel 		goto look_error;
    224     0  stevel 	}
    225     0  stevel 	(void) close(fd);
    226     0  stevel 	fd = -1;
    227     0  stevel 
    228     0  stevel 	(void) printf("%d:\t%.70s\n", (int)psinfo.pr_pid, psinfo.pr_psargs);
    229     0  stevel 
    230     0  stevel 	(void) sigfillset(&holdmask);
    231     0  stevel 	(void) Plwp_iter(Pr, lwp_iter, &holdmask);
    232     0  stevel 
    233     0  stevel 	if ((uberaddr = uberdata_addr(Pr, psinfo.pr_dmodel)) == 0) {
    234     0  stevel 		aharraddr = 0;
    235     0  stevel 		aharrlen = 0;
    236     0  stevel 		intfnaddr = 0;
    237     0  stevel 	} else {
    238     0  stevel #ifdef _LP64
    239     0  stevel 		if (psinfo.pr_dmodel != PR_MODEL_NATIVE) {
    240     0  stevel 			caddr32_t addr;
    241     0  stevel 			aharraddr = uberaddr +
    242     0  stevel 				offsetof(uberdata32_t, siguaction);
    243     0  stevel 			aharrlen = sizeof (siguaction32_t) * NSIG;
    244     0  stevel 			(void) Pread(Pr, &addr, sizeof (addr),
    245     0  stevel 			    uberaddr + offsetof(uberdata32_t, sigacthandler));
    246     0  stevel 			intfnaddr = (uintptr_t)addr;
    247     0  stevel 		} else
    248     0  stevel #endif
    249     0  stevel 		{
    250     0  stevel 			aharraddr = uberaddr +
    251     0  stevel 				offsetof(uberdata_t, siguaction);
    252     0  stevel 			aharrlen = sizeof (siguaction_t) * NSIG;
    253     0  stevel 			(void) Pread(Pr, &intfnaddr, sizeof (intfnaddr),
    254     0  stevel 			    uberaddr + offsetof(uberdata_t, sigacthandler));
    255     0  stevel 		}
    256     0  stevel 	}
    257     0  stevel 
    258     0  stevel 	if (aharraddr) {
    259     0  stevel 		aharr = malloc(aharrlen);
    260     0  stevel 		if (aharr == NULL) {
    261     0  stevel 			(void) fprintf(stderr,
    262     0  stevel 			"%s: cannot malloc() space for actual handler array\n",
    263     0  stevel 			    command);
    264     0  stevel 			goto look_error;
    265     0  stevel 		}
    266     0  stevel 
    267     0  stevel 		if (Pread(Pr, aharr, aharrlen, aharraddr) != aharrlen) {
    268     0  stevel 			(void) fprintf(stderr,
    269     0  stevel 			    "%s: signal handler data at %p cannot be read.\n",
    270     0  stevel 			    command, (void *)aharraddr);
    271     0  stevel 			free(aharr);
    272     0  stevel 			aharr = NULL;
    273     0  stevel 		}
    274     0  stevel 	}
    275     0  stevel 
    276     0  stevel 	for (sig = 1; sig <= maxsig; sig++) {
    277     0  stevel 		struct sigaction *sp = &action[sig - 1];
    278     0  stevel 		int caught = 0;
    279     0  stevel 		char buf[SIG2STR_MAX];
    280     0  stevel 		char *s;
    281     0  stevel 
    282     0  stevel 		/* proc_signame() returns "SIG..."; skip the "SIG" part */
    283     0  stevel 		(void) printf("%s\t", proc_signame(sig, buf, sizeof (buf)) + 3);
    284     0  stevel 
    285     0  stevel 		if (prismember(&holdmask, sig))
    286     0  stevel 			(void) printf("blocked,");
    287     0  stevel 
    288     0  stevel 		if (sp->sa_handler == SIG_DFL)
    289     0  stevel 			(void) printf("default");
    290     0  stevel 		else if (sp->sa_handler == SIG_IGN)
    291     0  stevel 			(void) printf("ignored");
    292     0  stevel 		else
    293     0  stevel 			caught = 1;
    294     0  stevel 
    295     0  stevel 		if (caught || all_flag) {
    296     0  stevel 			uintptr_t haddr;
    297     0  stevel 			GElf_Sym hsym;
    298     0  stevel 			char hname[MAX_SYMNAMLEN];
    299     0  stevel 			char buf[PRSIGBUFSZ];
    300     0  stevel 
    301     0  stevel 			haddr = (uintptr_t)sp->sa_handler;
    302     0  stevel 
    303     0  stevel 			if (aharr && intfnaddr && haddr == intfnaddr)
    304     0  stevel 				haddr = deinterpose(sig, aharr, &psinfo, sp);
    305     0  stevel 
    306     0  stevel 			if (haddr == (uintptr_t)SIG_DFL) {
    307     0  stevel 				if (caught)
    308     0  stevel 					(void) printf("default");
    309     0  stevel 				caught = 0;
    310     0  stevel 			} else if (haddr == (uintptr_t)SIG_IGN) {
    311     0  stevel 				if (caught)
    312     0  stevel 					(void) printf("ignored");
    313     0  stevel 				caught = 0;
    314     0  stevel 			} else {
    315     0  stevel 				if (caught)
    316     0  stevel 					(void) printf("caught");
    317     0  stevel 			}
    318     0  stevel 
    319     0  stevel 			if (caught || all_flag) {
    320     0  stevel 				if (lookuphandlers_flag && haddr > 1 &&
    321     0  stevel 				    Plookup_by_addr(Pr, haddr, hname,
    322     0  stevel 				    sizeof (hname), &hsym) == 0)
    323     0  stevel 					(void) printf("\t%-8s", hname);
    324     0  stevel 				else
    325     0  stevel 					(void) printf("\t0x%-8lx",
    326     0  stevel 						(ulong_t)haddr);
    327     0  stevel 
    328     0  stevel 				s = sigflags(sig, sp->sa_flags);
    329     0  stevel 				(void) printf("%s", (*s != '\0')? s : "\t0");
    330     0  stevel 				(void) proc_sigset2str(&sp->sa_mask, ",", 1,
    331     0  stevel 				    buf, sizeof (buf));
    332     0  stevel 				if (buf[0] != '\0')
    333     0  stevel 					(void) printf("\t%s", buf);
    334     0  stevel 			}
    335     0  stevel 		} else if (sig == SIGCLD) {
    336     0  stevel 			s = sigflags(sig,
    337     0  stevel 				sp->sa_flags & (SA_NOCLDWAIT|SA_NOCLDSTOP));
    338     0  stevel 			if (*s != '\0')
    339     0  stevel 				(void) printf("\t\t%s", s);
    340     0  stevel 		}
    341     0  stevel 		(void) printf("\n");
    342     0  stevel 	}
    343     0  stevel 
    344     0  stevel 	error = 0;
    345     0  stevel 
    346     0  stevel look_error:
    347     0  stevel 	if (fd >= 0)
    348     0  stevel 		(void) close(fd);
    349     0  stevel 	if (aharr)
    350     0  stevel 		free(aharr);
    351     0  stevel 	if (action)
    352     0  stevel 		free(action);
    353     0  stevel 	if (Pr)
    354     0  stevel 		Prelease(Pr, 0);
    355     0  stevel 	return (error);
    356     0  stevel }
    357     0  stevel 
    358     0  stevel static void
    359     0  stevel perr(char *s)
    360     0  stevel {
    361     0  stevel 	if (s)
    362     0  stevel 		(void) fprintf(stderr, "%s: ", procname);
    363     0  stevel 	else
    364     0  stevel 		s = procname;
    365     0  stevel 	perror(s);
    366     0  stevel }
    367     0  stevel 
    368     0  stevel static char *
    369     0  stevel sigflags(int sig, int flags)
    370     0  stevel {
    371     0  stevel 	static char code_buf[100];
    372     0  stevel 	char *str = code_buf;
    373     0  stevel 	int flagmask =
    374     0  stevel 		(SA_ONSTACK|SA_RESETHAND|SA_RESTART|SA_SIGINFO|SA_NODEFER);
    375     0  stevel 
    376     0  stevel 	if (sig == SIGCLD)
    377     0  stevel 		flagmask |= (SA_NOCLDSTOP|SA_NOCLDWAIT);
    378     0  stevel 
    379     0  stevel 	*str = '\0';
    380     0  stevel 	if (flags & ~flagmask)
    381     0  stevel 		(void) sprintf(str, ",0x%x,", flags & ~flagmask);
    382     0  stevel 	else if (flags == 0)
    383     0  stevel 		return (str);
    384     0  stevel 
    385     0  stevel 	if (flags & SA_RESTART)
    386     0  stevel 		(void) strcat(str, ",RESTART");
    387     0  stevel 	if (flags & SA_RESETHAND)
    388     0  stevel 		(void) strcat(str, ",RESETHAND");
    389     0  stevel 	if (flags & SA_ONSTACK)
    390     0  stevel 		(void) strcat(str, ",ONSTACK");
    391     0  stevel 	if (flags & SA_SIGINFO)
    392     0  stevel 		(void) strcat(str, ",SIGINFO");
    393     0  stevel 	if (flags & SA_NODEFER)
    394     0  stevel 		(void) strcat(str, ",NODEFER");
    395     0  stevel 
    396     0  stevel 	if (sig == SIGCLD) {
    397     0  stevel 		if (flags & SA_NOCLDWAIT)
    398     0  stevel 			(void) strcat(str, ",NOCLDWAIT");
    399     0  stevel 		if (flags & SA_NOCLDSTOP)
    400     0  stevel 			(void) strcat(str, ",NOCLDSTOP");
    401     0  stevel 	}
    402     0  stevel 
    403     0  stevel 	*str = '\t';
    404     0  stevel 
    405     0  stevel 	return (str);
    406     0  stevel }
    407     0  stevel 
    408     0  stevel /*ARGSUSED2*/
    409     0  stevel static uintptr_t
    410     0  stevel deinterpose(int sig, void *aharr, psinfo_t *psinfo, struct sigaction *sp)
    411     0  stevel {
    412     0  stevel 	if (sp->sa_handler == SIG_DFL || sp->sa_handler == SIG_IGN)
    413     0  stevel 		return ((uintptr_t)sp->sa_handler);
    414     0  stevel #ifdef _LP64
    415     0  stevel 	if (psinfo->pr_dmodel != PR_MODEL_NATIVE) {
    416     0  stevel 		struct sigaction32 *sa32 = (struct sigaction32 *)
    417     0  stevel 			((uintptr_t)aharr + sig * sizeof (siguaction32_t) +
    418     0  stevel 			offsetof(siguaction32_t, sig_uaction));
    419     0  stevel 
    420     0  stevel 		sp->sa_flags = sa32->sa_flags;
    421     0  stevel 		sp->sa_handler = (void (*)())(uintptr_t)sa32->sa_handler;
    422     0  stevel 		(void) memcpy(&sp->sa_mask, &sa32->sa_mask,
    423     0  stevel 			sizeof (sp->sa_mask));
    424     0  stevel 	} else
    425     0  stevel #endif
    426     0  stevel 	{
    427     0  stevel 		struct sigaction *sa = (struct sigaction *)
    428     0  stevel 			((uintptr_t)aharr + sig * sizeof (siguaction_t) +
    429     0  stevel 			offsetof(siguaction_t, sig_uaction));
    430     0  stevel 
    431     0  stevel 		sp->sa_flags = sa->sa_flags;
    432     0  stevel 		sp->sa_handler = sa->sa_handler;
    433     0  stevel 		sp->sa_mask = sa->sa_mask;
    434     0  stevel 	}
    435     0  stevel 	return ((uintptr_t)sp->sa_handler);
    436     0  stevel }
    437