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