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         if (dcmd != NULL)
 347                 mdb_tab_setmbase(mcp, dcmd);
 348         mdb_nv_sort_iter(&mdb.m_dcmds, tab_complete_dcmd, mcp,
 349             UM_GC | UM_SLEEP);
 350         return (0);
 351 }
 352 
 353 static int
 354 tab_complete_walker(mdb_var_t *v, void *arg)
 355 {
 356         mdb_iwalker_t *iwp = mdb_nv_get_cookie(mdb_nv_get_cookie(v));
 357         mdb_tab_cookie_t *mcp = arg;
 358 
 359         mdb_tab_insert(mcp, iwp->iwlk_name);
 360         return (0);
 361 }
 362 
 363 int
 364 mdb_tab_complete_walker(mdb_tab_cookie_t *mcp, const char *walker)
 365 {
 366         if (walker != NULL)
 367                 mdb_tab_setmbase(mcp, walker);
 368         mdb_nv_sort_iter(&mdb.m_walkers, tab_complete_walker, mcp,
 369             UM_GC | UM_SLEEP);
 370 
 371         return (0);
 372 }
 373 
 374 mdb_tab_cookie_t *
 375 mdb_tab_init(void)
 376 {
 377         mdb_tab_cookie_t *mcp;
 378 
 379         mcp = mdb_zalloc(sizeof (mdb_tab_cookie_t), UM_SLEEP | UM_GC);
 380         (void) mdb_nv_create(&mcp->mtc_nv, UM_SLEEP | UM_GC);
 381 
 382         return (mcp);
 383 }
 384 
 385 size_t
 386 mdb_tab_size(mdb_tab_cookie_t *mcp)
 387 {
 388         return (mdb_nv_size(&mcp->mtc_nv));
 389 }
 390 
 391 /*
 392  * Determine whether the specified name is a valid tab completion for
 393  * the given command. If the name is a valid tab completion then
 394  * it will be saved in the mdb_tab_cookie_t.
 395  */
 396 void
 397 mdb_tab_insert(mdb_tab_cookie_t *mcp, const char *name)
 398 {
 399         size_t matches, index;
 400         mdb_var_t *v;
 401 
 402         /*
 403          * If we have a match set, then we want to verify that we actually match
 404          * it.
 405          */
 406         if (mcp->mtc_base != NULL &&
 407             strncmp(name, mcp->mtc_base, strlen(mcp->mtc_base)) != 0)
 408                 return;
 409 
 410         v = mdb_nv_lookup(&mcp->mtc_nv, name);
 411         if (v != NULL)
 412                 return;
 413 
 414         (void) mdb_nv_insert(&mcp->mtc_nv, name, NULL, 0, MDB_NV_RDONLY);
 415 
 416         matches = mdb_tab_size(mcp);
 417         if (matches == 1) {
 418                 (void) strlcpy(mcp->mtc_match, name, MDB_SYM_NAMLEN);
 419         } else {
 420                 index = 0;
 421                 while (mcp->mtc_match[index] &&
 422                     mcp->mtc_match[index] == name[index])
 423                         index++;
 424 
 425                 mcp->mtc_match[index] = '\0';
 426         }
 427 }
 428 
 429 /*ARGSUSED*/
 430 static int
 431 tab_print_cb(mdb_var_t *v, void *ignored)
 432 {
 433         mdb_printf("%s\n", mdb_nv_get_name(v));
 434         return (0);
 435 }
 436 
 437 void
 438 mdb_tab_print(mdb_tab_cookie_t *mcp)
 439 {
 440         mdb_nv_sort_iter(&mcp->mtc_nv, tab_print_cb, NULL, UM_SLEEP | UM_GC);
 441 }
 442 
 443 const char *
 444 mdb_tab_match(mdb_tab_cookie_t *mcp)
 445 {
 446         size_t blen;
 447 
 448         if (mcp->mtc_base == NULL)
 449                 blen = 0;
 450         else
 451                 blen = strlen(mcp->mtc_base);
 452         return (mcp->mtc_match + blen);
 453 }
 454 
 455 void
 456 mdb_tab_setmbase(mdb_tab_cookie_t *mcp, const char *base)
 457 {
 458         (void) strlcpy(mcp->mtc_base, base, MDB_SYM_NAMLEN);
 459 }
 460 
 461 /*
 462  * This function is currently a no-op due to the fact that we have to GC because
 463  * we're in command context.
 464  */
 465 /*ARGSUSED*/
 466 void
 467 mdb_tab_fini(mdb_tab_cookie_t *mcp)
 468 {
 469 }
 470 
 471 /*ARGSUSED*/
 472 static int
 473 tab_complete_global(void *arg, const GElf_Sym *sym, const char *name,
 474     const mdb_syminfo_t *sip, const char *obj)
 475 {
 476         mdb_tab_cookie_t *mcp = arg;
 477         mdb_tab_insert(mcp, name);
 478         return (0);
 479 }
 480 
 481 /*
 482  * This function tab completes against all loaded global symbols.
 483  */
 484 int
 485 mdb_tab_complete_global(mdb_tab_cookie_t *mcp, const char *name)
 486 {
 487         mdb_tab_setmbase(mcp, name);
 488         (void) mdb_tgt_symbol_iter(mdb.m_target, MDB_TGT_OBJ_EVERY,
 489             MDB_TGT_SYMTAB, MDB_TGT_BIND_ANY | MDB_TGT_TYPE_OBJECT |
 490             MDB_TGT_TYPE_FUNC, tab_complete_global, mcp);
 491         return (0);
 492 }
 493 
 494 /*
 495  * This function takes a ctf id and determines whether or not the associated
 496  * type should be considered as a potential match for the given tab
 497  * completion command. We verify that the type itself is valid
 498  * for completion given the current context of the command, resolve
 499  * its actual name, and then pass it off to mdb_tab_insert to determine
 500  * if it's an actual match.
 501  */
 502 static int
 503 tab_complete_type(mdb_ctf_id_t id, void *arg)
 504 {
 505         int rkind;
 506         char buf[MDB_SYM_NAMLEN];
 507         mdb_ctf_id_t rid;
 508         mdb_tab_cookie_t *mcp = arg;
 509         uint_t flags = (uint_t)(uintptr_t)mcp->mtc_cba;
 510 
 511         /*
 512          * CTF data includes types that mdb commands don't understand. Before
 513          * we resolve the actual type prune any entry that is a type we
 514          * don't care about.
 515          */
 516         switch (mdb_ctf_type_kind(id)) {
 517         case CTF_K_CONST:
 518         case CTF_K_RESTRICT:
 519         case CTF_K_VOLATILE:
 520                 return (0);
 521         }
 522 
 523         if (mdb_ctf_type_resolve(id, &rid) != 0)
 524                 return (1);
 525 
 526         rkind = mdb_ctf_type_kind(rid);
 527 
 528         if ((flags & MDB_TABC_MEMBERS) && rkind != CTF_K_STRUCT &&
 529             rkind != CTF_K_UNION)
 530                 return (0);
 531 
 532         if ((flags & MDB_TABC_NOPOINT) && rkind == CTF_K_POINTER)
 533                 return (0);
 534 
 535         if ((flags & MDB_TABC_NOARRAY) && rkind == CTF_K_ARRAY)
 536                 return (0);
 537 
 538         (void) mdb_ctf_type_name(id, buf, sizeof (buf));
 539 
 540         mdb_tab_insert(mcp, buf);
 541         return (0);
 542 }
 543 
 544 /*ARGSUSED*/
 545 static int
 546 mdb_tab_complete_module(void *data, const mdb_map_t *mp, const char *name)
 547 {
 548         (void) mdb_ctf_type_iter(name, tab_complete_type, data);
 549         return (0);
 550 }
 551 
 552 int
 553 mdb_tab_complete_type(mdb_tab_cookie_t *mcp, const char *name, uint_t flags)
 554 {
 555         mdb_tgt_t *t = mdb.m_target;
 556 
 557         mcp->mtc_cba = (void *)(uintptr_t)flags;
 558         if (name != NULL)
 559                 mdb_tab_setmbase(mcp, name);
 560 
 561         (void) mdb_tgt_object_iter(t, mdb_tab_complete_module, mcp);
 562         (void) mdb_ctf_type_iter(MDB_CTF_SYNTHETIC_ITER, tab_complete_type,
 563             mcp);
 564         return (0);
 565 }
 566 
 567 /*ARGSUSED*/
 568 static int
 569 tab_complete_member(const char *name, mdb_ctf_id_t id, ulong_t off, void *arg)
 570 {
 571         mdb_tab_cookie_t *mcp = arg;
 572         mdb_tab_insert(mcp, name);
 573         return (0);
 574 }
 575 
 576 int
 577 mdb_tab_complete_member_by_id(mdb_tab_cookie_t *mcp, mdb_ctf_id_t id,
 578     const char *member)
 579 {
 580         if (member != NULL)
 581                 mdb_tab_setmbase(mcp, member);
 582         (void) mdb_ctf_member_iter(id, tab_complete_member, mcp);
 583         return (0);
 584 }
 585 
 586 int
 587 mdb_tab_complete_member(mdb_tab_cookie_t *mcp, const char *type,
 588     const char *member)
 589 {
 590         mdb_ctf_id_t id;
 591 
 592         if (mdb_ctf_lookup_by_name(type, &id) != 0)
 593                 return (-1);
 594 
 595         return (mdb_tab_complete_member_by_id(mcp, id, member));
 596 }
 597 
 598 int
 599 mdb_tab_complete_mt(mdb_tab_cookie_t *mcp, uint_t flags, int argc,
 600     const mdb_arg_t *argv)
 601 {
 602         char tn[MDB_SYM_NAMLEN];
 603         int ret;
 604 
 605         if (argc == 0 && !(flags & DCMD_TAB_SPACE))
 606                 return (0);
 607 
 608         if (argc == 0)
 609                 return (mdb_tab_complete_type(mcp, NULL, MDB_TABC_MEMBERS));
 610 
 611         if ((ret = mdb_tab_typename(&argc, &argv, tn, sizeof (tn))) < 0)
 612                 return (ret);
 613 
 614         if (argc == 1 && (!(flags & DCMD_TAB_SPACE) || ret == 1))
 615                 return (mdb_tab_complete_type(mcp, tn, MDB_TABC_MEMBERS));
 616 
 617         if (argc == 1 && (flags & DCMD_TAB_SPACE))
 618                 return (mdb_tab_complete_member(mcp, tn, NULL));
 619 
 620         if (argc == 2)
 621                 return (mdb_tab_complete_member(mcp, tn, argv[1].a_un.a_str));
 622 
 623         return (0);
 624 }
 625 
 626 /*
 627  * This is similar to mdb_print.c's args_to_typename, but it has subtle
 628  * differences surrounding how the strings of one element are handled that have
 629  * 'struct', 'enum', or 'union' in them and instead works with them for tab
 630  * completion purposes.
 631  */
 632 int
 633 mdb_tab_typename(int *argcp, const mdb_arg_t **argvp, char *buf, size_t len)
 634 {
 635         int argc = *argcp;
 636         const mdb_arg_t *argv = *argvp;
 637 
 638         if (argc < 1 || argv->a_type != MDB_TYPE_STRING)
 639                 return (DCMD_USAGE);
 640 
 641         if (strcmp(argv->a_un.a_str, "struct") == 0 ||
 642             strcmp(argv->a_un.a_str, "enum") == 0 ||
 643             strcmp(argv->a_un.a_str, "union") == 0) {
 644                 if (argc == 1) {
 645                         (void) mdb_snprintf(buf, len, "%s ",
 646                             argv[0].a_un.a_str);
 647                         return (1);
 648                 }
 649 
 650                 if (argv[1].a_type != MDB_TYPE_STRING)
 651                         return (DCMD_USAGE);
 652 
 653                 (void) mdb_snprintf(buf, len, "%s %s",
 654                     argv[0].a_un.a_str, argv[1].a_un.a_str);
 655 
 656                 *argcp = argc - 1;
 657                 *argvp = argv + 1;
 658         } else {
 659                 (void) mdb_snprintf(buf, len, "%s", argv[0].a_un.a_str);
 660         }
 661 
 662         return (0);
 663 }