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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 /*
  26  * Copyright (c) 2012 by Delphix. All rights reserved.
  27  * Copyright (c) 2012 Joyent, Inc. All rights reserved.
  28  */
  29 
  30 /*
  31  * Modular Debugger (MDB)
  32  *
  33  * Refer to the white paper "A Modular Debugger for Solaris" for information
  34  * on the design, features, and goals of MDB.  See /shared/sac/PSARC/1999/169
  35  * for copies of the paper and related documentation.
  36  *
  37  * This file provides the basic construction and destruction of the debugger's
  38  * global state, as well as the main execution loop, mdb_run().  MDB maintains
  39  * a stack of execution frames (mdb_frame_t's) that keep track of its current
  40  * state, including a stack of input and output buffers, walk and memory
  41  * garbage collect lists, and a list of commands (mdb_cmd_t's).  As the
  42  * parser consumes input, it fills in a list of commands to execute, and then
  43  * invokes mdb_call(), below.  A command consists of a dcmd, telling us
  44  * what function to execute, and a list of arguments and other invocation-
  45  * specific data.  Each frame may have more than one command, kept on a list,
  46  * when multiple commands are separated by | operators.  New frames may be
  47  * stacked on old ones by nested calls to mdb_run: this occurs when, for
  48  * example, in the middle of processing one input source (such as a file
  49  * or the terminal), we invoke a dcmd that in turn calls mdb_eval().  mdb_eval
  50  * will construct a new frame whose input source is the string passed to
  51  * the eval function, and then execute this frame to completion.
  52  */
  53 
  54 #include <sys/param.h>
  55 #include <stropts.h>
  56 
  57 #define _MDB_PRIVATE
  58 #include <mdb/mdb.h>
  59 
  60 #include <mdb/mdb_context.h>
  61 #include <mdb/mdb_argvec.h>
  62 #include <mdb/mdb_signal.h>
  63 #include <mdb/mdb_macalias.h>
  64 #include <mdb/mdb_module.h>
  65 #include <mdb/mdb_modapi.h>
  66 #include <mdb/mdb_string.h>
  67 #include <mdb/mdb_callb.h>
  68 #include <mdb/mdb_debug.h>
  69 #include <mdb/mdb_frame.h>
  70 #include <mdb/mdb_conf.h>
  71 #include <mdb/mdb_err.h>
  72 #include <mdb/mdb_lex.h>
  73 #include <mdb/mdb_io.h>
  74 #include <mdb/mdb_ctf.h>
  75 #ifdef _KMDB
  76 #include <kmdb/kmdb_module.h>
  77 #endif
  78 
  79 /*
  80  * Macro for testing if a dcmd's return status (x) indicates that we should
  81  * abort the current loop or pipeline.
  82  */
  83 #define DCMD_ABORTED(x) ((x) == DCMD_USAGE || (x) == DCMD_ABORT)
  84 
  85 extern const mdb_dcmd_t mdb_dcmd_builtins[];
  86 extern mdb_dis_ctor_f *const mdb_dis_builtins[];
  87 
  88 /*
  89  * Variable discipline for toggling MDB_FL_PSYM based on the value of the
  90  * undocumented '_' variable.  Once adb(1) has been removed from the system,
  91  * we should just remove this functionality and always disable PSYM for macros.
  92  */
  93 static uintmax_t
  94 psym_disc_get(const mdb_var_t *v)
  95 {
  96         int i = (mdb.m_flags & MDB_FL_PSYM) ? 1 : 0;
  97         int j = (MDB_NV_VALUE(v) != 0) ? 1 : 0;
  98 
  99         if ((i ^ j) == 0)
 100                 MDB_NV_VALUE((mdb_var_t *)v) = j ^ 1;
 101 
 102         return (MDB_NV_VALUE(v));
 103 }
 104 
 105 static void
 106 psym_disc_set(mdb_var_t *v, uintmax_t value)
 107 {
 108         if (value == 0)
 109                 mdb.m_flags |= MDB_FL_PSYM;
 110         else
 111                 mdb.m_flags &= ~MDB_FL_PSYM;
 112 
 113         MDB_NV_VALUE(v) = value;
 114 }
 115 
 116 /*
 117  * Variable discipline for making <1 (most recent offset) behave properly.
 118  */
 119 static uintmax_t
 120 roff_disc_get(const mdb_var_t *v)
 121 {
 122         return (MDB_NV_VALUE(v));
 123 }
 124 
 125 static void
 126 roff_disc_set(mdb_var_t *v, uintmax_t value)
 127 {
 128         mdb_nv_set_value(mdb.m_proffset, MDB_NV_VALUE(v));
 129         MDB_NV_VALUE(v) = value;
 130 }
 131 
 132 /*
 133  * Variable discipline for exporting the representative thread.
 134  */
 135 static uintmax_t
 136 thr_disc_get(const mdb_var_t *v)
 137 {
 138         mdb_tgt_status_t s;
 139 
 140         if (mdb.m_target != NULL && mdb_tgt_status(mdb.m_target, &s) == 0)
 141                 return (s.st_tid);
 142 
 143         return (MDB_NV_VALUE(v));
 144 }
 145 
 146 const char **
 147 mdb_path_alloc(const char *s, size_t *newlen)
 148 {
 149         char *format = mdb_alloc(strlen(s) * 2 + 1, UM_NOSLEEP);
 150         const char **path;
 151         char *p, *q;
 152 
 153         struct utsname uts;
 154         size_t len;
 155         int i;
 156 
 157         mdb_arg_t arg_i, arg_m, arg_p, arg_r, arg_t, arg_R, arg_V;
 158         mdb_argvec_t argv;
 159 
 160         static const char *empty_path[] = { NULL };
 161 
 162         if (format == NULL)
 163                 goto nomem;
 164 
 165         while (*s == ':')
 166                 s++; /* strip leading delimiters */
 167 
 168         if (*s == '\0') {
 169                 *newlen = 0;
 170                 return (empty_path);
 171         }
 172 
 173         (void) strcpy(format, s);
 174         mdb_argvec_create(&argv);
 175 
 176         /*
 177          * %i embedded in path string expands to ISA.
 178          */
 179         arg_i.a_type = MDB_TYPE_STRING;
 180         if (mdb.m_target != NULL)
 181                 arg_i.a_un.a_str = mdb_tgt_isa(mdb.m_target);
 182         else
 183                 arg_i.a_un.a_str = mdb_conf_isa();
 184 
 185         /*
 186          * %p embedded in path string expands to the platform name.
 187          */
 188         arg_p.a_type = MDB_TYPE_STRING;
 189         if (mdb.m_target != NULL)
 190                 arg_p.a_un.a_str = mdb_tgt_platform(mdb.m_target);
 191         else
 192                 arg_p.a_un.a_str = mdb_conf_platform();
 193 
 194         /*
 195          * %r embedded in path string expands to root directory, or
 196          * to the empty string if root is "/" (to avoid // in paths).
 197          */
 198         arg_r.a_type = MDB_TYPE_STRING;
 199         arg_r.a_un.a_str = strcmp(mdb.m_root, "/") ? mdb.m_root : "";
 200 
 201         /*
 202          * %t embedded in path string expands to the target name, defaulting to
 203          * kvm; this is so we can find mdb_kb, which is used during bootstrap.
 204          */
 205         arg_t.a_type = MDB_TYPE_STRING;
 206         arg_t.a_un.a_str = mdb.m_target ? mdb_tgt_name(mdb.m_target) : "kvm";
 207 
 208         /*
 209          * %R and %V expand to uname -r (release) and uname -v (version).
 210          */
 211         if (mdb.m_target == NULL || mdb_tgt_uname(mdb.m_target, &uts) < 0)
 212                 mdb_conf_uname(&uts);
 213 
 214         arg_m.a_type = MDB_TYPE_STRING;
 215         arg_m.a_un.a_str = uts.machine;
 216 
 217         arg_R.a_type = MDB_TYPE_STRING;
 218         arg_R.a_un.a_str = uts.release;
 219 
 220         arg_V.a_type = MDB_TYPE_STRING;
 221         if (mdb.m_flags & MDB_FL_LATEST)
 222                 arg_V.a_un.a_str = "latest";
 223         else
 224                 arg_V.a_un.a_str = uts.version;
 225 
 226         /*
 227          * In order to expand the buffer, we examine the format string for
 228          * our % tokens and construct an argvec, replacing each % token
 229          * with %s along the way.  If we encounter an unknown token, we
 230          * shift over the remaining format buffer and stick in %%.
 231          */
 232         for (q = format; (q = strchr(q, '%')) != NULL; q++) {
 233                 switch (q[1]) {
 234                 case 'i':
 235                         mdb_argvec_append(&argv, &arg_i);
 236                         *++q = 's';
 237                         break;
 238                 case 'm':
 239                         mdb_argvec_append(&argv, &arg_m);
 240                         *++q = 's';
 241                         break;
 242                 case 'p':
 243                         mdb_argvec_append(&argv, &arg_p);
 244                         *++q = 's';
 245                         break;
 246                 case 'r':
 247                         mdb_argvec_append(&argv, &arg_r);
 248                         *++q = 's';
 249                         break;
 250                 case 't':
 251                         mdb_argvec_append(&argv, &arg_t);
 252                         *++q = 's';
 253                         break;
 254                 case 'R':
 255                         mdb_argvec_append(&argv, &arg_R);
 256                         *++q = 's';
 257                         break;
 258                 case 'V':
 259                         mdb_argvec_append(&argv, &arg_V);
 260                         *++q = 's';
 261                         break;
 262                 default:
 263                         bcopy(q + 1, q + 2, strlen(q));
 264                         *++q = '%';
 265                 }
 266         }
 267 
 268         /*
 269          * We're now ready to use our printf engine to format the final string.
 270          * Take one lap with a NULL buffer to determine how long the final
 271          * string will be, allocate it, and format it.
 272          */
 273         len = mdb_iob_asnprintf(NULL, 0, format, argv.a_data);
 274         if ((p = mdb_alloc(len + 1, UM_NOSLEEP)) != NULL)
 275                 (void) mdb_iob_asnprintf(p, len + 1, format, argv.a_data);
 276         else
 277                 goto nomem;
 278 
 279         mdb_argvec_zero(&argv);
 280         mdb_argvec_destroy(&argv);
 281 
 282         mdb_free(format, strlen(s) * 2 + 1);
 283         format = NULL;
 284 
 285         /*
 286          * Compress the string to exclude any leading delimiters.
 287          */
 288         for (q = p; *q == ':'; q++)
 289                 continue;
 290         if (q != p)
 291                 bcopy(q, p, strlen(q) + 1);
 292 
 293         /*
 294          * Count up the number of delimited elements.  A sequence of
 295          * consecutive delimiters is only counted once.
 296          */
 297         for (i = 1, q = p; (q = strchr(q, ':')) != NULL; i++) {
 298                 while (*q == ':')
 299                         q++;
 300         }
 301 
 302         if ((path = mdb_alloc(sizeof (char *) * (i + 1), UM_NOSLEEP)) == NULL) {
 303                 mdb_free(p, len + 1);
 304                 goto nomem;
 305         }
 306 
 307         for (i = 0, q = strtok(p, ":"); q != NULL; q = strtok(NULL, ":"))
 308                 path[i++] = q;
 309 
 310         path[i] = NULL;
 311         *newlen = len + 1;
 312         return (path);
 313 
 314 nomem:
 315         warn("failed to allocate memory for path");
 316         if (format != NULL)
 317                 mdb_free(format, strlen(s) * 2 + 1);
 318         *newlen = 0;
 319         return (empty_path);
 320 }
 321 
 322 const char **
 323 mdb_path_dup(const char *path[], size_t pathlen, size_t *npathlenp)
 324 {
 325         char **npath;
 326         int i, j;
 327 
 328         for (i = 0; path[i] != NULL; i++)
 329                 continue; /* count the path elements */
 330 
 331         npath = mdb_zalloc(sizeof (char *) * (i + 1), UM_SLEEP);
 332         if (pathlen > 0) {
 333                 npath[0] = mdb_alloc(pathlen, UM_SLEEP);
 334                 bcopy(path[0], npath[0], pathlen);
 335         }
 336 
 337         for (j = 1; j < i; j++)
 338                 npath[j] = npath[0] + (path[j] - path[0]);
 339         npath[i] = NULL;
 340 
 341         *npathlenp = pathlen;
 342         return ((const char **)npath);
 343 }
 344 
 345 void
 346 mdb_path_free(const char *path[], size_t pathlen)
 347 {
 348         int i;
 349 
 350         for (i = 0; path[i] != NULL; i++)
 351                 continue; /* count the path elements */
 352 
 353         if (i > 0) {
 354                 mdb_free((void *)path[0], pathlen);
 355                 mdb_free(path, sizeof (char *) * (i + 1));
 356         }
 357 }
 358 
 359 /*
 360  * Convert path string "s" to canonical form, expanding any %o tokens that are
 361  * found within the path.  The old path string is specified by "path", a buffer
 362  * of size MAXPATHLEN which is then overwritten with the new path string.
 363  */
 364 static const char *
 365 path_canon(char *path, const char *s)
 366 {
 367         char *p = path;
 368         char *q = p + MAXPATHLEN - 1;
 369 
 370         char old[MAXPATHLEN];
 371         char c;
 372 
 373         (void) strcpy(old, p);
 374         *q = '\0';
 375 
 376         while (p < q && (c = *s++) != '\0') {
 377                 if (c == '%') {
 378                         if ((c = *s++) == 'o') {
 379                                 (void) strncpy(p, old, (size_t)(q - p));
 380                                 p += strlen(p);
 381                         } else {
 382                                 *p++ = '%';
 383                                 if (p < q && c != '\0')
 384                                         *p++ = c;
 385                                 else
 386                                         break;
 387                         }
 388                 } else
 389                         *p++ = c;
 390         }
 391 
 392         *p = '\0';
 393         return (path);
 394 }
 395 
 396 void
 397 mdb_set_ipath(const char *path)
 398 {
 399         if (mdb.m_ipath != NULL)
 400                 mdb_path_free(mdb.m_ipath, mdb.m_ipathlen);
 401 
 402         path = path_canon(mdb.m_ipathstr, path);
 403         mdb.m_ipath = mdb_path_alloc(path, &mdb.m_ipathlen);
 404 }
 405 
 406 void
 407 mdb_set_lpath(const char *path)
 408 {
 409         if (mdb.m_lpath != NULL)
 410                 mdb_path_free(mdb.m_lpath, mdb.m_lpathlen);
 411 
 412         path = path_canon(mdb.m_lpathstr, path);
 413         mdb.m_lpath = mdb_path_alloc(path, &mdb.m_lpathlen);
 414 
 415 #ifdef _KMDB
 416         kmdb_module_path_set(mdb.m_lpath, mdb.m_lpathlen);
 417 #endif
 418 }
 419 
 420 static void
 421 prompt_update(void)
 422 {
 423         (void) mdb_snprintf(mdb.m_prompt, sizeof (mdb.m_prompt),
 424             mdb.m_promptraw);
 425         mdb.m_promptlen = strlen(mdb.m_prompt);
 426 }
 427 
 428 const char *
 429 mdb_get_prompt(void)
 430 {
 431         if (mdb.m_promptlen == 0)
 432                 return (NULL);
 433         else
 434                 return (mdb.m_prompt);
 435 }
 436 
 437 int
 438 mdb_set_prompt(const char *p)
 439 {
 440         size_t len = strlen(p);
 441 
 442         if (len > MDB_PROMPTLEN) {
 443                 warn("prompt may not exceed %d characters\n", MDB_PROMPTLEN);
 444                 return (0);
 445         }
 446 
 447         (void) strcpy(mdb.m_promptraw, p);
 448         prompt_update();
 449         return (1);
 450 }
 451 
 452 static mdb_frame_t frame0;
 453 
 454 void
 455 mdb_create(const char *execname, const char *arg0)
 456 {
 457         static const mdb_nv_disc_t psym_disc = { psym_disc_set, psym_disc_get };
 458         static const mdb_nv_disc_t roff_disc = { roff_disc_set, roff_disc_get };
 459         static const mdb_nv_disc_t thr_disc = { NULL, thr_disc_get };
 460 
 461         static char rootdir[MAXPATHLEN];
 462 
 463         const mdb_dcmd_t *dcp;
 464         int i;
 465 
 466         bzero(&mdb, sizeof (mdb_t));
 467 
 468         mdb.m_flags = MDB_FL_PSYM | MDB_FL_PAGER | MDB_FL_BPTNOSYMSTOP |
 469             MDB_FL_READBACK;
 470         mdb.m_radix = MDB_DEF_RADIX;
 471         mdb.m_nargs = MDB_DEF_NARGS;
 472         mdb.m_histlen = MDB_DEF_HISTLEN;
 473         mdb.m_armemlim = MDB_DEF_ARRMEM;
 474         mdb.m_arstrlim = MDB_DEF_ARRSTR;
 475 
 476         mdb.m_pname = strbasename(arg0);
 477         if (strcmp(mdb.m_pname, "adb") == 0) {
 478                 mdb.m_flags |= MDB_FL_NOMODS | MDB_FL_ADB | MDB_FL_REPLAST;
 479                 mdb.m_flags &= ~MDB_FL_PAGER;
 480         }
 481 
 482         mdb.m_ipathstr = mdb_zalloc(MAXPATHLEN, UM_SLEEP);
 483         mdb.m_lpathstr = mdb_zalloc(MAXPATHLEN, UM_SLEEP);
 484 
 485         (void) strncpy(rootdir, execname, sizeof (rootdir));
 486         rootdir[sizeof (rootdir) - 1] = '\0';
 487         (void) strdirname(rootdir);
 488 
 489         if (strcmp(strbasename(rootdir), "sparcv9") == 0 ||
 490             strcmp(strbasename(rootdir), "sparcv7") == 0 ||
 491             strcmp(strbasename(rootdir), "amd64") == 0 ||
 492             strcmp(strbasename(rootdir), "i86") == 0)
 493                 (void) strdirname(rootdir);
 494 
 495         if (strcmp(strbasename(rootdir), "bin") == 0) {
 496                 (void) strdirname(rootdir);
 497                 if (strcmp(strbasename(rootdir), "usr") == 0)
 498                         (void) strdirname(rootdir);
 499         } else
 500                 (void) strcpy(rootdir, "/");
 501 
 502         mdb.m_root = rootdir;
 503 
 504         mdb.m_rminfo.mi_dvers = MDB_API_VERSION;
 505         mdb.m_rminfo.mi_dcmds = mdb_dcmd_builtins;
 506         mdb.m_rminfo.mi_walkers = NULL;
 507 
 508         (void) mdb_nv_create(&mdb.m_rmod.mod_walkers, UM_SLEEP);
 509         (void) mdb_nv_create(&mdb.m_rmod.mod_dcmds, UM_SLEEP);
 510 
 511         mdb.m_rmod.mod_name = mdb.m_pname;
 512         mdb.m_rmod.mod_info = &mdb.m_rminfo;
 513 
 514         (void) mdb_nv_create(&mdb.m_disasms, UM_SLEEP);
 515         (void) mdb_nv_create(&mdb.m_modules, UM_SLEEP);
 516         (void) mdb_nv_create(&mdb.m_dcmds, UM_SLEEP);
 517         (void) mdb_nv_create(&mdb.m_walkers, UM_SLEEP);
 518         (void) mdb_nv_create(&mdb.m_nv, UM_SLEEP);
 519 
 520         mdb.m_dot = mdb_nv_insert(&mdb.m_nv, ".", NULL, 0, MDB_NV_PERSIST);
 521         mdb.m_rvalue = mdb_nv_insert(&mdb.m_nv, "0", NULL, 0, MDB_NV_PERSIST);
 522 
 523         mdb.m_roffset =
 524             mdb_nv_insert(&mdb.m_nv, "1", &roff_disc, 0, MDB_NV_PERSIST);
 525 
 526         mdb.m_proffset = mdb_nv_insert(&mdb.m_nv, "2", NULL, 0, MDB_NV_PERSIST);
 527         mdb.m_rcount = mdb_nv_insert(&mdb.m_nv, "9", NULL, 0, MDB_NV_PERSIST);
 528 
 529         (void) mdb_nv_insert(&mdb.m_nv, "b", NULL, 0, MDB_NV_PERSIST);
 530         (void) mdb_nv_insert(&mdb.m_nv, "d", NULL, 0, MDB_NV_PERSIST);
 531         (void) mdb_nv_insert(&mdb.m_nv, "e", NULL, 0, MDB_NV_PERSIST);
 532         (void) mdb_nv_insert(&mdb.m_nv, "m", NULL, 0, MDB_NV_PERSIST);
 533         (void) mdb_nv_insert(&mdb.m_nv, "t", NULL, 0, MDB_NV_PERSIST);
 534         (void) mdb_nv_insert(&mdb.m_nv, "_", &psym_disc, 0, MDB_NV_PERSIST);
 535         (void) mdb_nv_insert(&mdb.m_nv, "hits", NULL, 0, MDB_NV_PERSIST);
 536 
 537         (void) mdb_nv_insert(&mdb.m_nv, "thread", &thr_disc, 0,
 538             MDB_NV_PERSIST | MDB_NV_RDONLY);
 539 
 540         mdb.m_prsym = mdb_gelf_symtab_create_mutable();
 541 
 542         (void) mdb_nv_insert(&mdb.m_modules, mdb.m_pname, NULL,
 543             (uintptr_t)&mdb.m_rmod, MDB_NV_RDONLY);
 544 
 545         for (dcp = &mdb_dcmd_builtins[0]; dcp->dc_name != NULL; dcp++)
 546                 (void) mdb_module_add_dcmd(&mdb.m_rmod, dcp, 0);
 547 
 548         for (i = 0; mdb_dis_builtins[i] != NULL; i++)
 549                 (void) mdb_dis_create(mdb_dis_builtins[i]);
 550 
 551         mdb_macalias_create();
 552 
 553         mdb_create_builtin_tgts();
 554 
 555         (void) mdb_callb_add(NULL, MDB_CALLB_PROMPT, (mdb_callb_f)prompt_update,
 556             NULL);
 557 
 558         /*
 559          * The call to ctf_create that this does can in fact fail, but that's
 560          * okay. All of the ctf functions that might use the synthetic types
 561          * make sure that this is safe.
 562          */
 563         (void) mdb_ctf_synthetics_init();
 564 
 565 #ifdef _KMDB
 566         (void) mdb_nv_create(&mdb.m_dmodctl, UM_SLEEP);
 567 #endif
 568         mdb_lex_state_create(&frame0);
 569 
 570         mdb_list_append(&mdb.m_flist, &frame0);
 571         mdb.m_frame = &frame0;
 572 }
 573 
 574 void
 575 mdb_destroy(void)
 576 {
 577         const mdb_dcmd_t *dcp;
 578         mdb_var_t *v;
 579         int unload_mode = MDB_MOD_SILENT;
 580 
 581 #ifdef _KMDB
 582         unload_mode |= MDB_MOD_DEFER;
 583 #endif
 584 
 585         mdb_intr_disable();
 586 
 587         mdb_ctf_synthetics_fini();
 588 
 589         mdb_macalias_destroy();
 590 
 591         /*
 592          * Some targets use modules during ->t_destroy, so do it first.
 593          */
 594         if (mdb.m_target != NULL)
 595                 (void) mdb_tgt_destroy(mdb.m_target);
 596 
 597         /*
 598          * Unload modules _before_ destroying the disassemblers since a
 599          * module that installs a disassembler should try to clean up after
 600          * itself.
 601          */
 602         mdb_module_unload_all(unload_mode);
 603 
 604         mdb_nv_rewind(&mdb.m_disasms);
 605         while ((v = mdb_nv_advance(&mdb.m_disasms)) != NULL)
 606                 mdb_dis_destroy(mdb_nv_get_cookie(v));
 607 
 608         mdb_callb_remove_all();
 609 
 610         if (mdb.m_defdisasm != NULL)
 611                 strfree(mdb.m_defdisasm);
 612 
 613         if (mdb.m_prsym != NULL)
 614                 mdb_gelf_symtab_destroy(mdb.m_prsym);
 615 
 616         for (dcp = &mdb_dcmd_builtins[0]; dcp->dc_name != NULL; dcp++)
 617                 (void) mdb_module_remove_dcmd(&mdb.m_rmod, dcp->dc_name);
 618 
 619         mdb_nv_destroy(&mdb.m_nv);
 620         mdb_nv_destroy(&mdb.m_walkers);
 621         mdb_nv_destroy(&mdb.m_dcmds);
 622         mdb_nv_destroy(&mdb.m_modules);
 623         mdb_nv_destroy(&mdb.m_disasms);
 624 
 625         mdb_free(mdb.m_ipathstr, MAXPATHLEN);
 626         mdb_free(mdb.m_lpathstr, MAXPATHLEN);
 627 
 628         if (mdb.m_ipath != NULL)
 629                 mdb_path_free(mdb.m_ipath, mdb.m_ipathlen);
 630 
 631         if (mdb.m_lpath != NULL)
 632                 mdb_path_free(mdb.m_lpath, mdb.m_lpathlen);
 633 
 634         if (mdb.m_in != NULL)
 635                 mdb_iob_destroy(mdb.m_in);
 636 
 637         mdb_iob_destroy(mdb.m_out);
 638         mdb.m_out = NULL;
 639         mdb_iob_destroy(mdb.m_err);
 640         mdb.m_err = NULL;
 641 
 642         if (mdb.m_log != NULL)
 643                 mdb_io_rele(mdb.m_log);
 644 
 645         mdb_lex_state_destroy(&frame0);
 646 }
 647 
 648 /*
 649  * The real main loop of the debugger: create a new execution frame on the
 650  * debugger stack, and while we have input available, call into the parser.
 651  */
 652 int
 653 mdb_run(void)
 654 {
 655         volatile int err;
 656         mdb_frame_t f;
 657 
 658         mdb_intr_disable();
 659         mdb_frame_push(&f);
 660 
 661         /*
 662          * This is a fresh mdb context, so ignore any pipe command we may have
 663          * inherited from the previous frame.
 664          */
 665         f.f_pcmd = NULL;
 666 
 667         if ((err = setjmp(f.f_pcb)) != 0) {
 668                 int pop = (mdb.m_in != NULL &&
 669                     (mdb_iob_isapipe(mdb.m_in) || mdb_iob_isastr(mdb.m_in)));
 670                 int fromcmd = (f.f_cp != NULL);
 671 
 672                 mdb_dprintf(MDB_DBG_DSTK, "frame <%u> caught event %s\n",
 673                     f.f_id, mdb_err2str(err));
 674 
 675                 /*
 676                  * If a syntax error or other failure has occurred, pop all
 677                  * input buffers pushed by commands executed in this frame.
 678                  */
 679                 while (mdb_iob_stack_size(&f.f_istk) != 0) {
 680                         if (mdb.m_in != NULL)
 681                                 mdb_iob_destroy(mdb.m_in);
 682                         mdb.m_in = mdb_iob_stack_pop(&f.f_istk);
 683                         yylineno = mdb_iob_lineno(mdb.m_in);
 684                 }
 685 
 686                 /*
 687                  * Reset standard output and the current frame to a known,
 688                  * clean state, so we can continue execution.
 689                  */
 690                 mdb_iob_margin(mdb.m_out, MDB_IOB_DEFMARGIN);
 691                 mdb_iob_clrflags(mdb.m_out, MDB_IOB_INDENT);
 692                 mdb_iob_discard(mdb.m_out);
 693                 mdb_frame_reset(&f);
 694 
 695                 /*
 696                  * If there was an error writing to output, display a warning
 697                  * message if this is the topmost frame.
 698                  */
 699                 if (err == MDB_ERR_OUTPUT && mdb.m_depth == 1 && errno != EPIPE)
 700                         mdb_warn("write failed");
 701 
 702                 /*
 703                  * If an interrupt or quit signal is reported, we may have been
 704                  * in the middle of typing or processing the command line:
 705                  * print a newline and discard everything in the parser's iob.
 706                  * Note that we do this after m_out has been reset, otherwise
 707                  * we could trigger a pipe context switch or cause a write
 708                  * to a broken pipe (in the case of a shell command) when
 709                  * writing the newline.
 710                  */
 711                 if (err == MDB_ERR_SIGINT || err == MDB_ERR_QUIT) {
 712                         mdb_iob_nl(mdb.m_out);
 713                         yydiscard();
 714                 }
 715 
 716                 /*
 717                  * If we quit or abort using the output pager, reset the
 718                  * line count on standard output back to zero.
 719                  */
 720                 if (err == MDB_ERR_PAGER || MDB_ERR_IS_FATAL(err))
 721                         mdb_iob_clearlines(mdb.m_out);
 722 
 723                 /*
 724                  * If the user requested the debugger quit or abort back to
 725                  * the top, or if standard input is a pipe or mdb_eval("..."),
 726                  * then propagate the error up the debugger stack.
 727                  */
 728                 if (MDB_ERR_IS_FATAL(err) || pop != 0 ||
 729                     (err == MDB_ERR_PAGER && mdb.m_fmark != &f) ||
 730                     (err == MDB_ERR_NOMEM && !fromcmd)) {
 731                         mdb_frame_pop(&f, err);
 732                         return (err);
 733                 }
 734 
 735                 /*
 736                  * If we've returned here from a context where signals were
 737                  * blocked (e.g. a signal handler), we can now unblock them.
 738                  */
 739                 if (err == MDB_ERR_SIGINT)
 740                         (void) mdb_signal_unblock(SIGINT);
 741         } else
 742                 mdb_intr_enable();
 743 
 744         for (;;) {
 745                 while (mdb.m_in != NULL && (mdb_iob_getflags(mdb.m_in) &
 746                     (MDB_IOB_ERR | MDB_IOB_EOF)) == 0) {
 747                         if (mdb.m_depth == 1 &&
 748                             mdb_iob_stack_size(&f.f_istk) == 0) {
 749                                 mdb_iob_clearlines(mdb.m_out);
 750                                 mdb_tgt_periodic(mdb.m_target);
 751                         }
 752 
 753                         (void) yyparse();
 754                 }
 755 
 756                 if (mdb.m_in != NULL) {
 757                         if (mdb_iob_err(mdb.m_in)) {
 758                                 warn("error reading input stream %s\n",
 759                                     mdb_iob_name(mdb.m_in));
 760                         }
 761                         mdb_iob_destroy(mdb.m_in);
 762                         mdb.m_in = NULL;
 763                 }
 764 
 765                 if (mdb_iob_stack_size(&f.f_istk) == 0)
 766                         break; /* return when we're out of input */
 767 
 768                 mdb.m_in = mdb_iob_stack_pop(&f.f_istk);
 769                 yylineno = mdb_iob_lineno(mdb.m_in);
 770         }
 771 
 772         mdb_frame_pop(&f, 0);
 773 
 774         /*
 775          * The value of '.' is a per-frame attribute, to preserve it properly
 776          * when switching frames.  But in the case of calling mdb_run()
 777          * explicitly (such as through mdb_eval), we want to propagate the value
 778          * of '.' to the parent.
 779          */
 780         mdb_nv_set_value(mdb.m_dot, f.f_dot);
 781 
 782         return (0);
 783 }
 784 
 785 /*
 786  * The read-side of the pipe executes this service routine.  We simply call
 787  * mdb_run to create a new frame on the execution stack and run the MDB parser,
 788  * and then propagate any error code back to the previous frame.
 789  */
 790 static int
 791 runsvc(void)
 792 {
 793         int err = mdb_run();
 794 
 795         if (err != 0) {
 796                 mdb_dprintf(MDB_DBG_DSTK, "forwarding error %s from pipeline\n",
 797                     mdb_err2str(err));
 798                 longjmp(mdb.m_frame->f_pcb, err);
 799         }
 800 
 801         return (err);
 802 }
 803 
 804 /*
 805  * Read-side pipe service routine: if we longjmp here, just return to the read
 806  * routine because now we have more data to consume.  Otherwise:
 807  * (1) if ctx_data is non-NULL, longjmp to the write-side to produce more data;
 808  * (2) if wriob is NULL, there is no writer but this is the first read, so we
 809  *     can just execute mdb_run() to completion on the current stack;
 810  * (3) if (1) and (2) are false, then there is a writer and this is the first
 811  *     read, so create a co-routine context to execute mdb_run().
 812  */
 813 /*ARGSUSED*/
 814 static void
 815 rdsvc(mdb_iob_t *rdiob, mdb_iob_t *wriob, mdb_iob_ctx_t *ctx)
 816 {
 817         if (setjmp(ctx->ctx_rpcb) == 0) {
 818                 /*
 819                  * Save the current standard input into the pipe context, and
 820                  * reset m_in to point to the pipe.  We will restore it on
 821                  * the way back in wrsvc() below.
 822                  */
 823                 ctx->ctx_iob = mdb.m_in;
 824                 mdb.m_in = rdiob;
 825 
 826                 ctx->ctx_rptr = mdb.m_frame;
 827                 if (ctx->ctx_wptr != NULL)
 828                         mdb_frame_switch(ctx->ctx_wptr);
 829 
 830                 if (ctx->ctx_data != NULL)
 831                         longjmp(ctx->ctx_wpcb, 1);
 832                 else if (wriob == NULL)
 833                         (void) runsvc();
 834                 else if ((ctx->ctx_data = mdb_context_create(runsvc)) != NULL)
 835                         mdb_context_switch(ctx->ctx_data);
 836                 else
 837                         mdb_warn("failed to create pipe context");
 838         }
 839 }
 840 
 841 /*
 842  * Write-side pipe service routine: if we longjmp here, just return to the
 843  * write routine because now we have free space in the pipe buffer for writing;
 844  * otherwise longjmp to the read-side to consume data and create space for us.
 845  */
 846 /*ARGSUSED*/
 847 static void
 848 wrsvc(mdb_iob_t *rdiob, mdb_iob_t *wriob, mdb_iob_ctx_t *ctx)
 849 {
 850         if (setjmp(ctx->ctx_wpcb) == 0) {
 851                 ctx->ctx_wptr = mdb.m_frame;
 852                 if (ctx->ctx_rptr != NULL)
 853                         mdb_frame_switch(ctx->ctx_rptr);
 854 
 855                 mdb.m_in = ctx->ctx_iob;
 856                 longjmp(ctx->ctx_rpcb, 1);
 857         }
 858 }
 859 
 860 /*
 861  * Call the current frame's mdb command.  This entry point is used by the
 862  * MDB parser to actually execute a command once it has successfully parsed
 863  * a line of input.  The command is waiting for us in the current frame.
 864  * We loop through each command on the list, executing its dcmd with the
 865  * appropriate argument.  If the command has a successor, we know it had
 866  * a | operator after it, and so we need to create a pipe and replace
 867  * stdout with the pipe's output buffer.
 868  */
 869 int
 870 mdb_call(uintmax_t addr, uintmax_t count, uint_t flags)
 871 {
 872         mdb_frame_t *fp = mdb.m_frame;
 873         mdb_cmd_t *cp, *ncp;
 874         mdb_iob_t *iobs[2];
 875         int status, err = 0;
 876         jmp_buf pcb;
 877 
 878         if (mdb_iob_isapipe(mdb.m_in))
 879                 yyerror("syntax error");
 880 
 881         mdb_intr_disable();
 882         fp->f_cp = mdb_list_next(&fp->f_cmds);
 883 
 884         if (flags & DCMD_LOOP)
 885                 flags |= DCMD_LOOPFIRST; /* set LOOPFIRST if this is a loop */
 886 
 887         for (cp = mdb_list_next(&fp->f_cmds); cp; cp = mdb_list_next(cp)) {
 888                 if (mdb_list_next(cp) != NULL) {
 889                         mdb_iob_pipe(iobs, rdsvc, wrsvc);
 890 
 891                         mdb_iob_stack_push(&fp->f_istk, mdb.m_in, yylineno);
 892                         mdb.m_in = iobs[MDB_IOB_RDIOB];
 893 
 894                         mdb_iob_stack_push(&fp->f_ostk, mdb.m_out, 0);
 895                         mdb.m_out = iobs[MDB_IOB_WRIOB];
 896 
 897                         ncp = mdb_list_next(cp);
 898                         mdb_vcb_inherit(cp, ncp);
 899 
 900                         bcopy(fp->f_pcb, pcb, sizeof (jmp_buf));
 901                         ASSERT(fp->f_pcmd == NULL);
 902                         fp->f_pcmd = ncp;
 903 
 904                         mdb_frame_set_pipe(fp);
 905 
 906                         if ((err = setjmp(fp->f_pcb)) == 0) {
 907                                 status = mdb_call_idcmd(cp->c_dcmd, addr, count,
 908                                     flags | DCMD_PIPE_OUT, &cp->c_argv,
 909                                     &cp->c_addrv, cp->c_vcbs);
 910 
 911                                 mdb.m_lastret = status;
 912 
 913                                 ASSERT(mdb.m_in == iobs[MDB_IOB_RDIOB]);
 914                                 ASSERT(mdb.m_out == iobs[MDB_IOB_WRIOB]);
 915                         } else {
 916                                 mdb_dprintf(MDB_DBG_DSTK, "frame <%u> caught "
 917                                     "error %s from pipeline\n", fp->f_id,
 918                                     mdb_err2str(err));
 919                         }
 920 
 921                         if (err != 0 || DCMD_ABORTED(status)) {
 922                                 mdb_iob_setflags(mdb.m_in, MDB_IOB_ERR);
 923                                 mdb_iob_setflags(mdb.m_out, MDB_IOB_ERR);
 924                         } else {
 925                                 mdb_iob_flush(mdb.m_out);
 926                                 (void) mdb_iob_ctl(mdb.m_out, I_FLUSH,
 927                                     (void *)FLUSHW);
 928                         }
 929 
 930                         mdb_frame_clear_pipe(fp);
 931 
 932                         mdb_iob_destroy(mdb.m_out);
 933                         mdb.m_out = mdb_iob_stack_pop(&fp->f_ostk);
 934 
 935                         if (mdb.m_in != NULL)
 936                                 mdb_iob_destroy(mdb.m_in);
 937 
 938                         mdb.m_in = mdb_iob_stack_pop(&fp->f_istk);
 939                         yylineno = mdb_iob_lineno(mdb.m_in);
 940 
 941                         fp->f_pcmd = NULL;
 942                         bcopy(pcb, fp->f_pcb, sizeof (jmp_buf));
 943 
 944                         if (MDB_ERR_IS_FATAL(err))
 945                                 longjmp(fp->f_pcb, err);
 946 
 947                         if (err != 0 || DCMD_ABORTED(status) ||
 948                             mdb_addrvec_length(&ncp->c_addrv) == 0)
 949                                 break;
 950 
 951                         addr = mdb_nv_get_value(mdb.m_dot);
 952                         count = 1;
 953                         flags = 0;
 954 
 955                 } else {
 956                         mdb_intr_enable();
 957                         mdb.m_lastret = mdb_call_idcmd(cp->c_dcmd, addr, count,
 958                             flags, &cp->c_argv, &cp->c_addrv, cp->c_vcbs);
 959                         mdb_intr_disable();
 960                 }
 961 
 962                 fp->f_cp = mdb_list_next(cp);
 963                 mdb_cmd_reset(cp);
 964         }
 965 
 966         /*
 967          * If our last-command list is non-empty, destroy it.  Then copy the
 968          * current frame's cmd list to the m_lastc list and reset the frame.
 969          */
 970         while ((cp = mdb_list_next(&mdb.m_lastc)) != NULL) {
 971                 mdb_list_delete(&mdb.m_lastc, cp);
 972                 mdb_cmd_destroy(cp);
 973         }
 974 
 975         mdb_list_move(&fp->f_cmds, &mdb.m_lastc);
 976         mdb_frame_reset(fp);
 977         mdb_intr_enable();
 978         return (err == 0);
 979 }
 980 
 981 uintmax_t
 982 mdb_dot_incr(const char *op)
 983 {
 984         uintmax_t odot, ndot;
 985 
 986         odot = mdb_nv_get_value(mdb.m_dot);
 987         ndot = odot + mdb.m_incr;
 988 
 989         if ((odot ^ ndot) & 0x8000000000000000ull)
 990                 yyerror("'%s' would cause '.' to overflow\n", op);
 991 
 992         return (ndot);
 993 }
 994 
 995 uintmax_t
 996 mdb_dot_decr(const char *op)
 997 {
 998         uintmax_t odot, ndot;
 999 
1000         odot = mdb_nv_get_value(mdb.m_dot);
1001         ndot = odot - mdb.m_incr;
1002 
1003         if (ndot > odot)
1004                 yyerror("'%s' would cause '.' to underflow\n", op);
1005 
1006         return (ndot);
1007 }
1008 
1009 mdb_iwalker_t *
1010 mdb_walker_lookup(const char *s)
1011 {
1012         const char *p = strchr(s, '`');
1013         mdb_var_t *v;
1014 
1015         if (p != NULL) {
1016                 size_t nbytes = MIN((size_t)(p - s), MDB_NV_NAMELEN - 1);
1017                 char mname[MDB_NV_NAMELEN];
1018                 mdb_module_t *mod;
1019 
1020                 (void) strncpy(mname, s, nbytes);
1021                 mname[nbytes] = '\0';
1022 
1023                 if ((v = mdb_nv_lookup(&mdb.m_modules, mname)) == NULL) {
1024                         (void) set_errno(EMDB_NOMOD);
1025                         return (NULL);
1026                 }
1027 
1028                 mod = mdb_nv_get_cookie(v);
1029 
1030                 if ((v = mdb_nv_lookup(&mod->mod_walkers, ++p)) != NULL)
1031                         return (mdb_nv_get_cookie(v));
1032 
1033         } else if ((v = mdb_nv_lookup(&mdb.m_walkers, s)) != NULL)
1034                 return (mdb_nv_get_cookie(mdb_nv_get_cookie(v)));
1035 
1036         (void) set_errno(EMDB_NOWALK);
1037         return (NULL);
1038 }
1039 
1040 mdb_idcmd_t *
1041 mdb_dcmd_lookup(const char *s)
1042 {
1043         const char *p = strchr(s, '`');
1044         mdb_var_t *v;
1045 
1046         if (p != NULL) {
1047                 size_t nbytes = MIN((size_t)(p - s), MDB_NV_NAMELEN - 1);
1048                 char mname[MDB_NV_NAMELEN];
1049                 mdb_module_t *mod;
1050 
1051                 (void) strncpy(mname, s, nbytes);
1052                 mname[nbytes] = '\0';
1053 
1054                 if ((v = mdb_nv_lookup(&mdb.m_modules, mname)) == NULL) {
1055                         (void) set_errno(EMDB_NOMOD);
1056                         return (NULL);
1057                 }
1058 
1059                 mod = mdb_nv_get_cookie(v);
1060 
1061                 if ((v = mdb_nv_lookup(&mod->mod_dcmds, ++p)) != NULL)
1062                         return (mdb_nv_get_cookie(v));
1063 
1064         } else if ((v = mdb_nv_lookup(&mdb.m_dcmds, s)) != NULL)
1065                 return (mdb_nv_get_cookie(mdb_nv_get_cookie(v)));
1066 
1067         (void) set_errno(EMDB_NODCMD);
1068         return (NULL);
1069 }
1070 
1071 void
1072 mdb_dcmd_usage(const mdb_idcmd_t *idcp, mdb_iob_t *iob)
1073 {
1074         const char *prefix = "", *usage = "";
1075         char name0 = idcp->idc_name[0];
1076 
1077         if (idcp->idc_usage != NULL) {
1078                 if (idcp->idc_usage[0] == ':') {
1079                         if (name0 != ':' && name0 != '$')
1080                                 prefix = "address::";
1081                         else
1082                                 prefix = "address";
1083                         usage = &idcp->idc_usage[1];
1084 
1085                 } else if (idcp->idc_usage[0] == '?') {
1086                         if (name0 != ':' && name0 != '$')
1087                                 prefix = "[address]::";
1088                         else
1089                                 prefix = "[address]";
1090                         usage = &idcp->idc_usage[1];
1091 
1092                 } else
1093                         usage = idcp->idc_usage;
1094         }
1095 
1096         mdb_iob_printf(iob, "Usage: %s%s %s\n", prefix, idcp->idc_name, usage);
1097 
1098         if (idcp->idc_help != NULL) {
1099                 mdb_iob_printf(iob, "%s: try '::help %s' for more "
1100                     "information\n", mdb.m_pname, idcp->idc_name);
1101         }
1102 }
1103 
1104 static mdb_idcmd_t *
1105 dcmd_ndef(const mdb_idcmd_t *idcp)
1106 {
1107         mdb_var_t *v = mdb_nv_get_ndef(idcp->idc_var);
1108 
1109         if (v != NULL)
1110                 return (mdb_nv_get_cookie(mdb_nv_get_cookie(v)));
1111 
1112         return (NULL);
1113 }
1114 
1115 static int
1116 dcmd_invoke(mdb_idcmd_t *idcp, uintptr_t addr, uint_t flags,
1117     int argc, const mdb_arg_t *argv, const mdb_vcb_t *vcbs)
1118 {
1119         int status;
1120 
1121         mdb_dprintf(MDB_DBG_DCMD, "dcmd %s`%s dot = %lr incr = %llr\n",
1122             idcp->idc_modp->mod_name, idcp->idc_name, addr, mdb.m_incr);
1123 
1124         if ((status = idcp->idc_funcp(addr, flags, argc, argv)) == DCMD_USAGE) {
1125                 mdb_dcmd_usage(idcp, mdb.m_err);
1126                 goto done;
1127         }
1128 
1129         while (status == DCMD_NEXT && (idcp = dcmd_ndef(idcp)) != NULL)
1130                 status = idcp->idc_funcp(addr, flags, argc, argv);
1131 
1132         if (status == DCMD_USAGE)
1133                 mdb_dcmd_usage(idcp, mdb.m_err);
1134 
1135         if (status == DCMD_NEXT)
1136                 status = DCMD_OK;
1137 done:
1138         /*
1139          * If standard output is a pipe and there are vcbs active, we need to
1140          * flush standard out and the write-side of the pipe.  The reasons for
1141          * this are explained in more detail in mdb_vcb.c.
1142          */
1143         if ((flags & DCMD_PIPE_OUT) && (vcbs != NULL)) {
1144                 mdb_iob_flush(mdb.m_out);
1145                 (void) mdb_iob_ctl(mdb.m_out, I_FLUSH, (void *)FLUSHW);
1146         }
1147 
1148         return (status);
1149 }
1150 
1151 void
1152 mdb_call_tab(mdb_idcmd_t *idcp, mdb_tab_cookie_t *mcp, uint_t flags,
1153     uintmax_t argc, mdb_arg_t *argv)
1154 {
1155         if (idcp->idc_tabp == NULL)
1156                 return;
1157 
1158         idcp->idc_tabp(mcp, flags, argc, argv);
1159 }
1160 
1161 /*
1162  * Call an internal dcmd directly: this code is used by module API functions
1163  * that need to execute dcmds, and by mdb_call() above.
1164  */
1165 int
1166 mdb_call_idcmd(mdb_idcmd_t *idcp, uintmax_t addr, uintmax_t count,
1167     uint_t flags, mdb_argvec_t *avp, mdb_addrvec_t *adp, mdb_vcb_t *vcbs)
1168 {
1169         int is_exec = (strcmp(idcp->idc_name, "$<") == 0);
1170         mdb_arg_t *argv;
1171         int argc;
1172         uintmax_t i;
1173         int status;
1174 
1175         /*
1176          * Update the values of dot and the most recent address and count
1177          * to the values of our input parameters.
1178          */
1179         mdb_nv_set_value(mdb.m_dot, addr);
1180         mdb.m_raddr = addr;
1181         mdb.m_dcount = count;
1182 
1183         /*
1184          * Here the adb(1) man page lies: '9' is only set to count
1185          * when the command is $<, not when it's $<<.
1186          */
1187         if (is_exec)
1188                 mdb_nv_set_value(mdb.m_rcount, count);
1189 
1190         /*
1191          * We can now return if the repeat count is zero.
1192          */
1193         if (count == 0)
1194                 return (DCMD_OK);
1195 
1196         /*
1197          * To guard against bad dcmds, we avoid passing the actual argv that
1198          * we will use to free argument strings directly to the dcmd.  Instead,
1199          * we pass a copy that will be garbage collected automatically.
1200          */
1201         argc = avp->a_nelems;
1202         argv = mdb_alloc(sizeof (mdb_arg_t) * argc, UM_SLEEP | UM_GC);
1203         bcopy(avp->a_data, argv, sizeof (mdb_arg_t) * argc);
1204 
1205         if (mdb_addrvec_length(adp) != 0) {
1206                 flags |= DCMD_PIPE | DCMD_LOOP | DCMD_LOOPFIRST | DCMD_ADDRSPEC;
1207                 addr = mdb_addrvec_shift(adp);
1208                 mdb_nv_set_value(mdb.m_dot, addr);
1209                 mdb_vcb_propagate(vcbs);
1210                 count = 1;
1211         }
1212 
1213         status = dcmd_invoke(idcp, addr, flags, argc, argv, vcbs);
1214         if (DCMD_ABORTED(status))
1215                 goto done;
1216 
1217         /*
1218          * If the command is $< and we're not receiving input from a pipe, we
1219          * ignore the repeat count and just return since the macro file is now
1220          * pushed on to the input stack.
1221          */
1222         if (is_exec && mdb_addrvec_length(adp) == 0)
1223                 goto done;
1224 
1225         /*
1226          * If we're going to loop, we've already executed the dcmd once,
1227          * so clear the LOOPFIRST flag before proceeding.
1228          */
1229         if (flags & DCMD_LOOP)
1230                 flags &= ~DCMD_LOOPFIRST;
1231 
1232         for (i = 1; i < count; i++) {
1233                 addr = mdb_dot_incr(",");
1234                 mdb_nv_set_value(mdb.m_dot, addr);
1235                 status = dcmd_invoke(idcp, addr, flags, argc, argv, vcbs);
1236                 if (DCMD_ABORTED(status))
1237                         goto done;
1238         }
1239 
1240         while (mdb_addrvec_length(adp) != 0) {
1241                 addr = mdb_addrvec_shift(adp);
1242                 mdb_nv_set_value(mdb.m_dot, addr);
1243                 mdb_vcb_propagate(vcbs);
1244                 status = dcmd_invoke(idcp, addr, flags, argc, argv, vcbs);
1245                 if (DCMD_ABORTED(status))
1246                         goto done;
1247         }
1248 done:
1249         mdb_iob_nlflush(mdb.m_out);
1250         return (status);
1251 }
1252 
1253 void
1254 mdb_intr_enable(void)
1255 {
1256         ASSERT(mdb.m_intr >= 1);
1257         if (mdb.m_intr == 1 && mdb.m_pend != 0) {
1258                 (void) mdb_signal_block(SIGINT);
1259                 mdb.m_intr = mdb.m_pend = 0;
1260                 mdb_dprintf(MDB_DBG_DSTK, "delivering pending INT\n");
1261                 longjmp(mdb.m_frame->f_pcb, MDB_ERR_SIGINT);
1262         } else
1263                 mdb.m_intr--;
1264 }
1265 
1266 void
1267 mdb_intr_disable(void)
1268 {
1269         mdb.m_intr++;
1270         ASSERT(mdb.m_intr >= 1);
1271 }
1272 
1273 /*
1274  * Create an encoded string representing the internal user-modifiable
1275  * configuration of the debugger and return a pointer to it.  The string can be
1276  * used to initialize another instance of the debugger with the same
1277  * configuration as this one.
1278  */
1279 char *
1280 mdb_get_config(void)
1281 {
1282         size_t r, n = 0;
1283         char *s = NULL;
1284 
1285         while ((r = mdb_snprintf(s, n,
1286             "%x;%x;%x;%x;%x;%x;%lx;%x;%x;%s;%s;%s;%s;%s",
1287             mdb.m_tgtflags, mdb.m_flags, mdb.m_debug, mdb.m_radix, mdb.m_nargs,
1288             mdb.m_histlen, (ulong_t)mdb.m_symdist, mdb.m_execmode,
1289             mdb.m_forkmode, mdb.m_root, mdb.m_termtype, mdb.m_ipathstr,
1290             mdb.m_lpathstr, mdb.m_prompt)) > n) {
1291 
1292                 mdb_free(s, n);
1293                 n = r + 1;
1294                 s = mdb_alloc(r + 1, UM_SLEEP);
1295         }
1296 
1297         return (s);
1298 }
1299 
1300 /*
1301  * Decode a configuration string created with mdb_get_config() and reset the
1302  * appropriate parts of the global mdb_t accordingly.
1303  */
1304 void
1305 mdb_set_config(const char *s)
1306 {
1307         const char *p;
1308         size_t len;
1309 
1310         if ((p = strchr(s, ';')) != NULL) {
1311                 mdb.m_tgtflags = strntoul(s, (size_t)(p - s), 16);
1312                 s = p + 1;
1313         }
1314 
1315         if ((p = strchr(s, ';')) != NULL) {
1316                 mdb.m_flags = strntoul(s, (size_t)(p - s), 16);
1317                 mdb.m_flags &= ~(MDB_FL_LOG | MDB_FL_LATEST);
1318                 s = p + 1;
1319         }
1320 
1321         if ((p = strchr(s, ';')) != NULL) {
1322                 mdb.m_debug = strntoul(s, (size_t)(p - s), 16);
1323                 s = p + 1;
1324         }
1325 
1326         if ((p = strchr(s, ';')) != NULL) {
1327                 mdb.m_radix = (int)strntoul(s, (size_t)(p - s), 16);
1328                 if (mdb.m_radix < 2 || mdb.m_radix > 16)
1329                         mdb.m_radix = MDB_DEF_RADIX;
1330                 s = p + 1;
1331         }
1332 
1333         if ((p = strchr(s, ';')) != NULL) {
1334                 mdb.m_nargs = (int)strntoul(s, (size_t)(p - s), 16);
1335                 mdb.m_nargs = MAX(mdb.m_nargs, 0);
1336                 s = p + 1;
1337         }
1338 
1339         if ((p = strchr(s, ';')) != NULL) {
1340                 mdb.m_histlen = (int)strntoul(s, (size_t)(p - s), 16);
1341                 mdb.m_histlen = MAX(mdb.m_histlen, 1);
1342                 s = p + 1;
1343         }
1344 
1345         if ((p = strchr(s, ';')) != NULL) {
1346                 mdb.m_symdist = strntoul(s, (size_t)(p - s), 16);
1347                 s = p + 1;
1348         }
1349 
1350         if ((p = strchr(s, ';')) != NULL) {
1351                 mdb.m_execmode = (uchar_t)strntoul(s, (size_t)(p - s), 16);
1352                 if (mdb.m_execmode > MDB_EM_FOLLOW)
1353                         mdb.m_execmode = MDB_EM_ASK;
1354                 s = p + 1;
1355         }
1356 
1357         if ((p = strchr(s, ';')) != NULL) {
1358                 mdb.m_forkmode = (uchar_t)strntoul(s, (size_t)(p - s), 16);
1359                 if (mdb.m_forkmode > MDB_FM_CHILD)
1360                         mdb.m_forkmode = MDB_FM_ASK;
1361                 s = p + 1;
1362         }
1363 
1364         if ((p = strchr(s, ';')) != NULL) {
1365                 mdb.m_root = strndup(s, (size_t)(p - s));
1366                 s = p + 1;
1367         }
1368 
1369         if ((p = strchr(s, ';')) != NULL) {
1370                 mdb.m_termtype = strndup(s, (size_t)(p - s));
1371                 s = p + 1;
1372         }
1373 
1374         if ((p = strchr(s, ';')) != NULL) {
1375                 size_t len = MIN(sizeof (mdb.m_ipathstr) - 1, p - s);
1376                 (void) strncpy(mdb.m_ipathstr, s, len);
1377                 mdb.m_ipathstr[len] = '\0';
1378                 s = p + 1;
1379         }
1380 
1381         if ((p = strchr(s, ';')) != NULL) {
1382                 size_t len = MIN(sizeof (mdb.m_lpathstr) - 1, p - s);
1383                 (void) strncpy(mdb.m_lpathstr, s, len);
1384                 mdb.m_lpathstr[len] = '\0';
1385                 s = p + 1;
1386         }
1387 
1388         p = s + strlen(s);
1389         len = MIN(MDB_PROMPTLEN, (size_t)(p - s));
1390         (void) strncpy(mdb.m_prompt, s, len);
1391         mdb.m_prompt[len] = '\0';
1392         mdb.m_promptlen = len;
1393 }
1394 
1395 mdb_module_t *
1396 mdb_get_module(void)
1397 {
1398         if (mdb.m_lmod)
1399                 return (mdb.m_lmod);
1400 
1401         if (mdb.m_frame == NULL)
1402                 return (NULL);
1403 
1404         if (mdb.m_frame->f_wcbs && mdb.m_frame->f_wcbs->w_walker &&
1405             mdb.m_frame->f_wcbs->w_walker->iwlk_modp &&
1406             !mdb.m_frame->f_cbactive)
1407                 return (mdb.m_frame->f_wcbs->w_walker->iwlk_modp);
1408 
1409         if (mdb.m_frame->f_cp && mdb.m_frame->f_cp->c_dcmd)
1410                 return (mdb.m_frame->f_cp->c_dcmd->idc_modp);
1411 
1412         return (NULL);
1413 }