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