xref: /onnv-gate/usr/src/cmd/sgs/link_audit/common/dumpbind.c (revision 12927:a27c46eb192b)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*12927SRod.Evans@Sun.COM  * Common Development and Distribution License (the "License").
6*12927SRod.Evans@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*12927SRod.Evans@Sun.COM 
220Sstevel@tonic-gate /*
23*12927SRod.Evans@Sun.COM  * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate #include	<stdlib.h>
260Sstevel@tonic-gate #include	<unistd.h>
270Sstevel@tonic-gate #include	<sys/types.h>
280Sstevel@tonic-gate #include	<sys/stat.h>
290Sstevel@tonic-gate #include	<sys/lwp.h>
300Sstevel@tonic-gate #include	<fcntl.h>
310Sstevel@tonic-gate #include	<stdio.h>
320Sstevel@tonic-gate #include	<sys/mman.h>
330Sstevel@tonic-gate #include	<synch.h>
340Sstevel@tonic-gate #include	<errno.h>
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include	"bindings.h"
370Sstevel@tonic-gate 
380Sstevel@tonic-gate void
usage()390Sstevel@tonic-gate usage()
400Sstevel@tonic-gate {
410Sstevel@tonic-gate 	(void) printf("usage: dumpbind [-pqsc] <bindings.data>\n");
420Sstevel@tonic-gate 	(void) printf("\t-p\tdisplay output in parsable format\n");
430Sstevel@tonic-gate 	(void) printf("\t-q\tquery all mutex_locks in data buffer\n");
440Sstevel@tonic-gate 	(void) printf("\t-c\tclear all mutex_locks in data buffer\n");
450Sstevel@tonic-gate 	(void) printf("\t-s\tset all mutex_locks in data buffer\n");
460Sstevel@tonic-gate 	(void) printf("\t-b\tprint bucket usage statistics\n");
470Sstevel@tonic-gate }
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * Returns 1 if lock held - 0 otherwise.
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate static int
query_lock(lwp_mutex_t * lock)530Sstevel@tonic-gate query_lock(lwp_mutex_t *lock) {
540Sstevel@tonic-gate 	if (_lwp_mutex_trylock(lock) == 0) {
550Sstevel@tonic-gate 		(void) _lwp_mutex_unlock(lock);
560Sstevel@tonic-gate 		return (0);
570Sstevel@tonic-gate 	} else
580Sstevel@tonic-gate 		return (1);
590Sstevel@tonic-gate }
600Sstevel@tonic-gate 
610Sstevel@tonic-gate static void
query_buffer_locks(bindhead * bhp)620Sstevel@tonic-gate query_buffer_locks(bindhead * bhp)
630Sstevel@tonic-gate {
640Sstevel@tonic-gate 	int	i, bkt_locks_held = 0;
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	(void) printf("bh_strlock: ");
670Sstevel@tonic-gate 	if (query_lock(&bhp->bh_strlock) == 1)
680Sstevel@tonic-gate 		(void) printf("lock held\n");
690Sstevel@tonic-gate 	else
700Sstevel@tonic-gate 		(void) printf("free\n");
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	(void) printf("bh_lock: ");
730Sstevel@tonic-gate 	if (query_lock(&bhp->bh_lock) == 1)
740Sstevel@tonic-gate 		(void) printf("lock held\n");
750Sstevel@tonic-gate 	else
760Sstevel@tonic-gate 		(void) printf("free\n");
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	(void) printf("Buckets: %d - locks held:\n", bhp->bh_bktcnt);
790Sstevel@tonic-gate 	for (i = 0; i < bhp->bh_bktcnt; i++) {
800Sstevel@tonic-gate 		if (query_lock(&bhp->bh_bkts[i].bb_lock) == 1) {
810Sstevel@tonic-gate 			bkt_locks_held++;
820Sstevel@tonic-gate 			(void) printf("\tbkt[%d]: lock held\n", i);
830Sstevel@tonic-gate 		}
840Sstevel@tonic-gate 	}
850Sstevel@tonic-gate 	if (bkt_locks_held == 0)
860Sstevel@tonic-gate 		(void) printf("\tnone.\n");
870Sstevel@tonic-gate 	else
880Sstevel@tonic-gate 		(void) printf("\t[%d bucket(s) locked]\n", bkt_locks_held);
890Sstevel@tonic-gate }
900Sstevel@tonic-gate 
910Sstevel@tonic-gate static void
clear_buffer_locks(bindhead * bhp)920Sstevel@tonic-gate clear_buffer_locks(bindhead * bhp)
930Sstevel@tonic-gate {
940Sstevel@tonic-gate 	int	i;
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	if (query_lock(&bhp->bh_strlock) == 1) {
970Sstevel@tonic-gate 		(void) _lwp_mutex_unlock(&bhp->bh_strlock);
980Sstevel@tonic-gate 		(void) printf("bh_strlock: cleared\n");
990Sstevel@tonic-gate 	}
1000Sstevel@tonic-gate 	if (query_lock(&bhp->bh_lock) == 1) {
1010Sstevel@tonic-gate 		(void) _lwp_mutex_unlock(&bhp->bh_lock);
1020Sstevel@tonic-gate 		(void) printf("bh_lock: cleared\n");
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 	for (i = 0; i < bhp->bh_bktcnt; i++) {
1050Sstevel@tonic-gate 		if (query_lock(&bhp->bh_bkts[i].bb_lock) == 1) {
1060Sstevel@tonic-gate 			(void) _lwp_mutex_unlock(&bhp->bh_bkts[i].bb_lock);
1070Sstevel@tonic-gate 			(void) printf("bkt[%d]: lock cleared\n", i);
1080Sstevel@tonic-gate 		}
1090Sstevel@tonic-gate 	}
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate static void
set_buffer_locks(bindhead * bhp)1130Sstevel@tonic-gate set_buffer_locks(bindhead * bhp)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate 	int	i;
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	for (i = 0; i < bhp->bh_bktcnt; i++)
1180Sstevel@tonic-gate 		(void) _lwp_mutex_lock(&bhp->bh_bkts[i].bb_lock);
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	(void) _lwp_mutex_lock(&bhp->bh_strlock);
1210Sstevel@tonic-gate 	(void) _lwp_mutex_lock(&bhp->bh_lock);
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate int
main(int argc,char ** argv)1250Sstevel@tonic-gate main(int argc, char **argv)
1260Sstevel@tonic-gate {
1270Sstevel@tonic-gate 	int		fd;
1280Sstevel@tonic-gate 	char		*fname, *format_string;
1290Sstevel@tonic-gate 	bindhead	*bhp, *tmp_bhp;
1300Sstevel@tonic-gate 	int		i, c;
1310Sstevel@tonic-gate 	int		bflag = 0, pflag = 0, qflag = 0, cflag = 0, sflag = 0;
1320Sstevel@tonic-gate 	ulong_t		symcount, callcount;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "bspcq")) != EOF)
1350Sstevel@tonic-gate 		switch (c) {
1360Sstevel@tonic-gate 		case 'b':
1370Sstevel@tonic-gate 			bflag++;
1380Sstevel@tonic-gate 			break;
1390Sstevel@tonic-gate 		case 'p':
1400Sstevel@tonic-gate 			pflag++;
1410Sstevel@tonic-gate 			break;
1420Sstevel@tonic-gate 		case 'q':
1430Sstevel@tonic-gate 			qflag++;
1440Sstevel@tonic-gate 			break;
1450Sstevel@tonic-gate 		case 'c':
1460Sstevel@tonic-gate 			cflag++;
1470Sstevel@tonic-gate 			break;
1480Sstevel@tonic-gate 		case 's':
1490Sstevel@tonic-gate 			sflag++;
1500Sstevel@tonic-gate 			break;
1510Sstevel@tonic-gate 		case '?':
1520Sstevel@tonic-gate 			usage();
1530Sstevel@tonic-gate 			return (1);
1540Sstevel@tonic-gate 		}
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	if (optind == argc) {
1570Sstevel@tonic-gate 		usage();
1580Sstevel@tonic-gate 		return (1);
1590Sstevel@tonic-gate 	}
1600Sstevel@tonic-gate 	fname = argv[optind];
1610Sstevel@tonic-gate 	if ((fd = open(fname, O_RDWR)) == -1) {
1620Sstevel@tonic-gate 		(void) fprintf(stderr,
1630Sstevel@tonic-gate 		    "dumpbindings: unable to open file: %s\n", fname);
1640Sstevel@tonic-gate 		perror("open");
1650Sstevel@tonic-gate 		return (1);
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 	/* LINTED */
1680Sstevel@tonic-gate 	if ((bhp = (bindhead *)mmap(0, sizeof (bindhead),
1690Sstevel@tonic-gate 	    (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0)) == MAP_FAILED) {
1700Sstevel@tonic-gate 		(void) fprintf(stderr, "dumpbind: mmap failed\n");
1710Sstevel@tonic-gate 		perror("mmap");
1720Sstevel@tonic-gate 		return (1);
1730Sstevel@tonic-gate 	}
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	if (qflag) {
1760Sstevel@tonic-gate 		query_buffer_locks(bhp);
1770Sstevel@tonic-gate 		return (0);
1780Sstevel@tonic-gate 	}
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	if (cflag) {
1810Sstevel@tonic-gate 		clear_buffer_locks(bhp);
1820Sstevel@tonic-gate 		return (0);
1830Sstevel@tonic-gate 	}
1840Sstevel@tonic-gate 	if (sflag) {
1850Sstevel@tonic-gate 		set_buffer_locks(bhp);
1860Sstevel@tonic-gate 		return (0);
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	/* LINTED */
1900Sstevel@tonic-gate 	if ((tmp_bhp = (bindhead *)mmap(0, bhp->bh_size,
1910Sstevel@tonic-gate 	    (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0)) == MAP_FAILED) {
1920Sstevel@tonic-gate 		(void) fprintf(stderr, "dumpbind: remap: mmap failed\n");
1930Sstevel@tonic-gate 		perror("mmap");
1940Sstevel@tonic-gate 		return (1);
1950Sstevel@tonic-gate 	}
1960Sstevel@tonic-gate 	(void) close(fd);
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	(void) munmap((void *)bhp, sizeof (bindhead));
1990Sstevel@tonic-gate 	bhp = tmp_bhp;
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	if (pflag)
2020Sstevel@tonic-gate 		format_string = "%s|%s|%8d\n";
2030Sstevel@tonic-gate 	else {
204*12927SRod.Evans@Sun.COM 		if (!bflag) {
205*12927SRod.Evans@Sun.COM 			(void) printf("                           "
206*12927SRod.Evans@Sun.COM 			    "Bindings Summary Report\n\n"
207*12927SRod.Evans@Sun.COM 			    "Library                             Symbol"
208*12927SRod.Evans@Sun.COM 			    "                   Call Count\n"
209*12927SRod.Evans@Sun.COM 			    "----------------------------------------------"
210*12927SRod.Evans@Sun.COM 			    "--------------------------\n");
211*12927SRod.Evans@Sun.COM 		}
2120Sstevel@tonic-gate 		format_string = "%-35s %-25s %5d\n";
2130Sstevel@tonic-gate 	}
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	symcount = 0;
2160Sstevel@tonic-gate 	callcount = 0;
2170Sstevel@tonic-gate 	for (i = 0; i < bhp->bh_bktcnt; i++) {
2180Sstevel@tonic-gate 		int		ent_cnt = 0;
2190Sstevel@tonic-gate 		binding_entry *	bep;
2200Sstevel@tonic-gate 		unsigned int	bep_off = bhp->bh_bkts[i].bb_head;
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 		while (bep_off) {
2230Sstevel@tonic-gate 			/* LINTED */
2240Sstevel@tonic-gate 			bep = (binding_entry *)((char *)bhp + bep_off);
2250Sstevel@tonic-gate 			if (!bflag) {
2260Sstevel@tonic-gate 				/* LINTED */
2270Sstevel@tonic-gate 				(void) printf(format_string,
2280Sstevel@tonic-gate 				    (char *)bhp + bep->be_lib_name,
2290Sstevel@tonic-gate 				    (char *)bhp + bep->be_sym_name,
2300Sstevel@tonic-gate 				    bep->be_count);
2310Sstevel@tonic-gate 				symcount++;
2320Sstevel@tonic-gate 				callcount += bep->be_count;
2330Sstevel@tonic-gate 			}
2340Sstevel@tonic-gate 			bep_off = bep->be_next;
2350Sstevel@tonic-gate 			ent_cnt++;
2360Sstevel@tonic-gate 		}
2370Sstevel@tonic-gate 		if (bflag)
2380Sstevel@tonic-gate 			(void) printf("bkt[%d] - %d entries\n", i, ent_cnt);
2390Sstevel@tonic-gate 	}
2400Sstevel@tonic-gate 
241*12927SRod.Evans@Sun.COM 	if (!bflag && !pflag) {
242*12927SRod.Evans@Sun.COM 		(void) printf("----------------------------------------------"
243*12927SRod.Evans@Sun.COM 		    "--------------------------\n"
244*12927SRod.Evans@Sun.COM 		    "Symbol Count: %lu    Call Count: %lu\n\n",
245*12927SRod.Evans@Sun.COM 		    symcount, callcount);
246*12927SRod.Evans@Sun.COM 	}
2470Sstevel@tonic-gate 	return (0);
2480Sstevel@tonic-gate }
249