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