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