17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
59acbbeafSnn35248 * Common Development and Distribution License (the "License").
69acbbeafSnn35248 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22ca3e8d88SDave Plauger * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
24ffd958e4SJosef 'Jeff' Sipek * Copyright 2012, Josef 'Jeff' Sipek <jeffpc@31bits.net>. All rights reserved.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
271320caf7SBryan Cantrill /*
281320caf7SBryan Cantrill * Copyright (c) 2013, Joyent, Inc. All rights reserved.
291320caf7SBryan Cantrill */
301320caf7SBryan Cantrill
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/mman.h>
337c478bd9Sstevel@tonic-gate #include <sys/priocntl.h>
347c478bd9Sstevel@tonic-gate #include <sys/rtpriocntl.h>
357c478bd9Sstevel@tonic-gate #include <sys/resource.h>
367c478bd9Sstevel@tonic-gate #include <sys/termios.h>
377c478bd9Sstevel@tonic-gate #include <sys/param.h>
387c478bd9Sstevel@tonic-gate #include <sys/regset.h>
397c478bd9Sstevel@tonic-gate #include <sys/frame.h>
407c478bd9Sstevel@tonic-gate #include <sys/stack.h>
417c478bd9Sstevel@tonic-gate #include <sys/reg.h>
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate #include <libproc.h>
447c478bd9Sstevel@tonic-gate #include <libscf.h>
457c478bd9Sstevel@tonic-gate #include <alloca.h>
467c478bd9Sstevel@tonic-gate #include <unistd.h>
477c478bd9Sstevel@tonic-gate #include <string.h>
487c478bd9Sstevel@tonic-gate #include <stdlib.h>
497c478bd9Sstevel@tonic-gate #include <fcntl.h>
507c478bd9Sstevel@tonic-gate #include <dlfcn.h>
517c478bd9Sstevel@tonic-gate #include <libctf.h>
527c478bd9Sstevel@tonic-gate #include <errno.h>
53843e1988Sjohnlev #include <kvm.h>
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate #include <mdb/mdb_lex.h>
567c478bd9Sstevel@tonic-gate #include <mdb/mdb_debug.h>
577c478bd9Sstevel@tonic-gate #include <mdb/mdb_signal.h>
587c478bd9Sstevel@tonic-gate #include <mdb/mdb_string.h>
597c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
607c478bd9Sstevel@tonic-gate #include <mdb/mdb_target.h>
617c478bd9Sstevel@tonic-gate #include <mdb/mdb_gelf.h>
627c478bd9Sstevel@tonic-gate #include <mdb/mdb_conf.h>
637c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h>
647c478bd9Sstevel@tonic-gate #include <mdb/mdb_io_impl.h>
657c478bd9Sstevel@tonic-gate #include <mdb/mdb_frame.h>
667c478bd9Sstevel@tonic-gate #include <mdb/mdb_set.h>
677c478bd9Sstevel@tonic-gate #include <kmdb/kmdb_kctl.h>
687c478bd9Sstevel@tonic-gate #include <mdb/mdb.h>
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate #ifndef STACK_BIAS
717c478bd9Sstevel@tonic-gate #define STACK_BIAS 0
727c478bd9Sstevel@tonic-gate #endif
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate #if defined(__sparc)
757c478bd9Sstevel@tonic-gate #define STACK_REGISTER SP
767c478bd9Sstevel@tonic-gate #else
777c478bd9Sstevel@tonic-gate #define STACK_REGISTER REG_FP
787c478bd9Sstevel@tonic-gate #endif
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate #ifdef _LP64
817c478bd9Sstevel@tonic-gate #define MDB_DEF_IPATH \
827c478bd9Sstevel@tonic-gate "%r/usr/platform/%p/lib/adb/%i:" \
837c478bd9Sstevel@tonic-gate "%r/usr/platform/%m/lib/adb/%i:" \
847c478bd9Sstevel@tonic-gate "%r/usr/lib/adb/%i"
857c478bd9Sstevel@tonic-gate #define MDB_DEF_LPATH \
867c478bd9Sstevel@tonic-gate "%r/usr/platform/%p/lib/mdb/%t/%i:" \
877c478bd9Sstevel@tonic-gate "%r/usr/platform/%m/lib/mdb/%t/%i:" \
887c478bd9Sstevel@tonic-gate "%r/usr/lib/mdb/%t/%i"
897c478bd9Sstevel@tonic-gate #else
907c478bd9Sstevel@tonic-gate #define MDB_DEF_IPATH \
917c478bd9Sstevel@tonic-gate "%r/usr/platform/%p/lib/adb:" \
927c478bd9Sstevel@tonic-gate "%r/usr/platform/%m/lib/adb:" \
937c478bd9Sstevel@tonic-gate "%r/usr/lib/adb"
947c478bd9Sstevel@tonic-gate #define MDB_DEF_LPATH \
957c478bd9Sstevel@tonic-gate "%r/usr/platform/%p/lib/mdb/%t:" \
967c478bd9Sstevel@tonic-gate "%r/usr/platform/%m/lib/mdb/%t:" \
977c478bd9Sstevel@tonic-gate "%r/usr/lib/mdb/%t"
987c478bd9Sstevel@tonic-gate #endif
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate #define MDB_DEF_PROMPT "> "
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate * Similar to the panic_* variables in the kernel, we keep some relevant
1047c478bd9Sstevel@tonic-gate * information stored in a set of global _mdb_abort_* variables; in the
1057c478bd9Sstevel@tonic-gate * event that the debugger dumps core, these will aid core dump analysis.
1067c478bd9Sstevel@tonic-gate */
1077c478bd9Sstevel@tonic-gate const char *volatile _mdb_abort_str; /* reason for failure */
1087c478bd9Sstevel@tonic-gate siginfo_t _mdb_abort_info; /* signal info for fatal signal */
1097c478bd9Sstevel@tonic-gate ucontext_t _mdb_abort_ctx; /* context fatal signal interrupted */
1107c478bd9Sstevel@tonic-gate int _mdb_abort_rcount; /* number of times resume requested */
1117c478bd9Sstevel@tonic-gate int _mdb_self_fd = -1; /* fd for self as for valid_frame */
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate static void
terminate(int status)1147c478bd9Sstevel@tonic-gate terminate(int status)
1157c478bd9Sstevel@tonic-gate {
11636c835a5Svitezslav batrla - Sun Microsystems - Prague Czech Republic (void) mdb_signal_blockall();
1177c478bd9Sstevel@tonic-gate mdb_destroy();
1187c478bd9Sstevel@tonic-gate exit(status);
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate static void
print_frame(uintptr_t pc,int fnum)1227c478bd9Sstevel@tonic-gate print_frame(uintptr_t pc, int fnum)
1237c478bd9Sstevel@tonic-gate {
1247c478bd9Sstevel@tonic-gate Dl_info dli;
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate if (dladdr((void *)pc, &dli)) {
1277c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, " [%d] %s`%s+0x%lx()\n", fnum,
1287c478bd9Sstevel@tonic-gate strbasename(dli.dli_fname), dli.dli_sname,
1297c478bd9Sstevel@tonic-gate pc - (uintptr_t)dli.dli_saddr);
1307c478bd9Sstevel@tonic-gate } else
1317c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, " [%d] %p()\n", fnum, pc);
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate static int
valid_frame(struct frame * fr)1357c478bd9Sstevel@tonic-gate valid_frame(struct frame *fr)
1367c478bd9Sstevel@tonic-gate {
1377c478bd9Sstevel@tonic-gate static struct frame fake;
1387c478bd9Sstevel@tonic-gate uintptr_t addr = (uintptr_t)fr;
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate if (pread(_mdb_self_fd, &fake, sizeof (fake), addr) != sizeof (fake)) {
1417c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, " invalid frame (%p)\n", fr);
1427c478bd9Sstevel@tonic-gate return (0);
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate if (addr & (STACK_ALIGN - 1)) {
1467c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, " mis-aligned frame (%p)\n", fr);
1477c478bd9Sstevel@tonic-gate return (0);
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate return (1);
1517c478bd9Sstevel@tonic-gate }
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1547c478bd9Sstevel@tonic-gate static void
flt_handler(int sig,siginfo_t * sip,ucontext_t * ucp,void * data)1557c478bd9Sstevel@tonic-gate flt_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data)
1567c478bd9Sstevel@tonic-gate {
1577c478bd9Sstevel@tonic-gate static const struct rlimit rl = {
1587c478bd9Sstevel@tonic-gate (rlim_t)RLIM_INFINITY, (rlim_t)RLIM_INFINITY
1597c478bd9Sstevel@tonic-gate };
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate const mdb_idcmd_t *idcp = NULL;
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate if (mdb.m_frame != NULL && mdb.m_frame->f_cp != NULL)
1647c478bd9Sstevel@tonic-gate idcp = mdb.m_frame->f_cp->c_dcmd;
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate if (sip != NULL)
1677c478bd9Sstevel@tonic-gate bcopy(sip, &_mdb_abort_info, sizeof (_mdb_abort_info));
1687c478bd9Sstevel@tonic-gate if (ucp != NULL)
1697c478bd9Sstevel@tonic-gate bcopy(ucp, &_mdb_abort_ctx, sizeof (_mdb_abort_ctx));
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate _mdb_abort_info.si_signo = sig;
1727c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(sig, SIG_DFL, NULL);
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate * If there is no current dcmd, or the current dcmd comes from a
1767c478bd9Sstevel@tonic-gate * builtin module, we don't allow resume and always core dump.
1777c478bd9Sstevel@tonic-gate */
1787c478bd9Sstevel@tonic-gate if (idcp == NULL || idcp->idc_modp == NULL ||
1797c478bd9Sstevel@tonic-gate idcp->idc_modp == &mdb.m_rmod || idcp->idc_modp->mod_hdl == NULL)
1807c478bd9Sstevel@tonic-gate goto dump;
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate if (mdb.m_term != NULL) {
1837c478bd9Sstevel@tonic-gate struct frame *fr = (struct frame *)
1847c478bd9Sstevel@tonic-gate (ucp->uc_mcontext.gregs[STACK_REGISTER] + STACK_BIAS);
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate char signame[SIG2STR_MAX];
1877c478bd9Sstevel@tonic-gate int i = 1;
1887c478bd9Sstevel@tonic-gate char c;
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate if (sig2str(sig, signame) == -1) {
1917c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err,
1927c478bd9Sstevel@tonic-gate "\n*** %s: received signal %d at:\n",
1937c478bd9Sstevel@tonic-gate mdb.m_pname, sig);
1947c478bd9Sstevel@tonic-gate } else {
1957c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err,
1967c478bd9Sstevel@tonic-gate "\n*** %s: received signal %s at:\n",
1977c478bd9Sstevel@tonic-gate mdb.m_pname, signame);
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate if (ucp->uc_mcontext.gregs[REG_PC] != 0)
2017c478bd9Sstevel@tonic-gate print_frame(ucp->uc_mcontext.gregs[REG_PC], i++);
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate while (fr != NULL && valid_frame(fr) && fr->fr_savpc != 0) {
2047c478bd9Sstevel@tonic-gate print_frame(fr->fr_savpc, i++);
2057c478bd9Sstevel@tonic-gate fr = (struct frame *)
2067c478bd9Sstevel@tonic-gate ((uintptr_t)fr->fr_savfp + STACK_BIAS);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate query:
2107c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, "\n%s: (c)ore dump, (q)uit, "
2117c478bd9Sstevel@tonic-gate "(r)ecover, or (s)top for debugger [cqrs]? ", mdb.m_pname);
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate mdb_iob_flush(mdb.m_err);
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate for (;;) {
2167c478bd9Sstevel@tonic-gate if (IOP_READ(mdb.m_term, &c, sizeof (c)) != sizeof (c))
2177c478bd9Sstevel@tonic-gate goto dump;
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate switch (c) {
2207c478bd9Sstevel@tonic-gate case 'c':
2217c478bd9Sstevel@tonic-gate case 'C':
2227c478bd9Sstevel@tonic-gate (void) setrlimit(RLIMIT_CORE, &rl);
2237c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, "\n%s: attempting "
2247c478bd9Sstevel@tonic-gate "to dump core ...\n", mdb.m_pname);
2257c478bd9Sstevel@tonic-gate goto dump;
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate case 'q':
2287c478bd9Sstevel@tonic-gate case 'Q':
2297c478bd9Sstevel@tonic-gate mdb_iob_discard(mdb.m_out);
2307c478bd9Sstevel@tonic-gate mdb_iob_nl(mdb.m_err);
2317c478bd9Sstevel@tonic-gate (void) mdb_signal_unblockall();
2327c478bd9Sstevel@tonic-gate terminate(1);
2337c478bd9Sstevel@tonic-gate /*NOTREACHED*/
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate case 'r':
2367c478bd9Sstevel@tonic-gate case 'R':
2377c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, "\n%s: unloading "
2387c478bd9Sstevel@tonic-gate "module '%s' ...\n", mdb.m_pname,
2397c478bd9Sstevel@tonic-gate idcp->idc_modp->mod_name);
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate (void) mdb_module_unload(
2427c478bd9Sstevel@tonic-gate idcp->idc_modp->mod_name, 0);
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(sig,
2457c478bd9Sstevel@tonic-gate flt_handler, NULL);
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate _mdb_abort_rcount++;
2487c478bd9Sstevel@tonic-gate mdb.m_intr = 0;
2497c478bd9Sstevel@tonic-gate mdb.m_pend = 0;
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate (void) mdb_signal_unblockall();
2527c478bd9Sstevel@tonic-gate longjmp(mdb.m_frame->f_pcb, MDB_ERR_ABORT);
2537c478bd9Sstevel@tonic-gate /*NOTREACHED*/
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate case 's':
2567c478bd9Sstevel@tonic-gate case 'S':
2577c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, "\n%s: "
2587c478bd9Sstevel@tonic-gate "attempting to stop pid %d ...\n",
2597c478bd9Sstevel@tonic-gate mdb.m_pname, (int)getpid());
2607c478bd9Sstevel@tonic-gate
2617c478bd9Sstevel@tonic-gate /*
2627c478bd9Sstevel@tonic-gate * Stop ourself; if this fails or we are
2637c478bd9Sstevel@tonic-gate * subsequently continued, ask again.
2647c478bd9Sstevel@tonic-gate */
2657c478bd9Sstevel@tonic-gate (void) mdb_signal_raise(SIGSTOP);
2667c478bd9Sstevel@tonic-gate (void) mdb_signal_unblockall();
2677c478bd9Sstevel@tonic-gate goto query;
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate dump:
2737c478bd9Sstevel@tonic-gate if (SI_FROMUSER(sip)) {
2747c478bd9Sstevel@tonic-gate (void) mdb_signal_block(sig);
2757c478bd9Sstevel@tonic-gate (void) mdb_signal_raise(sig);
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate (void) sigfillset(&ucp->uc_sigmask);
2797c478bd9Sstevel@tonic-gate (void) sigdelset(&ucp->uc_sigmask, sig);
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate if (_mdb_abort_str == NULL)
2827c478bd9Sstevel@tonic-gate _mdb_abort_str = "fatal signal received";
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate ucp->uc_flags |= UC_SIGMASK;
2857c478bd9Sstevel@tonic-gate (void) setcontext(ucp);
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2897c478bd9Sstevel@tonic-gate static void
int_handler(int sig,siginfo_t * sip,ucontext_t * ucp,void * data)2907c478bd9Sstevel@tonic-gate int_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate if (mdb.m_intr == 0)
2937c478bd9Sstevel@tonic-gate longjmp(mdb.m_frame->f_pcb, MDB_ERR_SIGINT);
2947c478bd9Sstevel@tonic-gate else
2957c478bd9Sstevel@tonic-gate mdb.m_pend++;
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate static void
control_kmdb(int start)2997c478bd9Sstevel@tonic-gate control_kmdb(int start)
3007c478bd9Sstevel@tonic-gate {
3017c478bd9Sstevel@tonic-gate int fd;
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate if ((fd = open("/dev/kmdb", O_RDONLY)) < 0)
3047c478bd9Sstevel@tonic-gate die("failed to open /dev/kmdb");
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate if (start) {
3077c478bd9Sstevel@tonic-gate char *state = mdb_get_config();
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate if (ioctl(fd, KMDB_IOC_START, state) < 0)
3107c478bd9Sstevel@tonic-gate die("failed to start kmdb");
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate strfree(state);
3137c478bd9Sstevel@tonic-gate } else {
3147c478bd9Sstevel@tonic-gate if (ioctl(fd, KMDB_IOC_STOP) < 0)
3157c478bd9Sstevel@tonic-gate die("failed to stop kmdb");
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate
31880148899SSurya Prakki (void) close(fd);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate static void
usage(int status)3227c478bd9Sstevel@tonic-gate usage(int status)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, "Usage: %s [-fkmuwyAFKMSUW] [+/-o option] "
3257c478bd9Sstevel@tonic-gate "[-p pid] [-s dist] [-I path] [-L path]\n\t[-P prompt] "
326*0a47c91cSRobert Mustacchi "[-R root] [-V dis-version] [-e expr] "
327*0a47c91cSRobert Mustacchi "[object [core] | core | suffix]\n\n",
3287c478bd9Sstevel@tonic-gate mdb.m_pname);
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate mdb_iob_puts(mdb.m_err,
331*0a47c91cSRobert Mustacchi "\t-e evaluate expr and return status\n"
3327c478bd9Sstevel@tonic-gate "\t-f force raw file debugging mode\n"
3337c478bd9Sstevel@tonic-gate "\t-k force kernel debugging mode\n"
3347c478bd9Sstevel@tonic-gate "\t-m disable demand-loading of module symbols\n"
3357c478bd9Sstevel@tonic-gate "\t-o set specified debugger option (+o to unset)\n"
3367c478bd9Sstevel@tonic-gate "\t-p attach to specified process-id\n"
3377c478bd9Sstevel@tonic-gate "\t-s set symbol matching distance\n"
3387c478bd9Sstevel@tonic-gate "\t-u force user program debugging mode\n"
3397c478bd9Sstevel@tonic-gate "\t-w enable write mode\n"
3407c478bd9Sstevel@tonic-gate "\t-y send terminal initialization sequences for tty mode\n"
3417c478bd9Sstevel@tonic-gate "\t-A disable automatic loading of mdb modules\n"
3427c478bd9Sstevel@tonic-gate "\t-F enable forcible takeover mode\n"
3437c478bd9Sstevel@tonic-gate "\t-K stop operating system and enter live kernel debugger\n"
3447c478bd9Sstevel@tonic-gate "\t-M preload all module symbols\n"
3457c478bd9Sstevel@tonic-gate "\t-I set initial path for macro files\n"
3467c478bd9Sstevel@tonic-gate "\t-L set initial path for module libs\n"
3477c478bd9Sstevel@tonic-gate "\t-P set command-line prompt\n"
3487c478bd9Sstevel@tonic-gate "\t-R set root directory for pathname expansion\n"
3497c478bd9Sstevel@tonic-gate "\t-S suppress processing of ~/.mdbrc file\n"
3507c478bd9Sstevel@tonic-gate "\t-U unload live kernel debugger\n"
3517c478bd9Sstevel@tonic-gate "\t-W enable I/O-mapped memory access (kernel only)\n"
3527c478bd9Sstevel@tonic-gate "\t-V set disassembler version\n");
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate terminate(status);
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate static char *
mdb_scf_console_term(void)3587c478bd9Sstevel@tonic-gate mdb_scf_console_term(void)
3597c478bd9Sstevel@tonic-gate {
3607c478bd9Sstevel@tonic-gate scf_simple_prop_t *prop;
3617c478bd9Sstevel@tonic-gate char *term = NULL;
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate if ((prop = scf_simple_prop_get(NULL,
3647c478bd9Sstevel@tonic-gate "svc:/system/console-login:default", "ttymon",
3657c478bd9Sstevel@tonic-gate "terminal_type")) == NULL)
3667c478bd9Sstevel@tonic-gate return (NULL);
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate if (scf_simple_prop_type(prop) == SCF_TYPE_ASTRING &&
3697c478bd9Sstevel@tonic-gate (term = scf_simple_prop_next_astring(prop)) != NULL)
3707c478bd9Sstevel@tonic-gate term = strdup(term);
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate scf_simple_prop_free(prop);
3737c478bd9Sstevel@tonic-gate return (term);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate
376a576ab5bSrab /*
377a576ab5bSrab * Unpleasant hack: we might be debugging a hypervisor domain dump.
378a576ab5bSrab * Earlier versions use a non-ELF file. Later versions are ELF, but are
379a576ab5bSrab * /always/ ELF64, so our standard ehdr check isn't good enough. Since
380a576ab5bSrab * we don't want to know too much about the file format, we'll ask
381a576ab5bSrab * mdb_kb.
382a576ab5bSrab */
383a576ab5bSrab #ifdef __x86
384a576ab5bSrab static int
identify_xvm_file(const char * file,int * longmode)385a576ab5bSrab identify_xvm_file(const char *file, int *longmode)
386a576ab5bSrab {
387a576ab5bSrab int (*identify)(const char *, int *);
388a576ab5bSrab
389a576ab5bSrab if (mdb_module_load("mdb_kb", MDB_MOD_GLOBAL | MDB_MOD_SILENT) != 0)
390a576ab5bSrab return (0);
391a576ab5bSrab
392a576ab5bSrab identify = (int (*)())dlsym(RTLD_NEXT, "xkb_identify");
393a576ab5bSrab
394a576ab5bSrab if (identify == NULL)
395a576ab5bSrab return (0);
396a576ab5bSrab
397a576ab5bSrab return (identify(file, longmode));
398a576ab5bSrab }
399a576ab5bSrab #else
400a576ab5bSrab /*ARGSUSED*/
401a576ab5bSrab static int
identify_xvm_file(const char * file,int * longmode)402a576ab5bSrab identify_xvm_file(const char *file, int *longmode)
403a576ab5bSrab {
404a576ab5bSrab return (0);
405a576ab5bSrab }
406a576ab5bSrab #endif /* __x86 */
407a576ab5bSrab
4087c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[],char * envp[])4097c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char *envp[])
4107c478bd9Sstevel@tonic-gate {
411ca3e8d88SDave Plauger extern int mdb_kvm_is_compressed_dump(mdb_io_t *);
4121320caf7SBryan Cantrill extern int mdb_kvm_is_dump(mdb_io_t *);
4137c478bd9Sstevel@tonic-gate mdb_tgt_ctor_f *tgt_ctor = NULL;
4141320caf7SBryan Cantrill const char **tgt_argv = alloca((argc + 2) * sizeof (char *));
4157c478bd9Sstevel@tonic-gate int tgt_argc = 0;
4167c478bd9Sstevel@tonic-gate mdb_tgt_t *tgt;
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate char object[MAXPATHLEN], execname[MAXPATHLEN];
4197c478bd9Sstevel@tonic-gate mdb_io_t *in_io, *out_io, *err_io, *null_io;
4207c478bd9Sstevel@tonic-gate struct termios tios;
4217c478bd9Sstevel@tonic-gate int status, c;
4227c478bd9Sstevel@tonic-gate char *p;
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate const char *Iflag = NULL, *Lflag = NULL, *Vflag = NULL, *pidarg = NULL;
425*0a47c91cSRobert Mustacchi const char *eflag = NULL;
426843e1988Sjohnlev int fflag = 0, Kflag = 0, Rflag = 0, Sflag = 0, Oflag = 0, Uflag = 0;
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate int ttylike;
429a576ab5bSrab int longmode = 0;
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate stack_t sigstack;
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate if (realpath(getexecname(), execname) == NULL) {
4347c478bd9Sstevel@tonic-gate (void) strncpy(execname, argv[0], MAXPATHLEN);
4357c478bd9Sstevel@tonic-gate execname[MAXPATHLEN - 1] = '\0';
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate mdb_create(execname, argv[0]);
4397c478bd9Sstevel@tonic-gate bzero(tgt_argv, argc * sizeof (char *));
4407c478bd9Sstevel@tonic-gate argv[0] = (char *)mdb.m_pname;
4417c478bd9Sstevel@tonic-gate _mdb_self_fd = open("/proc/self/as", O_RDONLY);
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate mdb.m_env = envp;
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate out_io = mdb_fdio_create(STDOUT_FILENO);
4467c478bd9Sstevel@tonic-gate mdb.m_out = mdb_iob_create(out_io, MDB_IOB_WRONLY);
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate err_io = mdb_fdio_create(STDERR_FILENO);
4497c478bd9Sstevel@tonic-gate mdb.m_err = mdb_iob_create(err_io, MDB_IOB_WRONLY);
4507c478bd9Sstevel@tonic-gate mdb_iob_clrflags(mdb.m_err, MDB_IOB_AUTOWRAP);
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate null_io = mdb_nullio_create();
4537c478bd9Sstevel@tonic-gate mdb.m_null = mdb_iob_create(null_io, MDB_IOB_WRONLY);
4547c478bd9Sstevel@tonic-gate
4557c478bd9Sstevel@tonic-gate in_io = mdb_fdio_create(STDIN_FILENO);
4567c478bd9Sstevel@tonic-gate if ((mdb.m_termtype = getenv("TERM")) != NULL) {
4577c478bd9Sstevel@tonic-gate mdb.m_termtype = strdup(mdb.m_termtype);
4587c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_TERMGUESS;
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate mdb.m_term = NULL;
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate mdb_dmode(mdb_dstr2mode(getenv("MDB_DEBUG")));
4637c478bd9Sstevel@tonic-gate mdb.m_pgid = getpgrp();
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate if (getenv("_MDB_EXEC") != NULL)
4667c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_EXEC;
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate /*
4697c478bd9Sstevel@tonic-gate * Setup an alternate signal stack. When tearing down pipelines in
4707c478bd9Sstevel@tonic-gate * terminate(), we may have to destroy the stack of the context in
4717c478bd9Sstevel@tonic-gate * which we are currently executing the signal handler.
4727c478bd9Sstevel@tonic-gate */
4737c478bd9Sstevel@tonic-gate sigstack.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
4747c478bd9Sstevel@tonic-gate MAP_PRIVATE | MAP_ANON, -1, 0);
4757c478bd9Sstevel@tonic-gate if (sigstack.ss_sp == MAP_FAILED)
4767c478bd9Sstevel@tonic-gate die("could not allocate signal stack");
4777c478bd9Sstevel@tonic-gate sigstack.ss_size = SIGSTKSZ;
4787c478bd9Sstevel@tonic-gate sigstack.ss_flags = 0;
4797c478bd9Sstevel@tonic-gate if (sigaltstack(&sigstack, NULL) != 0)
4807c478bd9Sstevel@tonic-gate die("could not set signal stack");
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGPIPE, SIG_IGN, NULL);
4837c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGQUIT, SIG_IGN, NULL);
4847c478bd9Sstevel@tonic-gate
4857c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGILL, flt_handler, NULL);
4867c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGTRAP, flt_handler, NULL);
4877c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGIOT, flt_handler, NULL);
4887c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGEMT, flt_handler, NULL);
4897c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGFPE, flt_handler, NULL);
4907c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGBUS, flt_handler, NULL);
4917c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGSEGV, flt_handler, NULL);
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGHUP, (mdb_signal_f *)terminate, NULL);
4947c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGTERM, (mdb_signal_f *)terminate, NULL);
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate for (mdb.m_rdvers = RD_VERSION; mdb.m_rdvers > 0; mdb.m_rdvers--) {
4977c478bd9Sstevel@tonic-gate if (rd_init(mdb.m_rdvers) == RD_OK)
4987c478bd9Sstevel@tonic-gate break;
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate for (mdb.m_ctfvers = CTF_VERSION; mdb.m_ctfvers > 0; mdb.m_ctfvers--) {
5027c478bd9Sstevel@tonic-gate if (ctf_version(mdb.m_ctfvers) != -1)
5037c478bd9Sstevel@tonic-gate break;
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate
5067c478bd9Sstevel@tonic-gate if ((p = getenv("HISTSIZE")) != NULL && strisnum(p)) {
5077c478bd9Sstevel@tonic-gate mdb.m_histlen = strtoi(p);
5087c478bd9Sstevel@tonic-gate if (mdb.m_histlen < 1)
5097c478bd9Sstevel@tonic-gate mdb.m_histlen = 1;
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate while (optind < argc) {
5137c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv,
514*0a47c91cSRobert Mustacchi "e:fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) {
5157c478bd9Sstevel@tonic-gate switch (c) {
516*0a47c91cSRobert Mustacchi case 'e':
517*0a47c91cSRobert Mustacchi if (eflag != NULL) {
518*0a47c91cSRobert Mustacchi warn("-e already specified\n");
519*0a47c91cSRobert Mustacchi terminate(2);
520*0a47c91cSRobert Mustacchi }
521*0a47c91cSRobert Mustacchi eflag = optarg;
522*0a47c91cSRobert Mustacchi break;
5237c478bd9Sstevel@tonic-gate case 'f':
524843e1988Sjohnlev fflag++;
5257c478bd9Sstevel@tonic-gate tgt_ctor = mdb_rawfile_tgt_create;
5267c478bd9Sstevel@tonic-gate break;
5277c478bd9Sstevel@tonic-gate case 'k':
5287c478bd9Sstevel@tonic-gate tgt_ctor = mdb_kvm_tgt_create;
5297c478bd9Sstevel@tonic-gate break;
5307c478bd9Sstevel@tonic-gate case 'm':
5317c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_NOLOAD;
5327c478bd9Sstevel@tonic-gate mdb.m_tgtflags &= ~MDB_TGT_F_PRELOAD;
5337c478bd9Sstevel@tonic-gate break;
5347c478bd9Sstevel@tonic-gate case 'o':
5357c478bd9Sstevel@tonic-gate if (!mdb_set_options(optarg, TRUE))
5367c478bd9Sstevel@tonic-gate terminate(2);
5377c478bd9Sstevel@tonic-gate break;
5387c478bd9Sstevel@tonic-gate case 'p':
5397c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create;
5407c478bd9Sstevel@tonic-gate pidarg = optarg;
5417c478bd9Sstevel@tonic-gate break;
5427c478bd9Sstevel@tonic-gate case 's':
5437c478bd9Sstevel@tonic-gate if (!strisnum(optarg)) {
5447c478bd9Sstevel@tonic-gate warn("expected integer following -s\n");
5457c478bd9Sstevel@tonic-gate terminate(2);
5467c478bd9Sstevel@tonic-gate }
5477c478bd9Sstevel@tonic-gate mdb.m_symdist = (size_t)(uint_t)strtoi(optarg);
5487c478bd9Sstevel@tonic-gate break;
5497c478bd9Sstevel@tonic-gate case 'u':
5507c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create;
5517c478bd9Sstevel@tonic-gate break;
5527c478bd9Sstevel@tonic-gate case 'w':
5537c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_RDWR;
5547c478bd9Sstevel@tonic-gate break;
5557c478bd9Sstevel@tonic-gate case 'y':
5567c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_USECUP;
5577c478bd9Sstevel@tonic-gate break;
5587c478bd9Sstevel@tonic-gate case 'A':
5597c478bd9Sstevel@tonic-gate (void) mdb_set_options("nomods", TRUE);
5607c478bd9Sstevel@tonic-gate break;
5617c478bd9Sstevel@tonic-gate case 'C':
5627c478bd9Sstevel@tonic-gate (void) mdb_set_options("noctf", TRUE);
5637c478bd9Sstevel@tonic-gate break;
5647c478bd9Sstevel@tonic-gate case 'D':
5657c478bd9Sstevel@tonic-gate mdb_dmode(mdb_dstr2mode(optarg));
5667c478bd9Sstevel@tonic-gate break;
5677c478bd9Sstevel@tonic-gate case 'F':
5687c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_FORCE;
5697c478bd9Sstevel@tonic-gate break;
5707c478bd9Sstevel@tonic-gate case 'I':
5717c478bd9Sstevel@tonic-gate Iflag = optarg;
5727c478bd9Sstevel@tonic-gate break;
5737c478bd9Sstevel@tonic-gate case 'L':
5747c478bd9Sstevel@tonic-gate Lflag = optarg;
5757c478bd9Sstevel@tonic-gate break;
5767c478bd9Sstevel@tonic-gate case 'K':
5777c478bd9Sstevel@tonic-gate Kflag++;
5787c478bd9Sstevel@tonic-gate break;
5797c478bd9Sstevel@tonic-gate case 'M':
5807c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_PRELOAD;
5817c478bd9Sstevel@tonic-gate mdb.m_tgtflags &= ~MDB_TGT_F_NOLOAD;
5827c478bd9Sstevel@tonic-gate break;
5837c478bd9Sstevel@tonic-gate case 'O':
5847c478bd9Sstevel@tonic-gate Oflag++;
5857c478bd9Sstevel@tonic-gate break;
5867c478bd9Sstevel@tonic-gate case 'P':
5877c478bd9Sstevel@tonic-gate if (!mdb_set_prompt(optarg))
5887c478bd9Sstevel@tonic-gate terminate(2);
5897c478bd9Sstevel@tonic-gate break;
5907c478bd9Sstevel@tonic-gate case 'R':
5917c478bd9Sstevel@tonic-gate (void) strncpy(mdb.m_root, optarg, MAXPATHLEN);
5927c478bd9Sstevel@tonic-gate mdb.m_root[MAXPATHLEN - 1] = '\0';
5937c478bd9Sstevel@tonic-gate Rflag++;
5947c478bd9Sstevel@tonic-gate break;
5957c478bd9Sstevel@tonic-gate case 'S':
5967c478bd9Sstevel@tonic-gate Sflag++;
5977c478bd9Sstevel@tonic-gate break;
5987c478bd9Sstevel@tonic-gate case 'U':
5997c478bd9Sstevel@tonic-gate Uflag++;
6007c478bd9Sstevel@tonic-gate break;
6017c478bd9Sstevel@tonic-gate case 'V':
6027c478bd9Sstevel@tonic-gate Vflag = optarg;
6037c478bd9Sstevel@tonic-gate break;
6047c478bd9Sstevel@tonic-gate case 'W':
6057c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_ALLOWIO;
6067c478bd9Sstevel@tonic-gate break;
6077c478bd9Sstevel@tonic-gate case '?':
6087c478bd9Sstevel@tonic-gate if (optopt == '?')
6097c478bd9Sstevel@tonic-gate usage(0);
6107c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
6117c478bd9Sstevel@tonic-gate default:
6127c478bd9Sstevel@tonic-gate usage(2);
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate if (optind < argc) {
6177c478bd9Sstevel@tonic-gate const char *arg = argv[optind++];
6187c478bd9Sstevel@tonic-gate
6197c478bd9Sstevel@tonic-gate if (arg[0] == '+' && strlen(arg) == 2) {
6207c478bd9Sstevel@tonic-gate if (arg[1] != 'o') {
6217c478bd9Sstevel@tonic-gate warn("illegal option -- %s\n", arg);
6227c478bd9Sstevel@tonic-gate terminate(2);
6237c478bd9Sstevel@tonic-gate }
6247c478bd9Sstevel@tonic-gate if (optind >= argc) {
6257c478bd9Sstevel@tonic-gate warn("option requires an argument -- "
6267c478bd9Sstevel@tonic-gate "%s\n", arg);
6277c478bd9Sstevel@tonic-gate terminate(2);
6287c478bd9Sstevel@tonic-gate }
6297c478bd9Sstevel@tonic-gate if (!mdb_set_options(argv[optind++], FALSE))
6307c478bd9Sstevel@tonic-gate terminate(2);
6317c478bd9Sstevel@tonic-gate } else
6327c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = arg;
6337c478bd9Sstevel@tonic-gate }
6347c478bd9Sstevel@tonic-gate }
6357c478bd9Sstevel@tonic-gate
6369acbbeafSnn35248 if (rd_ctl(RD_CTL_SET_HELPPATH, (void *)mdb.m_root) != RD_OK) {
6379acbbeafSnn35248 warn("cannot set librtld_db helper path to %s\n", mdb.m_root);
6389acbbeafSnn35248 terminate(2);
6399acbbeafSnn35248 }
6409acbbeafSnn35248
6417c478bd9Sstevel@tonic-gate if (mdb.m_debug & MDB_DBG_HELP)
6427c478bd9Sstevel@tonic-gate terminate(0); /* Quit here if we've printed out the tokens */
6437c478bd9Sstevel@tonic-gate
6449acbbeafSnn35248
6457c478bd9Sstevel@tonic-gate if (Iflag != NULL && strchr(Iflag, ';') != NULL) {
6467c478bd9Sstevel@tonic-gate warn("macro path cannot contain semicolons\n");
6477c478bd9Sstevel@tonic-gate terminate(2);
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate
6507c478bd9Sstevel@tonic-gate if (Lflag != NULL && strchr(Lflag, ';') != NULL) {
6517c478bd9Sstevel@tonic-gate warn("module path cannot contain semicolons\n");
6527c478bd9Sstevel@tonic-gate terminate(2);
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate
6557c478bd9Sstevel@tonic-gate if (Kflag || Uflag) {
6567c478bd9Sstevel@tonic-gate char *nm;
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate if (tgt_ctor != NULL || Iflag != NULL) {
6597c478bd9Sstevel@tonic-gate warn("neither -f, -k, -p, -u, nor -I "
6607c478bd9Sstevel@tonic-gate "may be used with -K\n");
6617c478bd9Sstevel@tonic-gate usage(2);
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate if (Lflag != NULL)
6657c478bd9Sstevel@tonic-gate mdb_set_lpath(Lflag);
6667c478bd9Sstevel@tonic-gate
6677c478bd9Sstevel@tonic-gate if ((nm = ttyname(STDIN_FILENO)) == NULL ||
6687c478bd9Sstevel@tonic-gate strcmp(nm, "/dev/console") != 0) {
6697c478bd9Sstevel@tonic-gate /*
6707c478bd9Sstevel@tonic-gate * Due to the consequences of typing mdb -K instead of
6717c478bd9Sstevel@tonic-gate * mdb -k on a tty other than /dev/console, we require
6727c478bd9Sstevel@tonic-gate * -F when starting kmdb from a tty other than
6737c478bd9Sstevel@tonic-gate * /dev/console.
6747c478bd9Sstevel@tonic-gate */
6757c478bd9Sstevel@tonic-gate if (!(mdb.m_tgtflags & MDB_TGT_F_FORCE)) {
6767c478bd9Sstevel@tonic-gate die("-F must also be supplied to start kmdb "
6777c478bd9Sstevel@tonic-gate "from non-console tty\n");
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate if (mdb.m_termtype == NULL || (mdb.m_flags &
6817c478bd9Sstevel@tonic-gate MDB_FL_TERMGUESS)) {
6827c478bd9Sstevel@tonic-gate if (mdb.m_termtype != NULL)
6837c478bd9Sstevel@tonic-gate strfree(mdb.m_termtype);
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate if ((mdb.m_termtype = mdb_scf_console_term()) !=
6867c478bd9Sstevel@tonic-gate NULL)
6877c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_TERMGUESS;
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate } else {
6907c478bd9Sstevel@tonic-gate /*
6917c478bd9Sstevel@tonic-gate * When on console, $TERM (if set) takes precedence over
6927c478bd9Sstevel@tonic-gate * the SMF setting.
6937c478bd9Sstevel@tonic-gate */
6947c478bd9Sstevel@tonic-gate if (mdb.m_termtype == NULL && (mdb.m_termtype =
6957c478bd9Sstevel@tonic-gate mdb_scf_console_term()) != NULL)
6967c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_TERMGUESS;
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate control_kmdb(Kflag);
7007c478bd9Sstevel@tonic-gate terminate(0);
7017c478bd9Sstevel@tonic-gate /*NOTREACHED*/
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate
704*0a47c91cSRobert Mustacchi if (eflag != NULL) {
705*0a47c91cSRobert Mustacchi IOP_CLOSE(in_io);
706*0a47c91cSRobert Mustacchi in_io = mdb_strio_create(eflag);
707*0a47c91cSRobert Mustacchi mdb.m_lastret = 0;
708*0a47c91cSRobert Mustacchi }
709*0a47c91cSRobert Mustacchi
7107c478bd9Sstevel@tonic-gate /*
7117c478bd9Sstevel@tonic-gate * If standard input appears to have tty attributes, attempt to
7127c478bd9Sstevel@tonic-gate * initialize a terminal i/o backend on top of stdin and stdout.
7137c478bd9Sstevel@tonic-gate */
7147c478bd9Sstevel@tonic-gate ttylike = (IOP_CTL(in_io, TCGETS, &tios) == 0);
7157c478bd9Sstevel@tonic-gate if (ttylike) {
7167c478bd9Sstevel@tonic-gate if ((mdb.m_term = mdb_termio_create(mdb.m_termtype,
7177c478bd9Sstevel@tonic-gate in_io, out_io)) == NULL) {
7187c478bd9Sstevel@tonic-gate if (!(mdb.m_flags & MDB_FL_EXEC)) {
7197c478bd9Sstevel@tonic-gate warn("term init failed: command-line editing "
7207c478bd9Sstevel@tonic-gate "and prompt will not be available\n");
7217c478bd9Sstevel@tonic-gate }
7227c478bd9Sstevel@tonic-gate } else {
7237c478bd9Sstevel@tonic-gate in_io = mdb.m_term;
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate }
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gate mdb.m_in = mdb_iob_create(in_io, MDB_IOB_RDONLY);
7287c478bd9Sstevel@tonic-gate if (mdb.m_term != NULL) {
7297c478bd9Sstevel@tonic-gate mdb_iob_setpager(mdb.m_out, mdb.m_term);
7307c478bd9Sstevel@tonic-gate if (mdb.m_flags & MDB_FL_PAGER)
7317c478bd9Sstevel@tonic-gate mdb_iob_setflags(mdb.m_out, MDB_IOB_PGENABLE);
7327c478bd9Sstevel@tonic-gate else
7337c478bd9Sstevel@tonic-gate mdb_iob_clrflags(mdb.m_out, MDB_IOB_PGENABLE);
7347c478bd9Sstevel@tonic-gate } else if (ttylike)
7357c478bd9Sstevel@tonic-gate mdb_iob_setflags(mdb.m_in, MDB_IOB_TTYLIKE);
7367c478bd9Sstevel@tonic-gate else
7377c478bd9Sstevel@tonic-gate mdb_iob_setbuf(mdb.m_in, mdb_alloc(1, UM_SLEEP), 1);
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gate mdb_pservice_init();
7407c478bd9Sstevel@tonic-gate mdb_lex_reset();
7417c478bd9Sstevel@tonic-gate
7427c478bd9Sstevel@tonic-gate if ((mdb.m_shell = getenv("SHELL")) == NULL)
7437c478bd9Sstevel@tonic-gate mdb.m_shell = "/bin/sh";
7447c478bd9Sstevel@tonic-gate
745a576ab5bSrab /*
746a576ab5bSrab * If the debugger state is to be inherited from a previous instance,
747a576ab5bSrab * restore it now prior to path evaluation so that %R is updated.
748a576ab5bSrab */
749a576ab5bSrab if ((p = getenv(MDB_CONFIG_ENV_VAR)) != NULL) {
750a576ab5bSrab mdb_set_config(p);
751a576ab5bSrab (void) unsetenv(MDB_CONFIG_ENV_VAR);
752a576ab5bSrab }
753a576ab5bSrab
754a576ab5bSrab /*
755a576ab5bSrab * Path evaluation part 1: Create the initial module path to allow
756a576ab5bSrab * the target constructor to load a support module. Then expand
757a576ab5bSrab * any command-line arguments that modify the paths.
758a576ab5bSrab */
759a576ab5bSrab if (Iflag != NULL)
760a576ab5bSrab mdb_set_ipath(Iflag);
761a576ab5bSrab else
762a576ab5bSrab mdb_set_ipath(MDB_DEF_IPATH);
763a576ab5bSrab
764a576ab5bSrab if (Lflag != NULL)
765a576ab5bSrab mdb_set_lpath(Lflag);
766a576ab5bSrab else
767a576ab5bSrab mdb_set_lpath(MDB_DEF_LPATH);
768a576ab5bSrab
769a576ab5bSrab if (mdb_get_prompt() == NULL && !(mdb.m_flags & MDB_FL_ADB))
770a576ab5bSrab (void) mdb_set_prompt(MDB_DEF_PROMPT);
771a576ab5bSrab
7727c478bd9Sstevel@tonic-gate if (tgt_ctor == mdb_kvm_tgt_create) {
7737c478bd9Sstevel@tonic-gate if (pidarg != NULL) {
7747c478bd9Sstevel@tonic-gate warn("-p and -k options are mutually exclusive\n");
7757c478bd9Sstevel@tonic-gate terminate(2);
7767c478bd9Sstevel@tonic-gate }
7777c478bd9Sstevel@tonic-gate
7787c478bd9Sstevel@tonic-gate if (tgt_argc == 0)
7797c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = "/dev/ksyms";
7807c478bd9Sstevel@tonic-gate if (tgt_argc == 1 && strisnum(tgt_argv[0]) == 0) {
7817c478bd9Sstevel@tonic-gate if (mdb.m_tgtflags & MDB_TGT_F_ALLOWIO)
7827c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = "/dev/allkmem";
7837c478bd9Sstevel@tonic-gate else
7847c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = "/dev/kmem";
7857c478bd9Sstevel@tonic-gate }
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate
7887c478bd9Sstevel@tonic-gate if (pidarg != NULL) {
7897c478bd9Sstevel@tonic-gate if (tgt_argc != 0) {
7907c478bd9Sstevel@tonic-gate warn("-p may not be used with other arguments\n");
7917c478bd9Sstevel@tonic-gate terminate(2);
7927c478bd9Sstevel@tonic-gate }
7937c478bd9Sstevel@tonic-gate if (proc_arg_psinfo(pidarg, PR_ARG_PIDS, NULL, &status) == -1) {
7947c478bd9Sstevel@tonic-gate die("cannot attach to %s: %s\n",
7957c478bd9Sstevel@tonic-gate pidarg, Pgrab_error(status));
7967c478bd9Sstevel@tonic-gate }
7977c478bd9Sstevel@tonic-gate if (strchr(pidarg, '/') != NULL)
7987c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(object, MAXPATHLEN,
7997c478bd9Sstevel@tonic-gate "%s/object/a.out", pidarg);
8007c478bd9Sstevel@tonic-gate else
8017c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(object, MAXPATHLEN,
8027c478bd9Sstevel@tonic-gate "/proc/%s/object/a.out", pidarg);
8037c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = object;
8047c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = pidarg;
8057c478bd9Sstevel@tonic-gate }
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate /*
8087c478bd9Sstevel@tonic-gate * Find the first argument that is not a special "-" token. If one is
8097c478bd9Sstevel@tonic-gate * found, we will examine this file and make some inferences below.
8107c478bd9Sstevel@tonic-gate */
8117c478bd9Sstevel@tonic-gate for (c = 0; c < tgt_argc && strcmp(tgt_argv[c], "-") == 0; c++)
8127c478bd9Sstevel@tonic-gate continue;
8137c478bd9Sstevel@tonic-gate
8147c478bd9Sstevel@tonic-gate if (c < tgt_argc) {
8157c478bd9Sstevel@tonic-gate Elf32_Ehdr ehdr;
8167c478bd9Sstevel@tonic-gate mdb_io_t *io;
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate /*
8197c478bd9Sstevel@tonic-gate * If special "-" tokens preceded an argument, shift the entire
8207c478bd9Sstevel@tonic-gate * argument list to the left to remove the leading "-" args.
8217c478bd9Sstevel@tonic-gate */
8227c478bd9Sstevel@tonic-gate if (c > 0) {
8237c478bd9Sstevel@tonic-gate bcopy(&tgt_argv[c], tgt_argv,
8247c478bd9Sstevel@tonic-gate sizeof (const char *) * (tgt_argc - c));
8257c478bd9Sstevel@tonic-gate tgt_argc -= c;
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate
828ffd958e4SJosef 'Jeff' Sipek if (fflag)
829ffd958e4SJosef 'Jeff' Sipek goto tcreate; /* skip re-exec and just create target */
830ffd958e4SJosef 'Jeff' Sipek
8317c478bd9Sstevel@tonic-gate /*
8327c478bd9Sstevel@tonic-gate * If we just have an object file name, and that file doesn't
8337c478bd9Sstevel@tonic-gate * exist, and it's a string of digits, infer it to be a
8347c478bd9Sstevel@tonic-gate * sequence number referring to a pair of crash dump files.
8357c478bd9Sstevel@tonic-gate */
8367c478bd9Sstevel@tonic-gate if (tgt_argc == 1 && access(tgt_argv[0], F_OK) == -1 &&
8377c478bd9Sstevel@tonic-gate strisnum(tgt_argv[0])) {
8387c478bd9Sstevel@tonic-gate
8397c478bd9Sstevel@tonic-gate size_t len = strlen(tgt_argv[0]) + 8;
8407c478bd9Sstevel@tonic-gate const char *object = tgt_argv[0];
8417c478bd9Sstevel@tonic-gate
8421320caf7SBryan Cantrill tgt_argv[0] = alloca(len);
8431320caf7SBryan Cantrill tgt_argv[1] = alloca(len);
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate (void) strcpy((char *)tgt_argv[0], "unix.");
8467c478bd9Sstevel@tonic-gate (void) strcat((char *)tgt_argv[0], object);
8477c478bd9Sstevel@tonic-gate (void) strcpy((char *)tgt_argv[1], "vmcore.");
8487c478bd9Sstevel@tonic-gate (void) strcat((char *)tgt_argv[1], object);
8497c478bd9Sstevel@tonic-gate
850ca3e8d88SDave Plauger if (access(tgt_argv[0], F_OK) == -1 &&
8511320caf7SBryan Cantrill access(tgt_argv[1], F_OK) != -1) {
8521320caf7SBryan Cantrill /*
8531320caf7SBryan Cantrill * If we have a vmcore but not a unix file,
8541320caf7SBryan Cantrill * set the symbol table to be the vmcore to
8551320caf7SBryan Cantrill * force libkvm to extract it out of the dump.
8561320caf7SBryan Cantrill */
8571320caf7SBryan Cantrill tgt_argv[0] = tgt_argv[1];
8581320caf7SBryan Cantrill } else if (access(tgt_argv[0], F_OK) == -1 &&
859ca3e8d88SDave Plauger access(tgt_argv[1], F_OK) == -1) {
860ca3e8d88SDave Plauger (void) strcpy((char *)tgt_argv[1], "vmdump.");
861ca3e8d88SDave Plauger (void) strcat((char *)tgt_argv[1], object);
862ca3e8d88SDave Plauger if (access(tgt_argv[1], F_OK) == 0) {
863ca3e8d88SDave Plauger mdb_iob_printf(mdb.m_err,
864ca3e8d88SDave Plauger "cannot open compressed dump; "
865ca3e8d88SDave Plauger "decompress using savecore -f %s\n",
866ca3e8d88SDave Plauger tgt_argv[1]);
867ca3e8d88SDave Plauger terminate(0);
868ca3e8d88SDave Plauger }
869ca3e8d88SDave Plauger }
870ca3e8d88SDave Plauger
8717c478bd9Sstevel@tonic-gate tgt_argc = 2;
8727c478bd9Sstevel@tonic-gate }
8737c478bd9Sstevel@tonic-gate
8747c478bd9Sstevel@tonic-gate /*
8757c478bd9Sstevel@tonic-gate * We need to open the object file in order to determine its
8767c478bd9Sstevel@tonic-gate * ELF class and potentially re-exec ourself.
8777c478bd9Sstevel@tonic-gate */
8787c478bd9Sstevel@tonic-gate if ((io = mdb_fdio_create_path(NULL, tgt_argv[0],
8797c478bd9Sstevel@tonic-gate O_RDONLY, 0)) == NULL)
8807c478bd9Sstevel@tonic-gate die("failed to open %s", tgt_argv[0]);
8817c478bd9Sstevel@tonic-gate
882ca3e8d88SDave Plauger if (tgt_argc == 1) {
883ca3e8d88SDave Plauger if (mdb_kvm_is_compressed_dump(io)) {
8841320caf7SBryan Cantrill /*
8851320caf7SBryan Cantrill * We have a single vmdump.N compressed dump
8861320caf7SBryan Cantrill * file; give a helpful message.
8871320caf7SBryan Cantrill */
888ca3e8d88SDave Plauger mdb_iob_printf(mdb.m_err,
889ca3e8d88SDave Plauger "cannot open compressed dump; "
890ca3e8d88SDave Plauger "decompress using savecore -f %s\n",
891ca3e8d88SDave Plauger tgt_argv[0]);
892ca3e8d88SDave Plauger terminate(0);
8931320caf7SBryan Cantrill } else if (mdb_kvm_is_dump(io)) {
8941320caf7SBryan Cantrill /*
8951320caf7SBryan Cantrill * We have an uncompressed dump as our only
8961320caf7SBryan Cantrill * argument; specify the dump as the symbol
8971320caf7SBryan Cantrill * table to force libkvm to dig it out of the
8981320caf7SBryan Cantrill * dump.
8991320caf7SBryan Cantrill */
9001320caf7SBryan Cantrill tgt_argv[tgt_argc++] = tgt_argv[0];
901ca3e8d88SDave Plauger }
902ca3e8d88SDave Plauger }
903ca3e8d88SDave Plauger
904ca3e8d88SDave Plauger /*
9057c478bd9Sstevel@tonic-gate * If the target is unknown or is not the rawfile target, do
9067c478bd9Sstevel@tonic-gate * a gelf_check to determine if the file is an ELF file. If
9077c478bd9Sstevel@tonic-gate * it is not and the target is unknown, use the rawfile tgt.
9087c478bd9Sstevel@tonic-gate * Otherwise an ELF-based target is needed, so we must abort.
9097c478bd9Sstevel@tonic-gate */
910ffd958e4SJosef 'Jeff' Sipek if (mdb_gelf_check(io, &ehdr, ET_NONE) == -1) {
9117c478bd9Sstevel@tonic-gate if (tgt_ctor != NULL) {
9127c478bd9Sstevel@tonic-gate (void) mdb_gelf_check(io, &ehdr, ET_EXEC);
9137c478bd9Sstevel@tonic-gate mdb_io_destroy(io);
9147c478bd9Sstevel@tonic-gate terminate(1);
9157c478bd9Sstevel@tonic-gate } else
9167c478bd9Sstevel@tonic-gate tgt_ctor = mdb_rawfile_tgt_create;
9177c478bd9Sstevel@tonic-gate }
9187c478bd9Sstevel@tonic-gate
9197c478bd9Sstevel@tonic-gate mdb_io_destroy(io);
9207c478bd9Sstevel@tonic-gate
921ffd958e4SJosef 'Jeff' Sipek if (identify_xvm_file(tgt_argv[0], &longmode) == 1) {
922a576ab5bSrab #ifdef _LP64
923a576ab5bSrab if (!longmode)
924a576ab5bSrab goto reexec;
925a576ab5bSrab #else
926a576ab5bSrab if (longmode)
927a576ab5bSrab goto reexec;
928a576ab5bSrab #endif
929a576ab5bSrab tgt_ctor = mdb_kvm_tgt_create;
930a576ab5bSrab goto tcreate;
931a576ab5bSrab }
932a576ab5bSrab
9337c478bd9Sstevel@tonic-gate /*
9347c478bd9Sstevel@tonic-gate * The object file turned out to be a user core file (ET_CORE),
9357c478bd9Sstevel@tonic-gate * and no other arguments were specified, swap 0 and 1. The
9367c478bd9Sstevel@tonic-gate * proc target will infer the executable for us.
9377c478bd9Sstevel@tonic-gate */
9387c478bd9Sstevel@tonic-gate if (ehdr.e_type == ET_CORE) {
9397c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = tgt_argv[0];
9407c478bd9Sstevel@tonic-gate tgt_argv[0] = NULL;
9417c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create;
9427c478bd9Sstevel@tonic-gate }
9437c478bd9Sstevel@tonic-gate
9447c478bd9Sstevel@tonic-gate /*
9457c478bd9Sstevel@tonic-gate * If tgt_argv[1] is filled in, open it up and determine if it
9467c478bd9Sstevel@tonic-gate * is a vmcore file. If it is, gelf_check will fail and we
9477c478bd9Sstevel@tonic-gate * set tgt_ctor to 'kvm'; otherwise we use the default.
9487c478bd9Sstevel@tonic-gate */
9497c478bd9Sstevel@tonic-gate if (tgt_argc > 1 && strcmp(tgt_argv[1], "-") != 0 &&
9507c478bd9Sstevel@tonic-gate tgt_argv[0] != NULL && pidarg == NULL) {
9517c478bd9Sstevel@tonic-gate Elf32_Ehdr chdr;
9527c478bd9Sstevel@tonic-gate
9537c478bd9Sstevel@tonic-gate if (access(tgt_argv[1], F_OK) == -1)
9547c478bd9Sstevel@tonic-gate die("failed to access %s", tgt_argv[1]);
9557c478bd9Sstevel@tonic-gate
956ca3e8d88SDave Plauger /* *.N case: drop vmdump.N from the list */
957ca3e8d88SDave Plauger if (tgt_argc == 3) {
958ca3e8d88SDave Plauger if ((io = mdb_fdio_create_path(NULL,
959ca3e8d88SDave Plauger tgt_argv[2], O_RDONLY, 0)) == NULL)
960ca3e8d88SDave Plauger die("failed to open %s", tgt_argv[2]);
961ca3e8d88SDave Plauger if (mdb_kvm_is_compressed_dump(io))
962ca3e8d88SDave Plauger tgt_argv[--tgt_argc] = NULL;
963ca3e8d88SDave Plauger mdb_io_destroy(io);
964ca3e8d88SDave Plauger }
965ca3e8d88SDave Plauger
9667c478bd9Sstevel@tonic-gate if ((io = mdb_fdio_create_path(NULL, tgt_argv[1],
9677c478bd9Sstevel@tonic-gate O_RDONLY, 0)) == NULL)
9687c478bd9Sstevel@tonic-gate die("failed to open %s", tgt_argv[1]);
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate if (mdb_gelf_check(io, &chdr, ET_NONE) == -1)
9717c478bd9Sstevel@tonic-gate tgt_ctor = mdb_kvm_tgt_create;
9727c478bd9Sstevel@tonic-gate
9737c478bd9Sstevel@tonic-gate mdb_io_destroy(io);
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate
9767c478bd9Sstevel@tonic-gate /*
9777c478bd9Sstevel@tonic-gate * At this point, we've read the ELF header for either an
9787c478bd9Sstevel@tonic-gate * object file or core into ehdr. If the class does not match
9797c478bd9Sstevel@tonic-gate * ours, attempt to exec the mdb of the appropriate class.
9807c478bd9Sstevel@tonic-gate */
9817c478bd9Sstevel@tonic-gate #ifdef _LP64
982843e1988Sjohnlev if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
983843e1988Sjohnlev goto reexec;
9847c478bd9Sstevel@tonic-gate #else
985843e1988Sjohnlev if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
986843e1988Sjohnlev goto reexec;
9877c478bd9Sstevel@tonic-gate #endif
9887c478bd9Sstevel@tonic-gate }
9897c478bd9Sstevel@tonic-gate
9907c478bd9Sstevel@tonic-gate tcreate:
9917c478bd9Sstevel@tonic-gate if (tgt_ctor == NULL)
9927c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create;
9937c478bd9Sstevel@tonic-gate
9947c478bd9Sstevel@tonic-gate tgt = mdb_tgt_create(tgt_ctor, mdb.m_tgtflags, tgt_argc, tgt_argv);
9957c478bd9Sstevel@tonic-gate
9967c478bd9Sstevel@tonic-gate if (tgt == NULL) {
9977c478bd9Sstevel@tonic-gate if (errno == EINVAL)
9987c478bd9Sstevel@tonic-gate usage(2); /* target can return EINVAL to get usage */
9997c478bd9Sstevel@tonic-gate if (errno == EMDB_TGT)
10007c478bd9Sstevel@tonic-gate terminate(1); /* target already printed error msg */
10017c478bd9Sstevel@tonic-gate die("failed to initialize target");
10027c478bd9Sstevel@tonic-gate }
10037c478bd9Sstevel@tonic-gate
10047c478bd9Sstevel@tonic-gate mdb_tgt_activate(tgt);
10057c478bd9Sstevel@tonic-gate
10067c478bd9Sstevel@tonic-gate mdb_create_loadable_disasms();
10077c478bd9Sstevel@tonic-gate
10087c478bd9Sstevel@tonic-gate if (Vflag != NULL && mdb_dis_select(Vflag) == -1)
10097c478bd9Sstevel@tonic-gate warn("invalid disassembler mode -- %s\n", Vflag);
10107c478bd9Sstevel@tonic-gate
10117c478bd9Sstevel@tonic-gate
10127c478bd9Sstevel@tonic-gate if (Rflag && mdb.m_term != NULL)
10137c478bd9Sstevel@tonic-gate warn("Using proto area %s\n", mdb.m_root);
10147c478bd9Sstevel@tonic-gate
10157c478bd9Sstevel@tonic-gate /*
10167c478bd9Sstevel@tonic-gate * If the target was successfully constructed and -O was specified,
10177c478bd9Sstevel@tonic-gate * we now attempt to enter piggy-mode for debugging jurassic problems.
10187c478bd9Sstevel@tonic-gate */
10197c478bd9Sstevel@tonic-gate if (Oflag) {
10207c478bd9Sstevel@tonic-gate pcinfo_t pci;
10217c478bd9Sstevel@tonic-gate
10227c478bd9Sstevel@tonic-gate (void) strcpy(pci.pc_clname, "RT");
10237c478bd9Sstevel@tonic-gate
10247c478bd9Sstevel@tonic-gate if (priocntl(P_LWPID, P_MYID, PC_GETCID, (caddr_t)&pci) != -1) {
10257c478bd9Sstevel@tonic-gate pcparms_t pcp;
10267c478bd9Sstevel@tonic-gate rtparms_t *rtp = (rtparms_t *)pcp.pc_clparms;
10277c478bd9Sstevel@tonic-gate
10287c478bd9Sstevel@tonic-gate rtp->rt_pri = 35;
10297c478bd9Sstevel@tonic-gate rtp->rt_tqsecs = 0;
10307c478bd9Sstevel@tonic-gate rtp->rt_tqnsecs = RT_TQDEF;
10317c478bd9Sstevel@tonic-gate
10327c478bd9Sstevel@tonic-gate pcp.pc_cid = pci.pc_cid;
10337c478bd9Sstevel@tonic-gate
10347c478bd9Sstevel@tonic-gate if (priocntl(P_LWPID, P_MYID, PC_SETPARMS,
10357c478bd9Sstevel@tonic-gate (caddr_t)&pcp) == -1) {
10367c478bd9Sstevel@tonic-gate warn("failed to set RT parameters");
10377c478bd9Sstevel@tonic-gate Oflag = 0;
10387c478bd9Sstevel@tonic-gate }
10397c478bd9Sstevel@tonic-gate } else {
10407c478bd9Sstevel@tonic-gate warn("failed to get RT class id");
10417c478bd9Sstevel@tonic-gate Oflag = 0;
10427c478bd9Sstevel@tonic-gate }
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
10457c478bd9Sstevel@tonic-gate warn("failed to lock address space");
10467c478bd9Sstevel@tonic-gate Oflag = 0;
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate
10497c478bd9Sstevel@tonic-gate if (Oflag)
10507c478bd9Sstevel@tonic-gate mdb_printf("%s: oink, oink!\n", mdb.m_pname);
10517c478bd9Sstevel@tonic-gate }
10527c478bd9Sstevel@tonic-gate
10537c478bd9Sstevel@tonic-gate /*
10547c478bd9Sstevel@tonic-gate * Path evaluation part 2: Re-evaluate the path now that the target
10557c478bd9Sstevel@tonic-gate * is ready (and thus we have access to the real platform string).
10567c478bd9Sstevel@tonic-gate * Do this before reading ~/.mdbrc to allow path modifications prior
10577c478bd9Sstevel@tonic-gate * to performing module auto-loading.
10587c478bd9Sstevel@tonic-gate */
10597c478bd9Sstevel@tonic-gate mdb_set_ipath(mdb.m_ipathstr);
10607c478bd9Sstevel@tonic-gate mdb_set_lpath(mdb.m_lpathstr);
10617c478bd9Sstevel@tonic-gate
10627c478bd9Sstevel@tonic-gate if (!Sflag && (p = getenv("HOME")) != NULL) {
10637c478bd9Sstevel@tonic-gate char rcpath[MAXPATHLEN];
10647c478bd9Sstevel@tonic-gate mdb_io_t *rc_io;
10657c478bd9Sstevel@tonic-gate int fd;
10667c478bd9Sstevel@tonic-gate
10677c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(rcpath, MAXPATHLEN, "%s/.mdbrc", p);
10687c478bd9Sstevel@tonic-gate fd = open64(rcpath, O_RDONLY);
10697c478bd9Sstevel@tonic-gate
10707c478bd9Sstevel@tonic-gate if (fd >= 0 && (rc_io = mdb_fdio_create_named(fd, rcpath))) {
10717c478bd9Sstevel@tonic-gate mdb_iob_t *iob = mdb_iob_create(rc_io, MDB_IOB_RDONLY);
10727c478bd9Sstevel@tonic-gate mdb_iob_t *old = mdb.m_in;
10737c478bd9Sstevel@tonic-gate
10747c478bd9Sstevel@tonic-gate mdb.m_in = iob;
10757c478bd9Sstevel@tonic-gate (void) mdb_run();
10767c478bd9Sstevel@tonic-gate mdb.m_in = old;
10777c478bd9Sstevel@tonic-gate }
10787c478bd9Sstevel@tonic-gate }
10797c478bd9Sstevel@tonic-gate
10807c478bd9Sstevel@tonic-gate if (!(mdb.m_flags & MDB_FL_NOMODS))
10817c478bd9Sstevel@tonic-gate mdb_module_load_all(0);
10827c478bd9Sstevel@tonic-gate
10837c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGINT, int_handler, NULL);
10847c478bd9Sstevel@tonic-gate while ((status = mdb_run()) == MDB_ERR_ABORT ||
10857c478bd9Sstevel@tonic-gate status == MDB_ERR_OUTPUT) {
10867c478bd9Sstevel@tonic-gate /*
10877c478bd9Sstevel@tonic-gate * If a write failed on stdout, give up. A more informative
10887c478bd9Sstevel@tonic-gate * error message will already have been printed by mdb_run().
10897c478bd9Sstevel@tonic-gate */
10907c478bd9Sstevel@tonic-gate if (status == MDB_ERR_OUTPUT &&
10917c478bd9Sstevel@tonic-gate mdb_iob_getflags(mdb.m_out) & MDB_IOB_ERR) {
10927c478bd9Sstevel@tonic-gate mdb_warn("write to stdout failed, exiting\n");
10937c478bd9Sstevel@tonic-gate break;
10947c478bd9Sstevel@tonic-gate }
10957c478bd9Sstevel@tonic-gate continue;
10967c478bd9Sstevel@tonic-gate }
10977c478bd9Sstevel@tonic-gate
1098*0a47c91cSRobert Mustacchi terminate((status == MDB_ERR_QUIT || status == 0) ?
1099*0a47c91cSRobert Mustacchi (eflag != NULL && mdb.m_lastret != 0 ? 1 : 0) : 1);
11007c478bd9Sstevel@tonic-gate /*NOTREACHED*/
11017c478bd9Sstevel@tonic-gate return (0);
1102843e1988Sjohnlev
1103843e1988Sjohnlev reexec:
1104843e1988Sjohnlev if ((p = strrchr(execname, '/')) == NULL)
1105843e1988Sjohnlev die("cannot determine absolute pathname\n");
1106843e1988Sjohnlev #ifdef _LP64
1107843e1988Sjohnlev #ifdef __sparc
1108843e1988Sjohnlev (void) strcpy(p, "/../sparcv7/");
1109843e1988Sjohnlev #else
1110843e1988Sjohnlev (void) strcpy(p, "/../i86/");
1111843e1988Sjohnlev #endif
1112843e1988Sjohnlev #else
1113843e1988Sjohnlev #ifdef __sparc
1114843e1988Sjohnlev (void) strcpy(p, "/../sparcv9/");
1115843e1988Sjohnlev #else
1116843e1988Sjohnlev (void) strcpy(p, "/../amd64/");
1117843e1988Sjohnlev #endif
1118843e1988Sjohnlev #endif
1119843e1988Sjohnlev (void) strcat(p, mdb.m_pname);
1120843e1988Sjohnlev
1121843e1988Sjohnlev if (mdb.m_term != NULL)
1122843e1988Sjohnlev (void) IOP_CTL(in_io, TCSETSW, &tios);
1123843e1988Sjohnlev
1124843e1988Sjohnlev (void) putenv("_MDB_EXEC=1");
1125843e1988Sjohnlev (void) execv(execname, argv);
1126843e1988Sjohnlev
1127843e1988Sjohnlev /*
1128843e1988Sjohnlev * If execv fails, suppress ENOEXEC. Experience shows the most common
1129843e1988Sjohnlev * reason is that the machine is booted under a 32-bit kernel, in which
1130843e1988Sjohnlev * case it is clearer to only print the message below.
1131843e1988Sjohnlev */
1132843e1988Sjohnlev if (errno != ENOEXEC)
1133843e1988Sjohnlev warn("failed to exec %s", execname);
1134843e1988Sjohnlev #ifdef _LP64
1135843e1988Sjohnlev die("64-bit %s cannot debug 32-bit program %s\n",
1136843e1988Sjohnlev mdb.m_pname, tgt_argv[0] ?
1137843e1988Sjohnlev tgt_argv[0] : tgt_argv[1]);
1138843e1988Sjohnlev #else
1139843e1988Sjohnlev die("32-bit %s cannot debug 64-bit program %s\n",
1140843e1988Sjohnlev mdb.m_pname, tgt_argv[0] ?
1141843e1988Sjohnlev tgt_argv[0] : tgt_argv[1]);
1142843e1988Sjohnlev #endif
1143843e1988Sjohnlev
1144843e1988Sjohnlev goto tcreate;
11457c478bd9Sstevel@tonic-gate }
1146