xref: /onnv-gate/usr/src/cmd/sgs/link_audit/common/dumpbind.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include	<stdlib.h>
30*0Sstevel@tonic-gate #include	<unistd.h>
31*0Sstevel@tonic-gate #include	<sys/types.h>
32*0Sstevel@tonic-gate #include	<sys/stat.h>
33*0Sstevel@tonic-gate #include	<sys/lwp.h>
34*0Sstevel@tonic-gate #include	<fcntl.h>
35*0Sstevel@tonic-gate #include	<stdio.h>
36*0Sstevel@tonic-gate #include	<sys/mman.h>
37*0Sstevel@tonic-gate #include	<synch.h>
38*0Sstevel@tonic-gate #include	<errno.h>
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate #include	"bindings.h"
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate void
43*0Sstevel@tonic-gate usage()
44*0Sstevel@tonic-gate {
45*0Sstevel@tonic-gate 	(void) printf("usage: dumpbind [-pqsc] <bindings.data>\n");
46*0Sstevel@tonic-gate 	(void) printf("\t-p\tdisplay output in parsable format\n");
47*0Sstevel@tonic-gate 	(void) printf("\t-q\tquery all mutex_locks in data buffer\n");
48*0Sstevel@tonic-gate 	(void) printf("\t-c\tclear all mutex_locks in data buffer\n");
49*0Sstevel@tonic-gate 	(void) printf("\t-s\tset all mutex_locks in data buffer\n");
50*0Sstevel@tonic-gate 	(void) printf("\t-b\tprint bucket usage statistics\n");
51*0Sstevel@tonic-gate }
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate /*
54*0Sstevel@tonic-gate  * Returns 1 if lock held - 0 otherwise.
55*0Sstevel@tonic-gate  */
56*0Sstevel@tonic-gate static int
57*0Sstevel@tonic-gate query_lock(lwp_mutex_t *lock) {
58*0Sstevel@tonic-gate 	if (_lwp_mutex_trylock(lock) == 0) {
59*0Sstevel@tonic-gate 		(void) _lwp_mutex_unlock(lock);
60*0Sstevel@tonic-gate 		return (0);
61*0Sstevel@tonic-gate 	} else
62*0Sstevel@tonic-gate 		return (1);
63*0Sstevel@tonic-gate }
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate static void
66*0Sstevel@tonic-gate query_buffer_locks(bindhead * bhp)
67*0Sstevel@tonic-gate {
68*0Sstevel@tonic-gate 	int	i, bkt_locks_held = 0;
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate 	(void) printf("bh_strlock: ");
71*0Sstevel@tonic-gate 	if (query_lock(&bhp->bh_strlock) == 1)
72*0Sstevel@tonic-gate 		(void) printf("lock held\n");
73*0Sstevel@tonic-gate 	else
74*0Sstevel@tonic-gate 		(void) printf("free\n");
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate 	(void) printf("bh_lock: ");
77*0Sstevel@tonic-gate 	if (query_lock(&bhp->bh_lock) == 1)
78*0Sstevel@tonic-gate 		(void) printf("lock held\n");
79*0Sstevel@tonic-gate 	else
80*0Sstevel@tonic-gate 		(void) printf("free\n");
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 	(void) printf("Buckets: %d - locks held:\n", bhp->bh_bktcnt);
83*0Sstevel@tonic-gate 	for (i = 0; i < bhp->bh_bktcnt; i++) {
84*0Sstevel@tonic-gate 		if (query_lock(&bhp->bh_bkts[i].bb_lock) == 1) {
85*0Sstevel@tonic-gate 			bkt_locks_held++;
86*0Sstevel@tonic-gate 			(void) printf("\tbkt[%d]: lock held\n", i);
87*0Sstevel@tonic-gate 		}
88*0Sstevel@tonic-gate 	}
89*0Sstevel@tonic-gate 	if (bkt_locks_held == 0)
90*0Sstevel@tonic-gate 		(void) printf("\tnone.\n");
91*0Sstevel@tonic-gate 	else
92*0Sstevel@tonic-gate 		(void) printf("\t[%d bucket(s) locked]\n", bkt_locks_held);
93*0Sstevel@tonic-gate }
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate static void
96*0Sstevel@tonic-gate clear_buffer_locks(bindhead * bhp)
97*0Sstevel@tonic-gate {
98*0Sstevel@tonic-gate 	int	i;
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate 	if (query_lock(&bhp->bh_strlock) == 1) {
101*0Sstevel@tonic-gate 		(void) _lwp_mutex_unlock(&bhp->bh_strlock);
102*0Sstevel@tonic-gate 		(void) printf("bh_strlock: cleared\n");
103*0Sstevel@tonic-gate 	}
104*0Sstevel@tonic-gate 	if (query_lock(&bhp->bh_lock) == 1) {
105*0Sstevel@tonic-gate 		(void) _lwp_mutex_unlock(&bhp->bh_lock);
106*0Sstevel@tonic-gate 		(void) printf("bh_lock: cleared\n");
107*0Sstevel@tonic-gate 	}
108*0Sstevel@tonic-gate 	for (i = 0; i < bhp->bh_bktcnt; i++) {
109*0Sstevel@tonic-gate 		if (query_lock(&bhp->bh_bkts[i].bb_lock) == 1) {
110*0Sstevel@tonic-gate 			(void) _lwp_mutex_unlock(&bhp->bh_bkts[i].bb_lock);
111*0Sstevel@tonic-gate 			(void) printf("bkt[%d]: lock cleared\n", i);
112*0Sstevel@tonic-gate 		}
113*0Sstevel@tonic-gate 	}
114*0Sstevel@tonic-gate }
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate static void
117*0Sstevel@tonic-gate set_buffer_locks(bindhead * bhp)
118*0Sstevel@tonic-gate {
119*0Sstevel@tonic-gate 	int	i;
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	for (i = 0; i < bhp->bh_bktcnt; i++)
122*0Sstevel@tonic-gate 		(void) _lwp_mutex_lock(&bhp->bh_bkts[i].bb_lock);
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	(void) _lwp_mutex_lock(&bhp->bh_strlock);
125*0Sstevel@tonic-gate 	(void) _lwp_mutex_lock(&bhp->bh_lock);
126*0Sstevel@tonic-gate }
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate int
129*0Sstevel@tonic-gate main(int argc, char **argv)
130*0Sstevel@tonic-gate {
131*0Sstevel@tonic-gate 	int		fd;
132*0Sstevel@tonic-gate 	char		*fname, *format_string;
133*0Sstevel@tonic-gate 	bindhead	*bhp, *tmp_bhp;
134*0Sstevel@tonic-gate 	int		i, c;
135*0Sstevel@tonic-gate 	int		bflag = 0, pflag = 0, qflag = 0, cflag = 0, sflag = 0;
136*0Sstevel@tonic-gate 	ulong_t		symcount, callcount;
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "bspcq")) != EOF)
139*0Sstevel@tonic-gate 		switch (c) {
140*0Sstevel@tonic-gate 		case 'b':
141*0Sstevel@tonic-gate 			bflag++;
142*0Sstevel@tonic-gate 			break;
143*0Sstevel@tonic-gate 		case 'p':
144*0Sstevel@tonic-gate 			pflag++;
145*0Sstevel@tonic-gate 			break;
146*0Sstevel@tonic-gate 		case 'q':
147*0Sstevel@tonic-gate 			qflag++;
148*0Sstevel@tonic-gate 			break;
149*0Sstevel@tonic-gate 		case 'c':
150*0Sstevel@tonic-gate 			cflag++;
151*0Sstevel@tonic-gate 			break;
152*0Sstevel@tonic-gate 		case 's':
153*0Sstevel@tonic-gate 			sflag++;
154*0Sstevel@tonic-gate 			break;
155*0Sstevel@tonic-gate 		case '?':
156*0Sstevel@tonic-gate 			usage();
157*0Sstevel@tonic-gate 			return (1);
158*0Sstevel@tonic-gate 		}
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	if (optind == argc) {
161*0Sstevel@tonic-gate 		usage();
162*0Sstevel@tonic-gate 		return (1);
163*0Sstevel@tonic-gate 	}
164*0Sstevel@tonic-gate 	fname = argv[optind];
165*0Sstevel@tonic-gate 	if ((fd = open(fname, O_RDWR)) == -1) {
166*0Sstevel@tonic-gate 		(void) fprintf(stderr,
167*0Sstevel@tonic-gate 		    "dumpbindings: unable to open file: %s\n", fname);
168*0Sstevel@tonic-gate 		perror("open");
169*0Sstevel@tonic-gate 		return (1);
170*0Sstevel@tonic-gate 	}
171*0Sstevel@tonic-gate 	/* LINTED */
172*0Sstevel@tonic-gate 	if ((bhp = (bindhead *)mmap(0, sizeof (bindhead),
173*0Sstevel@tonic-gate 	    (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0)) == MAP_FAILED) {
174*0Sstevel@tonic-gate 		(void) fprintf(stderr, "dumpbind: mmap failed\n");
175*0Sstevel@tonic-gate 		perror("mmap");
176*0Sstevel@tonic-gate 		return (1);
177*0Sstevel@tonic-gate 	}
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 	if (qflag) {
180*0Sstevel@tonic-gate 		query_buffer_locks(bhp);
181*0Sstevel@tonic-gate 		return (0);
182*0Sstevel@tonic-gate 	}
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 	if (cflag) {
185*0Sstevel@tonic-gate 		clear_buffer_locks(bhp);
186*0Sstevel@tonic-gate 		return (0);
187*0Sstevel@tonic-gate 	}
188*0Sstevel@tonic-gate 	if (sflag) {
189*0Sstevel@tonic-gate 		set_buffer_locks(bhp);
190*0Sstevel@tonic-gate 		return (0);
191*0Sstevel@tonic-gate 	}
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 	/* LINTED */
194*0Sstevel@tonic-gate 	if ((tmp_bhp = (bindhead *)mmap(0, bhp->bh_size,
195*0Sstevel@tonic-gate 	    (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0)) == MAP_FAILED) {
196*0Sstevel@tonic-gate 		(void) fprintf(stderr, "dumpbind: remap: mmap failed\n");
197*0Sstevel@tonic-gate 		perror("mmap");
198*0Sstevel@tonic-gate 		return (1);
199*0Sstevel@tonic-gate 	}
200*0Sstevel@tonic-gate 	(void) close(fd);
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate 	(void) munmap((void *)bhp, sizeof (bindhead));
203*0Sstevel@tonic-gate 	bhp = tmp_bhp;
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate 	if (pflag)
206*0Sstevel@tonic-gate 		format_string = "%s|%s|%8d\n";
207*0Sstevel@tonic-gate 	else {
208*0Sstevel@tonic-gate 		if (!bflag)
209*0Sstevel@tonic-gate 		    (void) printf(
210*0Sstevel@tonic-gate 			"                           Bindings Summary Report\n\n"
211*0Sstevel@tonic-gate 			"Library                             Symbol"
212*0Sstevel@tonic-gate 			"                   Call Count\n"
213*0Sstevel@tonic-gate 			"----------------------------------------------"
214*0Sstevel@tonic-gate 			"--------------------------\n");
215*0Sstevel@tonic-gate 		format_string = "%-35s %-25s %5d\n";
216*0Sstevel@tonic-gate 	}
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate 	symcount = 0;
219*0Sstevel@tonic-gate 	callcount = 0;
220*0Sstevel@tonic-gate 	for (i = 0; i < bhp->bh_bktcnt; i++) {
221*0Sstevel@tonic-gate 		int		ent_cnt = 0;
222*0Sstevel@tonic-gate 		binding_entry *	bep;
223*0Sstevel@tonic-gate 		unsigned int	bep_off = bhp->bh_bkts[i].bb_head;
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate 		while (bep_off) {
226*0Sstevel@tonic-gate 			/* LINTED */
227*0Sstevel@tonic-gate 			bep = (binding_entry *)((char *)bhp + bep_off);
228*0Sstevel@tonic-gate 			if (!bflag) {
229*0Sstevel@tonic-gate 				/* LINTED */
230*0Sstevel@tonic-gate 				(void) printf(format_string,
231*0Sstevel@tonic-gate 				    (char *)bhp + bep->be_lib_name,
232*0Sstevel@tonic-gate 				    (char *)bhp + bep->be_sym_name,
233*0Sstevel@tonic-gate 				    bep->be_count);
234*0Sstevel@tonic-gate 				symcount++;
235*0Sstevel@tonic-gate 				callcount += bep->be_count;
236*0Sstevel@tonic-gate 			}
237*0Sstevel@tonic-gate 			bep_off = bep->be_next;
238*0Sstevel@tonic-gate 			ent_cnt++;
239*0Sstevel@tonic-gate 		}
240*0Sstevel@tonic-gate 		if (bflag)
241*0Sstevel@tonic-gate 			(void) printf("bkt[%d] - %d entries\n", i, ent_cnt);
242*0Sstevel@tonic-gate 	}
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate 	if (!bflag && !pflag)
245*0Sstevel@tonic-gate 		(void) printf(
246*0Sstevel@tonic-gate 			"----------------------------------------------"
247*0Sstevel@tonic-gate 			"--------------------------\n"
248*0Sstevel@tonic-gate 			"Symbol Count: %lu    Call Count: %lu\n\n",
249*0Sstevel@tonic-gate 			symcount, callcount);
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 	return (0);
252*0Sstevel@tonic-gate }
253