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  * Copyright (c) 2013 by Delphix. All rights reserved.
  23  * Copyright (c) 2012 Joyent, Inc. All rights reserved.
  24  * Copyright (c) 2013 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  25  */
  26 /*
  27  * This file contains all of the interfaces for mdb's tab completion engine.
  28  * Currently some interfaces are private to mdb and its internal implementation,
  29  * those are in mdb_tab.h. Other pieces are public interfaces. Those are in
  30  * mdb_modapi.h.
  31  *
  32  * Memory allocations in tab completion context have to be done very carefully.
  33  * We need to think of ourselves as the same as any other command that is being
  34  * executed by the user, which means we must use UM_GC to handle being
  35  * interrupted.
  36  */
  37 
  38 #include <mdb/mdb_modapi.h>
  39 #include <mdb/mdb_ctf.h>
  40 #include <mdb/mdb_ctf_impl.h>
  41 #include <mdb/mdb_string.h>
  42 #include <mdb/mdb_module.h>
  43 #include <mdb/mdb_debug.h>
  44 #include <mdb/mdb_print.h>
  45 #include <mdb/mdb_nv.h>
  46 #include <mdb/mdb_tab.h>
  47 #include <mdb/mdb_target.h>
  48 #include <mdb/mdb.h>
  49 
  50 #include <ctype.h>
  51 
  52 /*
  53  * There may be another way to do this, but this works well enough.
  54  */
  55 #define COMMAND_SEPARATOR "::"
  56 
  57 /*
  58  * find_command_start --
  59  *
  60  *      Given a buffer find the start of the last command.
  61  */
  62 static char *
  63 tab_find_command_start(char *buf)
  64 {
  65         char *offset = strstr(buf, COMMAND_SEPARATOR);
  66 
  67         if (offset == NULL)
  68                 return (NULL);
  69 
  70         for (;;) {
  71                 char *next = strstr(offset + strlen(COMMAND_SEPARATOR),
  72                     COMMAND_SEPARATOR);
  73 
  74                 if (next == NULL) {
  75                         return (offset);
  76                 }
  77 
  78                 offset = next;
  79         }
  80 }
  81 
  82 /*
  83  * get_dcmd --
  84  *
  85  *      Given a buffer containing a command and its argument return
  86  *      the name of the command and the offset in the buffer where
  87  *      the command arguments start.
  88  *
  89  *      Note: This will modify the buffer.
  90  */
  91 char *
  92 tab_get_dcmd(char *buf, char **args, uint_t *flags)
  93 {
  94         char *start = buf + strlen(COMMAND_SEPARATOR);
  95         char *separator = start;
  96         const char *end = buf + strlen(buf);
  97         uint_t space = 0;
  98 
  99         while (separator < end && !isspace(*separator))
 100                 separator++;
 101 
 102         if (separator == end) {
 103                 *args = NULL;
 104         } else {
 105                 if (isspace(*separator))
 106                         space = 1;
 107 
 108                 *separator++ = '\0';
 109                 *args = separator;
 110         }
 111 
 112         if (space)
 113                 *flags |= DCMD_TAB_SPACE;
 114 
 115         return (start);
 116 }
 117 
 118 /*
 119  * count_args --
 120  *
 121  *      Given a buffer containing dmcd arguments return the total number
 122  *      of arguments.
 123  *
 124  *      While parsing arguments we need to keep track of whether or not the last
 125  *      arguments ends with a trailing space.
 126  */
 127 static int
 128 tab_count_args(const char *input, uint_t *flags)
 129 {
 130         const char *index;
 131         int argc = 0;
 132         uint_t space = *flags & DCMD_TAB_SPACE;
 133         index = input;
 134 
 135         while (*index != '\0') {
 136                 while (*index != '\0' && isspace(*index)) {
 137                         index++;
 138                         space = 1;
 139                 }
 140 
 141                 if (*index != '\0' && !isspace(*index)) {
 142                         argc++;
 143                         space = 0;
 144                         while (*index != '\0' && !isspace (*index)) {
 145                                 index++;
 146                         }
 147                 }
 148         }
 149 
 150         if (space)
 151                 *flags |= DCMD_TAB_SPACE;
 152         else
 153                 *flags &= ~DCMD_TAB_SPACE;
 154 
 155         return (argc);
 156 }
 157 
 158 /*
 159  * copy_args --
 160  *
 161  *      Given a buffer containing dcmd arguments and an array of mdb_arg_t's
 162  *      initialize the string value of each mdb_arg_t.
 163  *
 164  *      Note: This will modify the buffer.
 165  */
 166 static int
 167 tab_copy_args(char *input, int argc, mdb_arg_t *argv)
 168 {
 169         int i = 0;
 170         char *index;
 171 
 172         index = input;
 173 
 174         while (*index) {
 175                 while (*index && isspace(*index)) {
 176                         index++;
 177                 }
 178 
 179                 if (*index && !isspace(*index)) {
 180                         char *end = index;
 181 
 182                         while (*end && !isspace(*end)) {
 183                                 end++;
 184                         }
 185 
 186                         if (*end) {
 187                                 *end++ = '\0';
 188                         }
 189 
 190                         argv[i].a_type = MDB_TYPE_STRING;
 191                         argv[i].a_un.a_str = index;
 192 
 193                         index = end;
 194                         i++;
 195                 }
 196         }
 197 
 198         if (i != argc)
 199                 return (-1);
 200 
 201         return (0);
 202 }
 203 
 204 /*
 205  * parse-buf --
 206  *
 207  *      Parse the given buffer and return the specified dcmd, the number
 208  *      of arguments, and array of mdb_arg_t containing the argument
 209  *      values.
 210  *
 211  *      Note: this will modify the specified buffer. Caller is responisble
 212  *      for freeing argvp.
 213  */
 214 static int
 215 tab_parse_buf(char *buf, char **dcmdp, int *argcp, mdb_arg_t **argvp,
 216     uint_t *flags)
 217 {
 218         char *data = tab_find_command_start(buf);
 219         char *args_data = NULL;
 220         char *dcmd = NULL;
 221         int argc = 0;
 222         mdb_arg_t *argv = NULL;
 223 
 224         if (data == NULL) {
 225                 return (-1);
 226         }
 227 
 228         dcmd = tab_get_dcmd(data, &args_data, flags);
 229 
 230         if (dcmd == NULL) {
 231                 return (-1);
 232         }
 233 
 234         if (args_data != NULL) {
 235                 argc = tab_count_args(args_data, flags);
 236 
 237                 if (argc != 0) {
 238                         argv = mdb_alloc(sizeof (mdb_arg_t) * argc,
 239                             UM_SLEEP | UM_GC);
 240 
 241                         if (tab_copy_args(args_data, argc, argv) == -1)
 242                                 return (-1);
 243                 }
 244         }
 245 
 246         *dcmdp = dcmd;
 247         *argcp = argc;
 248         *argvp = argv;
 249 
 250         return (0);
 251 }
 252 
 253 /*
 254  * tab_command --
 255  *
 256  *      This function is executed anytime a tab is entered. It checks
 257  *      the current buffer to determine if there is a valid dmcd,
 258  *      if that dcmd has a tab completion handler it will invoke it.
 259  *
 260  *      This function returns the string (if any) that should be added to the
 261  *      existing buffer to complete it.
 262  */
 263 int
 264 mdb_tab_command(mdb_tab_cookie_t *mcp, const char *buf)
 265 {
 266         char *data;
 267         char *dcmd = NULL;
 268         int argc = 0;
 269         mdb_arg_t *argv = NULL;
 270         int ret = 0;
 271         mdb_idcmd_t *cp;
 272         uint_t flags = 0;
 273 
 274         /*
 275          * Parsing the command and arguments will modify the buffer
 276          * (replacing spaces with \0), so make a copy of the specified
 277          * buffer first.
 278          */
 279         data = mdb_alloc(strlen(buf) + 1, UM_SLEEP | UM_GC);
 280         (void) strcpy(data, buf);
 281 
 282         /*
 283          * Get the specified dcmd and arguments from the buffer.
 284          */
 285         ret = tab_parse_buf(data, &dcmd, &argc, &argv, &flags);
 286 
 287         /*
 288          * Match against global symbols if the input is not a dcmd
 289          */
 290         if (ret != 0) {
 291                 (void) mdb_tab_complete_global(mcp, buf);
 292                 goto out;
 293         }
 294 
 295         /*
 296          * Check to see if the buffer contains a valid dcmd
 297          */
 298         cp = mdb_dcmd_lookup(dcmd);
 299 
 300         /*
 301          * When argc is zero it indicates that we are trying to tab complete
 302          * a dcmd or a global symbol. Note, that if there isn't the start of
 303          * a dcmd, i.e. ::, then we will have already bailed in the call to
 304          * tab_parse_buf.
 305          */
 306         if (cp == NULL && argc != 0) {
 307                 goto out;
 308         }
 309 
 310         /*
 311          * Invoke the command specific tab completion handler or the built in
 312          * dcmd one if there is no dcmd.
 313          */
 314         if (cp == NULL)
 315                 (void) mdb_tab_complete_dcmd(mcp, dcmd);
 316         else
 317                 mdb_call_tab(cp, mcp, flags, argc, argv);
 318 
 319 out:
 320         return (mdb_tab_size(mcp));
 321 }
 322 
 323 static int
 324 tab_complete_dcmd(mdb_var_t *v, void *arg)
 325 {
 326         mdb_idcmd_t *idcp = mdb_nv_get_cookie(mdb_nv_get_cookie(v));
 327         mdb_tab_cookie_t *mcp = (mdb_tab_cookie_t *)arg;
 328 
 329         /*
 330          * The way that mdb is implemented, even commands like $C will show up
 331          * here. As such, we don't want to match anything that doesn't start
 332          * with an alpha or number. While nothing currently appears (via a
 333          * cursory search with mdb -k) to start with a capital letter or a
 334          * number, we'll support them anyways.
 335          */
 336         if (!isalnum(idcp->idc_name[0]))
 337                 return (0);
 338 
 339         mdb_tab_insert(mcp, idcp->idc_name);
 340         return (0);
 341 }
 342 
 343 int
 344 mdb_tab_complete_dcmd(mdb_tab_cookie_t *mcp, const char *dcmd)
 345 {
 346         mdb_tab_setmbase(mcp, dcmd);
 347         mdb_nv_sort_iter(&mdb.m_dcmds, tab_complete_dcmd, mcp,
 348             UM_GC | UM_SLEEP);
 349         return (0);
 350 }
 351 
 352 static int
 353 tab_complete_walker(mdb_var_t *v, void *arg)
 354 {
 355         mdb_iwalker_t *iwp = mdb_nv_get_cookie(mdb_nv_get_cookie(v));
 356         mdb_tab_cookie_t *mcp = arg;
 357 
 358         mdb_tab_insert(mcp, iwp->iwlk_name);
 359         return (0);
 360 }
 361 
 362 int
 363 mdb_tab_complete_walker(mdb_tab_cookie_t *mcp, const char *walker)
 364 {
 365         if (walker != NULL)
 366                 mdb_tab_setmbase(mcp, walker);
 367         mdb_nv_sort_iter(&mdb.m_walkers, tab_complete_walker, mcp,
 368             UM_GC | UM_SLEEP);
 369 
 370         return (0);
 371 }
 372 
 373 mdb_tab_cookie_t *
 374 mdb_tab_init(void)
 375 {
 376         mdb_tab_cookie_t *mcp;
 377 
 378         mcp = mdb_zalloc(sizeof (mdb_tab_cookie_t), UM_SLEEP | UM_GC);
 379         (void) mdb_nv_create(&mcp->mtc_nv, UM_SLEEP | UM_GC);
 380 
 381         return (mcp);
 382 }
 383 
 384 size_t
 385 mdb_tab_size(mdb_tab_cookie_t *mcp)
 386 {
 387         return (mdb_nv_size(&mcp->mtc_nv));
 388 }
 389 
 390 /*
 391  * Determine whether the specified name is a valid tab completion for
 392  * the given command. If the name is a valid tab completion then
 393  * it will be saved in the mdb_tab_cookie_t.
 394  */
 395 void
 396 mdb_tab_insert(mdb_tab_cookie_t *mcp, const char *name)
 397 {
 398         size_t matches, index;
 399         mdb_var_t *v;
 400 
 401         /*
 402          * If we have a match set, then we want to verify that we actually match
 403          * it.
 404          */
 405         if (mcp->mtc_base != NULL &&
 406             strncmp(name, mcp->mtc_base, strlen(mcp->mtc_base)) != 0)
 407                 return;
 408 
 409         v = mdb_nv_lookup(&mcp->mtc_nv, name);
 410         if (v != NULL)
 411                 return;
 412 
 413         (void) mdb_nv_insert(&mcp->mtc_nv, name, NULL, 0, MDB_NV_RDONLY);
 414 
 415         matches = mdb_tab_size(mcp);
 416         if (matches == 1) {
 417                 (void) strlcpy(mcp->mtc_match, name, MDB_SYM_NAMLEN);
 418         } else {
 419                 index = 0;
 420                 while (mcp->mtc_match[index] &&
 421                     mcp->mtc_match[index] == name[index])
 422                         index++;
 423 
 424                 mcp->mtc_match[index] = '\0';
 425         }
 426 }
 427 
 428 /*ARGSUSED*/
 429 static int
 430 tab_print_cb(mdb_var_t *v, void *ignored)
 431 {
 432         mdb_printf("%s\n", mdb_nv_get_name(v));
 433         return (0);
 434 }
 435 
 436 void
 437 mdb_tab_print(mdb_tab_cookie_t *mcp)
 438 {
 439         mdb_nv_sort_iter(&mcp->mtc_nv, tab_print_cb, NULL, UM_SLEEP | UM_GC);
 440 }
 441 
 442 const char *
 443 mdb_tab_match(mdb_tab_cookie_t *mcp)
 444 {
 445         size_t blen;
 446 
 447         if (mcp->mtc_base == NULL)
 448                 blen = 0;
 449         else
 450                 blen = strlen(mcp->mtc_base);
 451         return (mcp->mtc_match + blen);
 452 }
 453 
 454 void
 455 mdb_tab_setmbase(mdb_tab_cookie_t *mcp, const char *base)
 456 {
 457         (void) strlcpy(mcp->mtc_base, base, MDB_SYM_NAMLEN);
 458 }
 459 
 460 /*
 461  * This function is currently a no-op due to the fact that we have to GC because
 462  * we're in command context.
 463  */
 464 /*ARGSUSED*/
 465 void
 466 mdb_tab_fini(mdb_tab_cookie_t *mcp)
 467 {
 468 }
 469 
 470 /*ARGSUSED*/
 471 static int
 472 tab_complete_global(void *arg, const GElf_Sym *sym, const char *name,
 473     const mdb_syminfo_t *sip, const char *obj)
 474 {
 475         mdb_tab_cookie_t *mcp = arg;
 476         mdb_tab_insert(mcp, name);
 477         return (0);
 478 }
 479 
 480 /*
 481  * This function tab completes against all loaded global symbols.
 482  */
 483 int
 484 mdb_tab_complete_global(mdb_tab_cookie_t *mcp, const char *name)
 485 {
 486         mdb_tab_setmbase(mcp, name);
 487         (void) mdb_tgt_symbol_iter(mdb.m_target, MDB_TGT_OBJ_EVERY,
 488             MDB_TGT_SYMTAB, MDB_TGT_BIND_ANY | MDB_TGT_TYPE_OBJECT |
 489             MDB_TGT_TYPE_FUNC, tab_complete_global, mcp);
 490         return (0);
 491 }
 492 
 493 /*
 494  * This function takes a ctf id and determines whether or not the associated
 495  * type should be considered as a potential match for the given tab
 496  * completion command. We verify that the type itself is valid
 497  * for completion given the current context of the command, resolve
 498  * its actual name, and then pass it off to mdb_tab_insert to determine
 499  * if it's an actual match.
 500  */
 501 static int
 502 tab_complete_type(mdb_ctf_id_t id, void *arg)
 503 {
 504         int rkind;
 505         char buf[MDB_SYM_NAMLEN];
 506         mdb_ctf_id_t rid;
 507         mdb_tab_cookie_t *mcp = arg;
 508         uint_t flags = (uint_t)(uintptr_t)mcp->mtc_cba;
 509 
 510         /*
 511          * CTF data includes types that mdb commands don't understand. Before
 512          * we resolve the actual type prune any entry that is a type we
 513          * don't care about.
 514          */
 515         switch (mdb_ctf_type_kind(id)) {
 516         case CTF_K_CONST:
 517         case CTF_K_RESTRICT:
 518         case CTF_K_VOLATILE:
 519                 return (0);
 520         }
 521 
 522         if (mdb_ctf_type_resolve(id, &rid) != 0)
 523                 return (1);
 524 
 525         rkind = mdb_ctf_type_kind(rid);
 526 
 527         if ((flags & MDB_TABC_MEMBERS) && rkind != CTF_K_STRUCT &&
 528             rkind != CTF_K_UNION)
 529                 return (0);
 530 
 531         if ((flags & MDB_TABC_NOPOINT) && rkind == CTF_K_POINTER)
 532                 return (0);
 533 
 534         if ((flags & MDB_TABC_NOARRAY) && rkind == CTF_K_ARRAY)
 535                 return (0);
 536 
 537         (void) mdb_ctf_type_name(id, buf, sizeof (buf));
 538 
 539         mdb_tab_insert(mcp, buf);
 540         return (0);
 541 }
 542 
 543 /*ARGSUSED*/
 544 static int
 545 mdb_tab_complete_module(void *data, const mdb_map_t *mp, const char *name)
 546 {
 547         (void) mdb_ctf_type_iter(name, tab_complete_type, data);
 548         return (0);
 549 }
 550 
 551 int
 552 mdb_tab_complete_type(mdb_tab_cookie_t *mcp, const char *name, uint_t flags)
 553 {
 554         mdb_tgt_t *t = mdb.m_target;
 555 
 556         mcp->mtc_cba = (void *)(uintptr_t)flags;
 557         if (name != NULL)
 558                 mdb_tab_setmbase(mcp, name);
 559 
 560         (void) mdb_tgt_object_iter(t, mdb_tab_complete_module, mcp);
 561         (void) mdb_ctf_type_iter(MDB_CTF_SYNTHETIC_ITER, tab_complete_type,
 562             mcp);
 563         return (0);
 564 }
 565 
 566 /*ARGSUSED*/
 567 static int
 568 tab_complete_member(const char *name, mdb_ctf_id_t id, ulong_t off, void *arg)
 569 {
 570         mdb_tab_cookie_t *mcp = arg;
 571         mdb_tab_insert(mcp, name);
 572         return (0);
 573 }
 574 
 575 int
 576 mdb_tab_complete_member_by_id(mdb_tab_cookie_t *mcp, mdb_ctf_id_t id,
 577     const char *member)
 578 {
 579         if (member != NULL)
 580                 mdb_tab_setmbase(mcp, member);
 581         (void) mdb_ctf_member_iter(id, tab_complete_member, mcp);
 582         return (0);
 583 }
 584 
 585 int
 586 mdb_tab_complete_member(mdb_tab_cookie_t *mcp, const char *type,
 587     const char *member)
 588 {
 589         mdb_ctf_id_t id;
 590 
 591         if (mdb_ctf_lookup_by_name(type, &id) != 0)
 592                 return (-1);
 593 
 594         return (mdb_tab_complete_member_by_id(mcp, id, member));
 595 }
 596 
 597 int
 598 mdb_tab_complete_mt(mdb_tab_cookie_t *mcp, uint_t flags, int argc,
 599     const mdb_arg_t *argv)
 600 {
 601         char tn[MDB_SYM_NAMLEN];
 602         int ret;
 603 
 604         if (argc == 0 && !(flags & DCMD_TAB_SPACE))
 605                 return (0);
 606 
 607         if (argc == 0)
 608                 return (mdb_tab_complete_type(mcp, NULL, MDB_TABC_MEMBERS));
 609 
 610         if ((ret = mdb_tab_typename(&argc, &argv, tn, sizeof (tn))) < 0)
 611                 return (ret);
 612 
 613         if (argc == 1 && (!(flags & DCMD_TAB_SPACE) || ret == 1))
 614                 return (mdb_tab_complete_type(mcp, tn, MDB_TABC_MEMBERS));
 615 
 616         if (argc == 1 && (flags & DCMD_TAB_SPACE))
 617                 return (mdb_tab_complete_member(mcp, tn, NULL));
 618 
 619         if (argc == 2)
 620                 return (mdb_tab_complete_member(mcp, tn, argv[1].a_un.a_str));
 621 
 622         return (0);
 623 }
 624 
 625 /*
 626  * This is similar to mdb_print.c's args_to_typename, but it has subtle
 627  * differences surrounding how the strings of one element are handled that have
 628  * 'struct', 'enum', or 'union' in them and instead works with them for tab
 629  * completion purposes.
 630  */
 631 int
 632 mdb_tab_typename(int *argcp, const mdb_arg_t **argvp, char *buf, size_t len)
 633 {
 634         int argc = *argcp;
 635         const mdb_arg_t *argv = *argvp;
 636 
 637         if (argc < 1 || argv->a_type != MDB_TYPE_STRING)
 638                 return (DCMD_USAGE);
 639 
 640         if (strcmp(argv->a_un.a_str, "struct") == 0 ||
 641             strcmp(argv->a_un.a_str, "enum") == 0 ||
 642             strcmp(argv->a_un.a_str, "union") == 0) {
 643                 if (argc == 1) {
 644                         (void) mdb_snprintf(buf, len, "%s ",
 645                             argv[0].a_un.a_str);
 646                         return (1);
 647                 }
 648 
 649                 if (argv[1].a_type != MDB_TYPE_STRING)
 650                         return (DCMD_USAGE);
 651 
 652                 (void) mdb_snprintf(buf, len, "%s %s",
 653                     argv[0].a_un.a_str, argv[1].a_un.a_str);
 654 
 655                 *argcp = argc - 1;
 656                 *argvp = argv + 1;
 657         } else {
 658                 (void) mdb_snprintf(buf, len, "%s", argv[0].a_un.a_str);
 659         }
 660 
 661         return (0);
 662 }