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