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