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