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