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 <lut.h> 32 #include <itree.h> 33 #include "ipath_impl.h" 34 #include "lut_impl.h" 35 #include "config_impl.h" 36 #include "stats_impl.h" 37 38 #define LUT_SIZE_INIT 300 39 #define LUT_SIZE_INCR 100 40 41 struct lut_cp { 42 uintptr_t lutcp_addr; 43 struct lut lutcp_lut; 44 }; 45 46 #define LCPSZ sizeof (struct lut_cp) 47 48 struct lut_dump_desc { 49 struct lut_cp *ld_array; 50 int ld_arraysz; 51 int ld_nents; 52 }; 53 54 static void 55 lut_dump_array_alloc(struct lut_dump_desc *lddp) 56 { 57 struct lut_cp *new; 58 59 if (lddp->ld_array == NULL) { 60 lddp->ld_arraysz = LUT_SIZE_INIT; 61 lddp->ld_array = mdb_zalloc(LUT_SIZE_INIT * LCPSZ, UM_SLEEP); 62 return; 63 } 64 65 new = mdb_zalloc((lddp->ld_arraysz + LUT_SIZE_INCR) * LCPSZ, UM_SLEEP); 66 bcopy(lddp->ld_array, new, lddp->ld_arraysz * LCPSZ); 67 mdb_free(lddp->ld_array, lddp->ld_arraysz * LCPSZ); 68 lddp->ld_array = new; 69 lddp->ld_arraysz += LUT_SIZE_INCR; 70 } 71 72 static void 73 lut_dump_array_free(struct lut_dump_desc *lddp) 74 { 75 if (lddp->ld_array != NULL) { 76 mdb_free(lddp->ld_array, lddp->ld_arraysz * LCPSZ); 77 lddp->ld_array = NULL; 78 } 79 } 80 81 static void 82 lut_collect_addent(uintptr_t addr, struct lut *ent, struct lut_dump_desc *lddp) 83 { 84 struct lut_cp *lcp; 85 86 if (lddp->ld_nents == lddp->ld_arraysz) 87 lut_dump_array_alloc(lddp); 88 89 lcp = &lddp->ld_array[lddp->ld_nents++]; 90 91 lcp->lutcp_addr = addr; 92 bcopy(ent, &lcp->lutcp_lut, sizeof (struct lut)); 93 } 94 95 static int 96 eft_lut_walk(uintptr_t root, struct lut_dump_desc *lddp) 97 { 98 struct lut lutent; 99 100 if (root) { 101 if (mdb_vread(&lutent, sizeof (struct lut), root) != 102 sizeof (struct lut)) { 103 mdb_warn("failed to read struct lut at %p", root); 104 return (WALK_ERR); 105 } 106 107 if (eft_lut_walk((uintptr_t)lutent.lut_left, lddp) != WALK_NEXT) 108 return (WALK_ERR); 109 110 lut_collect_addent(root, &lutent, lddp); 111 112 if (eft_lut_walk((uintptr_t)lutent.lut_right, lddp) != 113 WALK_NEXT) 114 return (WALK_ERR); 115 } 116 return (WALK_NEXT); 117 } 118 119 static int 120 lut_collect(uintptr_t addr, struct lut_dump_desc *lddp) 121 { 122 lut_dump_array_alloc(lddp); 123 124 if (eft_lut_walk(addr, lddp) != WALK_NEXT) { 125 lut_dump_array_free(lddp); 126 return (WALK_ERR); 127 } else { 128 return (WALK_NEXT); /* caller must free dump array */ 129 } 130 } 131 132 static int 133 lut_walk_init(mdb_walk_state_t *wsp) 134 { 135 if (wsp->walk_addr == NULL) { 136 mdb_warn("lut walker requires a lut table address\n"); 137 return (WALK_ERR); 138 } 139 140 wsp->walk_data = mdb_zalloc(sizeof (struct lut_dump_desc), UM_SLEEP); 141 wsp->walk_arg = 0; 142 143 if (lut_collect(wsp->walk_addr, wsp->walk_data) == WALK_NEXT) { 144 return (WALK_NEXT); 145 } else { 146 mdb_warn("failed to suck in full lut\n"); 147 mdb_free(wsp->walk_data, sizeof (struct lut_dump_desc)); 148 return (WALK_ERR); 149 } 150 } 151 152 static int 153 lut_walk_step(mdb_walk_state_t *wsp) 154 { 155 struct lut_dump_desc *lddp = wsp->walk_data; 156 int *ip = (int *)&wsp->walk_arg; 157 struct lut_cp *lcp = &lddp->ld_array[*ip]; 158 159 if (*ip == lddp->ld_nents) 160 return (WALK_DONE); 161 162 ++*ip; 163 164 return (wsp->walk_callback(lcp->lutcp_addr, &lcp->lutcp_lut, 165 wsp->walk_cbdata)); 166 } 167 168 static int 169 ipath_walk_init(mdb_walk_state_t *wsp) 170 { 171 struct ipath *ipath; 172 173 ipath = mdb_alloc(sizeof (struct ipath), UM_SLEEP); 174 175 if (mdb_vread((void *)ipath, sizeof (struct ipath), 176 wsp->walk_addr) != sizeof (struct ipath)) { 177 mdb_warn("failed to read struct ipath at %p", wsp->walk_addr); 178 return (WALK_ERR); 179 } 180 wsp->walk_data = (void *)ipath; 181 182 if (ipath->s == NULL) 183 return (WALK_DONE); 184 else 185 return (WALK_NEXT); 186 } 187 188 static void 189 ipath_walk_fini(mdb_walk_state_t *wsp) 190 { 191 mdb_free(wsp->walk_data, sizeof (struct ipath)); 192 } 193 194 static int 195 ipath_walk_step(mdb_walk_state_t *wsp) 196 { 197 int status; 198 struct ipath *ipath = (struct ipath *)wsp->walk_data; 199 struct ipath *ip = (struct ipath *)wsp->walk_addr; 200 201 if (ip == NULL || ipath->s == NULL) 202 return (WALK_DONE); 203 204 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 205 wsp->walk_cbdata); 206 207 wsp->walk_addr = (uintptr_t)(ip + 1); 208 209 if (mdb_vread(wsp->walk_data, sizeof (struct ipath), 210 wsp->walk_addr) != sizeof (struct ipath)) { 211 mdb_warn("failed to read struct ipath at %p", wsp->walk_addr); 212 return (WALK_ERR); 213 } 214 215 return (status); 216 } 217 218 static void 219 lut_walk_fini(mdb_walk_state_t *wsp) 220 { 221 struct lut_dump_desc *lddp = wsp->walk_data; 222 223 lut_dump_array_free(lddp); 224 mdb_free(lddp, sizeof (struct lut_dump_desc)); 225 } 226 227 /*ARGSUSED*/ 228 static int 229 ipath_node(uintptr_t addr, const void *data, void *arg) 230 { 231 struct ipath *ipath = (struct ipath *)data; 232 char buf[128]; 233 234 mdb_readstr(buf, (size_t)sizeof (buf), (uintptr_t)ipath->s); 235 buf[sizeof (buf) - 1] = 0; 236 mdb_printf("/%s=%d", buf, ipath->i); 237 return (DCMD_OK); 238 } 239 240 /*ARGSUSED*/ 241 static int 242 ipath(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 243 { 244 if (argc) 245 return (DCMD_USAGE); 246 if (!(flags & DCMD_ADDRSPEC)) 247 addr = mdb_get_dot(); 248 if (mdb_pwalk("eft_ipath", ipath_node, NULL, addr) != 0) 249 return (DCMD_ERR); 250 return (DCMD_OK); 251 } 252 253 /*ARGSUSED*/ 254 static int 255 eft_count(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 256 { 257 struct lut lut; 258 struct istat_entry istat_entry; 259 struct stats count; 260 GElf_Sym sym; 261 char buf[128]; 262 263 if (argc) 264 return (DCMD_USAGE); 265 if (!(flags & DCMD_ADDRSPEC)) { 266 if (mdb_lookup_by_obj(MDB_OBJ_EVERY, "Istats", &sym) == -1 || 267 sym.st_size != sizeof (addr)) 268 return (DCMD_ERR); 269 if (mdb_vread(&addr, sizeof (addr), 270 (uintptr_t)sym.st_value) != sizeof (addr)) 271 return (DCMD_ERR); 272 if (addr == NULL) 273 return (DCMD_OK); 274 if (mdb_pwalk_dcmd("lut", "eft_count", argc, argv, addr) != 0) 275 return (DCMD_ERR); 276 return (DCMD_OK); 277 } 278 279 if (mdb_vread(&lut, sizeof (struct lut), addr) != sizeof (struct lut)) { 280 mdb_warn("failed to read struct lut at %p", addr); 281 return (DCMD_ERR); 282 } 283 if (mdb_vread(&istat_entry, sizeof (struct istat_entry), 284 (uintptr_t)lut.lut_lhs) != sizeof (struct istat_entry)) { 285 mdb_warn("failed to read struct istat_entry at %p", addr); 286 return (DCMD_ERR); 287 } 288 if (mdb_vread(&count, sizeof (struct stats), 289 (uintptr_t)lut.lut_rhs) != sizeof (struct stats)) { 290 mdb_warn("failed to read struct stats at %p", addr); 291 return (DCMD_ERR); 292 } 293 294 mdb_readstr(buf, (size_t)sizeof (buf), (uintptr_t)istat_entry.ename); 295 buf[sizeof (buf) - 1] = 0; 296 mdb_printf("%s@", buf); 297 (void) ipath((uintptr_t)istat_entry.ipath, DCMD_ADDRSPEC, 0, NULL); 298 mdb_printf(" %d\n", count.fmd_stats.fmds_value.i32); 299 return (DCMD_OK); 300 } 301 302 /*ARGSUSED*/ 303 static int 304 eft_time(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 305 { 306 unsigned long long val; 307 unsigned long long ull; 308 int opt_p = 0; 309 310 if (!(flags & DCMD_ADDRSPEC)) 311 addr = mdb_get_dot(); 312 ull = addr; 313 if (argc) { 314 if (mdb_getopts(argc, argv, 315 'l', MDB_OPT_UINT64, &ull, 316 'p', MDB_OPT_SETBITS, TRUE, &opt_p, 317 MDB_OPT_UINT64) != argc) { 318 return (DCMD_USAGE); 319 } 320 } 321 if (opt_p) { 322 if (mdb_vread(&ull, sizeof (ull), addr) != sizeof (ull)) { 323 mdb_warn("failed to read timeval at %p", addr); 324 return (DCMD_ERR); 325 } 326 } 327 #define NOREMAINDER(den, num, val) (((val) = ((den) / (num))) * (num) == (den)) 328 if (ull == 0) 329 mdb_printf("0us"); 330 else if (ull >= TIMEVAL_EVENTUALLY) 331 mdb_printf("infinity"); 332 else if (NOREMAINDER(ull, 1000000000ULL*60*60*24*365, val)) 333 mdb_printf("%lluyear%s", val, (val == 1) ? "" : "s"); 334 else if (NOREMAINDER(ull, 1000000000ULL*60*60*24*30, val)) 335 mdb_printf("%llumonth%s", val, (val == 1) ? "" : "s"); 336 else if (NOREMAINDER(ull, 1000000000ULL*60*60*24*7, val)) 337 mdb_printf("%lluweek%s", val, (val == 1) ? "" : "s"); 338 else if (NOREMAINDER(ull, 1000000000ULL*60*60*24, val)) 339 mdb_printf("%lluday%s", val, (val == 1) ? "" : "s"); 340 else if (NOREMAINDER(ull, 1000000000ULL*60*60, val)) 341 mdb_printf("%lluhour%s", val, (val == 1) ? "" : "s"); 342 else if (NOREMAINDER(ull, 1000000000ULL*60, val)) 343 mdb_printf("%lluminute%s", val, (val == 1) ? "" : "s"); 344 else if (NOREMAINDER(ull, 1000000000ULL, val)) 345 mdb_printf("%llusecond%s", val, (val == 1) ? "" : "s"); 346 else if (NOREMAINDER(ull, 1000000ULL, val)) 347 mdb_printf("%llums", val); 348 else if (NOREMAINDER(ull, 1000ULL, val)) 349 mdb_printf("%lluus", val); 350 else 351 mdb_printf("%lluns", ull); 352 353 return (DCMD_OK); 354 } 355 356 /*ARGSUSED*/ 357 static int 358 eft_node(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 359 { 360 struct node node; 361 int opt_v = 0; 362 char buf[128]; 363 364 if (!(flags & DCMD_ADDRSPEC)) 365 addr = mdb_get_dot(); 366 if (argc) { 367 if (mdb_getopts(argc, argv, 368 'v', MDB_OPT_SETBITS, TRUE, &opt_v, 369 NULL) != argc) { 370 return (DCMD_USAGE); 371 } 372 } 373 if (addr == NULL) 374 return (DCMD_OK); 375 if (mdb_vread(&node, sizeof (node), addr) != sizeof (node)) { 376 mdb_warn("failed to read struct node at %p", addr); 377 return (DCMD_ERR); 378 } 379 if (opt_v) { 380 mdb_readstr(buf, (size_t)sizeof (buf), (uintptr_t)node.file); 381 buf[sizeof (buf) - 1] = 0; 382 mdb_printf("%s len %d\n", buf, node.line); 383 } 384 switch (node.t) { 385 case T_NOTHING: /* used to keep going on error cases */ 386 mdb_printf("nothing"); 387 break; 388 case T_NAME: /* identifiers, sometimes chained */ 389 mdb_readstr(buf, (size_t)sizeof (buf), 390 (uintptr_t)node.u.name.s); 391 buf[sizeof (buf) - 1] = 0; 392 mdb_printf("%s", buf); 393 if (node.u.name.cp) { 394 struct config cp; 395 if (mdb_vread(&cp, sizeof (cp), 396 (uintptr_t)node.u.name.cp) != sizeof (cp)) { 397 mdb_warn("failed to read struct config at %p", 398 node.u.name.cp); 399 return (DCMD_ERR); 400 } 401 mdb_printf("%d", cp.num); 402 } else if (node.u.name.it == IT_HORIZONTAL) { 403 if (node.u.name.child && !node.u.name.childgen) { 404 mdb_printf("<"); 405 (void) eft_node((uintptr_t)node.u.name.child, 406 DCMD_ADDRSPEC, 0, NULL); 407 mdb_printf(">"); 408 } else { 409 mdb_printf("<> "); 410 } 411 } else if (node.u.name.child) { 412 mdb_printf("["); 413 (void) eft_node((uintptr_t)node.u.name.child, 414 DCMD_ADDRSPEC, 0, NULL); 415 mdb_printf("]"); 416 } 417 if (node.u.name.next) { 418 if (node.u.name.it == IT_ENAME) 419 mdb_printf("."); 420 else 421 mdb_printf("/"); 422 (void) eft_node((uintptr_t)node.u.name.next, 423 DCMD_ADDRSPEC, 0, NULL); 424 } 425 break; 426 case T_GLOBID: /* globals (e.g. $a) */ 427 mdb_readstr(buf, (size_t)sizeof (buf), 428 (uintptr_t)node.u.globid.s); 429 buf[sizeof (buf) - 1] = 0; 430 mdb_printf("$%s", buf); 431 break; 432 case T_EVENT: /* class@path{expr} */ 433 (void) eft_node((uintptr_t)node.u.event.ename, DCMD_ADDRSPEC, 0, 434 NULL); 435 mdb_printf("@"); 436 (void) eft_node((uintptr_t)node.u.event.epname, DCMD_ADDRSPEC, 437 0, NULL); 438 if (node.u.event.eexprlist) { 439 mdb_printf(" { "); 440 (void) eft_node((uintptr_t)node.u.event.eexprlist, 441 DCMD_ADDRSPEC, 0, NULL); 442 mdb_printf(" }"); 443 } 444 break; 445 case T_ENGINE: /* upset threshold engine (e.g. SERD) */ 446 mdb_printf("engine "); 447 (void) eft_node((uintptr_t)node.u.event.ename, DCMD_ADDRSPEC, 0, 448 NULL); 449 break; 450 case T_ASRU: /* ASRU declaration */ 451 mdb_printf("asru "); 452 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 453 NULL); 454 if (node.u.stmt.nvpairs) { 455 mdb_printf(" "); 456 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 457 DCMD_ADDRSPEC, 0, NULL); 458 459 } 460 break; 461 case T_FRU: /* FRU declaration */ 462 mdb_printf("fru "); 463 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 464 NULL); 465 if (node.u.stmt.nvpairs) { 466 mdb_printf(" "); 467 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 468 DCMD_ADDRSPEC, 0, NULL); 469 470 } 471 break; 472 case T_TIMEVAL: /* num w/time suffix (ns internally) */ 473 { 474 mdb_arg_t mdb_arg[2]; 475 mdb_arg[0].a_type = MDB_TYPE_STRING; 476 mdb_arg[0].a_un.a_str = "-l"; 477 mdb_arg[1].a_type = MDB_TYPE_IMMEDIATE; 478 mdb_arg[1].a_un.a_val = node.u.ull; 479 (void) eft_time((uintptr_t)0, 0, 2, mdb_arg); 480 break; 481 } 482 case T_NUM: /* num (ull internally) */ 483 mdb_printf("%llu", node.u.ull); 484 break; 485 case T_QUOTE: /* quoted string */ 486 mdb_readstr(buf, (size_t)sizeof (buf), 487 (uintptr_t)node.u.quote.s); 488 buf[sizeof (buf) - 1] = 0; 489 mdb_printf("\"%s\"", buf); 490 break; 491 case T_FUNC: /* func(arglist) */ 492 mdb_readstr(buf, (size_t)sizeof (buf), 493 (uintptr_t)node.u.func.s); 494 buf[sizeof (buf) - 1] = 0; 495 mdb_printf("%s(", buf); 496 (void) eft_node((uintptr_t)node.u.func.arglist, DCMD_ADDRSPEC, 497 0, NULL); 498 mdb_printf(")"); 499 break; 500 case T_NVPAIR: /* name=value pair in decl */ 501 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 502 NULL); 503 mdb_printf(" = "); 504 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 505 NULL); 506 break; 507 case T_ASSIGN: /* assignment statement */ 508 mdb_printf("("); 509 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 510 NULL); 511 mdb_printf(" = "); 512 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 513 NULL); 514 mdb_printf(")"); 515 break; 516 case T_CONDIF: /* a and T_CONDELSE in (a ? b : c ) */ 517 mdb_printf("("); 518 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 519 NULL); 520 mdb_printf(" ? "); 521 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 522 NULL); 523 mdb_printf(")"); 524 break; 525 case T_CONDELSE: /* lists b and c in (a ? b : c ) */ 526 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 527 NULL); 528 mdb_printf(" : "); 529 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 530 NULL); 531 break; 532 case T_NOT: /* boolean ! operator */ 533 mdb_printf("!"); 534 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 535 NULL); 536 break; 537 case T_AND: /* boolean && operator */ 538 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 539 NULL); 540 mdb_printf(" && "); 541 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 542 NULL); 543 break; 544 case T_OR: /* boolean || operator */ 545 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 546 NULL); 547 mdb_printf(" || "); 548 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 549 NULL); 550 break; 551 case T_EQ: /* boolean == operator */ 552 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 553 NULL); 554 mdb_printf(" == "); 555 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 556 NULL); 557 break; 558 case T_NE: /* boolean != operator */ 559 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 560 NULL); 561 mdb_printf(" != "); 562 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 563 NULL); 564 break; 565 case T_SUB: /* integer - operator */ 566 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 567 NULL); 568 mdb_printf(" - "); 569 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 570 NULL); 571 break; 572 case T_ADD: /* integer + operator */ 573 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 574 NULL); 575 mdb_printf(" + "); 576 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 577 NULL); 578 break; 579 case T_MUL: /* integer * operator */ 580 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 581 NULL); 582 mdb_printf(" * "); 583 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 584 NULL); 585 break; 586 case T_DIV: /* integer / operator */ 587 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 588 NULL); 589 mdb_printf(" / "); 590 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 591 NULL); 592 break; 593 case T_MOD: /* integer % operator */ 594 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 595 NULL); 596 mdb_printf(" % "); 597 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 598 NULL); 599 break; 600 case T_LT: /* boolean < operator */ 601 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 602 NULL); 603 mdb_printf(" < "); 604 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 605 NULL); 606 break; 607 case T_LE: /* boolean <= operator */ 608 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 609 NULL); 610 mdb_printf(" <= "); 611 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 612 NULL); 613 break; 614 case T_GT: /* boolean > operator */ 615 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 616 NULL); 617 mdb_printf(" > "); 618 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 619 NULL); 620 break; 621 case T_GE: /* boolean >= operator */ 622 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 623 NULL); 624 mdb_printf(" >= "); 625 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 626 NULL); 627 break; 628 case T_BITAND: /* bitwise & operator */ 629 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 630 NULL); 631 mdb_printf(" & "); 632 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 633 NULL); 634 break; 635 case T_BITOR: /* bitwise | operator */ 636 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 637 NULL); 638 mdb_printf(" | "); 639 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 640 NULL); 641 break; 642 case T_BITXOR: /* bitwise ^ operator */ 643 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 644 NULL); 645 mdb_printf(" ^ "); 646 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 647 NULL); 648 break; 649 case T_BITNOT: /* bitwise ~ operator */ 650 mdb_printf(" ~"); 651 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 652 NULL); 653 break; 654 case T_LSHIFT: /* bitwise << operator */ 655 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 656 NULL); 657 mdb_printf(" << "); 658 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 659 NULL); 660 break; 661 case T_RSHIFT: /* bitwise >> operator */ 662 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 663 NULL); 664 mdb_printf(" >> "); 665 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 666 NULL); 667 break; 668 case T_ARROW: /* lhs (N)->(K) rhs */ 669 (void) eft_node((uintptr_t)node.u.arrow.lhs, DCMD_ADDRSPEC, 0, 670 NULL); 671 if (node.u.arrow.nnp) { 672 mdb_printf("("); 673 (void) eft_node((uintptr_t)node.u.arrow.nnp, 674 DCMD_ADDRSPEC, 0, NULL); 675 mdb_printf(")"); 676 } 677 mdb_printf("->"); 678 if (node.u.arrow.knp) { 679 mdb_printf("("); 680 (void) eft_node((uintptr_t)node.u.arrow.knp, 681 DCMD_ADDRSPEC, 0, NULL); 682 mdb_printf(")"); 683 } 684 (void) eft_node((uintptr_t)node.u.arrow.rhs, DCMD_ADDRSPEC, 0, 685 NULL); 686 break; 687 case T_LIST: /* comma-separated list */ 688 (void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0, 689 NULL); 690 mdb_printf(", "); 691 (void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0, 692 NULL); 693 break; 694 case T_FAULT: /* fault declaration */ 695 mdb_printf("fault."); 696 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 697 NULL); 698 if (node.u.stmt.nvpairs) { 699 mdb_printf(" "); 700 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 701 DCMD_ADDRSPEC, 0, NULL); 702 703 } 704 break; 705 case T_UPSET: /* upset declaration */ 706 mdb_printf("upset."); 707 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 708 NULL); 709 if (node.u.stmt.nvpairs) { 710 mdb_printf(" "); 711 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 712 DCMD_ADDRSPEC, 0, NULL); 713 714 } 715 break; 716 case T_DEFECT: /* defect declaration */ 717 mdb_printf("defect."); 718 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 719 NULL); 720 if (node.u.stmt.nvpairs) { 721 mdb_printf(" "); 722 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 723 DCMD_ADDRSPEC, 0, NULL); 724 725 } 726 break; 727 case T_ERROR: /* error declaration */ 728 mdb_printf("error."); 729 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 730 NULL); 731 if (node.u.stmt.nvpairs) { 732 mdb_printf(" "); 733 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 734 DCMD_ADDRSPEC, 0, NULL); 735 736 } 737 break; 738 case T_EREPORT: /* ereport declaration */ 739 mdb_printf("ereport."); 740 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 741 NULL); 742 if (node.u.stmt.nvpairs) { 743 mdb_printf(" "); 744 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 745 DCMD_ADDRSPEC, 0, NULL); 746 747 } 748 break; 749 case T_SERD: /* SERD engine declaration */ 750 mdb_printf("serd."); 751 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 752 NULL); 753 if (node.u.stmt.nvpairs) { 754 mdb_printf(" "); 755 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 756 DCMD_ADDRSPEC, 0, NULL); 757 758 } else if (node.u.stmt.lutp) { 759 if (mdb_pwalk_dcmd("lut", "eft_node", 0, NULL, 760 (uintptr_t)node.u.stmt.lutp) != 0) 761 return (DCMD_ERR); 762 } 763 break; 764 case T_STAT: /* STAT engine declaration */ 765 mdb_printf("stat."); 766 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 767 NULL); 768 if (node.u.stmt.nvpairs) { 769 mdb_printf(" "); 770 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 771 DCMD_ADDRSPEC, 0, NULL); 772 773 } else if (node.u.stmt.lutp) { 774 if (mdb_pwalk_dcmd("lut", "eft_node", 0, NULL, 775 (uintptr_t)node.u.stmt.lutp) != 0) 776 return (DCMD_ERR); 777 } 778 break; 779 case T_PROP: /* prop statement */ 780 mdb_printf("prop "); 781 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 782 NULL); 783 break; 784 case T_MASK: /* mask statement */ 785 mdb_printf("mask "); 786 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 787 NULL); 788 break; 789 case T_CONFIG: /* config statement */ 790 mdb_printf("config "); 791 (void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0, 792 NULL); 793 if (node.u.stmt.nvpairs) { 794 mdb_printf(" "); 795 (void) eft_node((uintptr_t)node.u.stmt.nvpairs, 796 DCMD_ADDRSPEC, 0, NULL); 797 798 } 799 break; 800 default: 801 mdb_printf("not a eversholt node\n"); 802 break; 803 } 804 return (DCMD_OK); 805 } 806 807 static const mdb_walker_t walkers[] = { 808 { "lut", "walk a lookup table", lut_walk_init, lut_walk_step, 809 lut_walk_fini, NULL }, 810 { "eft_ipath", "walk ipath", ipath_walk_init, ipath_walk_step, 811 ipath_walk_fini, NULL }, 812 { NULL, NULL, NULL, NULL, NULL, NULL } 813 }; 814 815 static const mdb_dcmd_t dcmds[] = { 816 { "eft_ipath", "?", "print an ipath", ipath }, 817 { "eft_count", "?", "print eversholt stats", eft_count }, 818 { "eft_node", "?[-v]", "print eversholt node", eft_node }, 819 { "eft_time", "?[-p][-l time]", "print eversholt timeval", eft_time }, 820 { NULL } 821 }; 822 823 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 824 825 const mdb_modinfo_t * 826 _mdb_init(void) 827 { 828 return (&modinfo); 829 } 830