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
38 void
usage()39 usage()
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 */
52 static int
query_lock(lwp_mutex_t * lock)53 query_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
61 static void
query_buffer_locks(bindhead * bhp)62 query_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
91 static void
clear_buffer_locks(bindhead * bhp)92 clear_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
112 static void
set_buffer_locks(bindhead * bhp)113 set_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
124 int
main(int argc,char ** argv)125 main(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