1*fb2f18f8Sesaxe /* 2*fb2f18f8Sesaxe * CDDL HEADER START 3*fb2f18f8Sesaxe * 4*fb2f18f8Sesaxe * The contents of this file are subject to the terms of the 5*fb2f18f8Sesaxe * Common Development and Distribution License (the "License"). 6*fb2f18f8Sesaxe * You may not use this file except in compliance with the License. 7*fb2f18f8Sesaxe * 8*fb2f18f8Sesaxe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fb2f18f8Sesaxe * or http://www.opensolaris.org/os/licensing. 10*fb2f18f8Sesaxe * See the License for the specific language governing permissions 11*fb2f18f8Sesaxe * and limitations under the License. 12*fb2f18f8Sesaxe * 13*fb2f18f8Sesaxe * When distributing Covered Code, include this CDDL HEADER in each 14*fb2f18f8Sesaxe * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fb2f18f8Sesaxe * If applicable, add the following below this CDDL HEADER, with the 16*fb2f18f8Sesaxe * fields enclosed by brackets "[]" replaced with your own identifying 17*fb2f18f8Sesaxe * information: Portions Copyright [yyyy] [name of copyright owner] 18*fb2f18f8Sesaxe * 19*fb2f18f8Sesaxe * CDDL HEADER END 20*fb2f18f8Sesaxe */ 21*fb2f18f8Sesaxe 22*fb2f18f8Sesaxe /* 23*fb2f18f8Sesaxe * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*fb2f18f8Sesaxe * Use is subject to license terms. 25*fb2f18f8Sesaxe */ 26*fb2f18f8Sesaxe 27*fb2f18f8Sesaxe #pragma ident "%Z%%M% %I% %E% SMI" 28*fb2f18f8Sesaxe 29*fb2f18f8Sesaxe /* 30*fb2f18f8Sesaxe * Display group information and walk all elements of a group 31*fb2f18f8Sesaxe */ 32*fb2f18f8Sesaxe 33*fb2f18f8Sesaxe #include "group.h" 34*fb2f18f8Sesaxe 35*fb2f18f8Sesaxe #include <mdb/mdb_modapi.h> 36*fb2f18f8Sesaxe #include <sys/group.h> 37*fb2f18f8Sesaxe 38*fb2f18f8Sesaxe /* 39*fb2f18f8Sesaxe * Display group information 40*fb2f18f8Sesaxe */ 41*fb2f18f8Sesaxe 42*fb2f18f8Sesaxe /* ARGSUSED */ 43*fb2f18f8Sesaxe int 44*fb2f18f8Sesaxe group(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 45*fb2f18f8Sesaxe { 46*fb2f18f8Sesaxe group_t group; 47*fb2f18f8Sesaxe int opt_q = 0; /* display only address. */ 48*fb2f18f8Sesaxe 49*fb2f18f8Sesaxe /* Should provide an address */ 50*fb2f18f8Sesaxe if (!(flags & DCMD_ADDRSPEC)) 51*fb2f18f8Sesaxe return (DCMD_USAGE); 52*fb2f18f8Sesaxe 53*fb2f18f8Sesaxe if (mdb_getopts(argc, argv, 54*fb2f18f8Sesaxe 'q', MDB_OPT_SETBITS, TRUE, &opt_q, 55*fb2f18f8Sesaxe NULL) != argc) 56*fb2f18f8Sesaxe return (DCMD_USAGE); 57*fb2f18f8Sesaxe 58*fb2f18f8Sesaxe if (flags & DCMD_PIPE_OUT) 59*fb2f18f8Sesaxe opt_q = B_TRUE; 60*fb2f18f8Sesaxe 61*fb2f18f8Sesaxe if (DCMD_HDRSPEC(flags) && !opt_q) { 62*fb2f18f8Sesaxe mdb_printf("%?s %6s %9s %?s\n", 63*fb2f18f8Sesaxe "ADDR", 64*fb2f18f8Sesaxe "SIZE", 65*fb2f18f8Sesaxe "CAPACITY", 66*fb2f18f8Sesaxe "SET"); 67*fb2f18f8Sesaxe } 68*fb2f18f8Sesaxe 69*fb2f18f8Sesaxe if (mdb_vread(&group, sizeof (struct group), addr) == -1) { 70*fb2f18f8Sesaxe mdb_warn("unable to read 'group' at %p", addr); 71*fb2f18f8Sesaxe return (DCMD_ERR); 72*fb2f18f8Sesaxe } 73*fb2f18f8Sesaxe 74*fb2f18f8Sesaxe if (opt_q) { 75*fb2f18f8Sesaxe mdb_printf("%0?p\n", addr); 76*fb2f18f8Sesaxe return (DCMD_OK); 77*fb2f18f8Sesaxe } 78*fb2f18f8Sesaxe 79*fb2f18f8Sesaxe mdb_printf("%?p %6d %9d %?p\n", 80*fb2f18f8Sesaxe addr, group.grp_size, group.grp_capacity, group.grp_set); 81*fb2f18f8Sesaxe 82*fb2f18f8Sesaxe return (DCMD_OK); 83*fb2f18f8Sesaxe } 84*fb2f18f8Sesaxe 85*fb2f18f8Sesaxe /* 86*fb2f18f8Sesaxe * Walk all elements in the group set. 87*fb2f18f8Sesaxe */ 88*fb2f18f8Sesaxe 89*fb2f18f8Sesaxe typedef struct group_walk { 90*fb2f18f8Sesaxe uintptr_t *gw_set; 91*fb2f18f8Sesaxe int gw_size; 92*fb2f18f8Sesaxe int gw_pos; 93*fb2f18f8Sesaxe int gw_initialized; 94*fb2f18f8Sesaxe } group_walk_t; 95*fb2f18f8Sesaxe 96*fb2f18f8Sesaxe 97*fb2f18f8Sesaxe /* 98*fb2f18f8Sesaxe * Initialize the walk structure with the copy of a group set, its size and the 99*fb2f18f8Sesaxe * initial pointer position. 100*fb2f18f8Sesaxe */ 101*fb2f18f8Sesaxe int 102*fb2f18f8Sesaxe group_walk_init(mdb_walk_state_t *wsp) 103*fb2f18f8Sesaxe { 104*fb2f18f8Sesaxe group_walk_t *gw; 105*fb2f18f8Sesaxe group_t group; 106*fb2f18f8Sesaxe 107*fb2f18f8Sesaxe gw = mdb_alloc(sizeof (group_walk_t), UM_SLEEP | UM_GC); 108*fb2f18f8Sesaxe 109*fb2f18f8Sesaxe if (mdb_vread(&group, sizeof (struct group), wsp->walk_addr) == -1) { 110*fb2f18f8Sesaxe mdb_warn("couldn't read 'group' at %p", wsp->walk_addr); 111*fb2f18f8Sesaxe return (WALK_ERR); 112*fb2f18f8Sesaxe } 113*fb2f18f8Sesaxe 114*fb2f18f8Sesaxe gw->gw_size = group.grp_size; 115*fb2f18f8Sesaxe gw->gw_initialized = 0; 116*fb2f18f8Sesaxe gw->gw_pos = 0; 117*fb2f18f8Sesaxe 118*fb2f18f8Sesaxe if (gw->gw_size < 0) { 119*fb2f18f8Sesaxe mdb_warn("invalid group at %p", wsp->walk_addr); 120*fb2f18f8Sesaxe return (WALK_ERR); 121*fb2f18f8Sesaxe } 122*fb2f18f8Sesaxe 123*fb2f18f8Sesaxe if (gw->gw_size == 0) 124*fb2f18f8Sesaxe return (WALK_DONE); 125*fb2f18f8Sesaxe 126*fb2f18f8Sesaxe /* 127*fb2f18f8Sesaxe * Allocate space for the set and copy all set entries. 128*fb2f18f8Sesaxe */ 129*fb2f18f8Sesaxe gw->gw_set = mdb_alloc(group.grp_size * sizeof (uintptr_t), 130*fb2f18f8Sesaxe UM_SLEEP | UM_GC); 131*fb2f18f8Sesaxe 132*fb2f18f8Sesaxe if (mdb_vread(gw->gw_set, group.grp_size * sizeof (uintptr_t), 133*fb2f18f8Sesaxe (uintptr_t)group.grp_set) == -1) { 134*fb2f18f8Sesaxe mdb_warn("couldn't read 'group set' at %p", group.grp_set); 135*fb2f18f8Sesaxe return (WALK_ERR); 136*fb2f18f8Sesaxe } 137*fb2f18f8Sesaxe 138*fb2f18f8Sesaxe wsp->walk_data = gw; 139*fb2f18f8Sesaxe wsp->walk_addr = gw->gw_set[0]; 140*fb2f18f8Sesaxe gw->gw_pos = 0; 141*fb2f18f8Sesaxe 142*fb2f18f8Sesaxe return (WALK_NEXT); 143*fb2f18f8Sesaxe } 144*fb2f18f8Sesaxe 145*fb2f18f8Sesaxe /* 146*fb2f18f8Sesaxe * Print element of the set and advance the pointer. 147*fb2f18f8Sesaxe */ 148*fb2f18f8Sesaxe int 149*fb2f18f8Sesaxe group_walk_step(mdb_walk_state_t *wsp) 150*fb2f18f8Sesaxe { 151*fb2f18f8Sesaxe group_walk_t *gw = (group_walk_t *)wsp->walk_data; 152*fb2f18f8Sesaxe int status; 153*fb2f18f8Sesaxe 154*fb2f18f8Sesaxe /* 155*fb2f18f8Sesaxe * Already visited all valid elements, nothing else to do. 156*fb2f18f8Sesaxe */ 157*fb2f18f8Sesaxe if (gw->gw_size < 0) 158*fb2f18f8Sesaxe return (WALK_DONE); 159*fb2f18f8Sesaxe 160*fb2f18f8Sesaxe /* 161*fb2f18f8Sesaxe * Print non-NULL elements 162*fb2f18f8Sesaxe */ 163*fb2f18f8Sesaxe status = wsp->walk_addr == NULL ? 164*fb2f18f8Sesaxe WALK_NEXT : 165*fb2f18f8Sesaxe wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 166*fb2f18f8Sesaxe wsp->walk_cbdata); 167*fb2f18f8Sesaxe 168*fb2f18f8Sesaxe /* 169*fb2f18f8Sesaxe * Adjust walk_addr to point to the next element 170*fb2f18f8Sesaxe */ 171*fb2f18f8Sesaxe gw->gw_size--; 172*fb2f18f8Sesaxe 173*fb2f18f8Sesaxe if (gw->gw_size > 0) 174*fb2f18f8Sesaxe wsp->walk_addr = gw->gw_set[++gw->gw_pos]; 175*fb2f18f8Sesaxe else 176*fb2f18f8Sesaxe status = WALK_DONE; 177*fb2f18f8Sesaxe 178*fb2f18f8Sesaxe return (status); 179*fb2f18f8Sesaxe } 180