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