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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <sys/mdb_modapi.h> 31 32 #include <fmd_trace.h> 33 #include <fmd_module.h> 34 #include <fmd_thread.h> 35 #include <fmd_ustat.h> 36 #include <fmd_event.h> 37 #include <fmd_case.h> 38 #include <fmd_buf.h> 39 #include <fmd_asru.h> 40 #include <fmd_ckpt.h> 41 #include <fmd_timerq.h> 42 #include <fmd_xprt.h> 43 44 #include <fmd.h> 45 46 typedef struct trwalk_state { 47 struct trwalk_state *trw_next; 48 fmd_tracebuf_t trw_data; 49 pthread_t trw_tid; 50 uintptr_t trw_base; 51 const fmd_tracerec_t *trw_stop; 52 fmd_tracerec_t *trw_xrec; 53 } trwalk_state_t; 54 55 typedef struct hashwalk_data { 56 uintptr_t *hw_hash; 57 uint_t hw_hashlen; 58 uint_t hw_hashidx; 59 const char *hw_name; 60 void *hw_data; 61 size_t hw_size; 62 size_t hw_next; 63 } hashwalk_data_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 != NULL) { 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 != NULL; 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 = mdb_alloc(sizeof (hashwalk_data_t), UM_SLEEP); 309 size_t len = sizeof (uintptr_t) * hashlen; 310 311 hwp->hw_hash = mdb_zalloc(len, UM_SLEEP); 312 (void) mdb_vread(hwp->hw_hash, len, addr); 313 hwp->hw_hashlen = hashlen; 314 hwp->hw_hashidx = 0; 315 hwp->hw_name = name; 316 hwp->hw_data = mdb_zalloc(size, UM_SLEEP); 317 hwp->hw_size = size; 318 hwp->hw_next = next; 319 320 wsp->walk_addr = hwp->hw_hash[0]; 321 wsp->walk_data = hwp; 322 323 return (WALK_NEXT); 324 } 325 326 static int 327 hash_walk_step(mdb_walk_state_t *wsp) 328 { 329 hashwalk_data_t *hwp = wsp->walk_data; 330 int rv; 331 332 while (wsp->walk_addr == NULL) { 333 if (++hwp->hw_hashidx < hwp->hw_hashlen) 334 wsp->walk_addr = hwp->hw_hash[hwp->hw_hashidx]; 335 else 336 return (WALK_DONE); 337 } 338 339 if (mdb_vread(hwp->hw_data, hwp->hw_size, wsp->walk_addr) == -1) { 340 mdb_warn("failed to read %s at %p", 341 hwp->hw_name, wsp->walk_addr); 342 return (WALK_ERR); 343 } 344 345 rv = wsp->walk_callback(wsp->walk_addr, hwp->hw_data, wsp->walk_cbdata); 346 wsp->walk_addr = *(uintptr_t *)((uintptr_t)hwp->hw_data + hwp->hw_next); 347 return (rv); 348 } 349 350 static void 351 hash_walk_fini(mdb_walk_state_t *wsp) 352 { 353 hashwalk_data_t *hwp = wsp->walk_data; 354 355 mdb_free(hwp->hw_hash, sizeof (uintptr_t) * hwp->hw_hashlen); 356 mdb_free(hwp->hw_data, hwp->hw_size); 357 mdb_free(hwp, sizeof (hashwalk_data_t)); 358 } 359 360 static int 361 ustat_walk_init(mdb_walk_state_t *wsp) 362 { 363 fmd_ustat_t us; 364 365 if (mdb_vread(&us, sizeof (us), wsp->walk_addr) != sizeof (us)) { 366 mdb_warn("failed to read fmd_ustat_t at %p", wsp->walk_addr); 367 return (WALK_ERR); 368 } 369 370 return (hash_walk_init(wsp, 371 (uintptr_t)us.us_hash, us.us_hashlen, NULL, 0, 0)); 372 } 373 374 static int 375 ustat_walk_step(mdb_walk_state_t *wsp) 376 { 377 hashwalk_data_t *hwp = wsp->walk_data; 378 fmd_ustat_elem_t ue; 379 fmd_stat_t s; 380 381 while (wsp->walk_addr == NULL) { 382 if (++hwp->hw_hashidx < hwp->hw_hashlen) 383 wsp->walk_addr = hwp->hw_hash[hwp->hw_hashidx]; 384 else 385 return (WALK_DONE); 386 } 387 388 if (mdb_vread(&ue, sizeof (ue), wsp->walk_addr) != sizeof (ue) || 389 mdb_vread(&s, sizeof (s), (uintptr_t)ue.use_stat) != sizeof (s)) { 390 mdb_warn("failed to read stat element at %p", wsp->walk_addr); 391 return (WALK_ERR); 392 } 393 394 wsp->walk_addr = (uintptr_t)ue.use_next; 395 396 return (wsp->walk_callback( 397 (uintptr_t)ue.use_stat, &s, wsp->walk_cbdata)); 398 } 399 400 static int 401 fmd_ustat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 402 { 403 if (!(flags & DCMD_ADDRSPEC)) 404 return (DCMD_USAGE); 405 406 if (mdb_pwalk_dcmd("fmd_ustat", "fmd_stat", argc, argv, addr) != 0) { 407 mdb_warn("failed to walk fmd_ustat at %p", addr); 408 return (DCMD_ERR); 409 } 410 411 return (DCMD_OK); 412 } 413 414 /*ARGSUSED*/ 415 static int 416 fmd_stat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 417 { 418 char buf[512]; 419 fmd_stat_t s; 420 421 if (!(flags & DCMD_ADDRSPEC) || argc != 0) 422 return (DCMD_USAGE); 423 424 if (DCMD_HDRSPEC(flags)) 425 mdb_printf("%<u>%-11s %-4s %-32s %s%</u>\n", 426 "ADDR", "TYPE", "NAME", "VALUE"); 427 428 if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) { 429 mdb_warn("failed to read statistic at %p", addr); 430 return (DCMD_ERR); 431 } 432 433 switch (s.fmds_type) { 434 case FMD_TYPE_BOOL: 435 mdb_printf("%-11p %-4s %-32s %s\n", addr, "bool", 436 s.fmds_name, s.fmds_value.bool ? "true" : "false"); 437 break; 438 case FMD_TYPE_INT32: 439 mdb_printf("%-11p %-4s %-32s %d\n", addr, "i32", 440 s.fmds_name, s.fmds_value.i32); 441 break; 442 case FMD_TYPE_UINT32: 443 mdb_printf("%-11p %-4s %-32s %u\n", addr, "ui32", 444 s.fmds_name, s.fmds_value.i32); 445 break; 446 case FMD_TYPE_INT64: 447 mdb_printf("%-11p %-4s %-32s %lld\n", addr, "i64", 448 s.fmds_name, s.fmds_value.i64); 449 break; 450 case FMD_TYPE_UINT64: 451 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "ui64", 452 s.fmds_name, s.fmds_value.ui64); 453 break; 454 case FMD_TYPE_STRING: 455 if (mdb_readstr(buf, sizeof (buf), 456 (uintptr_t)s.fmds_value.str) < 0) { 457 (void) mdb_snprintf(buf, sizeof (buf), "<%p>", 458 s.fmds_value.str); 459 } 460 mdb_printf("%-11p %-4s %-32s %s\n", addr, "str", 461 s.fmds_name, buf); 462 break; 463 case FMD_TYPE_TIME: 464 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "time", 465 s.fmds_name, s.fmds_value.ui64); 466 break; 467 case FMD_TYPE_SIZE: 468 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "size", 469 s.fmds_name, s.fmds_value.ui64); 470 break; 471 default: 472 mdb_printf("%-11p %-4u %-32s ???\n", addr, 473 s.fmds_type, s.fmds_name); 474 break; 475 } 476 477 return (DCMD_OK); 478 } 479 480 /*ARGSUSED*/ 481 static int 482 fmd_event(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 483 { 484 char type[16], name[16]; 485 fmd_event_impl_t ev; 486 487 if (argc != 0) 488 return (DCMD_USAGE); 489 490 if (mdb_vread(&ev, sizeof (ev), addr) != sizeof (ev)) { 491 mdb_warn("failed to read fmd_event at %p", addr); 492 return (DCMD_ERR); 493 } 494 495 if (DCMD_HDRSPEC(flags)) { 496 mdb_printf("%<u>%-11s %-4s %-5s %-3s %-?s%</u>\n", 497 "ADDR", "TYPE", "STATE", "REF", "NVPAIR"); 498 } 499 500 switch (ev.ev_type) { 501 case FMD_EVT_PROTOCOL: 502 (void) strcpy(type, "PROT"); 503 break; 504 case FMD_EVT_GC: 505 (void) strcpy(type, "GC"); 506 break; 507 case FMD_EVT_CLOSE: 508 (void) strcpy(type, "CLSE"); 509 break; 510 case FMD_EVT_TIMEOUT: 511 (void) strcpy(type, "TIME"); 512 break; 513 case FMD_EVT_STATS: 514 (void) strcpy(type, "STAT"); 515 break; 516 case FMD_EVT_PUBLISH: 517 (void) strcpy(type, "PUBL"); 518 break; 519 default: 520 (void) mdb_snprintf(type, sizeof (type), "%u", ev.ev_type); 521 } 522 523 switch (ev.ev_state) { 524 case FMD_EVS_RECEIVED: 525 (void) strcpy(name, "RECVD"); 526 break; 527 case FMD_EVS_ACCEPTED: 528 (void) strcpy(name, "ACCPT"); 529 break; 530 case FMD_EVS_DISCARDED: 531 (void) strcpy(name, "DSCRD"); 532 break; 533 case FMD_EVS_DIAGNOSED: 534 (void) strcpy(name, "DIAGN"); 535 break; 536 default: 537 (void) mdb_snprintf(name, sizeof (name), "%u", ev.ev_state); 538 } 539 540 mdb_printf("%-11p %-4s %-5s %-3u %p\n", 541 addr, type, name, ev.ev_refs, ev.ev_nvl); 542 543 return (DCMD_OK); 544 } 545 546 static int 547 thread_walk_init(mdb_walk_state_t *wsp) 548 { 549 fmd_t F; 550 551 if (mdb_readvar(&F, "fmd") != sizeof (F)) { 552 mdb_warn("failed to read fmd meta-data"); 553 return (WALK_ERR); 554 } 555 556 wsp->walk_addr = (uintptr_t)F.d_thr_list.l_next; 557 return (WALK_NEXT); 558 } 559 560 static int 561 thread_walk_step(mdb_walk_state_t *wsp) 562 { 563 uintptr_t addr = wsp->walk_addr; 564 fmd_thread_t t; 565 566 if (addr == NULL) 567 return (WALK_DONE); 568 569 if (mdb_vread(&t, sizeof (t), addr) != sizeof (t)) { 570 mdb_warn("failed to read fmd_thread at %p", addr); 571 return (WALK_ERR); 572 } 573 574 wsp->walk_addr = (uintptr_t)t.thr_list.l_next; 575 return (wsp->walk_callback(addr, &t, wsp->walk_cbdata)); 576 } 577 578 static int 579 fmd_thread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 580 { 581 fmd_thread_t thr; 582 583 if (!(flags & DCMD_ADDRSPEC)) 584 return (mdb_walk_dcmd("fmd_thread", "fmd_thread", argc, argv)); 585 586 if (argc != 0) 587 return (DCMD_USAGE); 588 589 if (mdb_vread(&thr, sizeof (thr), addr) != sizeof (thr)) { 590 mdb_warn("failed to read fmd_thread at %p", addr); 591 return (DCMD_ERR); 592 } 593 594 if (DCMD_HDRSPEC(flags)) { 595 mdb_printf("%<u>%-11s %-11s %-8s %-16s%</u>\n", 596 "ADDR", "MOD", "TID", "FUNC"); 597 } 598 599 mdb_printf("%-11p %-11p %-8u %a\n", 600 addr, thr.thr_mod, thr.thr_tid, thr.thr_func); 601 602 return (DCMD_OK); 603 } 604 605 static int 606 mod_walk_init(mdb_walk_state_t *wsp) 607 { 608 fmd_t F; 609 610 if (mdb_readvar(&F, "fmd") != sizeof (F)) { 611 mdb_warn("failed to read fmd meta-data"); 612 return (WALK_ERR); 613 } 614 615 wsp->walk_addr = (uintptr_t)F.d_mod_list.l_next; 616 return (WALK_NEXT); 617 } 618 619 static int 620 mod_walk_step(mdb_walk_state_t *wsp) 621 { 622 uintptr_t addr = wsp->walk_addr; 623 fmd_module_t m; 624 625 if (addr == NULL) 626 return (WALK_DONE); 627 628 if (mdb_vread(&m, sizeof (m), addr) != sizeof (m)) { 629 mdb_warn("failed to read fmd_module at %p", addr); 630 return (WALK_ERR); 631 } 632 633 wsp->walk_addr = (uintptr_t)m.mod_list.l_next; 634 return (wsp->walk_callback(addr, &m, wsp->walk_cbdata)); 635 } 636 637 static int 638 fmd_module(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 639 { 640 fmd_module_t mod; 641 char name[256]; 642 643 if (!(flags & DCMD_ADDRSPEC)) 644 return (mdb_walk_dcmd("fmd_module", "fmd_module", argc, argv)); 645 646 if (argc != 0) 647 return (DCMD_USAGE); 648 649 if (mdb_vread(&mod, sizeof (mod), addr) != sizeof (mod)) { 650 mdb_warn("failed to read fmd_module at %p", addr); 651 return (DCMD_ERR); 652 } 653 654 if (DCMD_HDRSPEC(flags)) { 655 mdb_printf("%<u>%-11s %-16s %-11s %-4s %-?s %-16s%</u>\n", 656 "ADDR", "OPS", "DATA", "FLAG", "USTAT", "NAME"); 657 } 658 659 if (mdb_readstr(name, sizeof (name), (uintptr_t)mod.mod_name) <= 0) 660 (void) mdb_snprintf(name, sizeof (name), "<%p>", mod.mod_name); 661 662 mdb_printf("%-11p %-16a %-11p 0x%02x %-?p %s\n", addr, 663 mod.mod_ops, mod.mod_data, mod.mod_flags, mod.mod_ustat, name); 664 665 return (DCMD_OK); 666 } 667 668 static int 669 case_walk_init(mdb_walk_state_t *wsp) 670 { 671 fmd_module_t mod; 672 fmd_case_hash_t ch; 673 fmd_t F; 674 675 if (wsp->walk_addr != NULL) { 676 if (mdb_vread(&mod, sizeof (mod), wsp->walk_addr) == -1) { 677 mdb_warn("failed to read module at %p", wsp->walk_addr); 678 return (WALK_ERR); 679 } 680 681 wsp->walk_addr = (uintptr_t)mod.mod_cases.l_next; 682 return (WALK_NEXT); 683 } 684 685 if (mdb_readvar(&F, "fmd") != sizeof (F) || 686 mdb_vread(&ch, sizeof (ch), (uintptr_t)F.d_cases) != sizeof (ch)) { 687 mdb_warn("failed to read fmd meta-data"); 688 return (WALK_ERR); 689 } 690 691 return (hash_walk_init(wsp, (uintptr_t)ch.ch_hash, ch.ch_hashlen, 692 "fmd_case", sizeof (fmd_case_impl_t), 693 OFFSETOF(fmd_case_impl_t, ci_next))); 694 } 695 696 static int 697 case_walk_step(mdb_walk_state_t *wsp) 698 { 699 uintptr_t addr = wsp->walk_addr; 700 fmd_case_impl_t ci; 701 702 if (wsp->walk_data != NULL) 703 return (hash_walk_step(wsp)); 704 705 if (addr == NULL) 706 return (WALK_DONE); 707 708 if (mdb_vread(&ci, sizeof (ci), addr) != sizeof (ci)) { 709 mdb_warn("failed to read fmd_case at %p", addr); 710 return (WALK_ERR); 711 } 712 713 wsp->walk_addr = (uintptr_t)ci.ci_list.l_next; 714 return (wsp->walk_callback(addr, &ci, wsp->walk_cbdata)); 715 } 716 717 static void 718 case_walk_fini(mdb_walk_state_t *wsp) 719 { 720 if (wsp->walk_data != NULL) 721 hash_walk_fini(wsp); 722 } 723 724 static int 725 fmd_case(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 726 { 727 char uuid[48], name[16]; 728 fmd_case_impl_t ci; 729 730 if (!(flags & DCMD_ADDRSPEC)) { 731 if (mdb_walk_dcmd("fmd_case", "fmd_case", argc, argv) != 0) { 732 mdb_warn("failed to walk fmd_case hash"); 733 return (DCMD_ERR); 734 } 735 return (DCMD_OK); 736 } 737 738 if (mdb_vread(&ci, sizeof (ci), addr) != sizeof (ci)) { 739 mdb_warn("failed to read fmd_case at %p", addr); 740 return (DCMD_ERR); 741 } 742 743 if (DCMD_HDRSPEC(flags)) { 744 mdb_printf("%<u>%-11s %-5s %-3s %-?s %-36s%</u>\n", 745 "ADDR", "STATE", "REF", "DATA", "UUID"); 746 } 747 748 if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)ci.ci_uuid) <= 0) 749 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", ci.ci_uuid); 750 751 switch (ci.ci_state) { 752 case FMD_CASE_UNSOLVED: 753 (void) strcpy(name, "UNSLV"); 754 break; 755 case FMD_CASE_SOLVED: 756 (void) strcpy(name, "SOLVE"); 757 break; 758 case FMD_CASE_CLOSE_WAIT: 759 (void) strcpy(name, "CWAIT"); 760 break; 761 case FMD_CASE_CLOSED: 762 (void) strcpy(name, "CLOSE"); 763 break; 764 case FMD_CASE_REPAIRED: 765 (void) strcpy(name, "RPAIR"); 766 break; 767 default: 768 (void) mdb_snprintf(name, sizeof (name), "%u", ci.ci_state); 769 } 770 771 mdb_printf("%-11p %-5s %-3u %-?p %s\n", 772 addr, name, ci.ci_refs, ci.ci_data, uuid); 773 774 return (DCMD_OK); 775 } 776 777 static int 778 buf_walk_init(mdb_walk_state_t *wsp) 779 { 780 fmd_buf_hash_t bh; 781 782 if (mdb_vread(&bh, sizeof (bh), wsp->walk_addr) != sizeof (bh)) { 783 mdb_warn("failed to read fmd_buf_hash_t at %p", wsp->walk_addr); 784 return (WALK_ERR); 785 } 786 787 return (hash_walk_init(wsp, (uintptr_t)bh.bh_hash, bh.bh_hashlen, 788 "fmd_buf", sizeof (fmd_buf_t), OFFSETOF(fmd_buf_t, buf_next))); 789 } 790 791 /*ARGSUSED*/ 792 static int 793 fmd_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 794 { 795 char name[256]; 796 fmd_buf_t b; 797 798 if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 799 return (DCMD_USAGE); 800 801 if (mdb_vread(&b, sizeof (b), addr) != sizeof (b)) { 802 mdb_warn("failed to read fmd_buf at %p", addr); 803 return (DCMD_ERR); 804 } 805 806 if (DCMD_HDRSPEC(flags)) { 807 mdb_printf("%<u>%-11s %-32s %-5s %-?s %s%</u>\n", 808 "ADDR", "NAME", "FLAGS", "DATA", "SIZE"); 809 } 810 811 if (mdb_readstr(name, sizeof (name), (uintptr_t)b.buf_name) <= 0) 812 (void) mdb_snprintf(name, sizeof (name), "<%p>", b.buf_name); 813 814 mdb_printf("%-11p %-32s %-#5x %-?p %lu\n", 815 addr, name, b.buf_flags, b.buf_data, b.buf_size); 816 817 return (DCMD_OK); 818 } 819 820 static int 821 serd_walk_init(mdb_walk_state_t *wsp) 822 { 823 fmd_serd_hash_t sh; 824 825 if (mdb_vread(&sh, sizeof (sh), wsp->walk_addr) != sizeof (sh)) { 826 mdb_warn("failed to read fmd_serd_hash at %p", wsp->walk_addr); 827 return (WALK_ERR); 828 } 829 830 return (hash_walk_init(wsp, (uintptr_t)sh.sh_hash, sh.sh_hashlen, 831 "fmd_serd_eng", sizeof (fmd_serd_eng_t), 832 OFFSETOF(fmd_serd_eng_t, sg_next))); 833 } 834 835 /*ARGSUSED*/ 836 static int 837 fmd_serd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 838 { 839 char name[256]; 840 fmd_serd_eng_t sg; 841 842 if (argc != 0 || !(flags & DCMD_ADDRSPEC)) 843 return (DCMD_USAGE); 844 845 if (mdb_vread(&sg, sizeof (sg), addr) != sizeof (sg)) { 846 mdb_warn("failed to read fmd_serd_eng at %p", addr); 847 return (DCMD_ERR); 848 } 849 850 if (DCMD_HDRSPEC(flags)) { 851 mdb_printf("%<u>%-11s %-32s %-3s F >%-2s %-16s%</u>\n", 852 "ADDR", "NAME", "CNT", "N", "T"); 853 } 854 855 if (mdb_readstr(name, sizeof (name), (uintptr_t)sg.sg_name) <= 0) 856 (void) mdb_snprintf(name, sizeof (name), "<%p>", sg.sg_name); 857 858 mdb_printf("%-11p %-32s %-3u %c >%-2u %lluns\n", 859 addr, name, sg.sg_count, (sg.sg_flags & FMD_SERD_FIRED) ? 'F' : ' ', 860 sg.sg_n, (u_longlong_t)sg.sg_t); 861 862 return (DCMD_OK); 863 } 864 865 static int 866 asru_walk_init(mdb_walk_state_t *wsp) 867 { 868 fmd_asru_hash_t ah; 869 fmd_t F; 870 871 if (wsp->walk_addr == NULL && mdb_readvar(&F, "fmd") != sizeof (F)) { 872 mdb_warn("failed to read fmd meta-data"); 873 return (WALK_ERR); 874 } 875 876 if (wsp->walk_addr == NULL) 877 wsp->walk_addr = (uintptr_t)F.d_asrus; 878 879 if (mdb_vread(&ah, sizeof (ah), wsp->walk_addr) != sizeof (ah)) { 880 mdb_warn("failed to read asru_hash at %p", wsp->walk_addr); 881 return (WALK_ERR); 882 } 883 884 return (hash_walk_init(wsp, (uintptr_t)ah.ah_hash, ah.ah_hashlen, 885 "fmd_asru", sizeof (fmd_asru_t), OFFSETOF(fmd_asru_t, asru_next))); 886 } 887 888 static int 889 fmd_asru(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 890 { 891 char uuid[48], name[256]; 892 fmd_asru_t a; 893 894 if (!(flags & DCMD_ADDRSPEC)) { 895 if (mdb_walk_dcmd("fmd_asru", "fmd_asru", argc, argv) != 0) { 896 mdb_warn("failed to walk fmd_asru hash"); 897 return (DCMD_ERR); 898 } 899 return (DCMD_OK); 900 } 901 902 if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) { 903 mdb_warn("failed to read fmd_asru at %p", addr); 904 return (DCMD_ERR); 905 } 906 907 if (DCMD_HDRSPEC(flags)) 908 mdb_printf("%<u>%-8s %-36s %s%</u>\n", "ADDR", "UUID", "NAME"); 909 910 if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)a.asru_uuid) <= 0) 911 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", a.asru_uuid); 912 if (mdb_readstr(name, sizeof (name), (uintptr_t)a.asru_name) <= 0) 913 (void) mdb_snprintf(name, sizeof (name), "<%p>", a.asru_name); 914 915 mdb_printf("%-8p %-36s %s\n", addr, uuid, name); 916 return (DCMD_OK); 917 } 918 919 /*ARGSUSED*/ 920 static int 921 fcf_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 922 { 923 fcf_hdr_t h; 924 925 if (argc != 0) 926 return (DCMD_USAGE); 927 928 if (!(flags & DCMD_ADDRSPEC)) 929 addr = 0; /* assume base of file in file target */ 930 931 if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) { 932 mdb_warn("failed to read header at %p", addr); 933 return (DCMD_ERR); 934 } 935 936 mdb_printf("fcfh_ident.id_magic = 0x%x, %c, %c, %c\n", 937 h.fcfh_ident[FCF_ID_MAG0], h.fcfh_ident[FCF_ID_MAG1], 938 h.fcfh_ident[FCF_ID_MAG2], h.fcfh_ident[FCF_ID_MAG3]); 939 940 switch (h.fcfh_ident[FCF_ID_MODEL]) { 941 case FCF_MODEL_ILP32: 942 mdb_printf("fcfh_ident.id_model = ILP32\n"); 943 break; 944 case FCF_MODEL_LP64: 945 mdb_printf("fcfh_ident.id_model = LP64\n"); 946 break; 947 default: 948 mdb_printf("fcfh_ident.id_model = 0x%x\n", 949 h.fcfh_ident[FCF_ID_MODEL]); 950 } 951 952 switch (h.fcfh_ident[FCF_ID_ENCODING]) { 953 case FCF_ENCODE_LSB: 954 mdb_printf("fcfh_ident.id_encoding = LSB\n"); 955 break; 956 case FCF_ENCODE_MSB: 957 mdb_printf("fcfh_ident.id_encoding = MSB\n"); 958 break; 959 default: 960 mdb_printf("fcfh_ident.id_encoding = 0x%x\n", 961 h.fcfh_ident[FCF_ID_ENCODING]); 962 } 963 964 mdb_printf("fcfh_ident.id_version = %u\n", 965 h.fcfh_ident[FCF_ID_VERSION]); 966 967 mdb_printf("fcfh_flags = 0x%x\n", h.fcfh_flags); 968 mdb_printf("fcfh_hdrsize = %u\n", h.fcfh_hdrsize); 969 mdb_printf("fcfh_secsize = %u\n", h.fcfh_secsize); 970 mdb_printf("fcfh_secnum = %u\n", h.fcfh_secnum); 971 mdb_printf("fcfh_secoff = %llu\n", h.fcfh_secoff); 972 mdb_printf("fcfh_filesz = %llu\n", h.fcfh_filesz); 973 mdb_printf("fcfh_cgen = %llu\n", h.fcfh_cgen); 974 975 return (DCMD_OK); 976 } 977 978 /*ARGSUSED*/ 979 static int 980 fcf_sec_one(uintptr_t addr, void *ignored, uint_t *secp) 981 { 982 static int fcf_sec(uintptr_t, uint_t, int, const mdb_arg_t *); 983 984 mdb_printf("%3d ", (*secp)++); 985 (void) fcf_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL); 986 return (WALK_NEXT); 987 } 988 989 /*ARGSUSED*/ 990 static int 991 fcf_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 992 { 993 static const char *const types[] = { 994 "none", /* FCF_SECT_NONE */ 995 "strtab", /* FCF_SECT_STRTAB */ 996 "module", /* FCF_SECT_MODULE */ 997 "case", /* FCF_SECT_CASE */ 998 "bufs", /* FCF_SECT_BUFS */ 999 "buffer", /* FCF_SECT_BUFFER */ 1000 "serd", /* FCF_SECT_SERD */ 1001 "events", /* FCF_SECT_EVENTS */ 1002 "nvlists", /* FCF_SECT_NVLISTS */ 1003 }; 1004 1005 uint_t sec = 0; 1006 fcf_sec_t s; 1007 1008 if (!(flags & DCMD_ADDRSPEC)) 1009 mdb_printf("%<u>%-3s ", "NDX"); 1010 1011 if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) { 1012 mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n", 1013 "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFF", "SIZE"); 1014 } 1015 1016 if (!(flags & DCMD_ADDRSPEC)) { 1017 if (mdb_walk("fcf_sec", (mdb_walk_cb_t)fcf_sec_one, &sec) < 0) { 1018 mdb_warn("failed to walk fcf_sec"); 1019 return (DCMD_ERR); 1020 } 1021 return (DCMD_OK); 1022 } 1023 1024 if (argc != 0) 1025 return (DCMD_USAGE); 1026 1027 if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) { 1028 mdb_warn("failed to read section header at %p", addr); 1029 return (DCMD_ERR); 1030 } 1031 1032 mdb_printf("%?p ", addr); 1033 1034 if (s.fcfs_type < sizeof (types) / sizeof (types[0])) 1035 mdb_printf("%-10s ", types[s.fcfs_type]); 1036 else 1037 mdb_printf("%-10u ", s.fcfs_type); 1038 1039 mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.fcfs_align, 1040 s.fcfs_flags, s.fcfs_entsize, s.fcfs_offset, s.fcfs_size); 1041 1042 return (DCMD_OK); 1043 } 1044 1045 static int 1046 fcf_sec_walk_init(mdb_walk_state_t *wsp) 1047 { 1048 fcf_hdr_t h, *hp; 1049 size_t size; 1050 1051 if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) { 1052 mdb_warn("failed to read FCF header at %p", wsp->walk_addr); 1053 return (WALK_ERR); 1054 } 1055 1056 size = sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * h.fcfh_secnum; 1057 hp = mdb_alloc(size, UM_SLEEP); 1058 1059 if (mdb_vread(hp, size, wsp->walk_addr) != size) { 1060 mdb_warn("failed to read FCF sections at %p", wsp->walk_addr); 1061 mdb_free(hp, size); 1062 return (WALK_ERR); 1063 } 1064 1065 wsp->walk_data = hp; 1066 wsp->walk_arg = 0; 1067 1068 return (WALK_NEXT); 1069 } 1070 1071 static int 1072 fcf_sec_walk_step(mdb_walk_state_t *wsp) 1073 { 1074 uint_t i = (uint_t)wsp->walk_arg; 1075 size_t off = sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * i; 1076 fcf_hdr_t *hp = wsp->walk_data; 1077 fcf_sec_t *sp = (fcf_sec_t *)((uintptr_t)hp + off); 1078 1079 if (i >= hp->fcfh_secnum) 1080 return (WALK_DONE); 1081 1082 wsp->walk_arg = (void *)(i + 1); 1083 return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata)); 1084 } 1085 1086 static void 1087 fcf_sec_walk_fini(mdb_walk_state_t *wsp) 1088 { 1089 fcf_hdr_t *hp = wsp->walk_data; 1090 mdb_free(hp, sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * hp->fcfh_secnum); 1091 } 1092 1093 /*ARGSUSED*/ 1094 static int 1095 fcf_case(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1096 { 1097 fcf_case_t fcfc; 1098 1099 if (argc != 0) 1100 return (DCMD_USAGE); 1101 1102 if (mdb_vread(&fcfc, sizeof (fcfc), addr) != sizeof (fcfc)) { 1103 mdb_warn("failed to read case at %p", addr); 1104 return (DCMD_ERR); 1105 } 1106 1107 mdb_printf("fcfc_uuid = 0x%x\n", fcfc.fcfc_uuid); 1108 mdb_printf("fcfc_state = %u\n", fcfc.fcfc_state); 1109 mdb_printf("fcfc_bufs = %u\n", fcfc.fcfc_bufs); 1110 mdb_printf("fcfc_events = %u\n", fcfc.fcfc_events); 1111 mdb_printf("fcfc_suspects = %u\n", fcfc.fcfc_suspects); 1112 1113 return (DCMD_OK); 1114 } 1115 1116 /*ARGSUSED*/ 1117 static int 1118 fcf_event(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1119 { 1120 fcf_event_t fcfe; 1121 1122 if (argc != 0) 1123 return (DCMD_USAGE); 1124 1125 if (mdb_vread(&fcfe, sizeof (fcfe), addr) != sizeof (fcfe)) { 1126 mdb_warn("failed to read event at %p", addr); 1127 return (DCMD_ERR); 1128 } 1129 1130 mdb_printf("fcfe_todsec = %llu (%Y)\n", 1131 fcfe.fcfe_todsec, (time_t)fcfe.fcfe_todsec); 1132 mdb_printf("fcfe_todnsec = %llu\n", fcfe.fcfe_todnsec); 1133 mdb_printf("fcfe_major = %u\n", fcfe.fcfe_major); 1134 mdb_printf("fcfe_minor = %u\n", fcfe.fcfe_minor); 1135 mdb_printf("fcfe_inode = %llu\n", fcfe.fcfe_inode); 1136 mdb_printf("fcfe_offset = %llu\n", fcfe.fcfe_offset); 1137 1138 return (DCMD_OK); 1139 } 1140 1141 /*ARGSUSED*/ 1142 static int 1143 fcf_serd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1144 { 1145 fcf_serd_t fcfd; 1146 1147 if (argc != 0) 1148 return (DCMD_USAGE); 1149 1150 if (mdb_vread(&fcfd, sizeof (fcfd), addr) != sizeof (fcfd)) { 1151 mdb_warn("failed to read serd at %p", addr); 1152 return (DCMD_ERR); 1153 } 1154 1155 mdb_printf("fcfd_name = 0x%x\n", fcfd.fcfd_name); 1156 mdb_printf("fcfd_events = %u\n", fcfd.fcfd_events); 1157 mdb_printf("fcfd_n = >%u\n", fcfd.fcfd_n); 1158 mdb_printf("fcfd_t = %lluns\n", fcfd.fcfd_t); 1159 1160 return (DCMD_OK); 1161 } 1162 1163 static int 1164 tmq_walk_init(mdb_walk_state_t *wsp) 1165 { 1166 fmd_timerq_t tmq; 1167 fmd_t F; 1168 1169 if (wsp->walk_addr == NULL && mdb_readvar(&F, "fmd") != sizeof (F)) { 1170 mdb_warn("failed to read fmd meta-data"); 1171 return (WALK_ERR); 1172 } 1173 1174 if (wsp->walk_addr == NULL) 1175 wsp->walk_addr = (uintptr_t)F.d_timers; 1176 1177 if (mdb_vread(&tmq, sizeof (tmq), wsp->walk_addr) != sizeof (tmq)) { 1178 mdb_warn("failed to read timerq at %p", wsp->walk_addr); 1179 return (WALK_ERR); 1180 } 1181 1182 wsp->walk_addr = (uintptr_t)tmq.tmq_list.l_next; 1183 return (WALK_NEXT); 1184 } 1185 1186 static int 1187 tmq_walk_step(mdb_walk_state_t *wsp) 1188 { 1189 uintptr_t addr = wsp->walk_addr; 1190 fmd_timer_t tmr; 1191 1192 if (addr == NULL) 1193 return (WALK_DONE); 1194 1195 if (mdb_vread(&tmr, sizeof (tmr), addr) != sizeof (tmr)) { 1196 mdb_warn("failed to read fmd_timer at %p", addr); 1197 return (WALK_ERR); 1198 } 1199 1200 wsp->walk_addr = (uintptr_t)tmr.tmr_list.l_next; 1201 return (wsp->walk_callback(addr, &tmr, wsp->walk_cbdata)); 1202 } 1203 1204 static int 1205 fmd_timer(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1206 { 1207 char name[32], func[MDB_SYM_NAMLEN]; 1208 fmd_timer_t t; 1209 1210 if (!(flags & DCMD_ADDRSPEC)) { 1211 if (mdb_walk_dcmd("fmd_timerq", "fmd_timer", argc, argv) != 0) { 1212 mdb_warn("failed to walk fmd_timerq"); 1213 return (DCMD_ERR); 1214 } 1215 return (DCMD_OK); 1216 } 1217 1218 if (mdb_vread(&t, sizeof (t), addr) != sizeof (t)) { 1219 mdb_warn("failed to read fmd_timer at %p", addr); 1220 return (DCMD_ERR); 1221 } 1222 1223 if (DCMD_HDRSPEC(flags)) { 1224 mdb_printf("%<u>%-8s %-20s %-4s %-18s %-8s %s%</u>\n", 1225 "ADDR", "MODULE", "ID", "HRTIME", "ARG", "FUNC"); 1226 } 1227 1228 if (mdb_readstr(name, sizeof (name), (uintptr_t) 1229 t.tmr_ids + OFFSETOF(fmd_idspace_t, ids_name)) <= 0) 1230 (void) mdb_snprintf(name, sizeof (name), "<%p>", t.tmr_ids); 1231 1232 if (mdb_lookup_by_addr((uintptr_t)t.tmr_func, MDB_SYM_FUZZY, 1233 func, sizeof (func), NULL) != 0) 1234 (void) mdb_snprintf(func, sizeof (func), "<%p>", t.tmr_func); 1235 1236 mdb_printf("%-8p %-20s %4d 0x%-16llx %-8p %s\n", 1237 addr, name, t.tmr_id, t.tmr_hrt, t.tmr_arg, func); 1238 return (DCMD_OK); 1239 } 1240 1241 static int 1242 xprt_walk_init(mdb_walk_state_t *wsp) 1243 { 1244 fmd_module_t m; 1245 1246 if (wsp->walk_addr == NULL) { 1247 mdb_warn("transport walker requires fmd_module_t address\n"); 1248 return (WALK_ERR); 1249 } 1250 1251 if (mdb_vread(&m, sizeof (m), wsp->walk_addr) != sizeof (m)) { 1252 mdb_warn("failed to read module at %p", wsp->walk_addr); 1253 return (WALK_ERR); 1254 } 1255 1256 wsp->walk_addr = (uintptr_t)m.mod_transports.l_next; 1257 return (WALK_NEXT); 1258 } 1259 1260 static int 1261 xprt_walk_step(mdb_walk_state_t *wsp) 1262 { 1263 uintptr_t addr = wsp->walk_addr; 1264 fmd_xprt_impl_t xi; 1265 1266 if (addr == NULL) 1267 return (WALK_DONE); 1268 1269 if (mdb_vread(&xi, sizeof (xi), addr) != sizeof (xi)) { 1270 mdb_warn("failed to read fmd_xprt at %p", addr); 1271 return (WALK_ERR); 1272 } 1273 1274 wsp->walk_addr = (uintptr_t)xi.xi_list.l_next; 1275 return (wsp->walk_callback(addr, &xi, wsp->walk_cbdata)); 1276 } 1277 1278 static int 1279 xpc_walk_init(mdb_walk_state_t *wsp) 1280 { 1281 fmd_xprt_class_hash_t xch; 1282 1283 if (mdb_vread(&xch, sizeof (xch), wsp->walk_addr) != sizeof (xch)) { 1284 mdb_warn("failed to read fmd_xprt_class_hash at %p", 1285 wsp->walk_addr); 1286 return (WALK_ERR); 1287 } 1288 1289 return (hash_walk_init(wsp, (uintptr_t)xch.xch_hash, xch.xch_hashlen, 1290 "fmd_xprt_class", sizeof (fmd_xprt_class_t), 1291 OFFSETOF(fmd_xprt_class_t, xc_next))); 1292 } 1293 1294 /*ARGSUSED*/ 1295 static int 1296 fmd_xprt_class(uintptr_t addr, const void *data, void *arg) 1297 { 1298 const fmd_xprt_class_t *xcp = data; 1299 char name[1024]; 1300 1301 if (mdb_readstr(name, sizeof (name), (uintptr_t)xcp->xc_class) <= 0) 1302 (void) mdb_snprintf(name, sizeof (name), "<%p>", xcp->xc_class); 1303 1304 mdb_printf("%-8p %-4u %s\n", addr, xcp->xc_refs, name); 1305 return (WALK_NEXT); 1306 } 1307 1308 static int 1309 fmd_xprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1310 { 1311 uint_t opt_s = FALSE, opt_l = FALSE, opt_r = FALSE, opt_u = FALSE; 1312 fmd_xprt_impl_t xi; 1313 1314 if (mdb_getopts(argc, argv, 1315 'l', MDB_OPT_SETBITS, TRUE, &opt_l, 1316 'r', MDB_OPT_SETBITS, TRUE, &opt_r, 1317 's', MDB_OPT_SETBITS, TRUE, &opt_s, 1318 'u', MDB_OPT_SETBITS, TRUE, &opt_u, NULL) != argc) 1319 return (DCMD_USAGE); 1320 1321 if (!(flags & DCMD_ADDRSPEC)) { 1322 if (mdb_walk_dcmd("fmd_xprt", "fmd_xprt", argc, argv) != 0) { 1323 mdb_warn("failed to walk fmd_xprt"); 1324 return (DCMD_ERR); 1325 } 1326 return (DCMD_OK); 1327 } 1328 1329 if (mdb_vread(&xi, sizeof (xi), addr) != sizeof (xi)) { 1330 mdb_warn("failed to read fmd_xprt at %p", addr); 1331 return (DCMD_ERR); 1332 } 1333 1334 if (DCMD_HDRSPEC(flags)) { 1335 mdb_printf("%<u>%-8s %-4s %-4s %-5s %s%</u>\n", 1336 "ADDR", "ID", "VERS", "FLAGS", "STATE"); 1337 } 1338 1339 mdb_printf("%-8p %-4d %-4u %-5x %a\n", 1340 addr, xi.xi_id, xi.xi_version, xi.xi_flags, xi.xi_state); 1341 1342 if (opt_l | opt_s) { 1343 (void) mdb_inc_indent(4); 1344 mdb_printf("Local subscriptions requested by peer:\n"); 1345 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); 1346 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, 1347 addr + OFFSETOF(fmd_xprt_impl_t, xi_lsub)); 1348 (void) mdb_dec_indent(4); 1349 } 1350 1351 if (opt_r | opt_s) { 1352 (void) mdb_inc_indent(4); 1353 mdb_printf("Remote subscriptions requested of peer:\n"); 1354 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); 1355 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, 1356 addr + OFFSETOF(fmd_xprt_impl_t, xi_rsub)); 1357 (void) mdb_dec_indent(4); 1358 } 1359 1360 if (opt_u | opt_s) { 1361 (void) mdb_inc_indent(4); 1362 mdb_printf("Pending unsubscription acknowledgements:\n"); 1363 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); 1364 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, 1365 addr + OFFSETOF(fmd_xprt_impl_t, xi_usub)); 1366 (void) mdb_dec_indent(4); 1367 } 1368 1369 return (DCMD_OK); 1370 } 1371 1372 static const mdb_dcmd_t dcmds[] = { 1373 { "fcf_case", "?", "print a FCF case", fcf_case }, 1374 { "fcf_event", "?", "print a FCF event", fcf_event }, 1375 { "fcf_hdr", "?", "print a FCF header", fcf_hdr }, 1376 { "fcf_sec", ":", "print a FCF section header", fcf_sec }, 1377 { "fcf_serd", "?", "print a FCF serd engine", fcf_serd }, 1378 { "fmd_trace", "?[-cs]", "display thread trace buffer(s)", fmd_trace }, 1379 { "fmd_ustat", ":", "display statistics collection", fmd_ustat }, 1380 { "fmd_stat", ":", "display statistic structure", fmd_stat }, 1381 { "fmd_event", NULL, "display event structure", fmd_event }, 1382 { "fmd_thread", "?", "display thread or list of threads", fmd_thread }, 1383 { "fmd_module", "?", "display module or list of modules", fmd_module }, 1384 { "fmd_case", ":", "display case file structure", fmd_case }, 1385 { "fmd_buf", ":", "display buffer structure", fmd_buf }, 1386 { "fmd_serd", ":", "display serd engine structure", fmd_serd }, 1387 { "fmd_asru", "?", "display asru resource structure", fmd_asru }, 1388 { "fmd_timer", "?", "display pending timer(s)", fmd_timer }, 1389 { "fmd_xprt", "?[-lrsu]", "display event transport(s)", fmd_xprt }, 1390 { NULL } 1391 }; 1392 1393 static const mdb_walker_t walkers[] = { 1394 { "fcf_sec", "walk FCF section header table given header address", 1395 fcf_sec_walk_init, fcf_sec_walk_step, fcf_sec_walk_fini }, 1396 { "fmd_trace", "walk per-thread trace buffers", 1397 trwalk_init, trwalk_step, trwalk_fini }, 1398 { "fmd_ustat", "walk per-collection statistics", 1399 ustat_walk_init, ustat_walk_step, hash_walk_fini }, 1400 { "fmd_thread", "walk list of all fmd_thread_t's", 1401 thread_walk_init, thread_walk_step, NULL }, 1402 { "fmd_module", "walk list of all fmd_module_t's", 1403 mod_walk_init, mod_walk_step, NULL }, 1404 { "fmd_case", "walk per-module case objects", 1405 case_walk_init, case_walk_step, case_walk_fini }, 1406 { "fmd_buf", "walk per-buf_hash buffers", 1407 buf_walk_init, hash_walk_step, hash_walk_fini }, 1408 { "fmd_serd", "walk per-serd_hash engines", 1409 serd_walk_init, hash_walk_step, hash_walk_fini }, 1410 { "fmd_asru", "walk asru resource hash", 1411 asru_walk_init, hash_walk_step, hash_walk_fini }, 1412 { "fmd_timerq", "walk timer queue", 1413 tmq_walk_init, tmq_walk_step, NULL }, 1414 { "fmd_xprt", "walk per-module list of transports", 1415 xprt_walk_init, xprt_walk_step, NULL }, 1416 { "fmd_xprt_class", "walk hash table of subscription classes", 1417 xpc_walk_init, hash_walk_step, hash_walk_fini }, 1418 { NULL, NULL, NULL, NULL, NULL } 1419 }; 1420 1421 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 1422 1423 const mdb_modinfo_t * 1424 _mdb_init(void) 1425 { 1426 return (&modinfo); 1427 } 1428