/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include "bitset.h" /* XXX work out ifdef in include file... */ void bitset_help(void) { mdb_printf("Print the bitset at the address given\n"); } static void bitset_free(bitset_t *bs) { if (bs == NULL) return; if (bs->bs_set && bs->bs_words) mdb_free(bs->bs_set, bs->bs_words * sizeof (ulong_t)); mdb_free(bs, sizeof (*bs)); } static bitset_t * bitset_get(uintptr_t bsaddr) { bitset_t *bs; bs = mdb_zalloc(sizeof (*bs), UM_SLEEP); if (mdb_vread(bs, sizeof (*bs), bsaddr) == -1) { mdb_warn("couldn't read bitset 0x%p", bsaddr); bitset_free(bs); return (NULL); } bsaddr = (uintptr_t)bs->bs_set; bs->bs_set = mdb_alloc(bs->bs_words * sizeof (ulong_t), UM_SLEEP); if (mdb_vread(bs->bs_set, bs->bs_words * sizeof (ulong_t), bsaddr) == -1) { mdb_warn("couldn't read bitset bs_set 0x%p", bsaddr); bitset_free(bs); return (NULL); } return (bs); } static int bitset_highbit(bitset_t *bs) { int high; int i; if ((bs->bs_set == NULL) || (bs->bs_words == 0)) return (-1); /* move backwards through words */ for (i = bs->bs_words; i >= 0; i--) if (bs->bs_set[i]) break; if (i < 0) return (-1); /* move backwards through bits */ high = i << BT_ULSHIFT; for (i = BT_NBIPUL - 1; i; i--) if (BT_TEST(bs->bs_set, high + i)) break; return (high + i + 1); } static int pow10(int exp) { int res; for (res = 1; exp; exp--) res *= 10; return (res); } static int log10(int val) { int res = 0; do { res++; val /= 10; } while (val); return (res); } /* * The following prints a bitset with a 'ruler' that look like this * * 11111111112222222222333333333344444444445555555555666666666677 * 012345678901234567890123456789012345678901234567890123456789012345678901 * xx:........................................................................ * 11111111111111111111111111111111111111111111 * 777777778888888888999999999900000000001111111111222222222233333333334444 * 234567890123456789012345678901234567890123456789012345678901234567890123 * ........................................................................ * 111111111111111111111111111111111111111111111111111111112222222222222222 * 444444555555555566666666667777777777888888888899999999990000000000111111 * 456789012345678901234567890123456789012345678901234567890123456789012345 * ........................................................................ * 2222222222 * 1111222222 * 6789012345 * .......... * * to identify individual bits that are set. */ static void bitset_print(bitset_t *bs, char *label, int width) { int val_start; int val_max; int label_width; int ruler_width; int v, vm, vi; int nl, l; int i; int p; char c; val_start = 0; val_max = bitset_highbit(bs) + 1; if (val_max <= val_start) { mdb_printf("%s: empty-set", label); return; } label_width = strlen(label) + 1; ruler_width = width - label_width; for (v = val_start; v < val_max; v = vm) { if ((v + ruler_width) < val_max) vm = v + ruler_width; else vm = val_max; nl = log10(vm) - 1; for (l = nl; l >= 0; l--) { p = pow10(l); for (i = 0; i < label_width; i++) mdb_printf(" "); for (vi = v; vi < vm; vi++) { c = '0' + ((vi / p) % 10); if ((l == nl) && (c == '0')) c = ' '; mdb_printf("%c", c); } mdb_printf("\n"); } if (v == val_start) { mdb_printf("%s:", label); } else { for (i = 0; i < label_width; i++) mdb_printf(" "); } for (vi = v; vi < vm; vi++) { if (BT_TEST(bs->bs_set, vi)) mdb_printf("X"); else mdb_printf("."); } mdb_printf("\n"); } } /*ARGSUSED*/ int bitset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { bitset_t *bs; bs = bitset_get(addr); if (bs == NULL) return (DCMD_ERR); bitset_print(bs, "label", 80); bitset_free(bs); return (DCMD_OK); }