Home | History | Annotate | Download | only in mdb
      1      0     stevel /*
      2      0     stevel  * CDDL HEADER START
      3      0     stevel  *
      4      0     stevel  * The contents of this file are subject to the terms of the
      5   2712    nn35248  * Common Development and Distribution License (the "License").
      6   2712    nn35248  * You may not use this file except in compliance with the License.
      7      0     stevel  *
      8      0     stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0     stevel  * or http://www.opensolaris.org/os/licensing.
     10      0     stevel  * See the License for the specific language governing permissions
     11      0     stevel  * and limitations under the License.
     12      0     stevel  *
     13      0     stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0     stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0     stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0     stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0     stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0     stevel  *
     19      0     stevel  * CDDL HEADER END
     20      0     stevel  */
     21      0     stevel /*
     22  10843       Dave  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23      0     stevel  * Use is subject to license terms.
     24      0     stevel  */
     25      0     stevel 
     26      0     stevel #include <sys/types.h>
     27      0     stevel #include <sys/mman.h>
     28      0     stevel #include <sys/priocntl.h>
     29      0     stevel #include <sys/rtpriocntl.h>
     30      0     stevel #include <sys/resource.h>
     31      0     stevel #include <sys/termios.h>
     32      0     stevel #include <sys/param.h>
     33      0     stevel #include <sys/regset.h>
     34      0     stevel #include <sys/frame.h>
     35      0     stevel #include <sys/stack.h>
     36      0     stevel #include <sys/reg.h>
     37      0     stevel 
     38      0     stevel #include <libproc.h>
     39      0     stevel #include <libscf.h>
     40      0     stevel #include <alloca.h>
     41      0     stevel #include <unistd.h>
     42      0     stevel #include <string.h>
     43      0     stevel #include <stdlib.h>
     44      0     stevel #include <fcntl.h>
     45      0     stevel #include <dlfcn.h>
     46      0     stevel #include <libctf.h>
     47      0     stevel #include <errno.h>
     48   5084    johnlev #include <kvm.h>
     49      0     stevel 
     50      0     stevel #include <mdb/mdb_lex.h>
     51      0     stevel #include <mdb/mdb_debug.h>
     52      0     stevel #include <mdb/mdb_signal.h>
     53      0     stevel #include <mdb/mdb_string.h>
     54      0     stevel #include <mdb/mdb_modapi.h>
     55      0     stevel #include <mdb/mdb_target.h>
     56      0     stevel #include <mdb/mdb_gelf.h>
     57      0     stevel #include <mdb/mdb_conf.h>
     58      0     stevel #include <mdb/mdb_err.h>
     59      0     stevel #include <mdb/mdb_io_impl.h>
     60      0     stevel #include <mdb/mdb_frame.h>
     61      0     stevel #include <mdb/mdb_set.h>
     62      0     stevel #include <kmdb/kmdb_kctl.h>
     63      0     stevel #include <mdb/mdb.h>
     64      0     stevel 
     65      0     stevel #ifndef STACK_BIAS
     66      0     stevel #define	STACK_BIAS	0
     67      0     stevel #endif
     68      0     stevel 
     69      0     stevel #if defined(__sparc)
     70      0     stevel #define	STACK_REGISTER	SP
     71      0     stevel #else
     72      0     stevel #define	STACK_REGISTER	REG_FP
     73      0     stevel #endif
     74      0     stevel 
     75      0     stevel #ifdef _LP64
     76      0     stevel #define	MDB_DEF_IPATH	\
     77      0     stevel 	"%r/usr/platform/%p/lib/adb/%i:" \
     78      0     stevel 	"%r/usr/platform/%m/lib/adb/%i:" \
     79      0     stevel 	"%r/usr/lib/adb/%i"
     80      0     stevel #define	MDB_DEF_LPATH	\
     81      0     stevel 	"%r/usr/platform/%p/lib/mdb/%t/%i:" \
     82      0     stevel 	"%r/usr/platform/%m/lib/mdb/%t/%i:" \
     83      0     stevel 	"%r/usr/lib/mdb/%t/%i"
     84      0     stevel #else
     85      0     stevel #define	MDB_DEF_IPATH	\
     86      0     stevel 	"%r/usr/platform/%p/lib/adb:" \
     87      0     stevel 	"%r/usr/platform/%m/lib/adb:" \
     88      0     stevel 	"%r/usr/lib/adb"
     89      0     stevel #define	MDB_DEF_LPATH	\
     90      0     stevel 	"%r/usr/platform/%p/lib/mdb/%t:" \
     91      0     stevel 	"%r/usr/platform/%m/lib/mdb/%t:" \
     92      0     stevel 	"%r/usr/lib/mdb/%t"
     93      0     stevel #endif
     94      0     stevel 
     95      0     stevel #define	MDB_DEF_PROMPT "> "
     96      0     stevel 
     97      0     stevel /*
     98      0     stevel  * Similar to the panic_* variables in the kernel, we keep some relevant
     99      0     stevel  * information stored in a set of global _mdb_abort_* variables; in the
    100      0     stevel  * event that the debugger dumps core, these will aid core dump analysis.
    101      0     stevel  */
    102      0     stevel const char *volatile _mdb_abort_str;	/* reason for failure */
    103      0     stevel siginfo_t _mdb_abort_info;		/* signal info for fatal signal */
    104      0     stevel ucontext_t _mdb_abort_ctx;		/* context fatal signal interrupted */
    105      0     stevel int _mdb_abort_rcount;			/* number of times resume requested */
    106      0     stevel int _mdb_self_fd = -1;			/* fd for self as for valid_frame */
    107      0     stevel 
    108      0     stevel static void
    109      0     stevel terminate(int status)
    110      0     stevel {
    111   7383  Vitezslav 	(void) mdb_signal_blockall();
    112      0     stevel 	mdb_destroy();
    113      0     stevel 	exit(status);
    114      0     stevel }
    115      0     stevel 
    116      0     stevel static void
    117      0     stevel print_frame(uintptr_t pc, int fnum)
    118      0     stevel {
    119      0     stevel 	Dl_info dli;
    120      0     stevel 
    121      0     stevel 	if (dladdr((void *)pc, &dli)) {
    122      0     stevel 		mdb_iob_printf(mdb.m_err, "    [%d] %s`%s+0x%lx()\n", fnum,
    123      0     stevel 		    strbasename(dli.dli_fname), dli.dli_sname,
    124      0     stevel 		    pc - (uintptr_t)dli.dli_saddr);
    125      0     stevel 	} else
    126      0     stevel 		mdb_iob_printf(mdb.m_err, "    [%d] %p()\n", fnum, pc);
    127      0     stevel }
    128      0     stevel 
    129      0     stevel static int
    130      0     stevel valid_frame(struct frame *fr)
    131      0     stevel {
    132      0     stevel 	static struct frame fake;
    133      0     stevel 	uintptr_t addr = (uintptr_t)fr;
    134      0     stevel 
    135      0     stevel 	if (pread(_mdb_self_fd, &fake, sizeof (fake), addr) != sizeof (fake)) {
    136      0     stevel 		mdb_iob_printf(mdb.m_err, "    invalid frame (%p)\n", fr);
    137      0     stevel 		return (0);
    138      0     stevel 	}
    139      0     stevel 
    140      0     stevel 	if (addr & (STACK_ALIGN - 1)) {
    141      0     stevel 		mdb_iob_printf(mdb.m_err, "    mis-aligned frame (%p)\n", fr);
    142      0     stevel 		return (0);
    143      0     stevel 	}
    144      0     stevel 
    145      0     stevel 	return (1);
    146      0     stevel }
    147      0     stevel 
    148      0     stevel /*ARGSUSED*/
    149      0     stevel static void
    150      0     stevel flt_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data)
    151      0     stevel {
    152      0     stevel 	static const struct rlimit rl = {
    153      0     stevel 		(rlim_t)RLIM_INFINITY, (rlim_t)RLIM_INFINITY
    154      0     stevel 	};
    155      0     stevel 
    156      0     stevel 	const mdb_idcmd_t *idcp = NULL;
    157      0     stevel 
    158      0     stevel 	if (mdb.m_frame != NULL && mdb.m_frame->f_cp != NULL)
    159      0     stevel 		idcp = mdb.m_frame->f_cp->c_dcmd;
    160      0     stevel 
    161      0     stevel 	if (sip != NULL)
    162      0     stevel 		bcopy(sip, &_mdb_abort_info, sizeof (_mdb_abort_info));
    163      0     stevel 	if (ucp != NULL)
    164      0     stevel 		bcopy(ucp, &_mdb_abort_ctx, sizeof (_mdb_abort_ctx));
    165      0     stevel 
    166      0     stevel 	_mdb_abort_info.si_signo = sig;
    167      0     stevel 	(void) mdb_signal_sethandler(sig, SIG_DFL, NULL);
    168      0     stevel 
    169      0     stevel 	/*
    170      0     stevel 	 * If there is no current dcmd, or the current dcmd comes from a
    171      0     stevel 	 * builtin module, we don't allow resume and always core dump.
    172      0     stevel 	 */
    173      0     stevel 	if (idcp == NULL || idcp->idc_modp == NULL ||
    174      0     stevel 	    idcp->idc_modp == &mdb.m_rmod || idcp->idc_modp->mod_hdl == NULL)
    175      0     stevel 		goto dump;
    176      0     stevel 
    177      0     stevel 	if (mdb.m_term != NULL) {
    178      0     stevel 		struct frame *fr = (struct frame *)
    179      0     stevel 		    (ucp->uc_mcontext.gregs[STACK_REGISTER] + STACK_BIAS);
    180      0     stevel 
    181      0     stevel 		char signame[SIG2STR_MAX];
    182      0     stevel 		int i = 1;
    183      0     stevel 		char c;
    184      0     stevel 
    185      0     stevel 		if (sig2str(sig, signame) == -1) {
    186      0     stevel 			mdb_iob_printf(mdb.m_err,
    187      0     stevel 			    "\n*** %s: received signal %d at:\n",
    188      0     stevel 			    mdb.m_pname, sig);
    189      0     stevel 		} else {
    190      0     stevel 			mdb_iob_printf(mdb.m_err,
    191      0     stevel 			    "\n*** %s: received signal %s at:\n",
    192      0     stevel 			    mdb.m_pname, signame);
    193      0     stevel 		}
    194      0     stevel 
    195      0     stevel 		if (ucp->uc_mcontext.gregs[REG_PC] != 0)
    196      0     stevel 			print_frame(ucp->uc_mcontext.gregs[REG_PC], i++);
    197      0     stevel 
    198      0     stevel 		while (fr != NULL && valid_frame(fr) && fr->fr_savpc != 0) {
    199      0     stevel 			print_frame(fr->fr_savpc, i++);
    200      0     stevel 			fr = (struct frame *)
    201      0     stevel 			    ((uintptr_t)fr->fr_savfp + STACK_BIAS);
    202      0     stevel 		}
    203      0     stevel 
    204      0     stevel query:
    205      0     stevel 		mdb_iob_printf(mdb.m_err, "\n%s: (c)ore dump, (q)uit, "
    206      0     stevel 		    "(r)ecover, or (s)top for debugger [cqrs]? ", mdb.m_pname);
    207      0     stevel 
    208      0     stevel 		mdb_iob_flush(mdb.m_err);
    209      0     stevel 
    210      0     stevel 		for (;;) {
    211      0     stevel 			if (IOP_READ(mdb.m_term, &c, sizeof (c)) != sizeof (c))
    212      0     stevel 				goto dump;
    213      0     stevel 
    214      0     stevel 			switch (c) {
    215      0     stevel 			case 'c':
    216      0     stevel 			case 'C':
    217      0     stevel 				(void) setrlimit(RLIMIT_CORE, &rl);
    218      0     stevel 				mdb_iob_printf(mdb.m_err, "\n%s: attempting "
    219      0     stevel 				    "to dump core ...\n", mdb.m_pname);
    220      0     stevel 				goto dump;
    221      0     stevel 
    222      0     stevel 			case 'q':
    223      0     stevel 			case 'Q':
    224      0     stevel 				mdb_iob_discard(mdb.m_out);
    225      0     stevel 				mdb_iob_nl(mdb.m_err);
    226      0     stevel 				(void) mdb_signal_unblockall();
    227      0     stevel 				terminate(1);
    228      0     stevel 				/*NOTREACHED*/
    229      0     stevel 
    230      0     stevel 			case 'r':
    231      0     stevel 			case 'R':
    232      0     stevel 				mdb_iob_printf(mdb.m_err, "\n%s: unloading "
    233      0     stevel 				    "module '%s' ...\n", mdb.m_pname,
    234      0     stevel 				    idcp->idc_modp->mod_name);
    235      0     stevel 
    236      0     stevel 				(void) mdb_module_unload(
    237      0     stevel 				    idcp->idc_modp->mod_name, 0);
    238      0     stevel 
    239      0     stevel 				(void) mdb_signal_sethandler(sig,
    240      0     stevel 				    flt_handler, NULL);
    241      0     stevel 
    242      0     stevel 				_mdb_abort_rcount++;
    243      0     stevel 				mdb.m_intr = 0;
    244      0     stevel 				mdb.m_pend = 0;
    245      0     stevel 
    246      0     stevel 				(void) mdb_signal_unblockall();
    247      0     stevel 				longjmp(mdb.m_frame->f_pcb, MDB_ERR_ABORT);
    248      0     stevel 				/*NOTREACHED*/
    249      0     stevel 
    250      0     stevel 			case 's':
    251      0     stevel 			case 'S':
    252      0     stevel 				mdb_iob_printf(mdb.m_err, "\n%s: "
    253      0     stevel 				    "attempting to stop pid %d ...\n",
    254      0     stevel 				    mdb.m_pname, (int)getpid());
    255      0     stevel 
    256      0     stevel 				/*
    257      0     stevel 				 * Stop ourself; if this fails or we are
    258      0     stevel 				 * subsequently continued, ask again.
    259      0     stevel 				 */
    260      0     stevel 				(void) mdb_signal_raise(SIGSTOP);
    261      0     stevel 				(void) mdb_signal_unblockall();
    262      0     stevel 				goto query;
    263      0     stevel 			}
    264      0     stevel 		}
    265      0     stevel 	}
    266      0     stevel 
    267      0     stevel dump:
    268      0     stevel 	if (SI_FROMUSER(sip)) {
    269      0     stevel 		(void) mdb_signal_block(sig);
    270      0     stevel 		(void) mdb_signal_raise(sig);
    271      0     stevel 	}
    272      0     stevel 
    273      0     stevel 	(void) sigfillset(&ucp->uc_sigmask);
    274      0     stevel 	(void) sigdelset(&ucp->uc_sigmask, sig);
    275      0     stevel 
    276      0     stevel 	if (_mdb_abort_str == NULL)
    277      0     stevel 		_mdb_abort_str = "fatal signal received";
    278      0     stevel 
    279      0     stevel 	ucp->uc_flags |= UC_SIGMASK;
    280      0     stevel 	(void) setcontext(ucp);
    281      0     stevel }
    282      0     stevel 
    283      0     stevel /*ARGSUSED*/
    284      0     stevel static void
    285      0     stevel int_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data)
    286      0     stevel {
    287      0     stevel 	if (mdb.m_intr == 0)
    288      0     stevel 		longjmp(mdb.m_frame->f_pcb, MDB_ERR_SIGINT);
    289      0     stevel 	else
    290      0     stevel 		mdb.m_pend++;
    291      0     stevel }
    292      0     stevel 
    293      0     stevel static void
    294      0     stevel control_kmdb(int start)
    295      0     stevel {
    296      0     stevel 	int fd;
    297      0     stevel 
    298      0     stevel 	if ((fd = open("/dev/kmdb", O_RDONLY)) < 0)
    299      0     stevel 		die("failed to open /dev/kmdb");
    300      0     stevel 
    301      0     stevel 	if (start) {
    302      0     stevel 		char *state = mdb_get_config();
    303      0     stevel 
    304      0     stevel 		if (ioctl(fd, KMDB_IOC_START, state) < 0)
    305      0     stevel 			die("failed to start kmdb");
    306      0     stevel 
    307      0     stevel 		strfree(state);
    308      0     stevel 	} else {
    309      0     stevel 		if (ioctl(fd, KMDB_IOC_STOP) < 0)
    310      0     stevel 			die("failed to stop kmdb");
    311      0     stevel 	}
    312      0     stevel 
    313  11053      Surya 	(void) close(fd);
    314      0     stevel }
    315      0     stevel 
    316      0     stevel static void
    317      0     stevel usage(int status)
    318      0     stevel {
    319      0     stevel 	mdb_iob_printf(mdb.m_err, "Usage: %s [-fkmuwyAFKMSUW] [+/-o option] "
    320      0     stevel 	    "[-p pid] [-s dist] [-I path] [-L path]\n\t[-P prompt] "
    321      0     stevel 	    "[-R root] [-V dis-version] [object [core] | core | suffix]\n\n",
    322      0     stevel 	    mdb.m_pname);
    323      0     stevel 
    324      0     stevel 	mdb_iob_puts(mdb.m_err,
    325      0     stevel 	    "\t-f force raw file debugging mode\n"
    326      0     stevel 	    "\t-k force kernel debugging mode\n"
    327      0     stevel 	    "\t-m disable demand-loading of module symbols\n"
    328      0     stevel 	    "\t-o set specified debugger option (+o to unset)\n"
    329      0     stevel 	    "\t-p attach to specified process-id\n"
    330      0     stevel 	    "\t-s set symbol matching distance\n"
    331      0     stevel 	    "\t-u force user program debugging mode\n"
    332      0     stevel 	    "\t-w enable write mode\n"
    333      0     stevel 	    "\t-y send terminal initialization sequences for tty mode\n"
    334      0     stevel 	    "\t-A disable automatic loading of mdb modules\n"
    335      0     stevel 	    "\t-F enable forcible takeover mode\n"
    336      0     stevel 	    "\t-K stop operating system and enter live kernel debugger\n"
    337      0     stevel 	    "\t-M preload all module symbols\n"
    338      0     stevel 	    "\t-I set initial path for macro files\n"
    339      0     stevel 	    "\t-L set initial path for module libs\n"
    340      0     stevel 	    "\t-P set command-line prompt\n"
    341      0     stevel 	    "\t-R set root directory for pathname expansion\n"
    342      0     stevel 	    "\t-S suppress processing of ~/.mdbrc file\n"
    343      0     stevel 	    "\t-U unload live kernel debugger\n"
    344      0     stevel 	    "\t-W enable I/O-mapped memory access (kernel only)\n"
    345      0     stevel 	    "\t-V set disassembler version\n");
    346      0     stevel 
    347      0     stevel 	terminate(status);
    348      0     stevel }
    349      0     stevel 
    350      0     stevel static char *
    351      0     stevel mdb_scf_console_term(void)
    352      0     stevel {
    353      0     stevel 	scf_simple_prop_t *prop;
    354      0     stevel 	char *term = NULL;
    355      0     stevel 
    356      0     stevel 	if ((prop = scf_simple_prop_get(NULL,
    357      0     stevel 	    "svc:/system/console-login:default", "ttymon",
    358      0     stevel 	    "terminal_type")) == NULL)
    359      0     stevel 		return (NULL);
    360      0     stevel 
    361      0     stevel 	if (scf_simple_prop_type(prop) == SCF_TYPE_ASTRING &&
    362      0     stevel 	    (term = scf_simple_prop_next_astring(prop)) != NULL)
    363      0     stevel 		term = strdup(term);
    364      0     stevel 
    365      0     stevel 	scf_simple_prop_free(prop);
    366      0     stevel 	return (term);
    367      0     stevel }
    368      0     stevel 
    369   6144        rab /*
    370   6144        rab  * Unpleasant hack: we might be debugging a hypervisor domain dump.
    371   6144        rab  * Earlier versions use a non-ELF file.  Later versions are ELF, but are
    372   6144        rab  * /always/ ELF64, so our standard ehdr check isn't good enough.  Since
    373   6144        rab  * we don't want to know too much about the file format, we'll ask
    374   6144        rab  * mdb_kb.
    375   6144        rab  */
    376   6144        rab #ifdef __x86
    377   6144        rab static int
    378   6144        rab identify_xvm_file(const char *file, int *longmode)
    379   6144        rab {
    380   6144        rab 	int (*identify)(const char *, int *);
    381   6144        rab 
    382   6144        rab 	if (mdb_module_load("mdb_kb", MDB_MOD_GLOBAL | MDB_MOD_SILENT) != 0)
    383   6144        rab 		return (0);
    384   6144        rab 
    385   6144        rab 	identify = (int (*)())dlsym(RTLD_NEXT, "xkb_identify");
    386   6144        rab 
    387   6144        rab 	if (identify == NULL)
    388   6144        rab 		return (0);
    389   6144        rab 
    390   6144        rab 	return (identify(file, longmode));
    391   6144        rab }
    392   6144        rab #else
    393   6144        rab /*ARGSUSED*/
    394   6144        rab static int
    395   6144        rab identify_xvm_file(const char *file, int *longmode)
    396   6144        rab {
    397   6144        rab 	return (0);
    398   6144        rab }
    399   6144        rab #endif /* __x86 */
    400   6144        rab 
    401      0     stevel int
    402      0     stevel main(int argc, char *argv[], char *envp[])
    403      0     stevel {
    404  10843       Dave 	extern int mdb_kvm_is_compressed_dump(mdb_io_t *);
    405      0     stevel 	mdb_tgt_ctor_f *tgt_ctor = NULL;
    406      0     stevel 	const char **tgt_argv = alloca(argc * sizeof (char *));
    407      0     stevel 	int tgt_argc = 0;
    408      0     stevel 	mdb_tgt_t *tgt;
    409      0     stevel 
    410      0     stevel 	char object[MAXPATHLEN], execname[MAXPATHLEN];
    411      0     stevel 	mdb_io_t *in_io, *out_io, *err_io, *null_io;
    412      0     stevel 	struct termios tios;
    413      0     stevel 	int status, c;
    414      0     stevel 	char *p;
    415      0     stevel 
    416      0     stevel 	const char *Iflag = NULL, *Lflag = NULL, *Vflag = NULL, *pidarg = NULL;
    417   5084    johnlev 	int fflag = 0, Kflag = 0, Rflag = 0, Sflag = 0, Oflag = 0, Uflag = 0;
    418      0     stevel 
    419      0     stevel 	int ttylike;
    420   6144        rab 	int longmode = 0;
    421      0     stevel 
    422      0     stevel 	stack_t sigstack;
    423      0     stevel 
    424      0     stevel 	if (realpath(getexecname(), execname) == NULL) {
    425      0     stevel 		(void) strncpy(execname, argv[0], MAXPATHLEN);
    426      0     stevel 		execname[MAXPATHLEN - 1] = '\0';
    427      0     stevel 	}
    428      0     stevel 
    429      0     stevel 	mdb_create(execname, argv[0]);
    430      0     stevel 	bzero(tgt_argv, argc * sizeof (char *));
    431      0     stevel 	argv[0] = (char *)mdb.m_pname;
    432      0     stevel 	_mdb_self_fd = open("/proc/self/as", O_RDONLY);
    433      0     stevel 
    434      0     stevel 	mdb.m_env = envp;
    435      0     stevel 
    436      0     stevel 	out_io = mdb_fdio_create(STDOUT_FILENO);
    437      0     stevel 	mdb.m_out = mdb_iob_create(out_io, MDB_IOB_WRONLY);
    438      0     stevel 
    439      0     stevel 	err_io = mdb_fdio_create(STDERR_FILENO);
    440      0     stevel 	mdb.m_err = mdb_iob_create(err_io, MDB_IOB_WRONLY);
    441      0     stevel 	mdb_iob_clrflags(mdb.m_err, MDB_IOB_AUTOWRAP);
    442      0     stevel 
    443      0     stevel 	null_io = mdb_nullio_create();
    444      0     stevel 	mdb.m_null = mdb_iob_create(null_io, MDB_IOB_WRONLY);
    445      0     stevel 
    446      0     stevel 	in_io = mdb_fdio_create(STDIN_FILENO);
    447      0     stevel 	if ((mdb.m_termtype = getenv("TERM")) != NULL) {
    448      0     stevel 		mdb.m_termtype = strdup(mdb.m_termtype);
    449      0     stevel 		mdb.m_flags |= MDB_FL_TERMGUESS;
    450      0     stevel 	}
    451      0     stevel 	mdb.m_term = NULL;
    452      0     stevel 
    453      0     stevel 	mdb_dmode(mdb_dstr2mode(getenv("MDB_DEBUG")));
    454      0     stevel 	mdb.m_pgid = getpgrp();
    455      0     stevel 
    456      0     stevel 	if (getenv("_MDB_EXEC") != NULL)
    457      0     stevel 		mdb.m_flags |= MDB_FL_EXEC;
    458      0     stevel 
    459      0     stevel 	/*
    460      0     stevel 	 * Setup an alternate signal stack.  When tearing down pipelines in
    461      0     stevel 	 * terminate(), we may have to destroy the stack of the context in
    462      0     stevel 	 * which we are currently executing the signal handler.
    463      0     stevel 	 */
    464      0     stevel 	sigstack.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
    465      0     stevel 	    MAP_PRIVATE | MAP_ANON, -1, 0);
    466      0     stevel 	if (sigstack.ss_sp == MAP_FAILED)
    467      0     stevel 		die("could not allocate signal stack");
    468      0     stevel 	sigstack.ss_size = SIGSTKSZ;
    469      0     stevel 	sigstack.ss_flags = 0;
    470      0     stevel 	if (sigaltstack(&sigstack, NULL) != 0)
    471      0     stevel 		die("could not set signal stack");
    472      0     stevel 
    473      0     stevel 	(void) mdb_signal_sethandler(SIGPIPE, SIG_IGN, NULL);
    474      0     stevel 	(void) mdb_signal_sethandler(SIGQUIT, SIG_IGN, NULL);
    475      0     stevel 
    476      0     stevel 	(void) mdb_signal_sethandler(SIGILL, flt_handler, NULL);
    477      0     stevel 	(void) mdb_signal_sethandler(SIGTRAP, flt_handler, NULL);
    478      0     stevel 	(void) mdb_signal_sethandler(SIGIOT, flt_handler, NULL);
    479      0     stevel 	(void) mdb_signal_sethandler(SIGEMT, flt_handler, NULL);
    480      0     stevel 	(void) mdb_signal_sethandler(SIGFPE, flt_handler, NULL);
    481      0     stevel 	(void) mdb_signal_sethandler(SIGBUS, flt_handler, NULL);
    482      0     stevel 	(void) mdb_signal_sethandler(SIGSEGV, flt_handler, NULL);
    483      0     stevel 
    484      0     stevel 	(void) mdb_signal_sethandler(SIGHUP, (mdb_signal_f *)terminate, NULL);
    485      0     stevel 	(void) mdb_signal_sethandler(SIGTERM, (mdb_signal_f *)terminate, NULL);
    486      0     stevel 
    487      0     stevel 	for (mdb.m_rdvers = RD_VERSION; mdb.m_rdvers > 0; mdb.m_rdvers--) {
    488      0     stevel 		if (rd_init(mdb.m_rdvers) == RD_OK)
    489      0     stevel 			break;
    490      0     stevel 	}
    491      0     stevel 
    492      0     stevel 	for (mdb.m_ctfvers = CTF_VERSION; mdb.m_ctfvers > 0; mdb.m_ctfvers--) {
    493      0     stevel 		if (ctf_version(mdb.m_ctfvers) != -1)
    494      0     stevel 			break;
    495      0     stevel 	}
    496      0     stevel 
    497      0     stevel 	if ((p = getenv("HISTSIZE")) != NULL && strisnum(p)) {
    498      0     stevel 		mdb.m_histlen = strtoi(p);
    499      0     stevel 		if (mdb.m_histlen < 1)
    500      0     stevel 			mdb.m_histlen = 1;
    501      0     stevel 	}
    502      0     stevel 
    503      0     stevel 	while (optind < argc) {
    504      0     stevel 		while ((c = getopt(argc, argv,
    505      0     stevel 		    "fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) {
    506      0     stevel 			switch (c) {
    507      0     stevel 			case 'f':
    508   5084    johnlev 				fflag++;
    509      0     stevel 				tgt_ctor = mdb_rawfile_tgt_create;
    510      0     stevel 				break;
    511      0     stevel 			case 'k':
    512      0     stevel 				tgt_ctor = mdb_kvm_tgt_create;
    513      0     stevel 				break;
    514      0     stevel 			case 'm':
    515      0     stevel 				mdb.m_tgtflags |= MDB_TGT_F_NOLOAD;
    516      0     stevel 				mdb.m_tgtflags &= ~MDB_TGT_F_PRELOAD;
    517      0     stevel 				break;
    518      0     stevel 			case 'o':
    519      0     stevel 				if (!mdb_set_options(optarg, TRUE))
    520      0     stevel 					terminate(2);
    521      0     stevel 				break;
    522      0     stevel 			case 'p':
    523      0     stevel 				tgt_ctor = mdb_proc_tgt_create;
    524      0     stevel 				pidarg = optarg;
    525      0     stevel 				break;
    526      0     stevel 			case 's':
    527      0     stevel 				if (!strisnum(optarg)) {
    528      0     stevel 					warn("expected integer following -s\n");
    529      0     stevel 					terminate(2);
    530      0     stevel 				}
    531      0     stevel 				mdb.m_symdist = (size_t)(uint_t)strtoi(optarg);
    532      0     stevel 				break;
    533      0     stevel 			case 'u':
    534      0     stevel 				tgt_ctor = mdb_proc_tgt_create;
    535      0     stevel 				break;
    536      0     stevel 			case 'w':
    537      0     stevel 				mdb.m_tgtflags |= MDB_TGT_F_RDWR;
    538      0     stevel 				break;
    539      0     stevel 			case 'y':
    540      0     stevel 				mdb.m_flags |= MDB_FL_USECUP;
    541      0     stevel 				break;
    542      0     stevel 			case 'A':
    543      0     stevel 				(void) mdb_set_options("nomods", TRUE);
    544      0     stevel 				break;
    545      0     stevel 			case 'C':
    546      0     stevel 				(void) mdb_set_options("noctf", TRUE);
    547      0     stevel 				break;
    548      0     stevel 			case 'D':
    549      0     stevel 				mdb_dmode(mdb_dstr2mode(optarg));
    550      0     stevel 				break;
    551      0     stevel 			case 'F':
    552      0     stevel 				mdb.m_tgtflags |= MDB_TGT_F_FORCE;
    553      0     stevel 				break;
    554      0     stevel 			case 'I':
    555      0     stevel 				Iflag = optarg;
    556      0     stevel 				break;
    557      0     stevel 			case 'L':
    558      0     stevel 				Lflag = optarg;
    559      0     stevel 				break;
    560      0     stevel 			case 'K':
    561      0     stevel 				Kflag++;
    562      0     stevel 				break;
    563      0     stevel 			case 'M':
    564      0     stevel 				mdb.m_tgtflags |= MDB_TGT_F_PRELOAD;
    565      0     stevel 				mdb.m_tgtflags &= ~MDB_TGT_F_NOLOAD;
    566      0     stevel 				break;
    567      0     stevel 			case 'O':
    568      0     stevel 				Oflag++;
    569      0     stevel 				break;
    570      0     stevel 			case 'P':
    571      0     stevel 				if (!mdb_set_prompt(optarg))
    572      0     stevel 					terminate(2);
    573      0     stevel 				break;
    574      0     stevel 			case 'R':
    575      0     stevel 				(void) strncpy(mdb.m_root, optarg, MAXPATHLEN);
    576      0     stevel 				mdb.m_root[MAXPATHLEN - 1] = '\0';
    577      0     stevel 				Rflag++;
    578      0     stevel 				break;
    579      0     stevel 			case 'S':
    580      0     stevel 				Sflag++;
    581      0     stevel 				break;
    582      0     stevel 			case 'U':
    583      0     stevel 				Uflag++;
    584      0     stevel 				break;
    585      0     stevel 			case 'V':
    586      0     stevel 				Vflag = optarg;
    587      0     stevel 				break;
    588      0     stevel 			case 'W':
    589      0     stevel 				mdb.m_tgtflags |= MDB_TGT_F_ALLOWIO;
    590      0     stevel 				break;
    591      0     stevel 			case '?':
    592      0     stevel 				if (optopt == '?')
    593      0     stevel 					usage(0);
    594      0     stevel 				/* FALLTHROUGH */
    595      0     stevel 			default:
    596      0     stevel 				usage(2);
    597      0     stevel 			}
    598      0     stevel 		}
    599      0     stevel 
    600      0     stevel 		if (optind < argc) {
    601      0     stevel 			const char *arg = argv[optind++];
    602      0     stevel 
    603      0     stevel 			if (arg[0] == '+' && strlen(arg) == 2) {
    604      0     stevel 				if (arg[1] != 'o') {
    605      0     stevel 					warn("illegal option -- %s\n", arg);
    606      0     stevel 					terminate(2);
    607      0     stevel 				}
    608      0     stevel 				if (optind >= argc) {
    609      0     stevel 					warn("option requires an argument -- "
    610      0     stevel 					    "%s\n", arg);
    611      0     stevel 					terminate(2);
    612      0     stevel 				}
    613      0     stevel 				if (!mdb_set_options(argv[optind++], FALSE))
    614      0     stevel 					terminate(2);
    615      0     stevel 			} else
    616      0     stevel 				tgt_argv[tgt_argc++] = arg;
    617      0     stevel 		}
    618      0     stevel 	}
    619      0     stevel 
    620   2712    nn35248 	if (rd_ctl(RD_CTL_SET_HELPPATH, (void *)mdb.m_root) != RD_OK) {
    621   2712    nn35248 		warn("cannot set librtld_db helper path to %s\n", mdb.m_root);
    622   2712    nn35248 		terminate(2);
    623   2712    nn35248 	}
    624   2712    nn35248 
    625      0     stevel 	if (mdb.m_debug & MDB_DBG_HELP)
    626      0     stevel 		terminate(0); /* Quit here if we've printed out the tokens */
    627   2712    nn35248 
    628      0     stevel 
    629      0     stevel 	if (Iflag != NULL && strchr(Iflag, ';') != NULL) {
    630      0     stevel 		warn("macro path cannot contain semicolons\n");
    631      0     stevel 		terminate(2);
    632      0     stevel 	}
    633      0     stevel 
    634      0     stevel 	if (Lflag != NULL && strchr(Lflag, ';') != NULL) {
    635      0     stevel 		warn("module path cannot contain semicolons\n");
    636      0     stevel 		terminate(2);
    637      0     stevel 	}
    638      0     stevel 
    639      0     stevel 	if (Kflag || Uflag) {
    640      0     stevel 		char *nm;
    641      0     stevel 
    642      0     stevel 		if (tgt_ctor != NULL || Iflag != NULL) {
    643      0     stevel 			warn("neither -f, -k, -p, -u, nor -I "
    644      0     stevel 			    "may be used with -K\n");
    645      0     stevel 			usage(2);
    646      0     stevel 		}
    647      0     stevel 
    648      0     stevel 		if (Lflag != NULL)
    649      0     stevel 			mdb_set_lpath(Lflag);
    650      0     stevel 
    651      0     stevel 		if ((nm = ttyname(STDIN_FILENO)) == NULL ||
    652      0     stevel 		    strcmp(nm, "/dev/console") != 0) {
    653      0     stevel 			/*
    654      0     stevel 			 * Due to the consequences of typing mdb -K instead of
    655      0     stevel 			 * mdb -k on a tty other than /dev/console, we require
    656      0     stevel 			 * -F when starting kmdb from a tty other than
    657      0     stevel 			 * /dev/console.
    658      0     stevel 			 */
    659      0     stevel 			if (!(mdb.m_tgtflags & MDB_TGT_F_FORCE)) {
    660      0     stevel 				die("-F must also be supplied to start kmdb "
    661      0     stevel 				    "from non-console tty\n");
    662      0     stevel 			}
    663      0     stevel 
    664      0     stevel 			if (mdb.m_termtype == NULL || (mdb.m_flags &
    665      0     stevel 			    MDB_FL_TERMGUESS)) {
    666      0     stevel 				if (mdb.m_termtype != NULL)
    667      0     stevel 					strfree(mdb.m_termtype);
    668      0     stevel 
    669      0     stevel 				if ((mdb.m_termtype = mdb_scf_console_term()) !=
    670      0     stevel 				    NULL)
    671      0     stevel 					mdb.m_flags |= MDB_FL_TERMGUESS;
    672      0     stevel 			}
    673      0     stevel 		} else {
    674      0     stevel 			/*
    675      0     stevel 			 * When on console, $TERM (if set) takes precedence over
    676      0     stevel 			 * the SMF setting.
    677      0     stevel 			 */
    678      0     stevel 			if (mdb.m_termtype == NULL && (mdb.m_termtype =
    679      0     stevel 			    mdb_scf_console_term()) != NULL)
    680      0     stevel 				mdb.m_flags |= MDB_FL_TERMGUESS;
    681      0     stevel 		}
    682      0     stevel 
    683      0     stevel 		control_kmdb(Kflag);
    684      0     stevel 		terminate(0);
    685      0     stevel 		/*NOTREACHED*/
    686      0     stevel 	}
    687      0     stevel 
    688      0     stevel 	/*
    689      0     stevel 	 * If standard input appears to have tty attributes, attempt to
    690      0     stevel 	 * initialize a terminal i/o backend on top of stdin and stdout.
    691      0     stevel 	 */
    692      0     stevel 	ttylike = (IOP_CTL(in_io, TCGETS, &tios) == 0);
    693      0     stevel 	if (ttylike) {
    694      0     stevel 		if ((mdb.m_term = mdb_termio_create(mdb.m_termtype,
    695      0     stevel 		    in_io, out_io)) == NULL) {
    696      0     stevel 			if (!(mdb.m_flags & MDB_FL_EXEC)) {
    697      0     stevel 				warn("term init failed: command-line editing "
    698      0     stevel 				    "and prompt will not be available\n");
    699      0     stevel 			}
    700      0     stevel 		} else {
    701      0     stevel 			in_io = mdb.m_term;
    702      0     stevel 		}
    703      0     stevel 	}
    704      0     stevel 
    705      0     stevel 	mdb.m_in = mdb_iob_create(in_io, MDB_IOB_RDONLY);
    706      0     stevel 	if (mdb.m_term != NULL) {
    707      0     stevel 		mdb_iob_setpager(mdb.m_out, mdb.m_term);
    708      0     stevel 		if (mdb.m_flags & MDB_FL_PAGER)
    709      0     stevel 			mdb_iob_setflags(mdb.m_out, MDB_IOB_PGENABLE);
    710      0     stevel 		else
    711      0     stevel 			mdb_iob_clrflags(mdb.m_out, MDB_IOB_PGENABLE);
    712      0     stevel 	} else if (ttylike)
    713      0     stevel 		mdb_iob_setflags(mdb.m_in, MDB_IOB_TTYLIKE);
    714      0     stevel 	else
    715      0     stevel 		mdb_iob_setbuf(mdb.m_in, mdb_alloc(1, UM_SLEEP), 1);
    716      0     stevel 
    717      0     stevel 	mdb_pservice_init();
    718      0     stevel 	mdb_lex_reset();
    719      0     stevel 
    720      0     stevel 	if ((mdb.m_shell = getenv("SHELL")) == NULL)
    721      0     stevel 		mdb.m_shell = "/bin/sh";
    722      0     stevel 
    723   6144        rab 	/*
    724   6144        rab 	 * If the debugger state is to be inherited from a previous instance,
    725   6144        rab 	 * restore it now prior to path evaluation so that %R is updated.
    726   6144        rab 	 */
    727   6144        rab 	if ((p = getenv(MDB_CONFIG_ENV_VAR)) != NULL) {
    728   6144        rab 		mdb_set_config(p);
    729   6144        rab 		(void) unsetenv(MDB_CONFIG_ENV_VAR);
    730   6144        rab 	}
    731   6144        rab 
    732   6144        rab 	/*
    733   6144        rab 	 * Path evaluation part 1: Create the initial module path to allow
    734   6144        rab 	 * the target constructor to load a support module.  Then expand
    735   6144        rab 	 * any command-line arguments that modify the paths.
    736   6144        rab 	 */
    737   6144        rab 	if (Iflag != NULL)
    738   6144        rab 		mdb_set_ipath(Iflag);
    739   6144        rab 	else
    740   6144        rab 		mdb_set_ipath(MDB_DEF_IPATH);
    741   6144        rab 
    742   6144        rab 	if (Lflag != NULL)
    743   6144        rab 		mdb_set_lpath(Lflag);
    744   6144        rab 	else
    745   6144        rab 		mdb_set_lpath(MDB_DEF_LPATH);
    746   6144        rab 
    747   6144        rab 	if (mdb_get_prompt() == NULL && !(mdb.m_flags & MDB_FL_ADB))
    748   6144        rab 		(void) mdb_set_prompt(MDB_DEF_PROMPT);
    749   6144        rab 
    750      0     stevel 	if (tgt_ctor == mdb_kvm_tgt_create) {
    751      0     stevel 		if (pidarg != NULL) {
    752      0     stevel 			warn("-p and -k options are mutually exclusive\n");
    753      0     stevel 			terminate(2);
    754      0     stevel 		}
    755      0     stevel 
    756      0     stevel 		if (tgt_argc == 0)
    757      0     stevel 			tgt_argv[tgt_argc++] = "/dev/ksyms";
    758      0     stevel 		if (tgt_argc == 1 && strisnum(tgt_argv[0]) == 0) {
    759      0     stevel 			if (mdb.m_tgtflags & MDB_TGT_F_ALLOWIO)
    760      0     stevel 				tgt_argv[tgt_argc++] = "/dev/allkmem";
    761      0     stevel 			else
    762      0     stevel 				tgt_argv[tgt_argc++] = "/dev/kmem";
    763      0     stevel 		}
    764      0     stevel 	}
    765      0     stevel 
    766      0     stevel 	if (pidarg != NULL) {
    767      0     stevel 		if (tgt_argc != 0) {
    768      0     stevel 			warn("-p may not be used with other arguments\n");
    769      0     stevel 			terminate(2);
    770      0     stevel 		}
    771      0     stevel 		if (proc_arg_psinfo(pidarg, PR_ARG_PIDS, NULL, &status) == -1) {
    772      0     stevel 			die("cannot attach to %s: %s\n",
    773      0     stevel 			    pidarg, Pgrab_error(status));
    774      0     stevel 		}
    775      0     stevel 		if (strchr(pidarg, '/') != NULL)
    776      0     stevel 			(void) mdb_iob_snprintf(object, MAXPATHLEN,
    777      0     stevel 			    "%s/object/a.out", pidarg);
    778      0     stevel 		else
    779      0     stevel 			(void) mdb_iob_snprintf(object, MAXPATHLEN,
    780      0     stevel 			    "/proc/%s/object/a.out", pidarg);
    781      0     stevel 		tgt_argv[tgt_argc++] = object;
    782      0     stevel 		tgt_argv[tgt_argc++] = pidarg;
    783      0     stevel 	}
    784      0     stevel 
    785      0     stevel 	/*
    786      0     stevel 	 * Find the first argument that is not a special "-" token.  If one is
    787      0     stevel 	 * found, we will examine this file and make some inferences below.
    788      0     stevel 	 */
    789      0     stevel 	for (c = 0; c < tgt_argc && strcmp(tgt_argv[c], "-") == 0; c++)
    790      0     stevel 		continue;
    791      0     stevel 
    792      0     stevel 	if (c < tgt_argc) {
    793      0     stevel 		Elf32_Ehdr ehdr;
    794      0     stevel 		mdb_io_t *io;
    795      0     stevel 
    796      0     stevel 		/*
    797      0     stevel 		 * If special "-" tokens preceded an argument, shift the entire
    798      0     stevel 		 * argument list to the left to remove the leading "-" args.
    799      0     stevel 		 */
    800      0     stevel 		if (c > 0) {
    801      0     stevel 			bcopy(&tgt_argv[c], tgt_argv,
    802      0     stevel 			    sizeof (const char *) * (tgt_argc - c));
    803      0     stevel 			tgt_argc -= c;
    804      0     stevel 		}
    805      0     stevel 
    806      0     stevel 		/*
    807      0     stevel 		 * If we just have an object file name, and that file doesn't
    808      0     stevel 		 * exist, and it's a string of digits, infer it to be a
    809      0     stevel 		 * sequence number referring to a pair of crash dump files.
    810      0     stevel 		 */
    811      0     stevel 		if (tgt_argc == 1 && access(tgt_argv[0], F_OK) == -1 &&
    812      0     stevel 		    strisnum(tgt_argv[0])) {
    813      0     stevel 
    814      0     stevel 			size_t len = strlen(tgt_argv[0]) + 8;
    815      0     stevel 			const char *object = tgt_argv[0];
    816      0     stevel 
    817      0     stevel 			tgt_argv[0] = mdb_alloc(len, UM_SLEEP);
    818      0     stevel 			tgt_argv[1] = mdb_alloc(len, UM_SLEEP);
    819      0     stevel 
    820      0     stevel 			(void) strcpy((char *)tgt_argv[0], "unix.");
    821      0     stevel 			(void) strcat((char *)tgt_argv[0], object);
    822      0     stevel 			(void) strcpy((char *)tgt_argv[1], "vmcore.");
    823      0     stevel 			(void) strcat((char *)tgt_argv[1], object);
    824      0     stevel 
    825  10843       Dave 			if (access(tgt_argv[0], F_OK) == -1 &&
    826  10843       Dave 			    access(tgt_argv[1], F_OK) == -1) {
    827  10843       Dave 				(void) strcpy((char *)tgt_argv[1], "vmdump.");
    828  10843       Dave 				(void) strcat((char *)tgt_argv[1], object);
    829  10843       Dave 				if (access(tgt_argv[1], F_OK) == 0) {
    830  10843       Dave 					mdb_iob_printf(mdb.m_err,
    831  10843       Dave 					    "cannot open compressed dump; "
    832  10843       Dave 					    "decompress using savecore -f %s\n",
    833  10843       Dave 					    tgt_argv[1]);
    834  10843       Dave 					terminate(0);
    835  10843       Dave 				}
    836  10843       Dave 			}
    837  10843       Dave 
    838      0     stevel 			tgt_argc = 2;
    839      0     stevel 		}
    840      0     stevel 
    841      0     stevel 		/*
    842      0     stevel 		 * We need to open the object file in order to determine its
    843      0     stevel 		 * ELF class and potentially re-exec ourself.
    844      0     stevel 		 */
    845      0     stevel 		if ((io = mdb_fdio_create_path(NULL, tgt_argv[0],
    846      0     stevel 		    O_RDONLY, 0)) == NULL)
    847      0     stevel 			die("failed to open %s", tgt_argv[0]);
    848  10843       Dave 
    849  10843       Dave 		/*
    850  10843       Dave 		 * Check for a single vmdump.N compressed dump file,
    851  10843       Dave 		 * and give a helpful message.
    852  10843       Dave 		 */
    853  10843       Dave 		if (tgt_argc == 1) {
    854  10843       Dave 			if (mdb_kvm_is_compressed_dump(io)) {
    855  10843       Dave 				mdb_iob_printf(mdb.m_err,
    856  10843       Dave 				    "cannot open compressed dump; "
    857  10843       Dave 				    "decompress using savecore -f %s\n",
    858  10843       Dave 				    tgt_argv[0]);
    859  10843       Dave 				terminate(0);
    860  10843       Dave 			}
    861  10843       Dave 		}
    862      0     stevel 
    863      0     stevel 		/*
    864      0     stevel 		 * If the target is unknown or is not the rawfile target, do
    865      0     stevel 		 * a gelf_check to determine if the file is an ELF file.  If
    866      0     stevel 		 * it is not and the target is unknown, use the rawfile tgt.
    867      0     stevel 		 * Otherwise an ELF-based target is needed, so we must abort.
    868      0     stevel 		 */
    869      0     stevel 		if (tgt_ctor != mdb_rawfile_tgt_create &&
    870      0     stevel 		    mdb_gelf_check(io, &ehdr, ET_NONE) == -1) {
    871      0     stevel 			if (tgt_ctor != NULL) {
    872      0     stevel 				(void) mdb_gelf_check(io, &ehdr, ET_EXEC);
    873      0     stevel 				mdb_io_destroy(io);
    874      0     stevel 				terminate(1);
    875      0     stevel 			} else
    876      0     stevel 				tgt_ctor = mdb_rawfile_tgt_create;
    877      0     stevel 		}
    878      0     stevel 
    879      0     stevel 		mdb_io_destroy(io);
    880      0     stevel 
    881   6144        rab 		if (identify_xvm_file(tgt_argv[0], &longmode) == 1 &&
    882   6144        rab 		    !fflag) {
    883   6144        rab #ifdef _LP64
    884   6144        rab 			if (!longmode)
    885   6144        rab 				goto reexec;
    886   6144        rab #else
    887   6144        rab 			if (longmode)
    888   6144        rab 				goto reexec;
    889   6144        rab #endif
    890   6144        rab 			tgt_ctor = mdb_kvm_tgt_create;
    891   6144        rab 			goto tcreate;
    892   6144        rab 		}
    893   6144        rab 
    894      0     stevel 		if (tgt_ctor == mdb_rawfile_tgt_create)
    895      0     stevel 			goto tcreate; /* skip re-exec and just create target */
    896      0     stevel 
    897      0     stevel 		/*
    898      0     stevel 		 * The object file turned out to be a user core file (ET_CORE),
    899      0     stevel 		 * and no other arguments were specified, swap 0 and 1.  The
    900      0     stevel 		 * proc target will infer the executable for us.
    901      0     stevel 		 */
    902      0     stevel 		if (ehdr.e_type == ET_CORE) {
    903      0     stevel 			tgt_argv[tgt_argc++] = tgt_argv[0];
    904      0     stevel 			tgt_argv[0] = NULL;
    905      0     stevel 			tgt_ctor = mdb_proc_tgt_create;
    906      0     stevel 		}
    907      0     stevel 
    908      0     stevel 		/*
    909      0     stevel 		 * If tgt_argv[1] is filled in, open it up and determine if it
    910      0     stevel 		 * is a vmcore file.  If it is, gelf_check will fail and we
    911      0     stevel 		 * set tgt_ctor to 'kvm'; otherwise we use the default.
    912      0     stevel 		 */
    913      0     stevel 		if (tgt_argc > 1 && strcmp(tgt_argv[1], "-") != 0 &&
    914      0     stevel 		    tgt_argv[0] != NULL && pidarg == NULL) {
    915      0     stevel 			Elf32_Ehdr chdr;
    916      0     stevel 
    917      0     stevel 			if (access(tgt_argv[1], F_OK) == -1)
    918      0     stevel 				die("failed to access %s", tgt_argv[1]);
    919  10843       Dave 
    920  10843       Dave 			/* *.N case: drop vmdump.N from the list */
    921  10843       Dave 			if (tgt_argc == 3) {
    922  10843       Dave 				if ((io = mdb_fdio_create_path(NULL,
    923  10843       Dave 				    tgt_argv[2], O_RDONLY, 0)) == NULL)
    924  10843       Dave 					die("failed to open %s", tgt_argv[2]);
    925  10843       Dave 				if (mdb_kvm_is_compressed_dump(io))
    926  10843       Dave 					tgt_argv[--tgt_argc] = NULL;
    927  10843       Dave 				mdb_io_destroy(io);
    928  10843       Dave 			}
    929      0     stevel 
    930      0     stevel 			if ((io = mdb_fdio_create_path(NULL, tgt_argv[1],
    931      0     stevel 			    O_RDONLY, 0)) == NULL)
    932      0     stevel 				die("failed to open %s", tgt_argv[1]);
    933      0     stevel 
    934      0     stevel 			if (mdb_gelf_check(io, &chdr, ET_NONE) == -1)
    935      0     stevel 				tgt_ctor = mdb_kvm_tgt_create;
    936      0     stevel 
    937      0     stevel 			mdb_io_destroy(io);
    938      0     stevel 		}
    939      0     stevel 
    940      0     stevel 		/*
    941      0     stevel 		 * At this point, we've read the ELF header for either an
    942      0     stevel 		 * object file or core into ehdr.  If the class does not match
    943      0     stevel 		 * ours, attempt to exec the mdb of the appropriate class.
    944      0     stevel 		 */
    945      0     stevel #ifdef _LP64
    946   5084    johnlev 		if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
    947   5084    johnlev 			goto reexec;
    948      0     stevel #else
    949   5084    johnlev 		if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
    950   5084    johnlev 			goto reexec;
    951      0     stevel #endif
    952      0     stevel 	}
    953      0     stevel 
    954      0     stevel tcreate:
    955      0     stevel 	if (tgt_ctor == NULL)
    956      0     stevel 		tgt_ctor = mdb_proc_tgt_create;
    957      0     stevel 
    958      0     stevel 	tgt = mdb_tgt_create(tgt_ctor, mdb.m_tgtflags, tgt_argc, tgt_argv);
    959      0     stevel 
    960      0     stevel 	if (tgt == NULL) {
    961      0     stevel 		if (errno == EINVAL)
    962      0     stevel 			usage(2); /* target can return EINVAL to get usage */
    963      0     stevel 		if (errno == EMDB_TGT)
    964      0     stevel 			terminate(1); /* target already printed error msg */
    965      0     stevel 		die("failed to initialize target");
    966      0     stevel 	}
    967      0     stevel 
    968      0     stevel 	mdb_tgt_activate(tgt);
    969      0     stevel 
    970      0     stevel 	mdb_create_loadable_disasms();
    971      0     stevel 
    972      0     stevel 	if (Vflag != NULL && mdb_dis_select(Vflag) == -1)
    973      0     stevel 		warn("invalid disassembler mode -- %s\n", Vflag);
    974      0     stevel 
    975      0     stevel 
    976      0     stevel 	if (Rflag && mdb.m_term != NULL)
    977      0     stevel 		warn("Using proto area %s\n", mdb.m_root);
    978      0     stevel 
    979      0     stevel 	/*
    980      0     stevel 	 * If the target was successfully constructed and -O was specified,
    981      0     stevel 	 * we now attempt to enter piggy-mode for debugging jurassic problems.
    982      0     stevel 	 */
    983      0     stevel 	if (Oflag) {
    984      0     stevel 		pcinfo_t pci;
    985      0     stevel 
    986      0     stevel 		(void) strcpy(pci.pc_clname, "RT");
    987      0     stevel 
    988      0     stevel 		if (priocntl(P_LWPID, P_MYID, PC_GETCID, (caddr_t)&pci) != -1) {
    989      0     stevel 			pcparms_t pcp;
    990      0     stevel 			rtparms_t *rtp = (rtparms_t *)pcp.pc_clparms;
    991      0     stevel 
    992      0     stevel 			rtp->rt_pri = 35;
    993      0     stevel 			rtp->rt_tqsecs = 0;
    994      0     stevel 			rtp->rt_tqnsecs = RT_TQDEF;
    995      0     stevel 
    996      0     stevel 			pcp.pc_cid = pci.pc_cid;
    997      0     stevel 
    998      0     stevel 			if (priocntl(P_LWPID, P_MYID, PC_SETPARMS,
    999      0     stevel 			    (caddr_t)&pcp) == -1) {
   1000      0     stevel 				warn("failed to set RT parameters");
   1001      0     stevel 				Oflag = 0;
   1002      0     stevel 			}
   1003      0     stevel 		} else {
   1004      0     stevel 			warn("failed to get RT class id");
   1005      0     stevel 			Oflag = 0;
   1006      0     stevel 		}
   1007      0     stevel 
   1008      0     stevel 		if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
   1009      0     stevel 			warn("failed to lock address space");
   1010      0     stevel 			Oflag = 0;
   1011      0     stevel 		}
   1012      0     stevel 
   1013      0     stevel 		if (Oflag)
   1014      0     stevel 			mdb_printf("%s: oink, oink!\n", mdb.m_pname);
   1015      0     stevel 	}
   1016      0     stevel 
   1017      0     stevel 	/*
   1018      0     stevel 	 * Path evaluation part 2: Re-evaluate the path now that the target
   1019      0     stevel 	 * is ready (and thus we have access to the real platform string).
   1020      0     stevel 	 * Do this before reading ~/.mdbrc to allow path modifications prior
   1021      0     stevel 	 * to performing module auto-loading.
   1022      0     stevel 	 */
   1023      0     stevel 	mdb_set_ipath(mdb.m_ipathstr);
   1024      0     stevel 	mdb_set_lpath(mdb.m_lpathstr);
   1025      0     stevel 
   1026      0     stevel 	if (!Sflag && (p = getenv("HOME")) != NULL) {
   1027      0     stevel 		char rcpath[MAXPATHLEN];
   1028      0     stevel 		mdb_io_t *rc_io;
   1029      0     stevel 		int fd;
   1030      0     stevel 
   1031      0     stevel 		(void) mdb_iob_snprintf(rcpath, MAXPATHLEN, "%s/.mdbrc", p);
   1032      0     stevel 		fd = open64(rcpath, O_RDONLY);
   1033      0     stevel 
   1034      0     stevel 		if (fd >= 0 && (rc_io = mdb_fdio_create_named(fd, rcpath))) {
   1035      0     stevel 			mdb_iob_t *iob = mdb_iob_create(rc_io, MDB_IOB_RDONLY);
   1036      0     stevel 			mdb_iob_t *old = mdb.m_in;
   1037      0     stevel 
   1038      0     stevel 			mdb.m_in = iob;
   1039      0     stevel 			(void) mdb_run();
   1040      0     stevel 			mdb.m_in = old;
   1041      0     stevel 		}
   1042      0     stevel 	}
   1043      0     stevel 
   1044      0     stevel 	if (!(mdb.m_flags & MDB_FL_NOMODS))
   1045      0     stevel 		mdb_module_load_all(0);
   1046      0     stevel 
   1047      0     stevel 	(void) mdb_signal_sethandler(SIGINT, int_handler, NULL);
   1048      0     stevel 	while ((status = mdb_run()) == MDB_ERR_ABORT ||
   1049      0     stevel 	    status == MDB_ERR_OUTPUT) {
   1050      0     stevel 		/*
   1051      0     stevel 		 * If a write failed on stdout, give up.  A more informative
   1052      0     stevel 		 * error message will already have been printed by mdb_run().
   1053      0     stevel 		 */
   1054      0     stevel 		if (status == MDB_ERR_OUTPUT &&
   1055      0     stevel 		    mdb_iob_getflags(mdb.m_out) & MDB_IOB_ERR) {
   1056      0     stevel 			mdb_warn("write to stdout failed, exiting\n");
   1057      0     stevel 			break;
   1058      0     stevel 		}
   1059      0     stevel 		continue;
   1060      0     stevel 	}
   1061      0     stevel 
   1062      0     stevel 	terminate((status == MDB_ERR_QUIT || status == 0) ? 0 : 1);
   1063      0     stevel 	/*NOTREACHED*/
   1064      0     stevel 	return (0);
   1065   5084    johnlev 
   1066   5084    johnlev reexec:
   1067   5084    johnlev 	if ((p = strrchr(execname, '/')) == NULL)
   1068   5084    johnlev 		die("cannot determine absolute pathname\n");
   1069   5084    johnlev #ifdef _LP64
   1070   5084    johnlev #ifdef __sparc
   1071   5084    johnlev 	(void) strcpy(p, "/../sparcv7/");
   1072   5084    johnlev #else
   1073   5084    johnlev 	(void) strcpy(p, "/../i86/");
   1074   5084    johnlev #endif
   1075   5084    johnlev #else
   1076   5084    johnlev #ifdef __sparc
   1077   5084    johnlev 	(void) strcpy(p, "/../sparcv9/");
   1078   5084    johnlev #else
   1079   5084    johnlev 	(void) strcpy(p, "/../amd64/");
   1080   5084    johnlev #endif
   1081   5084    johnlev #endif
   1082   5084    johnlev 	(void) strcat(p, mdb.m_pname);
   1083   5084    johnlev 
   1084   5084    johnlev 	if (mdb.m_term != NULL)
   1085   5084    johnlev 		(void) IOP_CTL(in_io, TCSETSW, &tios);
   1086   5084    johnlev 
   1087   5084    johnlev 	(void) putenv("_MDB_EXEC=1");
   1088   5084    johnlev 	(void) execv(execname, argv);
   1089   5084    johnlev 
   1090   5084    johnlev 	/*
   1091   5084    johnlev 	 * If execv fails, suppress ENOEXEC.  Experience shows the most common
   1092   5084    johnlev 	 * reason is that the machine is booted under a 32-bit kernel, in which
   1093   5084    johnlev 	 * case it is clearer to only print the message below.
   1094   5084    johnlev 	 */
   1095   5084    johnlev 	if (errno != ENOEXEC)
   1096   5084    johnlev 		warn("failed to exec %s", execname);
   1097   5084    johnlev #ifdef _LP64
   1098   5084    johnlev 	die("64-bit %s cannot debug 32-bit program %s\n",
   1099   5084    johnlev 	    mdb.m_pname, tgt_argv[0] ?
   1100   5084    johnlev 	    tgt_argv[0] : tgt_argv[1]);
   1101   5084    johnlev #else
   1102   5084    johnlev 	die("32-bit %s cannot debug 64-bit program %s\n",
   1103   5084    johnlev 	    mdb.m_pname, tgt_argv[0] ?
   1104   5084    johnlev 	    tgt_argv[0] : tgt_argv[1]);
   1105   5084    johnlev #endif
   1106   5084    johnlev 
   1107   5084    johnlev 	goto tcreate;
   1108      0     stevel }
   1109