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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <mdb/mdb_param.h> 27 #include <mdb/mdb_modapi.h> 28 #include <mdb/mdb_ks.h> 29 30 #include "zone.h" 31 32 #include <stddef.h> 33 #include <sys/zone.h> 34 35 #define ZONE_NAMELEN 20 36 #ifdef _LP64 37 #define ZONE_PATHLEN 32 38 #else 39 #define ZONE_PATHLEN 40 40 #endif 41 42 int 43 zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 44 { 45 zone_t zn; 46 char name[ZONE_NAMELEN]; 47 char path[ZONE_PATHLEN]; 48 int len; 49 50 if (argc != 0) 51 return (DCMD_USAGE); 52 53 if (!(flags & DCMD_ADDRSPEC)) { 54 if (mdb_walk_dcmd("zone", "zone", argc, argv) == -1) { 55 mdb_warn("can't walk zones"); 56 return (DCMD_ERR); 57 } 58 return (DCMD_OK); 59 } 60 if (DCMD_HDRSPEC(flags)) { 61 mdb_printf("%<u>%?s %6s %-20s %-s%</u>\n", 62 "ADDR", "ID", "NAME", "PATH"); 63 } 64 if (mdb_vread(&zn, sizeof (zone_t), addr) == -1) { 65 mdb_warn("can't read zone_t structure at %p", addr); 66 return (DCMD_ERR); 67 } 68 len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zn.zone_name); 69 if (len > 0) { 70 if (len == ZONE_NAMELEN) 71 (void) strcpy(&name[len - 4], "..."); 72 } else { 73 (void) strcpy(name, "??"); 74 } 75 len = mdb_readstr(path, ZONE_PATHLEN, (uintptr_t)zn.zone_rootpath); 76 if (len > 0) { 77 if (len == ZONE_PATHLEN) 78 (void) strcpy(&path[len - 4], "..."); 79 } else { 80 (void) strcpy(path, "??"); 81 } 82 mdb_printf("%0?p %6d %-20s %s\n", addr, zn.zone_id, name, path); 83 return (DCMD_OK); 84 } 85 86 int 87 zone_walk_init(mdb_walk_state_t *wsp) 88 { 89 GElf_Sym sym; 90 91 if (wsp->walk_addr == NULL) { 92 if (mdb_lookup_by_name("zone_active", &sym) == -1) { 93 mdb_warn("failed to find 'zone_active'"); 94 return (WALK_ERR); 95 } 96 wsp->walk_addr = (uintptr_t)sym.st_value; 97 } 98 if (mdb_layered_walk("list", wsp) == -1) { 99 mdb_warn("couldn't walk 'list'"); 100 return (WALK_ERR); 101 } 102 return (WALK_NEXT); 103 } 104 105 int 106 zone_walk_step(mdb_walk_state_t *wsp) 107 { 108 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 109 wsp->walk_cbdata)); 110 } 111 112 int 113 zsd_walk_init(mdb_walk_state_t *wsp) 114 { 115 if (wsp->walk_addr == NULL) { 116 mdb_warn("global walk not supported\n"); 117 return (WALK_ERR); 118 } 119 wsp->walk_addr += offsetof(struct zone, zone_zsd); 120 if (mdb_layered_walk("list", wsp) == -1) { 121 mdb_warn("couldn't walk 'list'"); 122 return (WALK_ERR); 123 } 124 return (WALK_NEXT); 125 } 126 127 int 128 zsd_walk_step(mdb_walk_state_t *wsp) 129 { 130 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 131 wsp->walk_cbdata)); 132 } 133 134 /* 135 * Helper structure used when walking ZSD entries via zsd(). 136 */ 137 struct zsd_cb_data { 138 uint_t keygiven; /* Was a key specified (are we */ 139 /* searching for a specific ZSD */ 140 /* entry)? */ 141 zone_key_t key; /* Key of ZSD for which we're looking */ 142 uint_t found; /* Was the specific ZSD entry found? */ 143 uint_t voptgiven; /* Display verbose information? */ 144 }; 145 146 /* 147 * Helper function for zsd() that displays information from a single ZSD struct. 148 * 'datap' must point to a valid zsd_cb_data struct. 149 */ 150 /* ARGSUSED */ 151 static int 152 zsd_print(uintptr_t addrp, const void * datap, void * privatep) 153 { 154 struct zsd_entry entry; 155 struct zsd_cb_data *cbdp; 156 157 if (mdb_vread(&entry, sizeof (entry), addrp) == -1) { 158 mdb_warn("couldn't read zsd_entry at %p", addrp); 159 return (WALK_ERR); 160 } 161 cbdp = (struct zsd_cb_data *)privatep; 162 163 /* 164 * Are we looking for a single entry specified by a key? Then make sure 165 * that the current ZSD's key is what we're looking for. 166 */ 167 if (cbdp->keygiven == TRUE && cbdp->key != entry.zsd_key) 168 return (WALK_NEXT); 169 170 mdb_printf("%?x %0?p %8x\n", entry.zsd_key, entry.zsd_data, 171 entry.zsd_flags); 172 if (cbdp->voptgiven == TRUE) 173 mdb_printf(" Create CB: %a\n Shutdown CB: %a\n" 174 " Destroy CB: %a\n", entry.zsd_create, 175 entry.zsd_shutdown, entry.zsd_destroy); 176 if (cbdp->keygiven == TRUE) { 177 cbdp->found = TRUE; 178 return (WALK_DONE); 179 } 180 return (WALK_NEXT); 181 } 182 183 int 184 zsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 185 { 186 zone_t zone; 187 const mdb_arg_t *argp; 188 int argcindex; 189 struct zsd_cb_data cbd; 190 char name[ZONE_NAMELEN]; 191 int len; 192 193 /* 194 * Walk all zones if necessary. 195 */ 196 if (argc > 2) 197 return (DCMD_USAGE); 198 if ((flags & DCMD_ADDRSPEC) == 0) { 199 if (mdb_walk_dcmd("zone", "zsd", argc, argv) == -1) { 200 mdb_warn("failed to walk zone\n"); 201 return (DCMD_ERR); 202 } 203 return (DCMD_OK); 204 } 205 206 /* 207 * Make sure a zone_t can be read from the specified address. 208 */ 209 if (mdb_vread(&zone, sizeof (zone), addr) == -1) { 210 mdb_warn("couldn't read zone_t at %p", (void *)addr); 211 return (DCMD_ERR); 212 } 213 214 /* 215 * Get the optional arguments (key or -v or both). Note that 216 * mdb_getopts() will not parse a key argument because it is not 217 * preceded by an option letter. We'll get around this by requiring 218 * that all options precede the optional key argument. 219 */ 220 cbd.keygiven = FALSE; 221 cbd.voptgiven = FALSE; 222 if (argc > 0 && (argcindex = mdb_getopts(argc, argv, 'v', 223 MDB_OPT_SETBITS, TRUE, &cbd.voptgiven, NULL)) != argc) { 224 /* 225 * No options may appear after the key. 226 */ 227 if (argcindex != argc - 1) 228 return (DCMD_USAGE); 229 230 /* 231 * The missed argument should be a key. 232 */ 233 argp = &argv[argcindex]; 234 if (argp->a_type == MDB_TYPE_IMMEDIATE) 235 cbd.key = argp->a_un.a_val; 236 else 237 cbd.key = mdb_strtoull(argp->a_un.a_str); 238 cbd.keygiven = TRUE; 239 cbd.found = FALSE; 240 } 241 242 /* 243 * Prepare to output the specified zone's ZSD information. 244 */ 245 if (DCMD_HDRSPEC(flags)) 246 mdb_printf("%<u>%-20s %?s %?s %8s%</u>\n", "ZONE", "KEY", 247 "VALUE", "FLAGS"); 248 len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zone.zone_name); 249 if (len > 0) { 250 if (len == ZONE_NAMELEN) 251 (void) strcpy(&name[len - 4], "..."); 252 } else { 253 (void) strcpy(name, "??"); 254 } 255 mdb_printf("%-20s ", name); 256 257 /* 258 * Display the requested ZSD entries. 259 */ 260 mdb_inc_indent(21); 261 if (mdb_pwalk("zsd", zsd_print, &cbd, addr) != 0) { 262 mdb_warn("failed to walk zsd\n"); 263 mdb_dec_indent(21); 264 return (DCMD_ERR); 265 } 266 if (cbd.keygiven == TRUE && cbd.found == FALSE) { 267 mdb_printf("no corresponding ZSD entry found\n"); 268 mdb_dec_indent(21); 269 return (DCMD_ERR); 270 } 271 mdb_dec_indent(21); 272 return (DCMD_OK); 273 } 274