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