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) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <sys/mdb_modapi.h> 27 #include <limits.h> 28 29 #include <fmd_trace.h> 30 #include <fmd_module.h> 31 #include <fmd_thread.h> 32 #include <fmd_ustat.h> 33 #include <fmd_event.h> 34 #include <fmd_case.h> 35 #include <fmd_buf.h> 36 #include <fmd_asru.h> 37 #include <fmd_ckpt.h> 38 #include <fmd_timerq.h> 39 #include <fmd_xprt.h> 40 41 #include <fmd.h> 42 43 typedef struct trwalk_state { 44 struct trwalk_state *trw_next; 45 fmd_tracebuf_t trw_data; 46 pthread_t trw_tid; 47 uintptr_t trw_base; 48 const fmd_tracerec_t *trw_stop; 49 fmd_tracerec_t *trw_xrec; 50 } trwalk_state_t; 51 52 typedef struct hashwalk_data { 53 uintptr_t *hw_hash; 54 uint_t hw_hashlen; 55 uint_t hw_hashidx; 56 const char *hw_name; 57 void *hw_data; 58 size_t hw_size; 59 size_t hw_next; 60 } hashwalk_data_t; 61 62 static int fmd_stat(uintptr_t, uint_t, int, const mdb_arg_t *); 63 static int fmd_ustat(uintptr_t, uint_t, int, const mdb_arg_t *); 64 65 static int 66 trwalk_init(mdb_walk_state_t *wsp) 67 { 68 uintptr_t addr; 69 fmd_thread_t thr; 70 fmd_t F; 71 72 if (wsp->walk_addr != 0) { 73 mdb_warn("fmd_trace only supports global walks\n"); 74 return (WALK_ERR); 75 } 76 77 if (mdb_readvar(&F, "fmd") != sizeof (F)) { 78 mdb_warn("failed to read fmd meta-data"); 79 return (WALK_ERR); 80 } 81 82 for (addr = (uintptr_t)F.d_thr_list.l_next; addr != 0; 83 addr = (uintptr_t)thr.thr_list.l_next) { 84 85 size_t len, ptr_off, end_off; 86 fmd_tracerec_t *buf; 87 trwalk_state_t *t; 88 89 if (mdb_vread(&thr, sizeof (thr), addr) != sizeof (thr)) { 90 mdb_warn("failed to read thread at %p " 91 "(some trace data will be unavailable)", addr); 92 break; 93 } 94 95 t = mdb_zalloc(sizeof (trwalk_state_t), UM_SLEEP); 96 t->trw_next = wsp->walk_data; 97 wsp->walk_data = t; 98 99 (void) mdb_vread(&t->trw_data, 100 sizeof (t->trw_data), (uintptr_t)thr.thr_trdata); 101 102 if (t->trw_data.tb_recs == 0) 103 continue; /* no trace buffer allocated for thread */ 104 105 len = t->trw_data.tb_recs * t->trw_data.tb_size; 106 buf = mdb_alloc(len, UM_SLEEP); 107 108 t->trw_tid = thr.thr_tid; 109 t->trw_base = (uintptr_t)t->trw_data.tb_buf; 110 111 if (mdb_vread(buf, len, t->trw_base) == -1) { 112 mdb_warn("failed to read buffer for t%u", t->trw_tid); 113 bzero(buf, len); 114 } 115 116 end_off = (uintptr_t)t->trw_data.tb_end - t->trw_base; 117 ptr_off = (uintptr_t)t->trw_data.tb_ptr - t->trw_base; 118 119 t->trw_data.tb_buf = buf; 120 t->trw_data.tb_end = (void *)((uintptr_t)buf + end_off); 121 t->trw_data.tb_ptr = (void *)((uintptr_t)buf + ptr_off); 122 123 if (t->trw_data.tb_ptr < t->trw_data.tb_buf || 124 t->trw_data.tb_ptr > t->trw_data.tb_end) { 125 mdb_warn("trace record ptr for t%u is corrupt " 126 "(some data may be unavailable)\n", t->trw_tid); 127 t->trw_data.tb_ptr = t->trw_data.tb_buf; 128 } 129 130 t->trw_stop = t->trw_data.tb_ptr; 131 t->trw_xrec = mdb_alloc( 132 t->trw_data.tb_size + sizeof (uintptr_t), UM_SLEEP); 133 } 134 135 return (WALK_NEXT); 136 } 137 138 static fmd_tracerec_t * 139 trwalk_nextrec(trwalk_state_t *t) 140 { 141 if (t->trw_stop == NULL) 142 return (t->trw_data.tb_ptr); 143 144 if (t->trw_data.tb_ptr == t->trw_data.tb_buf) 145 t->trw_data.tb_ptr = t->trw_data.tb_end; 146 else 147 t->trw_data.tb_ptr = (fmd_tracerec_t *) 148 ((uintptr_t)t->trw_data.tb_ptr - t->trw_data.tb_size); 149 150 if (t->trw_data.tb_ptr == t->trw_stop) 151 t->trw_stop = NULL; /* mark buffer as empty */ 152 153 return (t->trw_data.tb_ptr); 154 } 155 156 static int 157 trwalk_step(mdb_walk_state_t *wsp) 158 { 159 trwalk_state_t *t, *oldest_t; 160 hrtime_t oldest_time = 0; 161 fmd_tracerec_t *trp; 162 int status; 163 164 for (t = wsp->walk_data; t != NULL; t = t->trw_next) { 165 for (trp = t->trw_data.tb_ptr; t->trw_stop != NULL && 166 trp->tr_time == 0; trp = trwalk_nextrec(t)) 167 continue; 168 169 if (t->trw_stop == NULL) 170 continue; /* buffer has been emptied */ 171 172 if (trp->tr_time > oldest_time) { 173 oldest_time = trp->tr_time; 174 oldest_t = t; 175 } 176 } 177 178 if (oldest_time == 0) 179 return (WALK_DONE); 180 181 t = oldest_t; 182 trp = t->trw_data.tb_ptr; 183 184 bcopy(trp, t->trw_xrec, t->trw_data.tb_size); 185 t->trw_xrec->tr_depth = MIN(trp->tr_depth, t->trw_data.tb_frames); 186 t->trw_xrec->tr_stack[t->trw_xrec->tr_depth] = t->trw_tid; 187 188 status = wsp->walk_callback((uintptr_t)trp - (uintptr_t) 189 t->trw_data.tb_buf + t->trw_base, t->trw_xrec, wsp->walk_cbdata); 190 191 (void) trwalk_nextrec(t); 192 return (status); 193 } 194 195 static void 196 trwalk_fini(mdb_walk_state_t *wsp) 197 { 198 trwalk_state_t *t, *u; 199 200 for (t = wsp->walk_data; t != NULL; t = u) { 201 u = t->trw_next; 202 mdb_free(t->trw_data.tb_buf, 203 t->trw_data.tb_recs * t->trw_data.tb_size); 204 mdb_free(t->trw_xrec, t->trw_data.tb_size + sizeof (uintptr_t)); 205 mdb_free(t, sizeof (trwalk_state_t)); 206 } 207 } 208 209 /*ARGSUSED*/ 210 static int 211 trprint_msg(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid) 212 { 213 if (tid == 0) 214 mdb_printf("%3lu ", trp->tr_stack[trp->tr_depth]); 215 else if (trp->tr_stack[trp->tr_depth] != tid) 216 return (WALK_NEXT); 217 218 mdb_printf("%016llx %04x %-5u %s\n", 219 trp->tr_time, 1 << trp->tr_tag, trp->tr_errno, trp->tr_msg); 220 221 return (WALK_NEXT); 222 } 223 224 /*ARGSUSED*/ 225 static int 226 trprint_cpp(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid) 227 { 228 char file[64]; 229 230 if (tid == 0) 231 mdb_printf("%3lu ", trp->tr_stack[trp->tr_depth]); 232 else if (trp->tr_stack[trp->tr_depth] != tid) 233 return (WALK_NEXT); 234 235 if (mdb_readstr(file, sizeof (file), (uintptr_t)trp->tr_file) <= 0) 236 (void) strcpy(file, "???"); 237 238 mdb_printf("%016llx %04x %s: %u\n", 239 trp->tr_time, 1 << trp->tr_tag, file, trp->tr_line); 240 241 return (WALK_NEXT); 242 } 243 244 static void 245 trprint_stack(const fmd_tracerec_t *trp) 246 { 247 uint8_t i; 248 249 for (i = 0; i < trp->tr_depth; i++) 250 mdb_printf("\t%a\n", trp->tr_stack[i]); 251 252 if (trp->tr_depth != 0) 253 mdb_printf("\n"); 254 } 255 256 static int 257 trprint_msg_stack(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid) 258 { 259 int status = trprint_msg(addr, trp, tid); 260 trprint_stack(trp); 261 return (status); 262 } 263 264 static int 265 trprint_cpp_stack(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid) 266 { 267 int status = trprint_cpp(addr, trp, tid); 268 trprint_stack(trp); 269 return (status); 270 } 271 272 static int 273 fmd_trace(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv) 274 { 275 int (*func)(uintptr_t, const fmd_tracerec_t *, uintptr_t); 276 uint_t opt_c = FALSE, opt_s = FALSE; 277 278 if (mdb_getopts(argc, argv, 279 'c', MDB_OPT_SETBITS, TRUE, &opt_c, 280 's', MDB_OPT_SETBITS, TRUE, &opt_s, NULL) != argc) 281 return (DCMD_USAGE); 282 283 if (!(flags & DCMD_ADDRSPEC)) { 284 mdb_printf("TID "); 285 tid = 0; 286 } 287 288 if (opt_c) { 289 mdb_printf("%-16s %-4s FILE:LINE\n", "TIME", "TAG"); 290 func = opt_s ? trprint_cpp_stack : trprint_cpp; 291 } else { 292 mdb_printf("%-16s %-4s %-5s MSG\n", "TIME", "TAG", "ERRNO"); 293 func = opt_s ? trprint_msg_stack : trprint_msg; 294 } 295 296 if (mdb_walk("fmd_trace", (mdb_walk_cb_t)func, (void *)tid) == -1) { 297 mdb_warn("failed to walk fmd_trace"); 298 return (DCMD_ERR); 299 } 300 301 return (DCMD_OK); 302 } 303 304 static int 305 hash_walk_init(mdb_walk_state_t *wsp, uintptr_t addr, uint_t hashlen, 306 const char *name, size_t size, size_t next) 307 { 308 hashwalk_data_t *hwp; 309 size_t len = sizeof (uintptr_t) * hashlen; 310 311 if (len == 0) { 312 mdb_warn("failed to walk hash: invalid hash length\n"); 313 return (WALK_ERR); 314 } 315 316 hwp = mdb_alloc(sizeof (hashwalk_data_t), UM_SLEEP); 317 hwp->hw_hash = mdb_zalloc(len, UM_SLEEP); 318 (void) mdb_vread(hwp->hw_hash, len, addr); 319 hwp->hw_hashlen = hashlen; 320 hwp->hw_hashidx = 0; 321 hwp->hw_name = name; 322 hwp->hw_data = mdb_zalloc(size, UM_SLEEP); 323 hwp->hw_size = size; 324 hwp->hw_next = next; 325 326 wsp->walk_addr = hwp->hw_hash[0]; 327 wsp->walk_data = hwp; 328 329 return (WALK_NEXT); 330 } 331 332 static int 333 hash_walk_step(mdb_walk_state_t *wsp) 334 { 335 hashwalk_data_t *hwp = wsp->walk_data; 336 int rv; 337 338 while (wsp->walk_addr == 0) { 339 if (++hwp->hw_hashidx < hwp->hw_hashlen) 340 wsp->walk_addr = hwp->hw_hash[hwp->hw_hashidx]; 341 else 342 return (WALK_DONE); 343 } 344 345 if (mdb_vread(hwp->hw_data, hwp->hw_size, wsp->walk_addr) == -1) { 346 mdb_warn("failed to read %s at %p", 347 hwp->hw_name, wsp->walk_addr); 348 return (WALK_ERR); 349 } 350 351 rv = wsp->walk_callback(wsp->walk_addr, hwp->hw_data, wsp->walk_cbdata); 352 wsp->walk_addr = *(uintptr_t *)((uintptr_t)hwp->hw_data + hwp->hw_next); 353 return (rv); 354 } 355 356 static void 357 hash_walk_fini(mdb_walk_state_t *wsp) 358 { 359 hashwalk_data_t *hwp = wsp->walk_data; 360 361 mdb_free(hwp->hw_hash, sizeof (uintptr_t) * hwp->hw_hashlen); 362 mdb_free(hwp->hw_data, hwp->hw_size); 363 mdb_free(hwp, sizeof (hashwalk_data_t)); 364 } 365 366 static int 367 ustat_walk_init(mdb_walk_state_t *wsp) 368 { 369 fmd_ustat_t us; 370 371 if (mdb_vread(&us, sizeof (us), wsp->walk_addr) != sizeof (us)) { 372 mdb_warn("failed to read fmd_ustat_t at %p", wsp->walk_addr); 373 return (WALK_ERR); 374 } 375 376 return (hash_walk_init(wsp, 377 (uintptr_t)us.us_hash, us.us_hashlen, NULL, 0, 0)); 378 } 379 380 static int 381 ustat_walk_step(mdb_walk_state_t *wsp) 382 { 383 hashwalk_data_t *hwp = wsp->walk_data; 384 fmd_ustat_elem_t ue; 385 fmd_stat_t s; 386 387 while (wsp->walk_addr == 0) { 388 if (++hwp->hw_hashidx < hwp->hw_hashlen) 389 wsp->walk_addr = hwp->hw_hash[hwp->hw_hashidx]; 390 else 391 return (WALK_DONE); 392 } 393 394 if (mdb_vread(&ue, sizeof (ue), wsp->walk_addr) != sizeof (ue) || 395 mdb_vread(&s, sizeof (s), (uintptr_t)ue.use_stat) != sizeof (s)) { 396 mdb_warn("failed to read stat element at %p", wsp->walk_addr); 397 return (WALK_ERR); 398 } 399 400 wsp->walk_addr = (uintptr_t)ue.use_next; 401 402 return (wsp->walk_callback( 403 (uintptr_t)ue.use_stat, &s, wsp->walk_cbdata)); 404 } 405 406 struct fmd_cmd_data { 407 int argc; 408 const mdb_arg_t *argv; 409 }; 410 411 /* ARGSUSED */ 412 static int 413 module_ustat(uintptr_t addr, const void *data, void *wsp) 414 { 415 fmd_module_t *modp = (fmd_module_t *)data; 416 char name[PATH_MAX]; 417 const struct fmd_cmd_data *udp = wsp; 418 419 if (mdb_readstr(name, sizeof (name), (uintptr_t)modp->mod_name) <= 0) 420 (void) mdb_snprintf(name, sizeof (name), "<%p>", 421 modp->mod_name); 422 mdb_printf("%s\n", name); 423 (void) fmd_ustat((uintptr_t)modp->mod_ustat, 424 DCMD_ADDRSPEC | DCMD_LOOPFIRST, udp->argc, udp->argv); 425 return (WALK_NEXT); 426 } 427 428 static int 429 fmd_ustat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 430 { 431 if (!(flags & DCMD_ADDRSPEC)) { 432 struct fmd_cmd_data ud; 433 434 ud.argc = argc; 435 ud.argv = argv; 436 if (mdb_walk("fmd_module", module_ustat, &ud) == -1) { 437 mdb_warn("failed to walk 'fmd_module'"); 438 return (DCMD_ERR); 439 } 440 return (DCMD_OK); 441 } 442 443 if (mdb_pwalk_dcmd("fmd_ustat", "fmd_stat", argc, argv, addr) != 0) { 444 mdb_warn("failed to walk fmd_ustat at %p", addr); 445 return (DCMD_ERR); 446 } 447 448 return (DCMD_OK); 449 } 450 451 /* ARGSUSED */ 452 static int 453 module_stat(uintptr_t addr, const void *data, void *wsp) 454 { 455 fmd_module_t *modp = (fmd_module_t *)data; 456 char name[PATH_MAX]; 457 const struct fmd_cmd_data *udp = wsp; 458 fmd_modstat_t *mod_stats; 459 460 if (mdb_readstr(name, sizeof (name), (uintptr_t)modp->mod_name) <= 0) { 461 (void) mdb_snprintf(name, sizeof (name), "<%p>", 462 modp->mod_name); 463 } 464 mdb_printf("%s\n", name); 465 mod_stats = modp->mod_stats; 466 (void) fmd_stat((uintptr_t)&mod_stats->ms_loadtime, 467 DCMD_ADDRSPEC | DCMD_LOOPFIRST, udp->argc, udp->argv); 468 (void) fmd_stat((uintptr_t)&mod_stats->ms_snaptime, 469 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 470 (void) fmd_stat((uintptr_t)&mod_stats->ms_accepted, 471 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 472 (void) fmd_stat((uintptr_t)&mod_stats->ms_debugdrop, 473 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 474 (void) fmd_stat((uintptr_t)&mod_stats->ms_memtotal, 475 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 476 (void) fmd_stat((uintptr_t)&mod_stats->ms_memlimit, 477 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 478 (void) fmd_stat((uintptr_t)&mod_stats->ms_buftotal, 479 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 480 (void) fmd_stat((uintptr_t)&mod_stats->ms_buflimit, 481 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 482 (void) fmd_stat((uintptr_t)&mod_stats->ms_thrtotal, 483 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 484 (void) fmd_stat((uintptr_t)&mod_stats->ms_thrlimit, 485 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 486 (void) fmd_stat((uintptr_t)&mod_stats->ms_doorthrtotal, 487 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 488 (void) fmd_stat((uintptr_t)&mod_stats->ms_doorthrlimit, 489 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 490 (void) fmd_stat((uintptr_t)&mod_stats->ms_caseopen, 491 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 492 (void) fmd_stat((uintptr_t)&mod_stats->ms_casesolved, 493 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 494 (void) fmd_stat((uintptr_t)&mod_stats->ms_caseclosed, 495 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 496 (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_save, 497 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 498 (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_restore, 499 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 500 (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_zeroed, 501 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 502 (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_cnt, 503 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 504 (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_time, 505 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 506 (void) fmd_stat((uintptr_t)&mod_stats->ms_xprtopen, 507 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 508 (void) fmd_stat((uintptr_t)&mod_stats->ms_xprtlimit, 509 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 510 (void) fmd_stat((uintptr_t)&mod_stats->ms_xprtqlimit, 511 DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv); 512 return (WALK_NEXT); 513 } 514 515 /*ARGSUSED*/ 516 static int 517 fmd_stat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 518 { 519 char buf[512]; 520 fmd_stat_t s; 521 522 if (argc != 0) 523 return (DCMD_USAGE); 524 525 if (DCMD_HDRSPEC(flags)) 526 mdb_printf("%<u>%-11s %-4s %-32s %s%</u>\n", 527 "ADDR", "TYPE", "NAME", "VALUE"); 528 529 if (!(flags & DCMD_ADDRSPEC)) { 530 struct fmd_cmd_data ud; 531 532 ud.argc = argc; 533 ud.argv = argv; 534 535 if (mdb_walk("fmd_module", module_stat, &ud) == -1) { 536 mdb_warn("failed to walk 'fmd_module'"); 537 return (DCMD_ERR); 538 } 539 return (DCMD_OK); 540 } 541 542 if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) { 543 mdb_warn("failed to read statistic at %p", addr); 544 return (DCMD_ERR); 545 } 546 547 switch (s.fmds_type) { 548 case FMD_TYPE_BOOL: 549 mdb_printf("%-11p %-4s %-32s %s\n", addr, "bool", 550 s.fmds_name, s.fmds_value.bool ? "true" : "false"); 551 break; 552 case FMD_TYPE_INT32: 553 mdb_printf("%-11p %-4s %-32s %d\n", addr, "i32", 554 s.fmds_name, s.fmds_value.i32); 555 break; 556 case FMD_TYPE_UINT32: 557 mdb_printf("%-11p %-4s %-32s %u\n", addr, "ui32", 558 s.fmds_name, s.fmds_value.i32); 559 break; 560 case FMD_TYPE_INT64: 561 mdb_printf("%-11p %-4s %-32s %lld\n", addr, "i64", 562 s.fmds_name, s.fmds_value.i64); 563 break; 564 case FMD_TYPE_UINT64: 565 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "ui64", 566 s.fmds_name, s.fmds_value.ui64); 567 break; 568 case FMD_TYPE_STRING: 569 if (mdb_readstr(buf, sizeof (buf), 570 (uintptr_t)s.fmds_value.str) < 0) { 571 (void) mdb_snprintf(buf, sizeof (buf), "<%p>", 572 s.fmds_value.str); 573 } 574 mdb_printf("%-11p %-4s %-32s %s\n", addr, "str", 575 s.fmds_name, buf); 576 break; 577 case FMD_TYPE_TIME: 578 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "time", 579 s.fmds_name, s.fmds_value.ui64); 580 break; 581 case FMD_TYPE_SIZE: 582 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "size", 583 s.fmds_name, s.fmds_value.ui64); 584 break; 585 default: 586 mdb_printf("%-11p %-4u %-32s ???\n", addr, 587 s.fmds_type, s.fmds_name); 588 break; 589 } 590 591 return (DCMD_OK); 592 } 593 594 /*ARGSUSED*/ 595 static int 596 fmd_event(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 597 { 598 char type[16], name[16]; 599 fmd_event_impl_t ev; 600 601 if (argc != 0) 602 return (DCMD_USAGE); 603 604 if (mdb_vread(&ev, sizeof (ev), addr) != sizeof (ev)) { 605 mdb_warn("failed to read fmd_event at %p", addr); 606 return (DCMD_ERR); 607 } 608 609 if (DCMD_HDRSPEC(flags)) { 610 mdb_printf("%<u>%-11s %-4s %-5s %-3s %-?s%</u>\n", 611 "ADDR", "TYPE", "STATE", "REF", "NVPAIR"); 612 } 613 614 switch (ev.ev_type) { 615 case FMD_EVT_PROTOCOL: 616 (void) strcpy(type, "PROT"); 617 break; 618 case FMD_EVT_GC: 619 (void) strcpy(type, "GC"); 620 break; 621 case FMD_EVT_CLOSE: 622 (void) strcpy(type, "CLSE"); 623 break; 624 case FMD_EVT_TIMEOUT: 625 (void) strcpy(type, "TIME"); 626 break; 627 case FMD_EVT_STATS: 628 (void) strcpy(type, "STAT"); 629 break; 630 case FMD_EVT_PUBLISH: 631 (void) strcpy(type, "PUBL"); 632 break; 633 case FMD_EVT_TOPO: 634 (void) strcpy(type, "TOPO"); 635 break; 636 default: 637 (void) mdb_snprintf(type, sizeof (type), "%u", ev.ev_type); 638 } 639 640 switch (ev.ev_state) { 641 case FMD_EVS_RECEIVED: 642 (void) strcpy(name, "RECVD"); 643 break; 644 case FMD_EVS_ACCEPTED: 645 (void) strcpy(name, "ACCPT"); 646 break; 647 case FMD_EVS_DISCARDED: 648 (void) strcpy(name, "DSCRD"); 649 break; 650 case FMD_EVS_DIAGNOSED: 651 (void) strcpy(name, "DIAGN"); 652 break; 653 default: 654 (void) mdb_snprintf(name, sizeof (name), "%u", ev.ev_state); 655 } 656 657 mdb_printf("%-11p %-4s %-5s %-3u %p\n", 658 addr, type, name, ev.ev_refs, ev.ev_nvl); 659 660 return (DCMD_OK); 661 } 662 663 static int 664 thread_walk_init(mdb_walk_state_t *wsp) 665 { 666 fmd_t F; 667 668 if (mdb_readvar(&F, "fmd") != sizeof (F)) { 669 mdb_warn("failed to read fmd meta-data"); 670 return (WALK_ERR); 671 } 672 673 wsp->walk_addr = (uintptr_t)F.d_thr_list.l_next; 674 return (WALK_NEXT); 675 } 676 677 static int 678 thread_walk_step(mdb_walk_state_t *wsp) 679 { 680 uintptr_t addr = wsp->walk_addr; 681 fmd_thread_t t; 682 683 if (addr == 0) 684 return (WALK_DONE); 685 686 if (mdb_vread(&t, sizeof (t), addr) != sizeof (t)) { 687 mdb_warn("failed to read fmd_thread at %p", addr); 688 return (WALK_ERR); 689 } 690 691 wsp->walk_addr = (uintptr_t)t.thr_list.l_next; 692 return (wsp->walk_callback(addr, &t, wsp->walk_cbdata)); 693 } 694 695 static int 696 fmd_thread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 697 { 698 fmd_thread_t thr; 699 700 if (!(flags & DCMD_ADDRSPEC)) 701 return (mdb_walk_dcmd("fmd_thread", "fmd_thread", argc, argv)); 702 703 if (argc != 0) 704 return (DCMD_USAGE); 705 706 if (mdb_vread(&thr, sizeof (thr), addr) != sizeof (thr)) { 707 mdb_warn("failed to read fmd_thread at %p", addr); 708 return (DCMD_ERR); 709 } 710 711 if (DCMD_HDRSPEC(flags)) { 712 mdb_printf("%<u>%-11s %-11s %-8s %-16s%</u>\n", 713 "ADDR", "MOD", "TID", "FUNC"); 714 } 715 716 mdb_printf("%-11p %-11p %-8u %a\n", 717 addr, thr.thr_mod, thr.thr_tid, thr.thr_func); 718 719 return (DCMD_OK); 720 } 721 722 static int 723 mod_walk_init(mdb_walk_state_t *wsp) 724 { 725 fmd_t F; 726 727 if (mdb_readvar(&F, "fmd") != sizeof (F)) { 728 mdb_warn("failed to read fmd meta-data"); 729 return (WALK_ERR); 730 } 731 732 wsp->walk_addr = (uintptr_t)F.d_mod_list.l_next; 733 return (WALK_NEXT); 734 } 735 736 static int 737 mod_walk_step(mdb_walk_state_t *wsp) 738 { 739 uintptr_t addr = wsp->walk_addr; 740 fmd_module_t m; 741 742 if (addr == 0) 743 return (WALK_DONE); 744 745 if (mdb_vread(&m, sizeof (m), addr) != sizeof (m)) { 746 mdb_warn("failed to read fmd_module at %p", addr); 747 return (WALK_ERR); 748 } 749 750 wsp->walk_addr = (uintptr_t)m.mod_list.l_next; 751 return (wsp->walk_callback(addr, &m, wsp->walk_cbdata)); 752 } 753 754 static int 755 fmd_module(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 756 { 757 fmd_module_t mod; 758 char name[PATH_MAX]; 759 760 if (!(flags & DCMD_ADDRSPEC)) 761 return (mdb_walk_dcmd("fmd_module", "fmd_module", argc, argv)); 762 763 if (argc != 0) 764 return (DCMD_USAGE); 765 766 if (mdb_vread(&mod, sizeof (mod), addr) != sizeof (mod)) { 767 mdb_warn("failed to read fmd_module at %p", addr); 768 return (DCMD_ERR); 769 } 770 771 if (DCMD_HDRSPEC(flags)) { 772 mdb_printf("%<u>%-11s %-16s %-11s %-4s %-?s %-16s%</u>\n", 773 "ADDR", "OPS", "DATA", "FLAG", "USTAT", "NAME"); 774 } 775 776 if (mdb_readstr(name, sizeof (name), (uintptr_t)mod.mod_name) <= 0) 777 (void) mdb_snprintf(name, sizeof (name), "<%p>", mod.mod_name); 778 779 mdb_printf("%-11p %-16a %-11p 0x%02x %-?p %s\n", addr, 780 mod.mod_ops, mod.mod_data, mod.mod_flags, mod.mod_ustat, name); 781 782 return (DCMD_OK); 783 } 784 785 static int 786 case_walk_init(mdb_walk_state_t *wsp) 787 { 788 fmd_module_t mod; 789 fmd_case_hash_t ch; 790 fmd_t F; 791 792 if (wsp->walk_addr != 0) { 793 if (mdb_vread(&mod, sizeof (mod), wsp->walk_addr) == -1) { 794 mdb_warn("failed to read module at %p", wsp->walk_addr); 795 return (WALK_ERR); 796 } 797 798 wsp->walk_addr = (uintptr_t)mod.mod_cases.l_next; 799 return (WALK_NEXT); 800 } 801 802 if (mdb_readvar(&F, "fmd") != sizeof (F) || 803 mdb_vread(&ch, sizeof (ch), (uintptr_t)F.d_cases) != sizeof (ch)) { 804 mdb_warn("failed to read fmd meta-data"); 805 return (WALK_ERR); 806 } 807 808 return (hash_walk_init(wsp, (uintptr_t)ch.ch_hash, ch.ch_hashlen, 809 "fmd_case", sizeof (fmd_case_impl_t), 810 OFFSETOF(fmd_case_impl_t, ci_next))); 811 } 812 813 static int 814 case_walk_step(mdb_walk_state_t *wsp) 815 { 816 uintptr_t addr = wsp->walk_addr; 817 fmd_case_impl_t ci; 818 819 if (wsp->walk_data != NULL) 820 return (hash_walk_step(wsp)); 821 822 if (addr == 0) 823 return (WALK_DONE); 824 825 if (mdb_vread(&ci, sizeof (ci), addr) != sizeof (ci)) { 826 mdb_warn("failed to read fmd_case at %p", addr); 827 return (WALK_ERR); 828 } 829 830 wsp->walk_addr = (uintptr_t)ci.ci_list.l_next; 831 return (wsp->walk_callback(addr, &ci, wsp->walk_cbdata)); 832 } 833 834 static void 835 case_walk_fini(mdb_walk_state_t *wsp) 836 { 837 if (wsp->walk_data != NULL) 838 hash_walk_fini(wsp); 839 } 840 841 static int 842 fmd_case(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 843 { 844 char uuid[48], name[16]; 845 fmd_case_impl_t ci; 846 847 if (!(flags & DCMD_ADDRSPEC)) { 848 if (mdb_walk_dcmd("fmd_case", "fmd_case", argc, argv) != 0) { 849 mdb_warn("failed to walk fmd_case hash"); 850 return (DCMD_ERR); 851 } 852 return (DCMD_OK); 853 } 854 855 if (mdb_vread(&ci, sizeof (ci), addr) != sizeof (ci)) { 856 mdb_warn("failed to read fmd_case at %p", addr); 857 return (DCMD_ERR); 858 } 859 860 if (DCMD_HDRSPEC(flags)) { 861 mdb_printf("%<u>%-11s %-5s %-3s %-?s %-36s%</u>\n", 862 "ADDR", "STATE", "REF", "DATA", "UUID"); 863 } 864 865 if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)ci.ci_uuid) <= 0) 866 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", ci.ci_uuid); 867 868 switch (ci.ci_state) { 869 case FMD_CASE_UNSOLVED: 870 (void) strcpy(name, "UNSLV"); 871 break; 872 case FMD_CASE_SOLVED: 873 (void) strcpy(name, "SOLVE"); 874 break; 875 case FMD_CASE_CLOSE_WAIT: 876 (void) strcpy(name, "CWAIT"); 877 break; 878 case FMD_CASE_CLOSED: 879 (void) strcpy(name, "CLOSE"); 880 break; 881 case FMD_CASE_REPAIRED: 882 (void) strcpy(name, "RPAIR"); 883 break; 884 case FMD_CASE_RESOLVED: 885 (void) strcpy(name, "RSLVD"); 886 break; 887 default: 888 (void) mdb_snprintf(name, sizeof (name), "%u", ci.ci_state); 889 } 890 891 mdb_printf("%-11p %-5s %-3u %-?p %s\n", 892 addr, name, ci.ci_refs, ci.ci_data, uuid); 893 894 return (DCMD_OK); 895 } 896 897 static int 898 buf_walk_init(mdb_walk_state_t *wsp) 899 { 900 fmd_buf_hash_t bh; 901 902 if (mdb_vread(&bh, sizeof (bh), wsp->walk_addr) != sizeof (bh)) { 903 mdb_warn("failed to read fmd_buf_hash_t at %p", wsp->walk_addr); 904 return (WALK_ERR); 905 } 906 907 return (hash_walk_init(wsp, (uintptr_t)bh.bh_hash, bh.bh_hashlen, 908 "fmd_buf", sizeof (fmd_buf_t), OFFSETOF(fmd_buf_t, buf_next))); 909 } 910 911 /*ARGSUSED*/ 912 static int 913 fmd_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 914 { 915 char name[PATH_MAX]; 916 fmd_buf_t b; 917 918 if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 919 return (DCMD_USAGE); 920 921 if (mdb_vread(&b, sizeof (b), addr) != sizeof (b)) { 922 mdb_warn("failed to read fmd_buf at %p", addr); 923 return (DCMD_ERR); 924 } 925 926 if (DCMD_HDRSPEC(flags)) { 927 mdb_printf("%<u>%-11s %-32s %-5s %-?s %s%</u>\n", 928 "ADDR", "NAME", "FLAGS", "DATA", "SIZE"); 929 } 930 931 if (mdb_readstr(name, sizeof (name), (uintptr_t)b.buf_name) <= 0) 932 (void) mdb_snprintf(name, sizeof (name), "<%p>", b.buf_name); 933 934 mdb_printf("%-11p %-32s %-#5x %-?p %lu\n", 935 addr, name, b.buf_flags, b.buf_data, b.buf_size); 936 937 return (DCMD_OK); 938 } 939 940 static int 941 serd_walk_init(mdb_walk_state_t *wsp) 942 { 943 fmd_serd_hash_t sh; 944 945 if (mdb_vread(&sh, sizeof (sh), wsp->walk_addr) != sizeof (sh)) { 946 mdb_warn("failed to read fmd_serd_hash at %p", wsp->walk_addr); 947 return (WALK_ERR); 948 } 949 950 return (hash_walk_init(wsp, (uintptr_t)sh.sh_hash, sh.sh_hashlen, 951 "fmd_serd_eng", sizeof (fmd_serd_eng_t), 952 OFFSETOF(fmd_serd_eng_t, sg_next))); 953 } 954 955 /* ARGSUSED */ 956 static int 957 module_serd(uintptr_t addr, const void *data, void *wsp) 958 { 959 fmd_module_t *modp = (fmd_module_t *)data; 960 961 if (modp->mod_serds.sh_count != 0) { 962 modp = (fmd_module_t *)addr; 963 (void) mdb_pwalk_dcmd("fmd_serd", "fmd_serd", 0, 0, 964 (uintptr_t)&modp->mod_serds); 965 } 966 return (WALK_NEXT); 967 } 968 969 /*ARGSUSED*/ 970 static int 971 fmd_serd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 972 { 973 char name[PATH_MAX]; 974 fmd_serd_eng_t sg; 975 976 if (argc != 0) 977 return (DCMD_USAGE); 978 if (!(flags & DCMD_ADDRSPEC)) { 979 if (mdb_walk("fmd_module", module_serd, 0) == -1) { 980 mdb_warn("failed to walk 'fmd_module'"); 981 return (DCMD_ERR); 982 } 983 return (DCMD_OK); 984 } 985 986 if (mdb_vread(&sg, sizeof (sg), addr) != sizeof (sg)) { 987 mdb_warn("failed to read fmd_serd_eng at %p", addr); 988 return (DCMD_ERR); 989 } 990 991 if (DCMD_HDRSPEC(flags)) { 992 mdb_printf("%<u>%-11s %-32s %-3s F >%-2s %-16s%</u>\n", 993 "ADDR", "NAME", "CNT", "N", "T"); 994 } 995 996 if (mdb_readstr(name, sizeof (name), (uintptr_t)sg.sg_name) <= 0) 997 (void) mdb_snprintf(name, sizeof (name), "<%p>", sg.sg_name); 998 999 mdb_printf("%-11p %-32s %-3u %c >%-2u %lluns\n", 1000 addr, name, sg.sg_count, (sg.sg_flags & FMD_SERD_FIRED) ? 'F' : ' ', 1001 sg.sg_n, (u_longlong_t)sg.sg_t); 1002 1003 return (DCMD_OK); 1004 } 1005 1006 static int 1007 asru_walk_init(mdb_walk_state_t *wsp) 1008 { 1009 fmd_asru_hash_t ah; 1010 fmd_t F; 1011 1012 if (wsp->walk_addr == 0 && mdb_readvar(&F, "fmd") != sizeof (F)) { 1013 mdb_warn("failed to read fmd meta-data"); 1014 return (WALK_ERR); 1015 } 1016 1017 if (wsp->walk_addr == 0) 1018 wsp->walk_addr = (uintptr_t)F.d_asrus; 1019 1020 if (mdb_vread(&ah, sizeof (ah), wsp->walk_addr) != sizeof (ah)) { 1021 mdb_warn("failed to read asru_hash at %p", wsp->walk_addr); 1022 return (WALK_ERR); 1023 } 1024 1025 return (hash_walk_init(wsp, (uintptr_t)ah.ah_hash, ah.ah_hashlen, 1026 "fmd_asru", sizeof (fmd_asru_t), OFFSETOF(fmd_asru_t, asru_next))); 1027 } 1028 1029 static int 1030 fmd_asru(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1031 { 1032 char uuid[48], name[PATH_MAX]; 1033 fmd_asru_t a; 1034 1035 if (!(flags & DCMD_ADDRSPEC)) { 1036 if (mdb_walk_dcmd("fmd_asru", "fmd_asru", argc, argv) != 0) { 1037 mdb_warn("failed to walk fmd_asru hash"); 1038 return (DCMD_ERR); 1039 } 1040 return (DCMD_OK); 1041 } 1042 1043 if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) { 1044 mdb_warn("failed to read fmd_asru at %p", addr); 1045 return (DCMD_ERR); 1046 } 1047 1048 if (DCMD_HDRSPEC(flags)) 1049 mdb_printf("%<u>%-8s %-36s %s%</u>\n", "ADDR", "UUID", "NAME"); 1050 1051 if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)a.asru_uuid) <= 0) 1052 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", a.asru_uuid); 1053 if (mdb_readstr(name, sizeof (name), (uintptr_t)a.asru_name) <= 0) 1054 (void) mdb_snprintf(name, sizeof (name), "<%p>", a.asru_name); 1055 1056 mdb_printf("%-8p %-36s %s\n", addr, uuid, name); 1057 return (DCMD_OK); 1058 } 1059 1060 static int 1061 al_walk_init(mdb_walk_state_t *wsp) 1062 { 1063 fmd_asru_hash_t ah; 1064 fmd_t F; 1065 1066 if (wsp->walk_addr == 0 && mdb_readvar(&F, "fmd") != sizeof (F)) { 1067 mdb_warn("failed to read fmd meta-data"); 1068 return (WALK_ERR); 1069 } 1070 1071 if (wsp->walk_addr == 0) 1072 wsp->walk_addr = (uintptr_t)F.d_asrus; 1073 1074 if (mdb_vread(&ah, sizeof (ah), wsp->walk_addr) != sizeof (ah)) { 1075 mdb_warn("failed to read asru_hash at %p", wsp->walk_addr); 1076 return (WALK_ERR); 1077 } 1078 1079 return (hash_walk_init(wsp, (uintptr_t)ah.ah_rsrc_hash, ah.ah_hashlen, 1080 "fmd_asru_link", sizeof (fmd_asru_link_t), OFFSETOF(fmd_asru_link_t, 1081 al_rsrc_next))); 1082 } 1083 1084 static int 1085 fmd_asru_link(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1086 { 1087 char uuid[48], name[PATH_MAX]; 1088 fmd_asru_link_t a; 1089 1090 if (!(flags & DCMD_ADDRSPEC)) { 1091 if (mdb_walk_dcmd("fmd_asru_link", "fmd_asru_link", argc, 1092 argv) != 0) { 1093 mdb_warn("failed to walk fmd_asru_link hash"); 1094 return (DCMD_ERR); 1095 } 1096 return (DCMD_OK); 1097 } 1098 1099 if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) { 1100 mdb_warn("failed to read fmd_asru_link at %p", addr); 1101 return (DCMD_ERR); 1102 } 1103 1104 if (DCMD_HDRSPEC(flags)) 1105 mdb_printf("%<u>%-8s %-36s %s%</u>\n", "ADDR", "UUID", "NAME"); 1106 1107 if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)a.al_uuid) <= 0) 1108 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", a.al_uuid); 1109 if (mdb_readstr(name, sizeof (name), (uintptr_t)a.al_rsrc_name) <= 0) 1110 (void) mdb_snprintf(name, sizeof (name), "<%p>", 1111 a.al_rsrc_name); 1112 1113 mdb_printf("%-8p %-36s %s\n", addr, uuid, name); 1114 return (DCMD_OK); 1115 } 1116 1117 /*ARGSUSED*/ 1118 static int 1119 fcf_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1120 { 1121 fcf_hdr_t h; 1122 1123 if (argc != 0) 1124 return (DCMD_USAGE); 1125 1126 if (!(flags & DCMD_ADDRSPEC)) 1127 addr = 0; /* assume base of file in file target */ 1128 1129 if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) { 1130 mdb_warn("failed to read header at %p", addr); 1131 return (DCMD_ERR); 1132 } 1133 1134 mdb_printf("fcfh_ident.id_magic = 0x%x, %c, %c, %c\n", 1135 h.fcfh_ident[FCF_ID_MAG0], h.fcfh_ident[FCF_ID_MAG1], 1136 h.fcfh_ident[FCF_ID_MAG2], h.fcfh_ident[FCF_ID_MAG3]); 1137 1138 switch (h.fcfh_ident[FCF_ID_MODEL]) { 1139 case FCF_MODEL_ILP32: 1140 mdb_printf("fcfh_ident.id_model = ILP32\n"); 1141 break; 1142 case FCF_MODEL_LP64: 1143 mdb_printf("fcfh_ident.id_model = LP64\n"); 1144 break; 1145 default: 1146 mdb_printf("fcfh_ident.id_model = 0x%x\n", 1147 h.fcfh_ident[FCF_ID_MODEL]); 1148 } 1149 1150 switch (h.fcfh_ident[FCF_ID_ENCODING]) { 1151 case FCF_ENCODE_LSB: 1152 mdb_printf("fcfh_ident.id_encoding = LSB\n"); 1153 break; 1154 case FCF_ENCODE_MSB: 1155 mdb_printf("fcfh_ident.id_encoding = MSB\n"); 1156 break; 1157 default: 1158 mdb_printf("fcfh_ident.id_encoding = 0x%x\n", 1159 h.fcfh_ident[FCF_ID_ENCODING]); 1160 } 1161 1162 mdb_printf("fcfh_ident.id_version = %u\n", 1163 h.fcfh_ident[FCF_ID_VERSION]); 1164 1165 mdb_printf("fcfh_flags = 0x%x\n", h.fcfh_flags); 1166 mdb_printf("fcfh_hdrsize = %u\n", h.fcfh_hdrsize); 1167 mdb_printf("fcfh_secsize = %u\n", h.fcfh_secsize); 1168 mdb_printf("fcfh_secnum = %u\n", h.fcfh_secnum); 1169 mdb_printf("fcfh_secoff = %llu\n", h.fcfh_secoff); 1170 mdb_printf("fcfh_filesz = %llu\n", h.fcfh_filesz); 1171 mdb_printf("fcfh_cgen = %llu\n", h.fcfh_cgen); 1172 1173 return (DCMD_OK); 1174 } 1175 1176 static int fcf_sec(uintptr_t, uint_t, int, const mdb_arg_t *); 1177 /*ARGSUSED*/ 1178 static int 1179 fcf_sec_one(uintptr_t addr, void *ignored, uint_t *secp) 1180 { 1181 1182 mdb_printf("%3d ", (*secp)++); 1183 (void) fcf_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL); 1184 return (WALK_NEXT); 1185 } 1186 1187 /*ARGSUSED*/ 1188 static int 1189 fcf_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1190 { 1191 static const char *const types[] = { 1192 "none", /* FCF_SECT_NONE */ 1193 "strtab", /* FCF_SECT_STRTAB */ 1194 "module", /* FCF_SECT_MODULE */ 1195 "case", /* FCF_SECT_CASE */ 1196 "bufs", /* FCF_SECT_BUFS */ 1197 "buffer", /* FCF_SECT_BUFFER */ 1198 "serd", /* FCF_SECT_SERD */ 1199 "events", /* FCF_SECT_EVENTS */ 1200 "nvlists", /* FCF_SECT_NVLISTS */ 1201 }; 1202 1203 uint_t sec = 0; 1204 fcf_sec_t s; 1205 1206 if (!(flags & DCMD_ADDRSPEC)) 1207 mdb_printf("%<u>%-3s ", "NDX"); 1208 1209 if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) { 1210 mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n", 1211 "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFF", "SIZE"); 1212 } 1213 1214 if (!(flags & DCMD_ADDRSPEC)) { 1215 if (mdb_walk("fcf_sec", (mdb_walk_cb_t)fcf_sec_one, &sec) < 0) { 1216 mdb_warn("failed to walk fcf_sec"); 1217 return (DCMD_ERR); 1218 } 1219 return (DCMD_OK); 1220 } 1221 1222 if (argc != 0) 1223 return (DCMD_USAGE); 1224 1225 if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) { 1226 mdb_warn("failed to read section header at %p", addr); 1227 return (DCMD_ERR); 1228 } 1229 1230 mdb_printf("%?p ", addr); 1231 1232 if (s.fcfs_type < sizeof (types) / sizeof (types[0])) 1233 mdb_printf("%-10s ", types[s.fcfs_type]); 1234 else 1235 mdb_printf("%-10u ", s.fcfs_type); 1236 1237 mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.fcfs_align, 1238 s.fcfs_flags, s.fcfs_entsize, s.fcfs_offset, s.fcfs_size); 1239 1240 return (DCMD_OK); 1241 } 1242 1243 static int 1244 fcf_sec_walk_init(mdb_walk_state_t *wsp) 1245 { 1246 fcf_hdr_t h, *hp; 1247 size_t size; 1248 1249 if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) { 1250 mdb_warn("failed to read FCF header at %p", wsp->walk_addr); 1251 return (WALK_ERR); 1252 } 1253 1254 size = sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * h.fcfh_secnum; 1255 hp = mdb_alloc(size, UM_SLEEP); 1256 1257 if (mdb_vread(hp, size, wsp->walk_addr) != size) { 1258 mdb_warn("failed to read FCF sections at %p", wsp->walk_addr); 1259 mdb_free(hp, size); 1260 return (WALK_ERR); 1261 } 1262 1263 wsp->walk_data = hp; 1264 wsp->walk_arg = 0; 1265 1266 return (WALK_NEXT); 1267 } 1268 1269 static int 1270 fcf_sec_walk_step(mdb_walk_state_t *wsp) 1271 { 1272 uint_t i = (uint_t)wsp->walk_arg; 1273 size_t off = sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * i; 1274 fcf_hdr_t *hp = wsp->walk_data; 1275 fcf_sec_t *sp = (fcf_sec_t *)((uintptr_t)hp + off); 1276 1277 if (i >= hp->fcfh_secnum) 1278 return (WALK_DONE); 1279 1280 wsp->walk_arg = (void *)(i + 1); 1281 return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata)); 1282 } 1283 1284 static void 1285 fcf_sec_walk_fini(mdb_walk_state_t *wsp) 1286 { 1287 fcf_hdr_t *hp = wsp->walk_data; 1288 mdb_free(hp, sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * hp->fcfh_secnum); 1289 } 1290 1291 /*ARGSUSED*/ 1292 static int 1293 fcf_case(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1294 { 1295 fcf_case_t fcfc; 1296 1297 if (argc != 0) 1298 return (DCMD_USAGE); 1299 1300 if (mdb_vread(&fcfc, sizeof (fcfc), addr) != sizeof (fcfc)) { 1301 mdb_warn("failed to read case at %p", addr); 1302 return (DCMD_ERR); 1303 } 1304 1305 mdb_printf("fcfc_uuid = 0x%x\n", fcfc.fcfc_uuid); 1306 mdb_printf("fcfc_state = %u\n", fcfc.fcfc_state); 1307 mdb_printf("fcfc_bufs = %u\n", fcfc.fcfc_bufs); 1308 mdb_printf("fcfc_events = %u\n", fcfc.fcfc_events); 1309 mdb_printf("fcfc_suspects = %u\n", fcfc.fcfc_suspects); 1310 1311 return (DCMD_OK); 1312 } 1313 1314 /*ARGSUSED*/ 1315 static int 1316 fcf_event(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1317 { 1318 fcf_event_t fcfe; 1319 1320 if (argc != 0) 1321 return (DCMD_USAGE); 1322 1323 if (mdb_vread(&fcfe, sizeof (fcfe), addr) != sizeof (fcfe)) { 1324 mdb_warn("failed to read event at %p", addr); 1325 return (DCMD_ERR); 1326 } 1327 1328 mdb_printf("fcfe_todsec = %llu (%Y)\n", 1329 fcfe.fcfe_todsec, (time_t)fcfe.fcfe_todsec); 1330 mdb_printf("fcfe_todnsec = %llu\n", fcfe.fcfe_todnsec); 1331 mdb_printf("fcfe_major = %u\n", fcfe.fcfe_major); 1332 mdb_printf("fcfe_minor = %u\n", fcfe.fcfe_minor); 1333 mdb_printf("fcfe_inode = %llu\n", fcfe.fcfe_inode); 1334 mdb_printf("fcfe_offset = %llu\n", fcfe.fcfe_offset); 1335 1336 return (DCMD_OK); 1337 } 1338 1339 /*ARGSUSED*/ 1340 static int 1341 fcf_serd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1342 { 1343 fcf_serd_t fcfd; 1344 1345 if (argc != 0) 1346 return (DCMD_USAGE); 1347 1348 if (mdb_vread(&fcfd, sizeof (fcfd), addr) != sizeof (fcfd)) { 1349 mdb_warn("failed to read serd at %p", addr); 1350 return (DCMD_ERR); 1351 } 1352 1353 mdb_printf("fcfd_name = 0x%x\n", fcfd.fcfd_name); 1354 mdb_printf("fcfd_events = %u\n", fcfd.fcfd_events); 1355 mdb_printf("fcfd_n = >%u\n", fcfd.fcfd_n); 1356 mdb_printf("fcfd_t = %lluns\n", fcfd.fcfd_t); 1357 1358 return (DCMD_OK); 1359 } 1360 1361 static int 1362 tmq_walk_init(mdb_walk_state_t *wsp) 1363 { 1364 fmd_timerq_t tmq; 1365 fmd_t F; 1366 1367 if (wsp->walk_addr == 0 && mdb_readvar(&F, "fmd") != sizeof (F)) { 1368 mdb_warn("failed to read fmd meta-data"); 1369 return (WALK_ERR); 1370 } 1371 1372 if (wsp->walk_addr == 0) 1373 wsp->walk_addr = (uintptr_t)F.d_timers; 1374 1375 if (mdb_vread(&tmq, sizeof (tmq), wsp->walk_addr) != sizeof (tmq)) { 1376 mdb_warn("failed to read timerq at %p", wsp->walk_addr); 1377 return (WALK_ERR); 1378 } 1379 1380 wsp->walk_addr = (uintptr_t)tmq.tmq_list.l_next; 1381 return (WALK_NEXT); 1382 } 1383 1384 static int 1385 tmq_walk_step(mdb_walk_state_t *wsp) 1386 { 1387 uintptr_t addr = wsp->walk_addr; 1388 fmd_timer_t tmr; 1389 1390 if (addr == 0) 1391 return (WALK_DONE); 1392 1393 if (mdb_vread(&tmr, sizeof (tmr), addr) != sizeof (tmr)) { 1394 mdb_warn("failed to read fmd_timer at %p", addr); 1395 return (WALK_ERR); 1396 } 1397 1398 wsp->walk_addr = (uintptr_t)tmr.tmr_list.l_next; 1399 return (wsp->walk_callback(addr, &tmr, wsp->walk_cbdata)); 1400 } 1401 1402 static int 1403 fmd_timer(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1404 { 1405 char name[32], func[MDB_SYM_NAMLEN]; 1406 fmd_timer_t t; 1407 1408 if (!(flags & DCMD_ADDRSPEC)) { 1409 if (mdb_walk_dcmd("fmd_timerq", "fmd_timer", argc, argv) != 0) { 1410 mdb_warn("failed to walk fmd_timerq"); 1411 return (DCMD_ERR); 1412 } 1413 return (DCMD_OK); 1414 } 1415 1416 if (mdb_vread(&t, sizeof (t), addr) != sizeof (t)) { 1417 mdb_warn("failed to read fmd_timer at %p", addr); 1418 return (DCMD_ERR); 1419 } 1420 1421 if (DCMD_HDRSPEC(flags)) { 1422 mdb_printf("%<u>%-8s %-20s %-4s %-18s %-8s %s%</u>\n", 1423 "ADDR", "MODULE", "ID", "HRTIME", "ARG", "FUNC"); 1424 } 1425 1426 if (mdb_readstr(name, sizeof (name), (uintptr_t) 1427 t.tmr_ids + OFFSETOF(fmd_idspace_t, ids_name)) <= 0) 1428 (void) mdb_snprintf(name, sizeof (name), "<%p>", t.tmr_ids); 1429 1430 if (mdb_lookup_by_addr((uintptr_t)t.tmr_func, MDB_SYM_FUZZY, 1431 func, sizeof (func), NULL) != 0) 1432 (void) mdb_snprintf(func, sizeof (func), "<%p>", t.tmr_func); 1433 1434 mdb_printf("%-8p %-20s %4d 0x%-16llx %-8p %s\n", 1435 addr, name, t.tmr_id, t.tmr_hrt, t.tmr_arg, func); 1436 return (DCMD_OK); 1437 } 1438 1439 static int 1440 xprt_walk_init(mdb_walk_state_t *wsp) 1441 { 1442 fmd_module_t m; 1443 1444 if (wsp->walk_addr == 0) { 1445 mdb_warn("transport walker requires fmd_module_t address\n"); 1446 return (WALK_ERR); 1447 } 1448 1449 if (mdb_vread(&m, sizeof (m), wsp->walk_addr) != sizeof (m)) { 1450 mdb_warn("failed to read module at %p", wsp->walk_addr); 1451 return (WALK_ERR); 1452 } 1453 1454 wsp->walk_addr = (uintptr_t)m.mod_transports.l_next; 1455 return (WALK_NEXT); 1456 } 1457 1458 static int 1459 xprt_walk_step(mdb_walk_state_t *wsp) 1460 { 1461 uintptr_t addr = wsp->walk_addr; 1462 fmd_xprt_impl_t xi; 1463 1464 if (addr == 0) 1465 return (WALK_DONE); 1466 1467 if (mdb_vread(&xi, sizeof (xi), addr) != sizeof (xi)) { 1468 mdb_warn("failed to read fmd_xprt at %p", addr); 1469 return (WALK_ERR); 1470 } 1471 1472 wsp->walk_addr = (uintptr_t)xi.xi_list.l_next; 1473 return (wsp->walk_callback(addr, &xi, wsp->walk_cbdata)); 1474 } 1475 1476 static int 1477 xpc_walk_init(mdb_walk_state_t *wsp) 1478 { 1479 fmd_xprt_class_hash_t xch; 1480 1481 if (mdb_vread(&xch, sizeof (xch), wsp->walk_addr) != sizeof (xch)) { 1482 mdb_warn("failed to read fmd_xprt_class_hash at %p", 1483 wsp->walk_addr); 1484 return (WALK_ERR); 1485 } 1486 1487 return (hash_walk_init(wsp, (uintptr_t)xch.xch_hash, xch.xch_hashlen, 1488 "fmd_xprt_class", sizeof (fmd_xprt_class_t), 1489 OFFSETOF(fmd_xprt_class_t, xc_next))); 1490 } 1491 1492 /*ARGSUSED*/ 1493 static int 1494 fmd_xprt_class(uintptr_t addr, const void *data, void *arg) 1495 { 1496 const fmd_xprt_class_t *xcp = data; 1497 char name[1024]; 1498 1499 if (mdb_readstr(name, sizeof (name), (uintptr_t)xcp->xc_class) <= 0) 1500 (void) mdb_snprintf(name, sizeof (name), "<%p>", xcp->xc_class); 1501 1502 mdb_printf("%-8p %-4u %s\n", addr, xcp->xc_refs, name); 1503 return (WALK_NEXT); 1504 } 1505 1506 static int 1507 fmd_xprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1508 { 1509 uint_t opt_s = FALSE, opt_l = FALSE, opt_r = FALSE, opt_u = FALSE; 1510 fmd_xprt_impl_t xi; 1511 1512 if (mdb_getopts(argc, argv, 1513 'l', MDB_OPT_SETBITS, TRUE, &opt_l, 1514 'r', MDB_OPT_SETBITS, TRUE, &opt_r, 1515 's', MDB_OPT_SETBITS, TRUE, &opt_s, 1516 'u', MDB_OPT_SETBITS, TRUE, &opt_u, NULL) != argc) 1517 return (DCMD_USAGE); 1518 1519 if (!(flags & DCMD_ADDRSPEC)) { 1520 if (mdb_walk_dcmd("fmd_xprt", "fmd_xprt", argc, argv) != 0) { 1521 mdb_warn("failed to walk fmd_xprt"); 1522 return (DCMD_ERR); 1523 } 1524 return (DCMD_OK); 1525 } 1526 1527 if (mdb_vread(&xi, sizeof (xi), addr) != sizeof (xi)) { 1528 mdb_warn("failed to read fmd_xprt at %p", addr); 1529 return (DCMD_ERR); 1530 } 1531 1532 if (DCMD_HDRSPEC(flags)) { 1533 mdb_printf("%<u>%-8s %-4s %-4s %-5s %s%</u>\n", 1534 "ADDR", "ID", "VERS", "FLAGS", "STATE"); 1535 } 1536 1537 mdb_printf("%-8p %-4d %-4u %-5x %a\n", 1538 addr, xi.xi_id, xi.xi_version, xi.xi_flags, xi.xi_state); 1539 1540 if (opt_l | opt_s) { 1541 (void) mdb_inc_indent(4); 1542 mdb_printf("Local subscriptions requested by peer:\n"); 1543 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); 1544 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, 1545 addr + OFFSETOF(fmd_xprt_impl_t, xi_lsub)); 1546 (void) mdb_dec_indent(4); 1547 } 1548 1549 if (opt_r | opt_s) { 1550 (void) mdb_inc_indent(4); 1551 mdb_printf("Remote subscriptions requested of peer:\n"); 1552 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); 1553 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, 1554 addr + OFFSETOF(fmd_xprt_impl_t, xi_rsub)); 1555 (void) mdb_dec_indent(4); 1556 } 1557 1558 if (opt_u | opt_s) { 1559 (void) mdb_inc_indent(4); 1560 mdb_printf("Pending unsubscription acknowledgements:\n"); 1561 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); 1562 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, 1563 addr + OFFSETOF(fmd_xprt_impl_t, xi_usub)); 1564 (void) mdb_dec_indent(4); 1565 } 1566 1567 return (DCMD_OK); 1568 } 1569 1570 static int 1571 tsnap_walk_init(mdb_walk_state_t *wsp) 1572 { 1573 fmd_t F; 1574 1575 if (mdb_readvar(&F, "fmd") != sizeof (F)) { 1576 mdb_warn("failed to read fmd meta-data"); 1577 return (WALK_ERR); 1578 } 1579 1580 wsp->walk_addr = (uintptr_t)F.d_topo_list.l_next; 1581 return (WALK_NEXT); 1582 } 1583 1584 static int 1585 tsnap_walk_step(mdb_walk_state_t *wsp) 1586 { 1587 uintptr_t addr = wsp->walk_addr; 1588 fmd_topo_t ftp; 1589 1590 if (addr == 0) 1591 return (WALK_DONE); 1592 1593 if (mdb_vread(&ftp, sizeof (ftp), addr) != sizeof (ftp)) { 1594 mdb_warn("failed to read fmd_topo_t at %p", addr); 1595 return (WALK_ERR); 1596 } 1597 1598 wsp->walk_addr = (uintptr_t)ftp.ft_list.l_next; 1599 return (wsp->walk_callback(addr, &ftp, wsp->walk_cbdata)); 1600 } 1601 1602 static int 1603 mq_walk_init(mdb_walk_state_t *wsp) 1604 { 1605 fmd_module_t m; 1606 struct fmd_eventq eq; 1607 1608 if (wsp->walk_addr == 0) { 1609 mdb_warn("NULL fmd_module_t passed in"); 1610 return (WALK_ERR); 1611 } 1612 1613 if (mdb_vread(&m, sizeof (m), wsp->walk_addr) != sizeof (m)) { 1614 mdb_warn("failed to read fmd_module_t at %p", wsp->walk_addr); 1615 return (WALK_ERR); 1616 } 1617 if (mdb_vread(&eq, sizeof (eq), (uintptr_t)m.mod_queue) 1618 != sizeof (eq)) { 1619 mdb_warn("failed to read fmd_eventq at %p", wsp->walk_addr); 1620 return (WALK_ERR); 1621 } 1622 1623 wsp->walk_addr = (uintptr_t)eq.eq_list.l_next; 1624 1625 return (WALK_NEXT); 1626 } 1627 1628 static int 1629 mq_walk_step(mdb_walk_state_t *wsp) 1630 { 1631 uintptr_t addr = wsp->walk_addr; 1632 fmd_eventqelem_t eqe; 1633 1634 if (addr == 0) 1635 return (WALK_DONE); 1636 1637 if (mdb_vread(&eqe, sizeof (eqe), addr) != sizeof (eqe)) { 1638 mdb_warn("failed to read fmd_eventqelem_t at %p", addr); 1639 return (WALK_ERR); 1640 } 1641 1642 wsp->walk_addr = (uintptr_t)eqe.eqe_list.l_next; 1643 return (wsp->walk_callback(addr, &eqe, wsp->walk_cbdata)); 1644 } 1645 1646 static const mdb_dcmd_t dcmds[] = { 1647 { "fcf_case", "?", "print a FCF case", fcf_case }, 1648 { "fcf_event", "?", "print a FCF event", fcf_event }, 1649 { "fcf_hdr", "?", "print a FCF header", fcf_hdr }, 1650 { "fcf_sec", ":", "print a FCF section header", fcf_sec }, 1651 { "fcf_serd", "?", "print a FCF serd engine", fcf_serd }, 1652 { "fmd_trace", "?[-cs]", "display thread trace buffer(s)", fmd_trace }, 1653 { "fmd_ustat", "[:]", "display statistics collection", fmd_ustat }, 1654 { "fmd_stat", "[:]", "display statistic structure", fmd_stat }, 1655 { "fmd_event", NULL, "display event structure", fmd_event }, 1656 { "fmd_thread", "?", "display thread or list of threads", fmd_thread }, 1657 { "fmd_module", "?", "display module or list of modules", fmd_module }, 1658 { "fmd_case", ":", "display case file structure", fmd_case }, 1659 { "fmd_buf", ":", "display buffer structure", fmd_buf }, 1660 { "fmd_serd", "[:]", "display serd engine structure", fmd_serd }, 1661 { "fmd_asru", "?", "display asru resource structure", fmd_asru }, 1662 { "fmd_asru_link", "?", "display resource structure", fmd_asru_link }, 1663 { "fmd_timer", "?", "display pending timer(s)", fmd_timer }, 1664 { "fmd_xprt", "?[-lrsu]", "display event transport(s)", fmd_xprt }, 1665 { NULL } 1666 }; 1667 1668 static const mdb_walker_t walkers[] = { 1669 { "fcf_sec", "walk FCF section header table given header address", 1670 fcf_sec_walk_init, fcf_sec_walk_step, fcf_sec_walk_fini }, 1671 { "fmd_trace", "walk per-thread trace buffers", 1672 trwalk_init, trwalk_step, trwalk_fini }, 1673 { "fmd_ustat", "walk per-collection statistics", 1674 ustat_walk_init, ustat_walk_step, hash_walk_fini }, 1675 { "fmd_thread", "walk list of all fmd_thread_t's", 1676 thread_walk_init, thread_walk_step, NULL }, 1677 { "fmd_module", "walk list of all fmd_module_t's", 1678 mod_walk_init, mod_walk_step, NULL }, 1679 { "fmd_case", "walk per-module case objects", 1680 case_walk_init, case_walk_step, case_walk_fini }, 1681 { "fmd_buf", "walk per-buf_hash buffers", 1682 buf_walk_init, hash_walk_step, hash_walk_fini }, 1683 { "fmd_serd", "walk per-serd_hash engines", 1684 serd_walk_init, hash_walk_step, hash_walk_fini }, 1685 { "fmd_asru", "walk asru resource hash", 1686 asru_walk_init, hash_walk_step, hash_walk_fini }, 1687 { "fmd_asru_link", "walk resource hash", 1688 al_walk_init, hash_walk_step, hash_walk_fini }, 1689 { "fmd_timerq", "walk timer queue", 1690 tmq_walk_init, tmq_walk_step, NULL }, 1691 { "fmd_xprt", "walk per-module list of transports", 1692 xprt_walk_init, xprt_walk_step, NULL }, 1693 { "fmd_xprt_class", "walk hash table of subscription classes", 1694 xpc_walk_init, hash_walk_step, hash_walk_fini }, 1695 { "fmd_topo", "walk fmd's list of topo snapshots", 1696 tsnap_walk_init, tsnap_walk_step, NULL }, 1697 { "fmd_mod_queue", "walk per-module event queue", 1698 mq_walk_init, mq_walk_step, NULL }, 1699 { NULL, NULL, NULL, NULL, NULL } 1700 }; 1701 1702 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 1703 1704 const mdb_modinfo_t * 1705 _mdb_init(void) 1706 { 1707 return (&modinfo); 1708 } 1709