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 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 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 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 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 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 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