17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
59acbbeann * Common Development and Distribution License (the "License").
69acbbeann * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
22ca3e8d8Dave Plauger * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bdstevel@tonic-gate * Use is subject to license terms.
24ffd958eJosef 'Jeff' Sipek * Copyright 2012, Josef 'Jeff' Sipek <jeffpc@31bits.net>. All rights reserved.
257c478bdstevel@tonic-gate */
267c478bdstevel@tonic-gate
271320cafBryan Cantrill/*
2844bf619John Levon * Copyright 2019 Joyent, Inc.
291320cafBryan Cantrill */
301320cafBryan Cantrill
317c478bdstevel@tonic-gate#include <sys/types.h>
327c478bdstevel@tonic-gate#include <sys/mman.h>
337c478bdstevel@tonic-gate#include <sys/priocntl.h>
347c478bdstevel@tonic-gate#include <sys/rtpriocntl.h>
357c478bdstevel@tonic-gate#include <sys/resource.h>
367c478bdstevel@tonic-gate#include <sys/termios.h>
377c478bdstevel@tonic-gate#include <sys/param.h>
387c478bdstevel@tonic-gate#include <sys/regset.h>
397c478bdstevel@tonic-gate#include <sys/frame.h>
407c478bdstevel@tonic-gate#include <sys/stack.h>
417c478bdstevel@tonic-gate#include <sys/reg.h>
427c478bdstevel@tonic-gate
437c478bdstevel@tonic-gate#include <libproc.h>
447c478bdstevel@tonic-gate#include <libscf.h>
457c478bdstevel@tonic-gate#include <alloca.h>
467c478bdstevel@tonic-gate#include <unistd.h>
477c478bdstevel@tonic-gate#include <string.h>
487c478bdstevel@tonic-gate#include <stdlib.h>
497c478bdstevel@tonic-gate#include <fcntl.h>
507c478bdstevel@tonic-gate#include <dlfcn.h>
517c478bdstevel@tonic-gate#include <libctf.h>
527c478bdstevel@tonic-gate#include <errno.h>
53843e198johnlev#include <kvm.h>
547c478bdstevel@tonic-gate
557c478bdstevel@tonic-gate#include <mdb/mdb_lex.h>
567c478bdstevel@tonic-gate#include <mdb/mdb_debug.h>
577c478bdstevel@tonic-gate#include <mdb/mdb_signal.h>
587c478bdstevel@tonic-gate#include <mdb/mdb_string.h>
597c478bdstevel@tonic-gate#include <mdb/mdb_modapi.h>
607c478bdstevel@tonic-gate#include <mdb/mdb_target.h>
617c478bdstevel@tonic-gate#include <mdb/mdb_gelf.h>
627c478bdstevel@tonic-gate#include <mdb/mdb_conf.h>
637c478bdstevel@tonic-gate#include <mdb/mdb_err.h>
647c478bdstevel@tonic-gate#include <mdb/mdb_io_impl.h>
657c478bdstevel@tonic-gate#include <mdb/mdb_frame.h>
667c478bdstevel@tonic-gate#include <mdb/mdb_set.h>
677c478bdstevel@tonic-gate#include <kmdb/kmdb_kctl.h>
687c478bdstevel@tonic-gate#include <mdb/mdb.h>
697c478bdstevel@tonic-gate
707c478bdstevel@tonic-gate#ifndef STACK_BIAS
717c478bdstevel@tonic-gate#define	STACK_BIAS	0
727c478bdstevel@tonic-gate#endif
737c478bdstevel@tonic-gate
747c478bdstevel@tonic-gate#if defined(__sparc)
757c478bdstevel@tonic-gate#define	STACK_REGISTER	SP
767c478bdstevel@tonic-gate#else
777c478bdstevel@tonic-gate#define	STACK_REGISTER	REG_FP
787c478bdstevel@tonic-gate#endif
797c478bdstevel@tonic-gate
807c478bdstevel@tonic-gate#ifdef _LP64
817c478bdstevel@tonic-gate#define	MDB_DEF_IPATH	\
827c478bdstevel@tonic-gate	"%r/usr/platform/%p/lib/adb/%i:" \
837c478bdstevel@tonic-gate	"%r/usr/platform/%m/lib/adb/%i:" \
847c478bdstevel@tonic-gate	"%r/usr/lib/adb/%i"
857c478bdstevel@tonic-gate#define	MDB_DEF_LPATH	\
867c478bdstevel@tonic-gate	"%r/usr/platform/%p/lib/mdb/%t/%i:" \
877c478bdstevel@tonic-gate	"%r/usr/platform/%m/lib/mdb/%t/%i:" \
887c478bdstevel@tonic-gate	"%r/usr/lib/mdb/%t/%i"
897c478bdstevel@tonic-gate#else
907c478bdstevel@tonic-gate#define	MDB_DEF_IPATH	\
917c478bdstevel@tonic-gate	"%r/usr/platform/%p/lib/adb:" \
927c478bdstevel@tonic-gate	"%r/usr/platform/%m/lib/adb:" \
937c478bdstevel@tonic-gate	"%r/usr/lib/adb"
947c478bdstevel@tonic-gate#define	MDB_DEF_LPATH	\
957c478bdstevel@tonic-gate	"%r/usr/platform/%p/lib/mdb/%t:" \
967c478bdstevel@tonic-gate	"%r/usr/platform/%m/lib/mdb/%t:" \
977c478bdstevel@tonic-gate	"%r/usr/lib/mdb/%t"
987c478bdstevel@tonic-gate#endif
997c478bdstevel@tonic-gate
1007c478bdstevel@tonic-gate#define	MDB_DEF_PROMPT "> "
1017c478bdstevel@tonic-gate
1027c478bdstevel@tonic-gate/*
1037c478bdstevel@tonic-gate * Similar to the panic_* variables in the kernel, we keep some relevant
1047c478bdstevel@tonic-gate * information stored in a set of global _mdb_abort_* variables; in the
1057c478bdstevel@tonic-gate * event that the debugger dumps core, these will aid core dump analysis.
1067c478bdstevel@tonic-gate */
1077c478bdstevel@tonic-gateconst char *volatile _mdb_abort_str;	/* reason for failure */
1087c478bdstevel@tonic-gatesiginfo_t _mdb_abort_info;		/* signal info for fatal signal */
1097c478bdstevel@tonic-gateucontext_t _mdb_abort_ctx;		/* context fatal signal interrupted */
1107c478bdstevel@tonic-gateint _mdb_abort_rcount;			/* number of times resume requested */
1117c478bdstevel@tonic-gateint _mdb_self_fd = -1;			/* fd for self as for valid_frame */
1127c478bdstevel@tonic-gate
113b1da084Toomas Soome__NORETURN static void
1147c478bdstevel@tonic-gateterminate(int status)
1157c478bdstevel@tonic-gate{
11636c835avitezslav batrla - Sun Microsystems - Prague Czech Republic	(void) mdb_signal_blockall();
1177c478bdstevel@tonic-gate	mdb_destroy();
1187c478bdstevel@tonic-gate	exit(status);
1197c478bdstevel@tonic-gate}
1207c478bdstevel@tonic-gate
1217c478bdstevel@tonic-gatestatic void
1227c478bdstevel@tonic-gateprint_frame(uintptr_t pc, int fnum)
1237c478bdstevel@tonic-gate{
1247c478bdstevel@tonic-gate	Dl_info dli;
1257c478bdstevel@tonic-gate
1267c478bdstevel@tonic-gate	if (dladdr((void *)pc, &dli)) {
1277c478bdstevel@tonic-gate		mdb_iob_printf(mdb.m_err, "    [%d] %s`%s+0x%lx()\n", fnum,
1287c478bdstevel@tonic-gate		    strbasename(dli.dli_fname), dli.dli_sname,
1297c478bdstevel@tonic-gate		    pc - (uintptr_t)dli.dli_saddr);
1307c478bdstevel@tonic-gate	} else
1317c478bdstevel@tonic-gate		mdb_iob_printf(mdb.m_err, "    [%d] %p()\n", fnum, pc);
1327c478bdstevel@tonic-gate}
1337c478bdstevel@tonic-gate
1347c478bdstevel@tonic-gatestatic int
1357c478bdstevel@tonic-gatevalid_frame(struct frame *fr)
1367c478bdstevel@tonic-gate{
1377c478bdstevel@tonic-gate	static struct frame fake;
1387c478bdstevel@tonic-gate	uintptr_t addr = (uintptr_t)fr;
1397c478bdstevel@tonic-gate
1407c478bdstevel@tonic-gate	if (pread(_mdb_self_fd, &fake, sizeof (fake), addr) != sizeof (fake)) {
1417c478bdstevel@tonic-gate		mdb_iob_printf(mdb.m_err, "    invalid frame (%p)\n", fr);
1427c478bdstevel@tonic-gate		return (0);
1437c478bdstevel@tonic-gate	}
1447c478bdstevel@tonic-gate
1457c478bdstevel@tonic-gate	if (addr & (STACK_ALIGN - 1)) {
1467c478bdstevel@tonic-gate		mdb_iob_printf(mdb.m_err, "    mis-aligned frame (%p)\n", fr);
1477c478bdstevel@tonic-gate		return (0);
1487c478bdstevel@tonic-gate	}
1497c478bdstevel@tonic-gate
1507c478bdstevel@tonic-gate	return (1);
1517c478bdstevel@tonic-gate}
1527c478bdstevel@tonic-gate
1537c478bdstevel@tonic-gate/*ARGSUSED*/
1547c478bdstevel@tonic-gatestatic void
1557c478bdstevel@tonic-gateflt_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data)
1567c478bdstevel@tonic-gate{
1577c478bdstevel@tonic-gate	static const struct rlimit rl = {
1587c478bdstevel@tonic-gate		(rlim_t)RLIM_INFINITY, (rlim_t)RLIM_INFINITY
1597c478bdstevel@tonic-gate	};
1607c478bdstevel@tonic-gate
1617c478bdstevel@tonic-gate	const mdb_idcmd_t *idcp = NULL;
1627c478bdstevel@tonic-gate
1637c478bdstevel@tonic-gate	if (mdb.m_frame != NULL && mdb.m_frame->f_cp != NULL)
1647c478bdstevel@tonic-gate		idcp = mdb.m_frame->f_cp->c_dcmd;
1657c478bdstevel@tonic-gate
1667c478bdstevel@tonic-gate	if (sip != NULL)
1677c478bdstevel@tonic-gate		bcopy(sip, &_mdb_abort_info, sizeof (_mdb_abort_info));
1687c478bdstevel@tonic-gate	if (ucp != NULL)
1697c478bdstevel@tonic-gate		bcopy(ucp, &_mdb_abort_ctx, sizeof (_mdb_abort_ctx));
1707c478bdstevel@tonic-gate
1717c478bdstevel@tonic-gate	_mdb_abort_info.si_signo = sig;
1727c478bdstevel@tonic-gate	(void) mdb_signal_sethandler(sig, SIG_DFL, NULL);
1737c478bdstevel@tonic-gate
1747c478bdstevel@tonic-gate	/*
1757c478bdstevel@tonic-gate	 * If there is no current dcmd, or the current dcmd comes from a
1767c478bdstevel@tonic-gate	 * builtin module, we don't allow resume and always core dump.
1777c478bdstevel@tonic-gate	 */
1787c478bdstevel@tonic-gate	if (idcp == NULL || idcp->idc_modp == NULL ||
1797c478bdstevel@tonic-gate	    idcp->idc_modp == &mdb.m_rmod || idcp->idc_modp->mod_hdl == NULL)
1807c478bdstevel@tonic-gate		goto dump;
1817c478bdstevel@tonic-gate
1827c478bdstevel@tonic-gate	if (mdb.m_term != NULL) {
1837c478bdstevel@tonic-gate		struct frame *fr = (struct frame *)
1847c478bdstevel@tonic-gate		    (ucp->uc_mcontext.gregs[STACK_REGISTER] + STACK_BIAS);
1857c478bdstevel@tonic-gate
1867c478bdstevel@tonic-gate		char signame[SIG2STR_MAX];
1877c478bdstevel@tonic-gate		int i = 1;
1887c478bdstevel@tonic-gate		char c;
1897c478bdstevel@tonic-gate
1907c478bdstevel@tonic-gate		if (sig2str(sig, signame) == -1) {
1917c478bdstevel@tonic-gate			mdb_iob_printf(mdb.m_err,
1927c478bdstevel@tonic-gate			    "\n*** %s: received signal %d at:\n",
1937c478bdstevel@tonic-gate			    mdb.m_pname, sig);
1947c478bdstevel@tonic-gate		} else {
1957c478bdstevel@tonic-gate			mdb_iob_printf(mdb.m_err,
1967c478bdstevel@tonic-gate			    "\n*** %s: received signal %s at:\n",
1977c478bdstevel@tonic-gate			    mdb.m_pname, signame);
1987c478bdstevel@tonic-gate		}
1997c478bdstevel@tonic-gate
2007c478bdstevel@tonic-gate		if (ucp->uc_mcontext.gregs[REG_PC] != 0)
2017c478bdstevel@tonic-gate			print_frame(ucp->uc_mcontext.gregs[REG_PC], i++);
2027c478bdstevel@tonic-gate
2037c478bdstevel@tonic-gate		while (fr != NULL && valid_frame(fr) && fr->fr_savpc != 0) {
2047c478bdstevel@tonic-gate			print_frame(fr->fr_savpc, i++);
2057c478bdstevel@tonic-gate			fr = (struct frame *)
2067c478bdstevel@tonic-gate			    ((uintptr_t)fr->fr_savfp + STACK_BIAS);
2077c478bdstevel@tonic-gate		}
2087c478bdstevel@tonic-gate
2097c478bdstevel@tonic-gatequery:
2107c478bdstevel@tonic-gate		mdb_iob_printf(mdb.m_err, "\n%s: (c)ore dump, (q)uit, "
2117c478bdstevel@tonic-gate		    "(r)ecover, or (s)top for debugger [cqrs]? ", mdb.m_pname);
2127c478bdstevel@tonic-gate
2137c478bdstevel@tonic-gate		mdb_iob_flush(mdb.m_err);
2147c478bdstevel@tonic-gate
2157c478bdstevel@tonic-gate		for (;;) {
2167c478bdstevel@tonic-gate			if (IOP_READ(mdb.m_term, &c, sizeof (c)) != sizeof (c))
2177c478bdstevel@tonic-gate				goto dump;
2187c478bdstevel@tonic-gate
2197c478bdstevel@tonic-gate			switch (c) {
2207c478bdstevel@tonic-gate			case 'c':
2217c478bdstevel@tonic-gate			case 'C':
2227c478bdstevel@tonic-gate				(void) setrlimit(RLIMIT_CORE, &rl);
2237c478bdstevel@tonic-gate				mdb_iob_printf(mdb.m_err, "\n%s: attempting "
2247c478bdstevel@tonic-gate				    "to dump core ...\n", mdb.m_pname);
2257c478bdstevel@tonic-gate				goto dump;
2267c478bdstevel@tonic-gate
2277c478bdstevel@tonic-gate			case 'q':
2287c478bdstevel@tonic-gate			case 'Q':
2297c478bdstevel@tonic-gate				mdb_iob_discard(mdb.m_out);
2307c478bdstevel@tonic-gate				mdb_iob_nl(mdb.m_err);
2317c478bdstevel@tonic-gate				(void) mdb_signal_unblockall();
2327c478bdstevel@tonic-gate				terminate(1);
2337c478bdstevel@tonic-gate				/*NOTREACHED*/
2347c478bdstevel@tonic-gate
2357c478bdstevel@tonic-gate			case 'r':
2367c478bdstevel@tonic-gate			case 'R':
2377c478bdstevel@tonic-gate				mdb_iob_printf(mdb.m_err, "\n%s: unloading "
2387c478bdstevel@tonic-gate				    "module '%s' ...\n", mdb.m_pname,
2397c478bdstevel@tonic-gate				    idcp->idc_modp->mod_name);
2407c478bdstevel@tonic-gate
2417c478bdstevel@tonic-gate				(void) mdb_module_unload(
2427c478bdstevel@tonic-gate				    idcp->idc_modp->mod_name, 0);
2437c478bdstevel@tonic-gate
2447c478bdstevel@tonic-gate				(void) mdb_signal_sethandler(sig,
2457c478bdstevel@tonic-gate				    flt_handler, NULL);
2467c478bdstevel@tonic-gate
2477c478bdstevel@tonic-gate				_mdb_abort_rcount++;
2487c478bdstevel@tonic-gate				mdb.m_intr = 0;
2497c478bdstevel@tonic-gate				mdb.m_pend = 0;
2507c478bdstevel@tonic-gate
2517c478bdstevel@tonic-gate				(void) mdb_signal_unblockall();
2527c478bdstevel@tonic-gate				longjmp(mdb.m_frame->f_pcb, MDB_ERR_ABORT);
2537c478bdstevel@tonic-gate				/*NOTREACHED*/
2547c478bdstevel@tonic-gate
2557c478bdstevel@tonic-gate			case 's':
2567c478bdstevel@tonic-gate			case 'S':
2577c478bdstevel@tonic-gate				mdb_iob_printf(mdb.m_err, "\n%s: "
2587c478bdstevel@tonic-gate				    "attempting to stop pid %d ...\n",
2597c478bdstevel@tonic-gate				    mdb.m_pname, (int)getpid());
2607c478bdstevel@tonic-gate
2617c478bdstevel@tonic-gate				/*
2627c478bdstevel@tonic-gate				 * Stop ourself; if this fails or we are
2637c478bdstevel@tonic-gate				 * subsequently continued, ask again.
2647c478bdstevel@tonic-gate				 */
2657c478bdstevel@tonic-gate				(void) mdb_signal_raise(SIGSTOP);
2667c478bdstevel@tonic-gate				(void) mdb_signal_unblockall();
2677c478bdstevel@tonic-gate				goto query;
2687c478bdstevel@tonic-gate			}
2697c478bdstevel@tonic-gate		}
2707c478bdstevel@tonic-gate	}
2717c478bdstevel@tonic-gate
2727c478bdstevel@tonic-gatedump:
2737c478bdstevel@tonic-gate	if (SI_FROMUSER(sip)) {
2747c478bdstevel@tonic-gate		(void) mdb_signal_block(sig);
2757c478bdstevel@tonic-gate		(void) mdb_signal_raise(sig);
2767c478bdstevel@tonic-gate	}
2777c478bdstevel@tonic-gate
2787c478bdstevel@tonic-gate	(void) sigfillset(&ucp->uc_sigmask);
2797c478bdstevel@tonic-gate	(void) sigdelset(&ucp->uc_sigmask, sig);
2807c478bdstevel@tonic-gate
2817c478bdstevel@tonic-gate	if (_mdb_abort_str == NULL)
2827c478bdstevel@tonic-gate		_mdb_abort_str = "fatal signal received";
2837c478bdstevel@tonic-gate
2847c478bdstevel@tonic-gate	ucp->uc_flags |= UC_SIGMASK;
2857c478bdstevel@tonic-gate	(void) setcontext(ucp);
2867c478bdstevel@tonic-gate}
2877c478bdstevel@tonic-gate
2887c478bdstevel@tonic-gate/*ARGSUSED*/
2897c478bdstevel@tonic-gatestatic void
2907c478bdstevel@tonic-gateint_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data)
2917c478bdstevel@tonic-gate{
2927c478bdstevel@tonic-gate	if (mdb.m_intr == 0)
2937c478bdstevel@tonic-gate		longjmp(mdb.m_frame->f_pcb, MDB_ERR_SIGINT);
2947c478bdstevel@tonic-gate	else
2957c478bdstevel@tonic-gate		mdb.m_pend++;
2967c478bdstevel@tonic-gate}
2977c478bdstevel@tonic-gate
2987c478bdstevel@tonic-gatestatic void
2997c478bdstevel@tonic-gatecontrol_kmdb(int start)
3007c478bdstevel@tonic-gate{
3017c478bdstevel@tonic-gate	int fd;
3027c478bdstevel@tonic-gate
3037c478bdstevel@tonic-gate	if ((fd = open("/dev/kmdb", O_RDONLY)) < 0)
3047c478bdstevel@tonic-gate		die("failed to open /dev/kmdb");
3057c478bdstevel@tonic-gate
3067c478bdstevel@tonic-gate	if (start) {
3077c478bdstevel@tonic-gate		char *state = mdb_get_config();
3087c478bdstevel@tonic-gate
3097c478bdstevel@tonic-gate		if (ioctl(fd, KMDB_IOC_START, state) < 0)
3107c478bdstevel@tonic-gate			die("failed to start kmdb");
3117c478bdstevel@tonic-gate
3127c478bdstevel@tonic-gate		strfree(state);
3137c478bdstevel@tonic-gate	} else {
3147c478bdstevel@tonic-gate		if (ioctl(fd, KMDB_IOC_STOP) < 0)
3157c478bdstevel@tonic-gate			die("failed to stop kmdb");
3167c478bdstevel@tonic-gate	}
3177c478bdstevel@tonic-gate
3188014889Surya Prakki	(void) close(fd);
3197c478bdstevel@tonic-gate}
3207c478bdstevel@tonic-gate
3217c478bdstevel@tonic-gatestatic void
3227c478bdstevel@tonic-gateusage(int status)
3237c478bdstevel@tonic-gate{
3247c478bdstevel@tonic-gate	mdb_iob_printf(mdb.m_err, "Usage: %s [-fkmuwyAFKMSUW] [+/-o option] "
3259c3024aHans Rosenfeld	    "[-b VM] [-p pid] [-s dist] [-I path] [-L path]\n\t[-P prompt] "
3260a47c91Robert Mustacchi	    "[-R root] [-V dis-version] [-e expr] "
3270a47c91Robert Mustacchi	    "[object [core] | core | suffix]\n\n",
3287c478bdstevel@tonic-gate	    mdb.m_pname);
3297c478bdstevel@tonic-gate
3307c478bdstevel@tonic-gate	mdb_iob_puts(mdb.m_err,
3319c3024aHans Rosenfeld	    "\t-b attach to specified bhyve VM\n"
3320a47c91Robert Mustacchi	    "\t-e evaluate expr and return status\n"
3337c478bdstevel@tonic-gate	    "\t-f force raw file debugging mode\n"
3347c478bdstevel@tonic-gate	    "\t-k force kernel debugging mode\n"
3357c478bdstevel@tonic-gate	    "\t-m disable demand-loading of module symbols\n"
3367c478bdstevel@tonic-gate	    "\t-o set specified debugger option (+o to unset)\n"
3377c478bdstevel@tonic-gate	    "\t-p attach to specified process-id\n"
3387c478bdstevel@tonic-gate	    "\t-s set symbol matching distance\n"
3397c478bdstevel@tonic-gate	    "\t-u force user program debugging mode\n"
3407c478bdstevel@tonic-gate	    "\t-w enable write mode\n"
3417c478bdstevel@tonic-gate	    "\t-y send terminal initialization sequences for tty mode\n"
3427c478bdstevel@tonic-gate	    "\t-A disable automatic loading of mdb modules\n"
3437c478bdstevel@tonic-gate	    "\t-F enable forcible takeover mode\n"
3447c478bdstevel@tonic-gate	    "\t-K stop operating system and enter live kernel debugger\n"
3457c478bdstevel@tonic-gate	    "\t-M preload all module symbols\n"
3467c478bdstevel@tonic-gate	    "\t-I set initial path for macro files\n"
3477c478bdstevel@tonic-gate	    "\t-L set initial path for module libs\n"
3487c478bdstevel@tonic-gate	    "\t-P set command-line prompt\n"
3497c478bdstevel@tonic-gate	    "\t-R set root directory for pathname expansion\n"
3507c478bdstevel@tonic-gate	    "\t-S suppress processing of ~/.mdbrc file\n"
3517c478bdstevel@tonic-gate	    "\t-U unload live kernel debugger\n"
3527c478bdstevel@tonic-gate	    "\t-W enable I/O-mapped memory access (kernel only)\n"
3537c478bdstevel@tonic-gate	    "\t-V set disassembler version\n");
3547c478bdstevel@tonic-gate
3557c478bdstevel@tonic-gate	terminate(status);
3567c478bdstevel@tonic-gate}
3577c478bdstevel@tonic-gate
3587c478bdstevel@tonic-gatestatic char *
3597c478bdstevel@tonic-gatemdb_scf_console_term(void)
3607c478bdstevel@tonic-gate{
3617c478bdstevel@tonic-gate	scf_simple_prop_t *prop;
3627c478bdstevel@tonic-gate	char *term = NULL;
3637c478bdstevel@tonic-gate
3647c478bdstevel@tonic-gate	if ((prop = scf_simple_prop_get(NULL,
3657c478bdstevel@tonic-gate	    "svc:/system/console-login:default", "ttymon",
3667c478bdstevel@tonic-gate	    "terminal_type")) == NULL)
3677c478bdstevel@tonic-gate		return (NULL);
3687c478bdstevel@tonic-gate
3697c478bdstevel@tonic-gate	if (scf_simple_prop_type(prop) == SCF_TYPE_ASTRING &&
3707c478bdstevel@tonic-gate	    (term = scf_simple_prop_next_astring(prop)) != NULL)
3717c478bdstevel@tonic-gate		term = strdup(term);
3727c478bdstevel@tonic-gate
3737c478bdstevel@tonic-gate	scf_simple_prop_free(prop);
3747c478bdstevel@tonic-gate	return (term);
3757c478bdstevel@tonic-gate}
3767c478bdstevel@tonic-gate
377a576ab5rab/*
378a576ab5rab * Unpleasant hack: we might be debugging a hypervisor domain dump.
379a576ab5rab * Earlier versions use a non-ELF file.  Later versions are ELF, but are
380a576ab5rab * /always/ ELF64, so our standard ehdr check isn't good enough.  Since
381a576ab5rab * we don't want to know too much about the file format, we'll ask
382a576ab5rab * mdb_kb.
383a576ab5rab */
384a576ab5rab#ifdef __x86
385a576ab5rabstatic int
386a576ab5rabidentify_xvm_file(const char *file, int *longmode)
387a576ab5rab{
388a576ab5rab	int (*identify)(const char *, int *);
389a576ab5rab
390a576ab5rab	if (mdb_module_load("mdb_kb", MDB_MOD_GLOBAL | MDB_MOD_SILENT) != 0)
391a576ab5rab		return (0);
392a576ab5rab
393a576ab5rab	identify = (int (*)())dlsym(RTLD_NEXT, "xkb_identify");
394a576ab5rab
395a576ab5rab	if (identify == NULL)
396a576ab5rab		return (0);
397a576ab5rab
398a576ab5rab	return (identify(file, longmode));
399a576ab5rab}
400a576ab5rab#else
401a576ab5rab/*ARGSUSED*/
402a576ab5rabstatic int
403a576ab5rabidentify_xvm_file(const char *file, int *longmode)
404a576ab5rab{
405a576ab5rab	return (0);
406a576ab5rab}
407a576ab5rab#endif /* __x86 */
408a576ab5rab
4099c3024aHans Rosenfeld#ifndef __amd64
4109c3024aHans Rosenfeld/*
4119c3024aHans Rosenfeld * There is no bhyve target in a 32bit x86 or any SPARC mdb. This dummy helps
4129c3024aHans Rosenfeld * keep the code simpler.
4139c3024aHans Rosenfeld */
4149c3024aHans Rosenfeld/*ARGSUSED*/
4159c3024aHans Rosenfeldstatic int
4169c3024aHans Rosenfeldmdb_bhyve_tgt_create(mdb_tgt_t *t, int argc, const char *argv[])
4179c3024aHans Rosenfeld{
4189c3024aHans Rosenfeld	return (set_errno(EINVAL));
4199c3024aHans Rosenfeld}
4209c3024aHans Rosenfeld#endif
4219c3024aHans Rosenfeld
4227c478bdstevel@tonic-gateint
4237c478bdstevel@tonic-gatemain(int argc, char *argv[], char *envp[])
4247c478bdstevel@tonic-gate{
425ca3e8d8Dave Plauger	extern int mdb_kvm_is_compressed_dump(mdb_io_t *);
4261320cafBryan Cantrill	extern int mdb_kvm_is_dump(mdb_io_t *);
4277c478bdstevel@tonic-gate	mdb_tgt_ctor_f *tgt_ctor = NULL;
4281320cafBryan Cantrill	const char **tgt_argv = alloca((argc + 2) * sizeof (char *));
4297c478bdstevel@tonic-gate	int tgt_argc = 0;
4307c478bdstevel@tonic-gate	mdb_tgt_t *tgt;
4317c478bdstevel@tonic-gate
4327c478bdstevel@tonic-gate	char object[MAXPATHLEN], execname[MAXPATHLEN];
4337c478bdstevel@tonic-gate	mdb_io_t *in_io, *out_io, *err_io, *null_io;
4347c478bdstevel@tonic-gate	struct termios tios;
4357c478bdstevel@tonic-gate	int status, c;
4367c478bdstevel@tonic-gate	char *p;
4377c478bdstevel@tonic-gate
4387c478bdstevel@tonic-gate	const char *Iflag = NULL, *Lflag = NULL, *Vflag = NULL, *pidarg = NULL;
4390a47c91Robert Mustacchi	const char *eflag = NULL;
440843e198johnlev	int fflag = 0, Kflag = 0, Rflag = 0, Sflag = 0, Oflag = 0, Uflag = 0;
4419c3024aHans Rosenfeld	int bflag = 0;
4427c478bdstevel@tonic-gate
4437c478bdstevel@tonic-gate	int ttylike;
444a576ab5rab	int longmode = 0;
4457c478bdstevel@tonic-gate
4467c478bdstevel@tonic-gate	stack_t sigstack;
4477c478bdstevel@tonic-gate
4487c478bdstevel@tonic-gate	if (realpath(getexecname(), execname) == NULL) {
4497c478bdstevel@tonic-gate		(void) strncpy(execname, argv[0], MAXPATHLEN);
4507c478bdstevel@tonic-gate		execname[MAXPATHLEN - 1] = '\0';
4517c478bdstevel@tonic-gate	}
4527c478bdstevel@tonic-gate
4537c478bdstevel@tonic-gate	mdb_create(execname, argv[0]);
4547c478bdstevel@tonic-gate	bzero(tgt_argv, argc * sizeof (char *));
4557c478bdstevel@tonic-gate	argv[0] = (char *)mdb.m_pname;
4567c478bdstevel@tonic-gate	_mdb_self_fd = open("/proc/self/as", O_RDONLY);
4577c478bdstevel@tonic-gate
4587c478bdstevel@tonic-gate	mdb.m_env = envp;
4597c478bdstevel@tonic-gate
4607c478bdstevel@tonic-gate	out_io = mdb_fdio_create(STDOUT_FILENO);
4617c478bdstevel@tonic-gate	mdb.m_out = mdb_iob_create(out_io, MDB_IOB_WRONLY);
4627c478bdstevel@tonic-gate
4637c478bdstevel@tonic-gate	err_io = mdb_fdio_create(STDERR_FILENO);
4647c478bdstevel@tonic-gate	mdb.m_err = mdb_iob_create(err_io, MDB_IOB_WRONLY);
4657c478bdstevel@tonic-gate	mdb_iob_clrflags(mdb.m_err, MDB_IOB_AUTOWRAP);
4667c478bdstevel@tonic-gate
4677c478bdstevel@tonic-gate	null_io = mdb_nullio_create();
4687c478bdstevel@tonic-gate	mdb.m_null = mdb_iob_create(null_io, MDB_IOB_WRONLY);
4697c478bdstevel@tonic-gate
4707c478bdstevel@tonic-gate	in_io = mdb_fdio_create(STDIN_FILENO);
4717c478bdstevel@tonic-gate	if ((mdb.m_termtype = getenv("TERM")) != NULL) {
4727c478bdstevel@tonic-gate		mdb.m_termtype = strdup(mdb.m_termtype);
4737c478bdstevel@tonic-gate		mdb.m_flags |= MDB_FL_TERMGUESS;
4747c478bdstevel@tonic-gate	}
4757c478bdstevel@tonic-gate	mdb.m_term = NULL;
4767c478bdstevel@tonic-gate
4777c478bdstevel@tonic-gate	mdb_dmode(mdb_dstr2mode(getenv("MDB_DEBUG")));
4787c478bdstevel@tonic-gate	mdb.m_pgid = getpgrp();
4797c478bdstevel@tonic-gate
4807c478bdstevel@tonic-gate	if (getenv("_MDB_EXEC") != NULL)
4817c478bdstevel@tonic-gate		mdb.m_flags |= MDB_FL_EXEC;
4827c478bdstevel@tonic-gate
4837c478bdstevel@tonic-gate	/*
4847c478bdstevel@tonic-gate	 * Setup an alternate signal stack.  When tearing down pipelines in
4857c478bdstevel@tonic-gate	 * terminate(), we may have to destroy the stack of the context in
4867c478bdstevel@tonic-gate	 * which we are currently executing the signal handler.
4877c478bdstevel@tonic-gate	 */
4887c478bdstevel@tonic-gate	sigstack.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
4897c478bdstevel@tonic-gate	    MAP_PRIVATE | MAP_ANON, -1, 0);
4907c478bdstevel@tonic-gate	if (sigstack.ss_sp == MAP_FAILED)
4917c478bdstevel@tonic-gate		die("could not allocate signal stack");
4927c478bdstevel@tonic-gate	sigstack.ss_size = SIGSTKSZ;
4937c478bdstevel@tonic-gate	sigstack.ss_flags = 0;
4947c478bdstevel@tonic-gate	if (sigaltstack(&sigstack, NULL) != 0)
4957c478bdstevel@tonic-gate		die("could not set signal stack");
4967c478bdstevel@tonic-gate
4977c478bdstevel@tonic-gate	(void) mdb_signal_sethandler(SIGPIPE, SIG_IGN, NULL);
4987c478bdstevel@tonic-gate	(void) mdb_signal_sethandler(SIGQUIT, SIG_IGN, NULL);
4997c478bdstevel@tonic-gate
5007c478bdstevel@tonic-gate	(void) mdb_signal_sethandler(SIGILL, flt_handler, NULL);
5017c478bdstevel@tonic-gate	(void) mdb_signal_sethandler(SIGTRAP, flt_handler, NULL);
5027c478bdstevel@tonic-gate	(void) mdb_signal_sethandler(SIGIOT, flt_handler, NULL);
5037c478bdstevel@tonic-gate	(void) mdb_signal_sethandler(SIGEMT, flt_handler, NULL);
5047c478bdstevel@tonic-gate	(void) mdb_signal_sethandler(SIGFPE, flt_handler, NULL);
5057c478bdstevel@tonic-gate	(void) mdb_signal_sethandler(SIGBUS, flt_handler, NULL);
5067c478bdstevel@tonic-gate	(void) mdb_signal_sethandler(SIGSEGV, flt_handler, NULL);
5077c478bdstevel@tonic-gate
5082c687d6Toomas Soome	(void) mdb_signal_sethandler(SIGHUP,
5092c687d6Toomas Soome	    (mdb_signal_f *)(uintptr_t)terminate, NULL);
5102c687d6Toomas Soome	(void) mdb_signal_sethandler(SIGTERM,
5112c687d6Toomas Soome	    (mdb_signal_f *)(uintptr_t)terminate, NULL);
5127c478bdstevel@tonic-gate
5137c478bdstevel@tonic-gate	for (mdb.m_rdvers = RD_VERSION; mdb.m_rdvers > 0; mdb.m_rdvers--) {
5147c478bdstevel@tonic-gate		if (rd_init(mdb.m_rdvers) == RD_OK)
5157c478bdstevel@tonic-gate			break;
5167c478bdstevel@tonic-gate	}
5177c478bdstevel@tonic-gate
5187c478bdstevel@tonic-gate	for (mdb.m_ctfvers = CTF_VERSION; mdb.m_ctfvers > 0; mdb.m_ctfvers--) {
5197c478bdstevel@tonic-gate		if (ctf_version(mdb.m_ctfvers) != -1)
5207c478bdstevel@tonic-gate			break;
5217c478bdstevel@tonic-gate	}
5227c478bdstevel@tonic-gate
5237c478bdstevel@tonic-gate	if ((p = getenv("HISTSIZE")) != NULL && strisnum(p)) {
5247c478bdstevel@tonic-gate		mdb.m_histlen = strtoi(p);
5257c478bdstevel@tonic-gate		if (mdb.m_histlen < 1)
5267c478bdstevel@tonic-gate			mdb.m_histlen = 1;
5277c478bdstevel@tonic-gate	}
5287c478bdstevel@tonic-gate
5297c478bdstevel@tonic-gate	while (optind < argc) {
5307c478bdstevel@tonic-gate		while ((c = getopt(argc, argv,
5319c3024aHans Rosenfeld		    "be:fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) {
5327c478bdstevel@tonic-gate			switch (c) {
5339c3024aHans Rosenfeld			case 'b':
5349c3024aHans Rosenfeld				bflag++;
5359c3024aHans Rosenfeld				tgt_ctor = mdb_bhyve_tgt_create;
5369c3024aHans Rosenfeld				break;
5370a47c91Robert Mustacchi			case 'e':
5380a47c91Robert Mustacchi				if (eflag != NULL) {
5390a47c91Robert Mustacchi					warn("-e already specified\n");
5400a47c91Robert Mustacchi					terminate(2);
5410a47c91Robert Mustacchi				}
5420a47c91Robert Mustacchi				eflag = optarg;
5430a47c91Robert Mustacchi				break;
5447c478bdstevel@tonic-gate			case 'f':
545843e198johnlev				fflag++;
5467c478bdstevel@tonic-gate				tgt_ctor = mdb_rawfile_tgt_create;
5477c478bdstevel@tonic-gate				break;
5487c478bdstevel@tonic-gate			case 'k':
5497c478bdstevel@tonic-gate				tgt_ctor = mdb_kvm_tgt_create;
5507c478bdstevel@tonic-gate				break;
5517c478bdstevel@tonic-gate			case 'm':
5527c478bdstevel@tonic-gate				mdb.m_tgtflags |= MDB_TGT_F_NOLOAD;
5537c478bdstevel@tonic-gate				mdb.m_tgtflags &= ~MDB_TGT_F_PRELOAD;
5547c478bdstevel@tonic-gate				break;
5557c478bdstevel@tonic-gate			case 'o':
5567c478bdstevel@tonic-gate				if (!mdb_set_options(optarg, TRUE))
5577c478bdstevel@tonic-gate					terminate(2);
5587c478bdstevel@tonic-gate				break;
5597c478bdstevel@tonic-gate			case 'p':
5607c478bdstevel@tonic-gate				tgt_ctor = mdb_proc_tgt_create;
5617c478bdstevel@tonic-gate				pidarg = optarg;
5627c478bdstevel@tonic-gate				break;
5637c478bdstevel@tonic-gate			case 's':
5647c478bdstevel@tonic-gate				if (!strisnum(optarg)) {
5657c478bdstevel@tonic-gate					warn("expected integer following -s\n");
5667c478bdstevel@tonic-gate					terminate(2);
5677c478bdstevel@tonic-gate				}
5687c478bdstevel@tonic-gate				mdb.m_symdist = (size_t)(uint_t)strtoi(optarg);
5697c478bdstevel@tonic-gate				break;
5707c478bdstevel@tonic-gate			case 'u':
5717c478bdstevel@tonic-gate				tgt_ctor = mdb_proc_tgt_create;
5727c478bdstevel@tonic-gate				break;
5737c478bdstevel@tonic-gate			case 'w':
5747c478bdstevel@tonic-gate				mdb.m_tgtflags |= MDB_TGT_F_RDWR;
5757c478bdstevel@tonic-gate				break;
5767c478bdstevel@tonic-gate			case 'y':
5777c478bdstevel@tonic-gate				mdb.m_flags |= MDB_FL_USECUP;
5787c478bdstevel@tonic-gate				break;
5797c478bdstevel@tonic-gate			case 'A':
5807c478bdstevel@tonic-gate				(void) mdb_set_options("nomods", TRUE);
5817c478bdstevel@tonic-gate				break;
5827c478bdstevel@tonic-gate			case 'C':
5837c478bdstevel@tonic-gate				(void) mdb_set_options("noctf", TRUE);
5847c478bdstevel@tonic-gate				break;
5857c478bdstevel@tonic-gate			case 'D':
5867c478bdstevel@tonic-gate				mdb_dmode(mdb_dstr2mode(optarg));
5877c478bdstevel@tonic-gate				break;
5887c478bdstevel@tonic-gate			case 'F':
5897c478bdstevel@tonic-gate				mdb.m_tgtflags |= MDB_TGT_F_FORCE;
5907c478bdstevel@tonic-gate				break;
5917c478bdstevel@tonic-gate			case 'I':
5927c478bdstevel@tonic-gate				Iflag = optarg;
5937c478bdstevel@tonic-gate				break;
5947c478bdstevel@tonic-gate			case 'L':
5957c478bdstevel@tonic-gate				Lflag = optarg;
5967c478bdstevel@tonic-gate				break;
5977c478bdstevel@tonic-gate			case 'K':
5987c478bdstevel@tonic-gate				Kflag++;
5997c478bdstevel@tonic-gate				break;
6007c478bdstevel@tonic-gate			case 'M':
6017c478bdstevel@tonic-gate				mdb.m_tgtflags |= MDB_TGT_F_PRELOAD;
6027c478bdstevel@tonic-gate				mdb.m_tgtflags &= ~MDB_TGT_F_NOLOAD;
6037c478bdstevel@tonic-gate				break;
6047c478bdstevel@tonic-gate			case 'O':
6057c478bdstevel@tonic-gate				Oflag++;
6067c478bdstevel@tonic-gate				break;
6077c478bdstevel@tonic-gate			case 'P':
6087c478bdstevel@tonic-gate				if (!mdb_set_prompt(optarg))
6097c478bdstevel@tonic-gate					terminate(2);
6107c478bdstevel@tonic-gate				break;
6117c478bdstevel@tonic-gate			case 'R':
6127c478bdstevel@tonic-gate				(void) strncpy(mdb.m_root, optarg, MAXPATHLEN);
6137c478bdstevel@tonic-gate				mdb.m_root[MAXPATHLEN - 1] = '\0';
6147c478bdstevel@tonic-gate				Rflag++;
6157c478bdstevel@tonic-gate				break;
6167c478bdstevel@tonic-gate			case 'S':
6177c478bdstevel@tonic-gate				Sflag++;
6187c478bdstevel@tonic-gate				break;
6197c478bdstevel@tonic-gate			case 'U':
6207c478bdstevel@tonic-gate				Uflag++;
6217c478bdstevel@tonic-gate				break;
6227c478bdstevel@tonic-gate			case 'V':
6237c478bdstevel@tonic-gate				Vflag = optarg;
6247c478bdstevel@tonic-gate				break;
6257c478bdstevel@tonic-gate			case 'W':
6267c478bdstevel@tonic-gate				mdb.m_tgtflags |= MDB_TGT_F_ALLOWIO;
6277c478bdstevel@tonic-gate				break;
6287c478bdstevel@tonic-gate			case '?':
6297c478bdstevel@tonic-gate				if (optopt == '?')
6307c478bdstevel@tonic-gate					usage(0);
6317c478bdstevel@tonic-gate				/* FALLTHROUGH */
6327c478bdstevel@tonic-gate			default:
6337c478bdstevel@tonic-gate				usage(2);
6347c478bdstevel@tonic-gate			}
6357c478bdstevel@tonic-gate		}
6367c478bdstevel@tonic-gate
6377c478bdstevel@tonic-gate		if (optind < argc) {
6387c478bdstevel@tonic-gate			const char *arg = argv[optind++];
6397c478bdstevel@tonic-gate
6407c478bdstevel@tonic-gate			if (arg[0] == '+' && strlen(arg) == 2) {
6417c478bdstevel@tonic-gate				if (arg[1] != 'o') {
6427c478bdstevel@tonic-gate					warn("illegal option -- %s\n", arg);
6437c478bdstevel@tonic-gate					terminate(2);
6447c478bdstevel@tonic-gate				}
6457c478bdstevel@tonic-gate				if (optind >= argc) {
6467c478bdstevel@tonic-gate					warn("option requires an argument -- "
6477c478bdstevel@tonic-gate					    "%s\n", arg);
6487c478bdstevel@tonic-gate					terminate(2);
6497c478bdstevel@tonic-gate				}
6507c478bdstevel@tonic-gate				if (!mdb_set_options(argv[optind++], FALSE))
6517c478bdstevel@tonic-gate					terminate(2);
6527c478bdstevel@tonic-gate			} else
6537c478bdstevel@tonic-gate				tgt_argv[tgt_argc++] = arg;
6547c478bdstevel@tonic-gate		}
6557c478bdstevel@tonic-gate	}
6567c478bdstevel@tonic-gate
6579acbbeann	if (rd_ctl(RD_CTL_SET_HELPPATH, (void *)mdb.m_root) != RD_OK) {
6589acbbeann		warn("cannot set librtld_db helper path to %s\n", mdb.m_root);
6599acbbeann		terminate(2);
6609acbbeann	}
6619acbbeann
6627c478bdstevel@tonic-gate	if (mdb.m_debug & MDB_DBG_HELP)
6637c478bdstevel@tonic-gate		terminate(0); /* Quit here if we've printed out the tokens */
6647c478bdstevel@tonic-gate
6659acbbeann
6667c478bdstevel@tonic-gate	if (Iflag != NULL && strchr(Iflag, ';') != NULL) {
6677c478bdstevel@tonic-gate		warn("macro path cannot contain semicolons\n");
6687c478bdstevel@tonic-gate		terminate(2);
6697c478bdstevel@tonic-gate	}
6707c478bdstevel@tonic-gate
6717c478bdstevel@tonic-gate	if (Lflag != NULL && strchr(Lflag, ';') != NULL) {
6727c478bdstevel@tonic-gate		warn("module path cannot contain semicolons\n");
6737c478bdstevel@tonic-gate		terminate(2);
6747c478bdstevel@tonic-gate	}
6757c478bdstevel@tonic-gate
6767c478bdstevel@tonic-gate	if (Kflag || Uflag) {
6777c478bdstevel@tonic-gate		char *nm;
6787c478bdstevel@tonic-gate
6797c478bdstevel@tonic-gate		if (tgt_ctor != NULL || Iflag != NULL) {
6807c478bdstevel@tonic-gate			warn("neither -f, -k, -p, -u, nor -I "
6817c478bdstevel@tonic-gate			    "may be used with -K\n");
6827c478bdstevel@tonic-gate			usage(2);
6837c478bdstevel@tonic-gate		}
6847c478bdstevel@tonic-gate
6857c478bdstevel@tonic-gate		if (Lflag != NULL)
6867c478bdstevel@tonic-gate			mdb_set_lpath(Lflag);
6877c478bdstevel@tonic-gate
6887c478bdstevel@tonic-gate		if ((nm = ttyname(STDIN_FILENO)) == NULL ||
6897c478bdstevel@tonic-gate		    strcmp(nm, "/dev/console") != 0) {
6907c478bdstevel@tonic-gate			/*
6917c478bdstevel@tonic-gate			 * Due to the consequences of typing mdb -K instead of
6927c478bdstevel@tonic-gate			 * mdb -k on a tty other than /dev/console, we require
6937c478bdstevel@tonic-gate			 * -F when starting kmdb from a tty other than
6947c478bdstevel@tonic-gate			 * /dev/console.
6957c478bdstevel@tonic-gate			 */
6967c478bdstevel@tonic-gate			if (!(mdb.m_tgtflags & MDB_TGT_F_FORCE)) {
6977c478bdstevel@tonic-gate				die("-F must also be supplied to start kmdb "
6987c478bdstevel@tonic-gate				    "from non-console tty\n");
6997c478bdstevel@tonic-gate			}
7007c478bdstevel@tonic-gate
7017c478bdstevel@tonic-gate			if (mdb.m_termtype == NULL || (mdb.m_flags &
7027c478bdstevel@tonic-gate			    MDB_FL_TERMGUESS)) {
7037c478bdstevel@tonic-gate				if (mdb.m_termtype != NULL)
7047c478bdstevel@tonic-gate					strfree(mdb.m_termtype);
7057c478bdstevel@tonic-gate
7067c478bdstevel@tonic-gate				if ((mdb.m_termtype = mdb_scf_console_term()) !=
7077c478bdstevel@tonic-gate				    NULL)
7087c478bdstevel@tonic-gate					mdb.m_flags |= MDB_FL_TERMGUESS;
7097c478bdstevel@tonic-gate			}
7107c478bdstevel@tonic-gate		} else {
7117c478bdstevel@tonic-gate			/*
7127c478bdstevel@tonic-gate			 * When on console, $TERM (if set) takes precedence over
7137c478bdstevel@tonic-gate			 * the SMF setting.
7147c478bdstevel@tonic-gate			 */
7157c478bdstevel@tonic-gate			if (mdb.m_termtype == NULL && (mdb.m_termtype =
7167c478bdstevel@tonic-gate			    mdb_scf_console_term()) != NULL)
7177c478bdstevel@tonic-gate				mdb.m_flags |= MDB_FL_TERMGUESS;
7187c478bdstevel@tonic-gate		}
7197c478bdstevel@tonic-gate
7207c478bdstevel@tonic-gate		control_kmdb(Kflag);
7217c478bdstevel@tonic-gate		terminate(0);
7227c478bdstevel@tonic-gate		/*NOTREACHED*/
7237c478bdstevel@tonic-gate	}
7247c478bdstevel@tonic-gate
7250a47c91Robert Mustacchi	if (eflag != NULL) {
7260a47c91Robert Mustacchi		IOP_CLOSE(in_io);
7270a47c91Robert Mustacchi		in_io = mdb_strio_create(eflag);
7280a47c91Robert Mustacchi		mdb.m_lastret = 0;
7290a47c91Robert Mustacchi	}
7300a47c91Robert Mustacchi
7317c478bdstevel@tonic-gate	/*
7327c478bdstevel@tonic-gate	 * If standard input appears to have tty attributes, attempt to
7337c478bdstevel@tonic-gate	 * initialize a terminal i/o backend on top of stdin and stdout.
7347c478bdstevel@tonic-gate	 */
7357c478bdstevel@tonic-gate	ttylike = (IOP_CTL(in_io, TCGETS, &tios) == 0);
7367c478bdstevel@tonic-gate	if (ttylike) {
7377c478bdstevel@tonic-gate		if ((mdb.m_term = mdb_termio_create(mdb.m_termtype,
7387c478bdstevel@tonic-gate		    in_io, out_io)) == NULL) {
7397c478bdstevel@tonic-gate			if (!(mdb.m_flags & MDB_FL_EXEC)) {
7407c478bdstevel@tonic-gate				warn("term init failed: command-line editing "
7417c478bdstevel@tonic-gate				    "and prompt will not be available\n");
7427c478bdstevel@tonic-gate			}
7437c478bdstevel@tonic-gate		} else {
7447c478bdstevel@tonic-gate			in_io = mdb.m_term;
7457c478bdstevel@tonic-gate		}
7467c478bdstevel@tonic-gate	}
7477c478bdstevel@tonic-gate
7487c478bdstevel@tonic-gate	mdb.m_in = mdb_iob_create(in_io, MDB_IOB_RDONLY);
7497c478bdstevel@tonic-gate	if (mdb.m_term != NULL) {
7507c478bdstevel@tonic-gate		mdb_iob_setpager(mdb.m_out, mdb.m_term);
7517c478bdstevel@tonic-gate		if (mdb.m_flags & MDB_FL_PAGER)
7527c478bdstevel@tonic-gate			mdb_iob_setflags(mdb.m_out, MDB_IOB_PGENABLE);
7537c478bdstevel@tonic-gate		else
7547c478bdstevel@tonic-gate			mdb_iob_clrflags(mdb.m_out, MDB_IOB_PGENABLE);
7557c478bdstevel@tonic-gate	} else if (ttylike)
7567c478bdstevel@tonic-gate		mdb_iob_setflags(mdb.m_in, MDB_IOB_TTYLIKE);
7577c478bdstevel@tonic-gate	else
7587c478bdstevel@tonic-gate		mdb_iob_setbuf(mdb.m_in, mdb_alloc(1, UM_SLEEP), 1);
7597c478bdstevel@tonic-gate
7607c478bdstevel@tonic-gate	mdb_pservice_init();
7617c478bdstevel@tonic-gate	mdb_lex_reset();
7627c478bdstevel@tonic-gate
7637c478bdstevel@tonic-gate	if ((mdb.m_shell = getenv("SHELL")) == NULL)
7647c478bdstevel@tonic-gate		mdb.m_shell = "/bin/sh";
7657c478bdstevel@tonic-gate
766a576ab5rab	/*
767a576ab5rab	 * If the debugger state is to be inherited from a previous instance,
768a576ab5rab	 * restore it now prior to path evaluation so that %R is updated.
769a576ab5rab	 */
770a576ab5rab	if ((p = getenv(MDB_CONFIG_ENV_VAR)) != NULL) {
771a576ab5rab		mdb_set_config(p);
772a576ab5rab		(void) unsetenv(MDB_CONFIG_ENV_VAR);
773a576ab5rab	}
774a576ab5rab
775a576ab5rab	/*
776a576ab5rab	 * Path evaluation part 1: Create the initial module path to allow
777a576ab5rab	 * the target constructor to load a support module.  Then expand
778a576ab5rab	 * any command-line arguments that modify the paths.
779a576ab5rab	 */
780a576ab5rab	if (Iflag != NULL)
781a576ab5rab		mdb_set_ipath(Iflag);
782a576ab5rab	else
783a576ab5rab		mdb_set_ipath(MDB_DEF_IPATH);
784a576ab5rab
785a576ab5rab	if (Lflag != NULL)
786a576ab5rab		mdb_set_lpath(Lflag);
787a576ab5rab	else
788a576ab5rab		mdb_set_lpath(MDB_DEF_LPATH);
789a576ab5rab
790a576ab5rab	if (mdb_get_prompt() == NULL && !(mdb.m_flags & MDB_FL_ADB))
791a576ab5rab		(void) mdb_set_prompt(MDB_DEF_PROMPT);
792a576ab5rab
7937c478bdstevel@tonic-gate	if (tgt_ctor == mdb_kvm_tgt_create) {
7947c478bdstevel@tonic-gate		if (pidarg != NULL) {
7957c478bdstevel@tonic-gate			warn("-p and -k options are mutually exclusive\n");
7967c478bdstevel@tonic-gate			terminate(2);
7977c478bdstevel@tonic-gate		}
7987c478bdstevel@tonic-gate
7997c478bdstevel@tonic-gate		if (tgt_argc == 0)
8007c478bdstevel@tonic-gate			tgt_argv[tgt_argc++] = "/dev/ksyms";
8017c478bdstevel@tonic-gate		if (tgt_argc == 1 && strisnum(tgt_argv[0]) == 0) {
8027c478bdstevel@tonic-gate			if (mdb.m_tgtflags & MDB_TGT_F_ALLOWIO)
8037c478bdstevel@tonic-gate				tgt_argv[tgt_argc++] = "/dev/allkmem";
8047c478bdstevel@tonic-gate			else
8057c478bdstevel@tonic-gate				tgt_argv[tgt_argc++] = "/dev/kmem";
8067c478bdstevel@tonic-gate		}
8077c478bdstevel@tonic-gate	}
8087c478bdstevel@tonic-gate
8097c478bdstevel@tonic-gate	if (pidarg != NULL) {
8107c478bdstevel@tonic-gate		if (tgt_argc != 0) {
8117c478bdstevel@tonic-gate			warn("-p may not be used with other arguments\n");
8127c478bdstevel@tonic-gate			terminate(2);
8137c478bdstevel@tonic-gate		}
8147c478bdstevel@tonic-gate		if (proc_arg_psinfo(pidarg, PR_ARG_PIDS, NULL, &status) == -1) {
8157c478bdstevel@tonic-gate			die("cannot attach to %s: %s\n",
8167c478bdstevel@tonic-gate			    pidarg, Pgrab_error(status));
8177c478bdstevel@tonic-gate		}
8187c478bdstevel@tonic-gate		if (strchr(pidarg, '/') != NULL)
8197c478bdstevel@tonic-gate			(void) mdb_iob_snprintf(object, MAXPATHLEN,
8207c478bdstevel@tonic-gate			    "%s/object/a.out", pidarg);
8217c478bdstevel@tonic-gate		else
8227c478bdstevel@tonic-gate			(void) mdb_iob_snprintf(object, MAXPATHLEN,
8237c478bdstevel@tonic-gate			    "/proc/%s/object/a.out", pidarg);
8247c478bdstevel@tonic-gate		tgt_argv[tgt_argc++] = object;
8257c478bdstevel@tonic-gate		tgt_argv[tgt_argc++] = pidarg;
8267c478bdstevel@tonic-gate	}
8277c478bdstevel@tonic-gate
8287c478bdstevel@tonic-gate	/*
8297c478bdstevel@tonic-gate	 * Find the first argument that is not a special "-" token.  If one is
8307c478bdstevel@tonic-gate	 * found, we will examine this file and make some inferences below.
8317c478bdstevel@tonic-gate	 */
8327c478bdstevel@tonic-gate	for (c = 0; c < tgt_argc && strcmp(tgt_argv[c], "-") == 0; c++)
8337c478bdstevel@tonic-gate		continue;
8347c478bdstevel@tonic-gate
8357c478bdstevel@tonic-gate	if (c < tgt_argc) {
8367c478bdstevel@tonic-gate		Elf32_Ehdr ehdr;
8377c478bdstevel@tonic-gate		mdb_io_t *io;
8387c478bdstevel@tonic-gate
8397c478bdstevel@tonic-gate		/*
8407c478bdstevel@tonic-gate		 * If special "-" tokens preceded an argument, shift the entire
8417c478bdstevel@tonic-gate		 * argument list to the left to remove the leading "-" args.
8427c478bdstevel@tonic-gate		 */
8437c478bdstevel@tonic-gate		if (c > 0) {
8447c478bdstevel@tonic-gate			bcopy(&tgt_argv[c], tgt_argv,
8457c478bdstevel@tonic-gate			    sizeof (const char *) * (tgt_argc - c));
8467c478bdstevel@tonic-gate			tgt_argc -= c;
8477c478bdstevel@tonic-gate		}
8487c478bdstevel@tonic-gate
849ffd958eJosef 'Jeff' Sipek		if (fflag)
850ffd958eJosef 'Jeff' Sipek			goto tcreate; /* skip re-exec and just create target */
851ffd958eJosef 'Jeff' Sipek
8529c3024aHans Rosenfeld		/* bhyve: directly create target, or re-exec in case of 32bit */
8539c3024aHans Rosenfeld		if (bflag) {
8549c3024aHans Rosenfeld#ifndef __amd64
8559c3024aHans Rosenfeld			goto reexec;
8569c3024aHans Rosenfeld#else
8579c3024aHans Rosenfeld			goto tcreate;
8589c3024aHans Rosenfeld#endif
8599c3024aHans Rosenfeld		}
8609c3024aHans Rosenfeld
8617c478bdstevel@tonic-gate		/*
8627c478bdstevel@tonic-gate		 * If we just have an object file name, and that file doesn't
8637c478bdstevel@tonic-gate		 * exist, and it's a string of digits, infer it to be a
8647c478bdstevel@tonic-gate		 * sequence number referring to a pair of crash dump files.
8657c478bdstevel@tonic-gate		 */
8667c478bdstevel@tonic-gate		if (tgt_argc == 1 && access(tgt_argv[0], F_OK) == -1 &&
8677c478bdstevel@tonic-gate		    strisnum(tgt_argv[0])) {
8687c478bdstevel@tonic-gate
8697c478bdstevel@tonic-gate			size_t len = strlen(tgt_argv[0]) + 8;
8707c478bdstevel@tonic-gate			const char *object = tgt_argv[0];
8717c478bdstevel@tonic-gate
8721320cafBryan Cantrill			tgt_argv[0] = alloca(len);
8731320cafBryan Cantrill			tgt_argv[1] = alloca(len);
8747c478bdstevel@tonic-gate
8757c478bdstevel@tonic-gate			(void) strcpy((char *)tgt_argv[0], "unix.");
8767c478bdstevel@tonic-gate			(void) strcat((char *)tgt_argv[0], object);
8777c478bdstevel@tonic-gate			(void) strcpy((char *)tgt_argv[1], "vmcore.");
8787c478bdstevel@tonic-gate			(void) strcat((char *)tgt_argv[1], object);
8797c478bdstevel@tonic-gate
880ca3e8d8Dave Plauger			if (access(tgt_argv[0], F_OK) == -1 &&
8811320cafBryan Cantrill			    access(tgt_argv[1], F_OK) != -1) {
8821320cafBryan Cantrill				/*
8831320cafBryan Cantrill				 * If we have a vmcore but not a unix file,
8841320cafBryan Cantrill				 * set the symbol table to be the vmcore to
8851320cafBryan Cantrill				 * force libkvm to extract it out of the dump.
8861320cafBryan Cantrill				 */
8871320cafBryan Cantrill				tgt_argv[0] = tgt_argv[1];
8881320cafBryan Cantrill			} else if (access(tgt_argv[0], F_OK) == -1 &&
889ca3e8d8Dave Plauger			    access(tgt_argv[1], F_OK) == -1) {
890ca3e8d8Dave Plauger				(void) strcpy((char *)tgt_argv[1], "vmdump.");
891ca3e8d8Dave Plauger				(void) strcat((char *)tgt_argv[1], object);
892ca3e8d8Dave Plauger				if (access(tgt_argv[1], F_OK) == 0) {
893ca3e8d8Dave Plauger					mdb_iob_printf(mdb.m_err,
894ca3e8d8Dave Plauger					    "cannot open compressed dump; "
895ca3e8d8Dave Plauger					    "decompress using savecore -f %s\n",
896ca3e8d8Dave Plauger					    tgt_argv[1]);
897ca3e8d8Dave Plauger					terminate(0);
898ca3e8d8Dave Plauger				}
899ca3e8d8Dave Plauger			}
900ca3e8d8Dave Plauger
9017c478bdstevel@tonic-gate			tgt_argc = 2;
9027c478bdstevel@tonic-gate		}
9037c478bdstevel@tonic-gate
9047c478bdstevel@tonic-gate		/*
9057c478bdstevel@tonic-gate		 * We need to open the object file in order to determine its
9067c478bdstevel@tonic-gate		 * ELF class and potentially re-exec ourself.
9077c478bdstevel@tonic-gate		 */
9087c478bdstevel@tonic-gate		if ((io = mdb_fdio_create_path(NULL, tgt_argv[0],
9097c478bdstevel@tonic-gate		    O_RDONLY, 0)) == NULL)
9107c478bdstevel@tonic-gate			die("failed to open %s", tgt_argv[0]);
9117c478bdstevel@tonic-gate
912ca3e8d8Dave Plauger		if (tgt_argc == 1) {
913ca3e8d8Dave Plauger			if (mdb_kvm_is_compressed_dump(io)) {
9141320cafBryan Cantrill				/*
9151320cafBryan Cantrill				 * We have a single vmdump.N compressed dump
9161320cafBryan Cantrill				 * file; give a helpful message.
9171320cafBryan Cantrill				 */
918ca3e8d8Dave Plauger				mdb_iob_printf(mdb.m_err,
919ca3e8d8Dave Plauger				    "cannot open compressed dump; "
920ca3e8d8Dave Plauger				    "decompress using savecore -f %s\n",
921ca3e8d8Dave Plauger				    tgt_argv[0]);
922ca3e8d8Dave Plauger				terminate(0);
9231320cafBryan Cantrill			} else if (mdb_kvm_is_dump(io)) {
9241320cafBryan Cantrill				/*
9251320cafBryan Cantrill				 * We have an uncompressed dump as our only
9261320cafBryan Cantrill				 * argument; specify the dump as the symbol
9271320cafBryan Cantrill				 * table to force libkvm to dig it out of the
9281320cafBryan Cantrill				 * dump.
9291320cafBryan Cantrill				 */
9301320cafBryan Cantrill				tgt_argv[tgt_argc++] = tgt_argv[0];
931ca3e8d8Dave Plauger			}
932ca3e8d8Dave Plauger		}
933ca3e8d8Dave Plauger
934ca3e8d8Dave Plauger		/*
9357c478bdstevel@tonic-gate		 * If the target is unknown or is not the rawfile target, do
9367c478bdstevel@tonic-gate		 * a gelf_check to determine if the file is an ELF file.  If
9377c478bdstevel@tonic-gate		 * it is not and the target is unknown, use the rawfile tgt.
9387c478bdstevel@tonic-gate		 * Otherwise an ELF-based target is needed, so we must abort.
9397c478bdstevel@tonic-gate		 */
940ffd958eJosef 'Jeff' Sipek		if (mdb_gelf_check(io, &ehdr, ET_NONE) == -1) {
9417c478bdstevel@tonic-gate			if (tgt_ctor != NULL) {
9427c478bdstevel@tonic-gate				(void) mdb_gelf_check(io, &ehdr, ET_EXEC);
9437c478bdstevel@tonic-gate				mdb_io_destroy(io);
9447c478bdstevel@tonic-gate				terminate(1);
9457c478bdstevel@tonic-gate			} else
9467c478bdstevel@tonic-gate				tgt_ctor = mdb_rawfile_tgt_create;
9477c478bdstevel@tonic-gate		}
9487c478bdstevel@tonic-gate
9497c478bdstevel@tonic-gate		mdb_io_destroy(io);
9507c478bdstevel@tonic-gate
951ffd958eJosef 'Jeff' Sipek		if (identify_xvm_file(tgt_argv[0], &longmode) == 1) {
952a576ab5rab#ifdef _LP64
953a576ab5rab			if (!longmode)
954a576ab5rab				goto reexec;
955a576ab5rab#else
956a576ab5rab			if (longmode)
957a576ab5rab				goto reexec;
958a576ab5rab#endif
959a576ab5rab			tgt_ctor = mdb_kvm_tgt_create;
960a576ab5rab			goto tcreate;
961a576ab5rab		}
962a576ab5rab
9637c478bdstevel@tonic-gate		/*
9647c478bdstevel@tonic-gate		 * The object file turned out to be a user core file (ET_CORE),
9657c478bdstevel@tonic-gate		 * and no other arguments were specified, swap 0 and 1.  The
9667c478bdstevel@tonic-gate		 * proc target will infer the executable for us.
9677c478bdstevel@tonic-gate		 */
9687c478bdstevel@tonic-gate		if (ehdr.e_type == ET_CORE) {
9697c478bdstevel@tonic-gate			tgt_argv[tgt_argc++] = tgt_argv[0];
9707c478bdstevel@tonic-gate			tgt_argv[0] = NULL;
9717c478bdstevel@tonic-gate			tgt_ctor = mdb_proc_tgt_create;
9727c478bdstevel@tonic-gate		}
9737c478bdstevel@tonic-gate
9747c478bdstevel@tonic-gate		/*
9757c478bdstevel@tonic-gate		 * If tgt_argv[1] is filled in, open it up and determine if it
9767c478bdstevel@tonic-gate		 * is a vmcore file.  If it is, gelf_check will fail and we
9777c478bdstevel@tonic-gate		 * set tgt_ctor to 'kvm'; otherwise we use the default.
9787c478bdstevel@tonic-gate		 */
9797c478bdstevel@tonic-gate		if (tgt_argc > 1 && strcmp(tgt_argv[1], "-") != 0 &&
9807c478bdstevel@tonic-gate		    tgt_argv[0] != NULL && pidarg == NULL) {
9817c478bdstevel@tonic-gate			Elf32_Ehdr chdr;
9827c478bdstevel@tonic-gate
9837c478bdstevel@tonic-gate			if (access(tgt_argv[1], F_OK) == -1)
9847c478bdstevel@tonic-gate				die("failed to access %s", tgt_argv[1]);
9857c478bdstevel@tonic-gate
986ca3e8d8Dave Plauger			/* *.N case: drop vmdump.N from the list */
987ca3e8d8Dave Plauger			if (tgt_argc == 3) {
988ca3e8d8Dave Plauger				if ((io = mdb_fdio_create_path(NULL,
989ca3e8d8Dave Plauger				    tgt_argv[2], O_RDONLY, 0)) == NULL)
990ca3e8d8Dave Plauger					die("failed to open %s", tgt_argv[2]);
991ca3e8d8Dave Plauger				if (mdb_kvm_is_compressed_dump(io))
992ca3e8d8Dave Plauger					tgt_argv[--tgt_argc] = NULL;
993ca3e8d8Dave Plauger				mdb_io_destroy(io);
994ca3e8d8Dave Plauger			}
995ca3e8d8Dave Plauger
9967c478bdstevel@tonic-gate			if ((io = mdb_fdio_create_path(NULL, tgt_argv[1],
9977c478bdstevel@tonic-gate			    O_RDONLY, 0)) == NULL)
9987c478bdstevel@tonic-gate				die("failed to open %s", tgt_argv[1]);
9997c478bdstevel@tonic-gate
10007c478bdstevel@tonic-gate			if (mdb_gelf_check(io, &chdr, ET_NONE) == -1)
10017c478bdstevel@tonic-gate				tgt_ctor = mdb_kvm_tgt_create;
10027c478bdstevel@tonic-gate
10037c478bdstevel@tonic-gate			mdb_io_destroy(io);
10047c478bdstevel@tonic-gate		}
10057c478bdstevel@tonic-gate
10067c478bdstevel@tonic-gate		/*
10077c478bdstevel@tonic-gate		 * At this point, we've read the ELF header for either an
10087c478bdstevel@tonic-gate		 * object file or core into ehdr.  If the class does not match
10097c478bdstevel@tonic-gate		 * ours, attempt to exec the mdb of the appropriate class.
10107c478bdstevel@tonic-gate		 */
10117c478bdstevel@tonic-gate#ifdef _LP64
1012843e198johnlev		if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
1013843e198johnlev			goto reexec;
10147c478bdstevel@tonic-gate#else
1015843e198johnlev		if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
1016843e198johnlev			goto reexec;
10177c478bdstevel@tonic-gate#endif
10187c478bdstevel@tonic-gate	}
10197c478bdstevel@tonic-gate
10207c478bdstevel@tonic-gatetcreate:
10217c478bdstevel@tonic-gate	if (tgt_ctor == NULL)
10227c478bdstevel@tonic-gate		tgt_ctor = mdb_proc_tgt_create;
10237c478bdstevel@tonic-gate
10247c478bdstevel@tonic-gate	tgt = mdb_tgt_create(tgt_ctor, mdb.m_tgtflags, tgt_argc, tgt_argv);
10257c478bdstevel@tonic-gate
10267c478bdstevel@tonic-gate	if (tgt == NULL) {
10277c478bdstevel@tonic-gate		if (errno == EINVAL)
10287c478bdstevel@tonic-gate			usage(2); /* target can return EINVAL to get usage */
10297c478bdstevel@tonic-gate		if (errno == EMDB_TGT)
10307c478bdstevel@tonic-gate			terminate(1); /* target already printed error msg */
10317c478bdstevel@tonic-gate		die("failed to initialize target");
10327c478bdstevel@tonic-gate	}
10337c478bdstevel@tonic-gate
10347c478bdstevel@tonic-gate	mdb_tgt_activate(tgt);
10357c478bdstevel@tonic-gate
10367c478bdstevel@tonic-gate	mdb_create_loadable_disasms();
10377c478bdstevel@tonic-gate
10387c478bdstevel@tonic-gate	if (Vflag != NULL && mdb_dis_select(Vflag) == -1)
10397c478bdstevel@tonic-gate		warn("invalid disassembler mode -- %s\n", Vflag);
10407c478bdstevel@tonic-gate
10417c478bdstevel@tonic-gate
10427c478bdstevel@tonic-gate	if (Rflag && mdb.m_term != NULL)
10437c478bdstevel@tonic-gate		warn("Using proto area %s\n", mdb.m_root);
10447c478bdstevel@tonic-gate
10457c478bdstevel@tonic-gate	/*
10467c478bdstevel@tonic-gate	 * If the target was successfully constructed and -O was specified,
10477c478bdstevel@tonic-gate	 * we now attempt to enter piggy-mode for debugging jurassic problems.
10487c478bdstevel@tonic-gate	 */
10497c478bdstevel@tonic-gate	if (Oflag) {
10507c478bdstevel@tonic-gate		pcinfo_t pci;
10517c478bdstevel@tonic-gate
10527c478bdstevel@tonic-gate		(void) strcpy(pci.pc_clname, "RT");
10537c478bdstevel@tonic-gate
10547c478bdstevel@tonic-gate		if (priocntl(P_LWPID, P_MYID, PC_GETCID, (caddr_t)&pci) != -1) {
10557c478bdstevel@tonic-gate			pcparms_t pcp;
10567c478bdstevel@tonic-gate			rtparms_t *rtp = (rtparms_t *)pcp.pc_clparms;
10577c478bdstevel@tonic-gate
10587c478bdstevel@tonic-gate			rtp->rt_pri = 35;
10597c478bdstevel@tonic-gate			rtp->rt_tqsecs = 0;
10607c478bdstevel@tonic-gate			rtp->rt_tqnsecs = RT_TQDEF;
10617c478bdstevel@tonic-gate
10627c478bdstevel@tonic-gate			pcp.pc_cid = pci.pc_cid;
10637c478bdstevel@tonic-gate
10647c478bdstevel@tonic-gate			if (priocntl(P_LWPID, P_MYID, PC_SETPARMS,
10657c478bdstevel@tonic-gate			    (caddr_t)&pcp) == -1) {
10667c478bdstevel@tonic-gate				warn("failed to set RT parameters");
10677c478bdstevel@tonic-gate				Oflag = 0;
10687c478bdstevel@tonic-gate			}
10697c478bdstevel@tonic-gate		} else {
10707c478bdstevel@tonic-gate			warn("failed to get RT class id");
10717c478bdstevel@tonic-gate			Oflag = 0;
10727c478bdstevel@tonic-gate		}
10737c478bdstevel@tonic-gate
10747c478bdstevel@tonic-gate		if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
10757c478bdstevel@tonic-gate			warn("failed to lock address space");
10767c478bdstevel@tonic-gate			Oflag = 0;
10777c478bdstevel@tonic-gate		}
10787c478bdstevel@tonic-gate
10797c478bdstevel@tonic-gate		if (Oflag)
10807c478bdstevel@tonic-gate			mdb_printf("%s: oink, oink!\n", mdb.m_pname);
10817c478bdstevel@tonic-gate	}
10827c478bdstevel@tonic-gate
10837c478bdstevel@tonic-gate	/*
10847c478bdstevel@tonic-gate	 * Path evaluation part 2: Re-evaluate the path now that the target
10857c478bdstevel@tonic-gate	 * is ready (and thus we have access to the real platform string).
10867c478bdstevel@tonic-gate	 * Do this before reading ~/.mdbrc to allow path modifications prior
10877c478bdstevel@tonic-gate	 * to performing module auto-loading.
10887c478bdstevel@tonic-gate	 */
10897c478bdstevel@tonic-gate	mdb_set_ipath(mdb.m_ipathstr);
10907c478bdstevel@tonic-gate	mdb_set_lpath(mdb.m_lpathstr);
10917c478bdstevel@tonic-gate
10927c478bdstevel@tonic-gate	if (!Sflag && (p = getenv("HOME")) != NULL) {
10937c478bdstevel@tonic-gate		char rcpath[MAXPATHLEN];
10947c478bdstevel@tonic-gate		mdb_io_t *rc_io;
10957c478bdstevel@tonic-gate		int fd;
10967c478bdstevel@tonic-gate
10977c478bdstevel@tonic-gate		(void) mdb_iob_snprintf(rcpath, MAXPATHLEN, "%s/.mdbrc", p);
10987c478bdstevel@tonic-gate		fd = open64(rcpath, O_RDONLY);
10997c478bdstevel@tonic-gate
11007c478bdstevel@tonic-gate		if (fd >= 0 && (rc_io = mdb_fdio_create_named(fd, rcpath))) {
11017c478bdstevel@tonic-gate			mdb_iob_t *iob = mdb_iob_create(rc_io, MDB_IOB_RDONLY);
11027c478bdstevel@tonic-gate			mdb_iob_t *old = mdb.m_in;
11037c478bdstevel@tonic-gate
11047c478bdstevel@tonic-gate			mdb.m_in = iob;
11057c478bdstevel@tonic-gate			(void) mdb_run();
11067c478bdstevel@tonic-gate			mdb.m_in = old;
11077c478bdstevel@tonic-gate		}
11087c478bdstevel@tonic-gate	}
11097c478bdstevel@tonic-gate
11107c478bdstevel@tonic-gate	if (!(mdb.m_flags & MDB_FL_NOMODS))
11117c478bdstevel@tonic-gate		mdb_module_load_all(0);
11127c478bdstevel@tonic-gate
11137c478bdstevel@tonic-gate	(void) mdb_signal_sethandler(SIGINT, int_handler, NULL);
11147c478bdstevel@tonic-gate	while ((status = mdb_run()) == MDB_ERR_ABORT ||
11157c478bdstevel@tonic-gate	    status == MDB_ERR_OUTPUT) {
11167c478bdstevel@tonic-gate		/*
11177c478bdstevel@tonic-gate		 * If a write failed on stdout, give up.  A more informative
11187c478bdstevel@tonic-gate		 * error message will already have been printed by mdb_run().
11197c478bdstevel@tonic-gate		 */
11207c478bdstevel@tonic-gate		if (status == MDB_ERR_OUTPUT &&
11217c478bdstevel@tonic-gate		    mdb_iob_getflags(mdb.m_out) & MDB_IOB_ERR) {
11227c478bdstevel@tonic-gate			mdb_warn("write to stdout failed, exiting\n");
11237c478bdstevel@tonic-gate			break;
11247c478bdstevel@tonic-gate		}
11257c478bdstevel@tonic-gate		continue;
11267c478bdstevel@tonic-gate	}
11277c478bdstevel@tonic-gate
11280a47c91Robert Mustacchi	terminate((status == MDB_ERR_QUIT || status == 0) ?
11290a47c91Robert Mustacchi	    (eflag != NULL && mdb.m_lastret != 0 ? 1 : 0) : 1);
11307c478bdstevel@tonic-gate	/*NOTREACHED*/
1131843e198johnlev
1132843e198johnlevreexec:
1133843e198johnlev	if ((p = strrchr(execname, '/')) == NULL)
1134843e198johnlev		die("cannot determine absolute pathname\n");
1135843e198johnlev#ifdef _LP64
1136843e198johnlev#ifdef __sparc
1137843e198johnlev	(void) strcpy(p, "/../sparcv7/");
1138843e198johnlev#else
1139843e198johnlev	(void) strcpy(p, "/../i86/");
1140843e198johnlev#endif
1141843e198johnlev#else
1142843e198johnlev#ifdef __sparc
1143843e198johnlev	(void) strcpy(p, "/../sparcv9/");
1144843e198johnlev#else
1145843e198johnlev	(void) strcpy(p, "/../amd64/");
1146843e198johnlev#endif
1147843e198johnlev#endif
1148843e198johnlev	(void) strcat(p, mdb.m_pname);
1149843e198johnlev
1150843e198johnlev	if (mdb.m_term != NULL)
1151843e198johnlev		(void) IOP_CTL(in_io, TCSETSW, &tios);
1152843e198johnlev
1153843e198johnlev	(void) putenv("_MDB_EXEC=1");
1154843e198johnlev	(void) execv(execname, argv);
1155843e198johnlev
1156843e198johnlev	/*
1157843e198johnlev	 * If execv fails, suppress ENOEXEC.  Experience shows the most common
1158843e198johnlev	 * reason is that the machine is booted under a 32-bit kernel, in which
1159843e198johnlev	 * case it is clearer to only print the message below.
1160843e198johnlev	 */
1161843e198johnlev	if (errno != ENOEXEC)
1162843e198johnlev		warn("failed to exec %s", execname);
1163843e198johnlev#ifdef _LP64
1164843e198johnlev	die("64-bit %s cannot debug 32-bit program %s\n",
1165843e198johnlev	    mdb.m_pname, tgt_argv[0] ?
1166843e198johnlev	    tgt_argv[0] : tgt_argv[1]);
1167843e198johnlev#else
1168843e198johnlev	die("32-bit %s cannot debug 64-bit program %s\n",
1169843e198johnlev	    mdb.m_pname, tgt_argv[0] ?
1170843e198johnlev	    tgt_argv[0] : tgt_argv[1]);
1171843e198johnlev#endif
1172843e198johnlev
1173843e198johnlev	goto tcreate;
11747c478bdstevel@tonic-gate}
1175