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