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 59acbbeafSnn * Common Development and Distribution License (the "License"). 69acbbeafSnn * 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 /* 22a576ab5bSrab * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/mman.h> 287c478bd9Sstevel@tonic-gate #include <sys/priocntl.h> 297c478bd9Sstevel@tonic-gate #include <sys/rtpriocntl.h> 307c478bd9Sstevel@tonic-gate #include <sys/resource.h> 317c478bd9Sstevel@tonic-gate #include <sys/termios.h> 327c478bd9Sstevel@tonic-gate #include <sys/param.h> 337c478bd9Sstevel@tonic-gate #include <sys/regset.h> 347c478bd9Sstevel@tonic-gate #include <sys/frame.h> 357c478bd9Sstevel@tonic-gate #include <sys/stack.h> 367c478bd9Sstevel@tonic-gate #include <sys/reg.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include <libproc.h> 397c478bd9Sstevel@tonic-gate #include <libscf.h> 407c478bd9Sstevel@tonic-gate #include <alloca.h> 417c478bd9Sstevel@tonic-gate #include <unistd.h> 427c478bd9Sstevel@tonic-gate #include <string.h> 437c478bd9Sstevel@tonic-gate #include <stdlib.h> 447c478bd9Sstevel@tonic-gate #include <fcntl.h> 457c478bd9Sstevel@tonic-gate #include <dlfcn.h> 467c478bd9Sstevel@tonic-gate #include <libctf.h> 477c478bd9Sstevel@tonic-gate #include <errno.h> 48843e1988Sjohnlev #include <kvm.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #include <mdb/mdb_lex.h> 517c478bd9Sstevel@tonic-gate #include <mdb/mdb_debug.h> 527c478bd9Sstevel@tonic-gate #include <mdb/mdb_signal.h> 537c478bd9Sstevel@tonic-gate #include <mdb/mdb_string.h> 547c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 557c478bd9Sstevel@tonic-gate #include <mdb/mdb_target.h> 567c478bd9Sstevel@tonic-gate #include <mdb/mdb_gelf.h> 577c478bd9Sstevel@tonic-gate #include <mdb/mdb_conf.h> 587c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h> 597c478bd9Sstevel@tonic-gate #include <mdb/mdb_io_impl.h> 607c478bd9Sstevel@tonic-gate #include <mdb/mdb_frame.h> 617c478bd9Sstevel@tonic-gate #include <mdb/mdb_set.h> 627c478bd9Sstevel@tonic-gate #include <kmdb/kmdb_kctl.h> 637c478bd9Sstevel@tonic-gate #include <mdb/mdb.h> 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate #ifndef STACK_BIAS 667c478bd9Sstevel@tonic-gate #define STACK_BIAS 0 677c478bd9Sstevel@tonic-gate #endif 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate #if defined(__sparc) 707c478bd9Sstevel@tonic-gate #define STACK_REGISTER SP 717c478bd9Sstevel@tonic-gate #else 727c478bd9Sstevel@tonic-gate #define STACK_REGISTER REG_FP 737c478bd9Sstevel@tonic-gate #endif 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate #ifdef _LP64 767c478bd9Sstevel@tonic-gate #define MDB_DEF_IPATH \ 777c478bd9Sstevel@tonic-gate "%r/usr/platform/%p/lib/adb/%i:" \ 787c478bd9Sstevel@tonic-gate "%r/usr/platform/%m/lib/adb/%i:" \ 797c478bd9Sstevel@tonic-gate "%r/usr/lib/adb/%i" 807c478bd9Sstevel@tonic-gate #define MDB_DEF_LPATH \ 817c478bd9Sstevel@tonic-gate "%r/usr/platform/%p/lib/mdb/%t/%i:" \ 827c478bd9Sstevel@tonic-gate "%r/usr/platform/%m/lib/mdb/%t/%i:" \ 837c478bd9Sstevel@tonic-gate "%r/usr/lib/mdb/%t/%i" 847c478bd9Sstevel@tonic-gate #else 857c478bd9Sstevel@tonic-gate #define MDB_DEF_IPATH \ 867c478bd9Sstevel@tonic-gate "%r/usr/platform/%p/lib/adb:" \ 877c478bd9Sstevel@tonic-gate "%r/usr/platform/%m/lib/adb:" \ 887c478bd9Sstevel@tonic-gate "%r/usr/lib/adb" 897c478bd9Sstevel@tonic-gate #define MDB_DEF_LPATH \ 907c478bd9Sstevel@tonic-gate "%r/usr/platform/%p/lib/mdb/%t:" \ 917c478bd9Sstevel@tonic-gate "%r/usr/platform/%m/lib/mdb/%t:" \ 927c478bd9Sstevel@tonic-gate "%r/usr/lib/mdb/%t" 937c478bd9Sstevel@tonic-gate #endif 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate #define MDB_DEF_PROMPT "> " 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate * Similar to the panic_* variables in the kernel, we keep some relevant 997c478bd9Sstevel@tonic-gate * information stored in a set of global _mdb_abort_* variables; in the 1007c478bd9Sstevel@tonic-gate * event that the debugger dumps core, these will aid core dump analysis. 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate const char *volatile _mdb_abort_str; /* reason for failure */ 1037c478bd9Sstevel@tonic-gate siginfo_t _mdb_abort_info; /* signal info for fatal signal */ 1047c478bd9Sstevel@tonic-gate ucontext_t _mdb_abort_ctx; /* context fatal signal interrupted */ 1057c478bd9Sstevel@tonic-gate int _mdb_abort_rcount; /* number of times resume requested */ 1067c478bd9Sstevel@tonic-gate int _mdb_self_fd = -1; /* fd for self as for valid_frame */ 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate static void 1097c478bd9Sstevel@tonic-gate terminate(int status) 1107c478bd9Sstevel@tonic-gate { 111*36c835a5Svitezslav batrla - Sun Microsystems - Prague Czech Republic (void) mdb_signal_blockall(); 1127c478bd9Sstevel@tonic-gate mdb_destroy(); 1137c478bd9Sstevel@tonic-gate exit(status); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate static void 1177c478bd9Sstevel@tonic-gate print_frame(uintptr_t pc, int fnum) 1187c478bd9Sstevel@tonic-gate { 1197c478bd9Sstevel@tonic-gate Dl_info dli; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate if (dladdr((void *)pc, &dli)) { 1227c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, " [%d] %s`%s+0x%lx()\n", fnum, 1237c478bd9Sstevel@tonic-gate strbasename(dli.dli_fname), dli.dli_sname, 1247c478bd9Sstevel@tonic-gate pc - (uintptr_t)dli.dli_saddr); 1257c478bd9Sstevel@tonic-gate } else 1267c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, " [%d] %p()\n", fnum, pc); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate static int 1307c478bd9Sstevel@tonic-gate valid_frame(struct frame *fr) 1317c478bd9Sstevel@tonic-gate { 1327c478bd9Sstevel@tonic-gate static struct frame fake; 1337c478bd9Sstevel@tonic-gate uintptr_t addr = (uintptr_t)fr; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate if (pread(_mdb_self_fd, &fake, sizeof (fake), addr) != sizeof (fake)) { 1367c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, " invalid frame (%p)\n", fr); 1377c478bd9Sstevel@tonic-gate return (0); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate if (addr & (STACK_ALIGN - 1)) { 1417c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, " mis-aligned frame (%p)\n", fr); 1427c478bd9Sstevel@tonic-gate return (0); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate return (1); 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1497c478bd9Sstevel@tonic-gate static void 1507c478bd9Sstevel@tonic-gate flt_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data) 1517c478bd9Sstevel@tonic-gate { 1527c478bd9Sstevel@tonic-gate static const struct rlimit rl = { 1537c478bd9Sstevel@tonic-gate (rlim_t)RLIM_INFINITY, (rlim_t)RLIM_INFINITY 1547c478bd9Sstevel@tonic-gate }; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate const mdb_idcmd_t *idcp = NULL; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate if (mdb.m_frame != NULL && mdb.m_frame->f_cp != NULL) 1597c478bd9Sstevel@tonic-gate idcp = mdb.m_frame->f_cp->c_dcmd; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate if (sip != NULL) 1627c478bd9Sstevel@tonic-gate bcopy(sip, &_mdb_abort_info, sizeof (_mdb_abort_info)); 1637c478bd9Sstevel@tonic-gate if (ucp != NULL) 1647c478bd9Sstevel@tonic-gate bcopy(ucp, &_mdb_abort_ctx, sizeof (_mdb_abort_ctx)); 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate _mdb_abort_info.si_signo = sig; 1677c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(sig, SIG_DFL, NULL); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* 1707c478bd9Sstevel@tonic-gate * If there is no current dcmd, or the current dcmd comes from a 1717c478bd9Sstevel@tonic-gate * builtin module, we don't allow resume and always core dump. 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate if (idcp == NULL || idcp->idc_modp == NULL || 1747c478bd9Sstevel@tonic-gate idcp->idc_modp == &mdb.m_rmod || idcp->idc_modp->mod_hdl == NULL) 1757c478bd9Sstevel@tonic-gate goto dump; 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate if (mdb.m_term != NULL) { 1787c478bd9Sstevel@tonic-gate struct frame *fr = (struct frame *) 1797c478bd9Sstevel@tonic-gate (ucp->uc_mcontext.gregs[STACK_REGISTER] + STACK_BIAS); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate char signame[SIG2STR_MAX]; 1827c478bd9Sstevel@tonic-gate int i = 1; 1837c478bd9Sstevel@tonic-gate char c; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate if (sig2str(sig, signame) == -1) { 1867c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, 1877c478bd9Sstevel@tonic-gate "\n*** %s: received signal %d at:\n", 1887c478bd9Sstevel@tonic-gate mdb.m_pname, sig); 1897c478bd9Sstevel@tonic-gate } else { 1907c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, 1917c478bd9Sstevel@tonic-gate "\n*** %s: received signal %s at:\n", 1927c478bd9Sstevel@tonic-gate mdb.m_pname, signame); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate if (ucp->uc_mcontext.gregs[REG_PC] != 0) 1967c478bd9Sstevel@tonic-gate print_frame(ucp->uc_mcontext.gregs[REG_PC], i++); 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate while (fr != NULL && valid_frame(fr) && fr->fr_savpc != 0) { 1997c478bd9Sstevel@tonic-gate print_frame(fr->fr_savpc, i++); 2007c478bd9Sstevel@tonic-gate fr = (struct frame *) 2017c478bd9Sstevel@tonic-gate ((uintptr_t)fr->fr_savfp + STACK_BIAS); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate query: 2057c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, "\n%s: (c)ore dump, (q)uit, " 2067c478bd9Sstevel@tonic-gate "(r)ecover, or (s)top for debugger [cqrs]? ", mdb.m_pname); 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate mdb_iob_flush(mdb.m_err); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate for (;;) { 2117c478bd9Sstevel@tonic-gate if (IOP_READ(mdb.m_term, &c, sizeof (c)) != sizeof (c)) 2127c478bd9Sstevel@tonic-gate goto dump; 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate switch (c) { 2157c478bd9Sstevel@tonic-gate case 'c': 2167c478bd9Sstevel@tonic-gate case 'C': 2177c478bd9Sstevel@tonic-gate (void) setrlimit(RLIMIT_CORE, &rl); 2187c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, "\n%s: attempting " 2197c478bd9Sstevel@tonic-gate "to dump core ...\n", mdb.m_pname); 2207c478bd9Sstevel@tonic-gate goto dump; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate case 'q': 2237c478bd9Sstevel@tonic-gate case 'Q': 2247c478bd9Sstevel@tonic-gate mdb_iob_discard(mdb.m_out); 2257c478bd9Sstevel@tonic-gate mdb_iob_nl(mdb.m_err); 2267c478bd9Sstevel@tonic-gate (void) mdb_signal_unblockall(); 2277c478bd9Sstevel@tonic-gate terminate(1); 2287c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate case 'r': 2317c478bd9Sstevel@tonic-gate case 'R': 2327c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, "\n%s: unloading " 2337c478bd9Sstevel@tonic-gate "module '%s' ...\n", mdb.m_pname, 2347c478bd9Sstevel@tonic-gate idcp->idc_modp->mod_name); 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate (void) mdb_module_unload( 2377c478bd9Sstevel@tonic-gate idcp->idc_modp->mod_name, 0); 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(sig, 2407c478bd9Sstevel@tonic-gate flt_handler, NULL); 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate _mdb_abort_rcount++; 2437c478bd9Sstevel@tonic-gate mdb.m_intr = 0; 2447c478bd9Sstevel@tonic-gate mdb.m_pend = 0; 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate (void) mdb_signal_unblockall(); 2477c478bd9Sstevel@tonic-gate longjmp(mdb.m_frame->f_pcb, MDB_ERR_ABORT); 2487c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate case 's': 2517c478bd9Sstevel@tonic-gate case 'S': 2527c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, "\n%s: " 2537c478bd9Sstevel@tonic-gate "attempting to stop pid %d ...\n", 2547c478bd9Sstevel@tonic-gate mdb.m_pname, (int)getpid()); 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * Stop ourself; if this fails or we are 2587c478bd9Sstevel@tonic-gate * subsequently continued, ask again. 2597c478bd9Sstevel@tonic-gate */ 2607c478bd9Sstevel@tonic-gate (void) mdb_signal_raise(SIGSTOP); 2617c478bd9Sstevel@tonic-gate (void) mdb_signal_unblockall(); 2627c478bd9Sstevel@tonic-gate goto query; 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate dump: 2687c478bd9Sstevel@tonic-gate if (SI_FROMUSER(sip)) { 2697c478bd9Sstevel@tonic-gate (void) mdb_signal_block(sig); 2707c478bd9Sstevel@tonic-gate (void) mdb_signal_raise(sig); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate (void) sigfillset(&ucp->uc_sigmask); 2747c478bd9Sstevel@tonic-gate (void) sigdelset(&ucp->uc_sigmask, sig); 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (_mdb_abort_str == NULL) 2777c478bd9Sstevel@tonic-gate _mdb_abort_str = "fatal signal received"; 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate ucp->uc_flags |= UC_SIGMASK; 2807c478bd9Sstevel@tonic-gate (void) setcontext(ucp); 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2847c478bd9Sstevel@tonic-gate static void 2857c478bd9Sstevel@tonic-gate int_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data) 2867c478bd9Sstevel@tonic-gate { 2877c478bd9Sstevel@tonic-gate if (mdb.m_intr == 0) 2887c478bd9Sstevel@tonic-gate longjmp(mdb.m_frame->f_pcb, MDB_ERR_SIGINT); 2897c478bd9Sstevel@tonic-gate else 2907c478bd9Sstevel@tonic-gate mdb.m_pend++; 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate static void 2947c478bd9Sstevel@tonic-gate control_kmdb(int start) 2957c478bd9Sstevel@tonic-gate { 2967c478bd9Sstevel@tonic-gate int fd; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate if ((fd = open("/dev/kmdb", O_RDONLY)) < 0) 2997c478bd9Sstevel@tonic-gate die("failed to open /dev/kmdb"); 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate if (start) { 3027c478bd9Sstevel@tonic-gate char *state = mdb_get_config(); 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate if (ioctl(fd, KMDB_IOC_START, state) < 0) 3057c478bd9Sstevel@tonic-gate die("failed to start kmdb"); 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate strfree(state); 3087c478bd9Sstevel@tonic-gate } else { 3097c478bd9Sstevel@tonic-gate if (ioctl(fd, KMDB_IOC_STOP) < 0) 3107c478bd9Sstevel@tonic-gate die("failed to stop kmdb"); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate close(fd); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate static void 3177c478bd9Sstevel@tonic-gate usage(int status) 3187c478bd9Sstevel@tonic-gate { 3197c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_err, "Usage: %s [-fkmuwyAFKMSUW] [+/-o option] " 3207c478bd9Sstevel@tonic-gate "[-p pid] [-s dist] [-I path] [-L path]\n\t[-P prompt] " 3217c478bd9Sstevel@tonic-gate "[-R root] [-V dis-version] [object [core] | core | suffix]\n\n", 3227c478bd9Sstevel@tonic-gate mdb.m_pname); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate mdb_iob_puts(mdb.m_err, 3257c478bd9Sstevel@tonic-gate "\t-f force raw file debugging mode\n" 3267c478bd9Sstevel@tonic-gate "\t-k force kernel debugging mode\n" 3277c478bd9Sstevel@tonic-gate "\t-m disable demand-loading of module symbols\n" 3287c478bd9Sstevel@tonic-gate "\t-o set specified debugger option (+o to unset)\n" 3297c478bd9Sstevel@tonic-gate "\t-p attach to specified process-id\n" 3307c478bd9Sstevel@tonic-gate "\t-s set symbol matching distance\n" 3317c478bd9Sstevel@tonic-gate "\t-u force user program debugging mode\n" 3327c478bd9Sstevel@tonic-gate "\t-w enable write mode\n" 3337c478bd9Sstevel@tonic-gate "\t-y send terminal initialization sequences for tty mode\n" 3347c478bd9Sstevel@tonic-gate "\t-A disable automatic loading of mdb modules\n" 3357c478bd9Sstevel@tonic-gate "\t-F enable forcible takeover mode\n" 3367c478bd9Sstevel@tonic-gate "\t-K stop operating system and enter live kernel debugger\n" 3377c478bd9Sstevel@tonic-gate "\t-M preload all module symbols\n" 3387c478bd9Sstevel@tonic-gate "\t-I set initial path for macro files\n" 3397c478bd9Sstevel@tonic-gate "\t-L set initial path for module libs\n" 3407c478bd9Sstevel@tonic-gate "\t-P set command-line prompt\n" 3417c478bd9Sstevel@tonic-gate "\t-R set root directory for pathname expansion\n" 3427c478bd9Sstevel@tonic-gate "\t-S suppress processing of ~/.mdbrc file\n" 3437c478bd9Sstevel@tonic-gate "\t-U unload live kernel debugger\n" 3447c478bd9Sstevel@tonic-gate "\t-W enable I/O-mapped memory access (kernel only)\n" 3457c478bd9Sstevel@tonic-gate "\t-V set disassembler version\n"); 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate terminate(status); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate static char * 3517c478bd9Sstevel@tonic-gate mdb_scf_console_term(void) 3527c478bd9Sstevel@tonic-gate { 3537c478bd9Sstevel@tonic-gate scf_simple_prop_t *prop; 3547c478bd9Sstevel@tonic-gate char *term = NULL; 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate if ((prop = scf_simple_prop_get(NULL, 3577c478bd9Sstevel@tonic-gate "svc:/system/console-login:default", "ttymon", 3587c478bd9Sstevel@tonic-gate "terminal_type")) == NULL) 3597c478bd9Sstevel@tonic-gate return (NULL); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate if (scf_simple_prop_type(prop) == SCF_TYPE_ASTRING && 3627c478bd9Sstevel@tonic-gate (term = scf_simple_prop_next_astring(prop)) != NULL) 3637c478bd9Sstevel@tonic-gate term = strdup(term); 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate scf_simple_prop_free(prop); 3667c478bd9Sstevel@tonic-gate return (term); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate 369a576ab5bSrab /* 370a576ab5bSrab * Unpleasant hack: we might be debugging a hypervisor domain dump. 371a576ab5bSrab * Earlier versions use a non-ELF file. Later versions are ELF, but are 372a576ab5bSrab * /always/ ELF64, so our standard ehdr check isn't good enough. Since 373a576ab5bSrab * we don't want to know too much about the file format, we'll ask 374a576ab5bSrab * mdb_kb. 375a576ab5bSrab */ 376a576ab5bSrab #ifdef __x86 377a576ab5bSrab static int 378a576ab5bSrab identify_xvm_file(const char *file, int *longmode) 379a576ab5bSrab { 380a576ab5bSrab int (*identify)(const char *, int *); 381a576ab5bSrab 382a576ab5bSrab if (mdb_module_load("mdb_kb", MDB_MOD_GLOBAL | MDB_MOD_SILENT) != 0) 383a576ab5bSrab return (0); 384a576ab5bSrab 385a576ab5bSrab identify = (int (*)())dlsym(RTLD_NEXT, "xkb_identify"); 386a576ab5bSrab 387a576ab5bSrab if (identify == NULL) 388a576ab5bSrab return (0); 389a576ab5bSrab 390a576ab5bSrab return (identify(file, longmode)); 391a576ab5bSrab } 392a576ab5bSrab #else 393a576ab5bSrab /*ARGSUSED*/ 394a576ab5bSrab static int 395a576ab5bSrab identify_xvm_file(const char *file, int *longmode) 396a576ab5bSrab { 397a576ab5bSrab return (0); 398a576ab5bSrab } 399a576ab5bSrab #endif /* __x86 */ 400a576ab5bSrab 4017c478bd9Sstevel@tonic-gate int 4027c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char *envp[]) 4037c478bd9Sstevel@tonic-gate { 4047c478bd9Sstevel@tonic-gate mdb_tgt_ctor_f *tgt_ctor = NULL; 4057c478bd9Sstevel@tonic-gate const char **tgt_argv = alloca(argc * sizeof (char *)); 4067c478bd9Sstevel@tonic-gate int tgt_argc = 0; 4077c478bd9Sstevel@tonic-gate mdb_tgt_t *tgt; 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate char object[MAXPATHLEN], execname[MAXPATHLEN]; 4107c478bd9Sstevel@tonic-gate mdb_io_t *in_io, *out_io, *err_io, *null_io; 4117c478bd9Sstevel@tonic-gate struct termios tios; 4127c478bd9Sstevel@tonic-gate int status, c; 4137c478bd9Sstevel@tonic-gate char *p; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate const char *Iflag = NULL, *Lflag = NULL, *Vflag = NULL, *pidarg = NULL; 416843e1988Sjohnlev int fflag = 0, Kflag = 0, Rflag = 0, Sflag = 0, Oflag = 0, Uflag = 0; 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate int ttylike; 419a576ab5bSrab int longmode = 0; 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate stack_t sigstack; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if (realpath(getexecname(), execname) == NULL) { 4247c478bd9Sstevel@tonic-gate (void) strncpy(execname, argv[0], MAXPATHLEN); 4257c478bd9Sstevel@tonic-gate execname[MAXPATHLEN - 1] = '\0'; 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate mdb_create(execname, argv[0]); 4297c478bd9Sstevel@tonic-gate bzero(tgt_argv, argc * sizeof (char *)); 4307c478bd9Sstevel@tonic-gate argv[0] = (char *)mdb.m_pname; 4317c478bd9Sstevel@tonic-gate _mdb_self_fd = open("/proc/self/as", O_RDONLY); 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate mdb.m_env = envp; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate out_io = mdb_fdio_create(STDOUT_FILENO); 4367c478bd9Sstevel@tonic-gate mdb.m_out = mdb_iob_create(out_io, MDB_IOB_WRONLY); 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate err_io = mdb_fdio_create(STDERR_FILENO); 4397c478bd9Sstevel@tonic-gate mdb.m_err = mdb_iob_create(err_io, MDB_IOB_WRONLY); 4407c478bd9Sstevel@tonic-gate mdb_iob_clrflags(mdb.m_err, MDB_IOB_AUTOWRAP); 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate null_io = mdb_nullio_create(); 4437c478bd9Sstevel@tonic-gate mdb.m_null = mdb_iob_create(null_io, MDB_IOB_WRONLY); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate in_io = mdb_fdio_create(STDIN_FILENO); 4467c478bd9Sstevel@tonic-gate if ((mdb.m_termtype = getenv("TERM")) != NULL) { 4477c478bd9Sstevel@tonic-gate mdb.m_termtype = strdup(mdb.m_termtype); 4487c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_TERMGUESS; 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate mdb.m_term = NULL; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate mdb_dmode(mdb_dstr2mode(getenv("MDB_DEBUG"))); 4537c478bd9Sstevel@tonic-gate mdb.m_pgid = getpgrp(); 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate if (getenv("_MDB_EXEC") != NULL) 4567c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_EXEC; 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate /* 4597c478bd9Sstevel@tonic-gate * Setup an alternate signal stack. When tearing down pipelines in 4607c478bd9Sstevel@tonic-gate * terminate(), we may have to destroy the stack of the context in 4617c478bd9Sstevel@tonic-gate * which we are currently executing the signal handler. 4627c478bd9Sstevel@tonic-gate */ 4637c478bd9Sstevel@tonic-gate sigstack.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, 4647c478bd9Sstevel@tonic-gate MAP_PRIVATE | MAP_ANON, -1, 0); 4657c478bd9Sstevel@tonic-gate if (sigstack.ss_sp == MAP_FAILED) 4667c478bd9Sstevel@tonic-gate die("could not allocate signal stack"); 4677c478bd9Sstevel@tonic-gate sigstack.ss_size = SIGSTKSZ; 4687c478bd9Sstevel@tonic-gate sigstack.ss_flags = 0; 4697c478bd9Sstevel@tonic-gate if (sigaltstack(&sigstack, NULL) != 0) 4707c478bd9Sstevel@tonic-gate die("could not set signal stack"); 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGPIPE, SIG_IGN, NULL); 4737c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGQUIT, SIG_IGN, NULL); 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGILL, flt_handler, NULL); 4767c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGTRAP, flt_handler, NULL); 4777c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGIOT, flt_handler, NULL); 4787c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGEMT, flt_handler, NULL); 4797c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGFPE, flt_handler, NULL); 4807c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGBUS, flt_handler, NULL); 4817c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGSEGV, flt_handler, NULL); 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGHUP, (mdb_signal_f *)terminate, NULL); 4847c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGTERM, (mdb_signal_f *)terminate, NULL); 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate for (mdb.m_rdvers = RD_VERSION; mdb.m_rdvers > 0; mdb.m_rdvers--) { 4877c478bd9Sstevel@tonic-gate if (rd_init(mdb.m_rdvers) == RD_OK) 4887c478bd9Sstevel@tonic-gate break; 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate for (mdb.m_ctfvers = CTF_VERSION; mdb.m_ctfvers > 0; mdb.m_ctfvers--) { 4927c478bd9Sstevel@tonic-gate if (ctf_version(mdb.m_ctfvers) != -1) 4937c478bd9Sstevel@tonic-gate break; 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate if ((p = getenv("HISTSIZE")) != NULL && strisnum(p)) { 4977c478bd9Sstevel@tonic-gate mdb.m_histlen = strtoi(p); 4987c478bd9Sstevel@tonic-gate if (mdb.m_histlen < 1) 4997c478bd9Sstevel@tonic-gate mdb.m_histlen = 1; 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate while (optind < argc) { 5037c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, 5047c478bd9Sstevel@tonic-gate "fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) { 5057c478bd9Sstevel@tonic-gate switch (c) { 5067c478bd9Sstevel@tonic-gate case 'f': 507843e1988Sjohnlev fflag++; 5087c478bd9Sstevel@tonic-gate tgt_ctor = mdb_rawfile_tgt_create; 5097c478bd9Sstevel@tonic-gate break; 5107c478bd9Sstevel@tonic-gate case 'k': 5117c478bd9Sstevel@tonic-gate tgt_ctor = mdb_kvm_tgt_create; 5127c478bd9Sstevel@tonic-gate break; 5137c478bd9Sstevel@tonic-gate case 'm': 5147c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_NOLOAD; 5157c478bd9Sstevel@tonic-gate mdb.m_tgtflags &= ~MDB_TGT_F_PRELOAD; 5167c478bd9Sstevel@tonic-gate break; 5177c478bd9Sstevel@tonic-gate case 'o': 5187c478bd9Sstevel@tonic-gate if (!mdb_set_options(optarg, TRUE)) 5197c478bd9Sstevel@tonic-gate terminate(2); 5207c478bd9Sstevel@tonic-gate break; 5217c478bd9Sstevel@tonic-gate case 'p': 5227c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create; 5237c478bd9Sstevel@tonic-gate pidarg = optarg; 5247c478bd9Sstevel@tonic-gate break; 5257c478bd9Sstevel@tonic-gate case 's': 5267c478bd9Sstevel@tonic-gate if (!strisnum(optarg)) { 5277c478bd9Sstevel@tonic-gate warn("expected integer following -s\n"); 5287c478bd9Sstevel@tonic-gate terminate(2); 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate mdb.m_symdist = (size_t)(uint_t)strtoi(optarg); 5317c478bd9Sstevel@tonic-gate break; 5327c478bd9Sstevel@tonic-gate case 'u': 5337c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create; 5347c478bd9Sstevel@tonic-gate break; 5357c478bd9Sstevel@tonic-gate case 'w': 5367c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_RDWR; 5377c478bd9Sstevel@tonic-gate break; 5387c478bd9Sstevel@tonic-gate case 'y': 5397c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_USECUP; 5407c478bd9Sstevel@tonic-gate break; 5417c478bd9Sstevel@tonic-gate case 'A': 5427c478bd9Sstevel@tonic-gate (void) mdb_set_options("nomods", TRUE); 5437c478bd9Sstevel@tonic-gate break; 5447c478bd9Sstevel@tonic-gate case 'C': 5457c478bd9Sstevel@tonic-gate (void) mdb_set_options("noctf", TRUE); 5467c478bd9Sstevel@tonic-gate break; 5477c478bd9Sstevel@tonic-gate case 'D': 5487c478bd9Sstevel@tonic-gate mdb_dmode(mdb_dstr2mode(optarg)); 5497c478bd9Sstevel@tonic-gate break; 5507c478bd9Sstevel@tonic-gate case 'F': 5517c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_FORCE; 5527c478bd9Sstevel@tonic-gate break; 5537c478bd9Sstevel@tonic-gate case 'I': 5547c478bd9Sstevel@tonic-gate Iflag = optarg; 5557c478bd9Sstevel@tonic-gate break; 5567c478bd9Sstevel@tonic-gate case 'L': 5577c478bd9Sstevel@tonic-gate Lflag = optarg; 5587c478bd9Sstevel@tonic-gate break; 5597c478bd9Sstevel@tonic-gate case 'K': 5607c478bd9Sstevel@tonic-gate Kflag++; 5617c478bd9Sstevel@tonic-gate break; 5627c478bd9Sstevel@tonic-gate case 'M': 5637c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_PRELOAD; 5647c478bd9Sstevel@tonic-gate mdb.m_tgtflags &= ~MDB_TGT_F_NOLOAD; 5657c478bd9Sstevel@tonic-gate break; 5667c478bd9Sstevel@tonic-gate case 'O': 5677c478bd9Sstevel@tonic-gate Oflag++; 5687c478bd9Sstevel@tonic-gate break; 5697c478bd9Sstevel@tonic-gate case 'P': 5707c478bd9Sstevel@tonic-gate if (!mdb_set_prompt(optarg)) 5717c478bd9Sstevel@tonic-gate terminate(2); 5727c478bd9Sstevel@tonic-gate break; 5737c478bd9Sstevel@tonic-gate case 'R': 5747c478bd9Sstevel@tonic-gate (void) strncpy(mdb.m_root, optarg, MAXPATHLEN); 5757c478bd9Sstevel@tonic-gate mdb.m_root[MAXPATHLEN - 1] = '\0'; 5767c478bd9Sstevel@tonic-gate Rflag++; 5777c478bd9Sstevel@tonic-gate break; 5787c478bd9Sstevel@tonic-gate case 'S': 5797c478bd9Sstevel@tonic-gate Sflag++; 5807c478bd9Sstevel@tonic-gate break; 5817c478bd9Sstevel@tonic-gate case 'U': 5827c478bd9Sstevel@tonic-gate Uflag++; 5837c478bd9Sstevel@tonic-gate break; 5847c478bd9Sstevel@tonic-gate case 'V': 5857c478bd9Sstevel@tonic-gate Vflag = optarg; 5867c478bd9Sstevel@tonic-gate break; 5877c478bd9Sstevel@tonic-gate case 'W': 5887c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_ALLOWIO; 5897c478bd9Sstevel@tonic-gate break; 5907c478bd9Sstevel@tonic-gate case '?': 5917c478bd9Sstevel@tonic-gate if (optopt == '?') 5927c478bd9Sstevel@tonic-gate usage(0); 5937c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 5947c478bd9Sstevel@tonic-gate default: 5957c478bd9Sstevel@tonic-gate usage(2); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate if (optind < argc) { 6007c478bd9Sstevel@tonic-gate const char *arg = argv[optind++]; 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate if (arg[0] == '+' && strlen(arg) == 2) { 6037c478bd9Sstevel@tonic-gate if (arg[1] != 'o') { 6047c478bd9Sstevel@tonic-gate warn("illegal option -- %s\n", arg); 6057c478bd9Sstevel@tonic-gate terminate(2); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate if (optind >= argc) { 6087c478bd9Sstevel@tonic-gate warn("option requires an argument -- " 6097c478bd9Sstevel@tonic-gate "%s\n", arg); 6107c478bd9Sstevel@tonic-gate terminate(2); 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate if (!mdb_set_options(argv[optind++], FALSE)) 6137c478bd9Sstevel@tonic-gate terminate(2); 6147c478bd9Sstevel@tonic-gate } else 6157c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = arg; 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate 6199acbbeafSnn if (rd_ctl(RD_CTL_SET_HELPPATH, (void *)mdb.m_root) != RD_OK) { 6209acbbeafSnn warn("cannot set librtld_db helper path to %s\n", mdb.m_root); 6219acbbeafSnn terminate(2); 6229acbbeafSnn } 6239acbbeafSnn 6247c478bd9Sstevel@tonic-gate if (mdb.m_debug & MDB_DBG_HELP) 6257c478bd9Sstevel@tonic-gate terminate(0); /* Quit here if we've printed out the tokens */ 6267c478bd9Sstevel@tonic-gate 6279acbbeafSnn 6287c478bd9Sstevel@tonic-gate if (Iflag != NULL && strchr(Iflag, ';') != NULL) { 6297c478bd9Sstevel@tonic-gate warn("macro path cannot contain semicolons\n"); 6307c478bd9Sstevel@tonic-gate terminate(2); 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate if (Lflag != NULL && strchr(Lflag, ';') != NULL) { 6347c478bd9Sstevel@tonic-gate warn("module path cannot contain semicolons\n"); 6357c478bd9Sstevel@tonic-gate terminate(2); 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate if (Kflag || Uflag) { 6397c478bd9Sstevel@tonic-gate char *nm; 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate if (tgt_ctor != NULL || Iflag != NULL) { 6427c478bd9Sstevel@tonic-gate warn("neither -f, -k, -p, -u, nor -I " 6437c478bd9Sstevel@tonic-gate "may be used with -K\n"); 6447c478bd9Sstevel@tonic-gate usage(2); 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate if (Lflag != NULL) 6487c478bd9Sstevel@tonic-gate mdb_set_lpath(Lflag); 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate if ((nm = ttyname(STDIN_FILENO)) == NULL || 6517c478bd9Sstevel@tonic-gate strcmp(nm, "/dev/console") != 0) { 6527c478bd9Sstevel@tonic-gate /* 6537c478bd9Sstevel@tonic-gate * Due to the consequences of typing mdb -K instead of 6547c478bd9Sstevel@tonic-gate * mdb -k on a tty other than /dev/console, we require 6557c478bd9Sstevel@tonic-gate * -F when starting kmdb from a tty other than 6567c478bd9Sstevel@tonic-gate * /dev/console. 6577c478bd9Sstevel@tonic-gate */ 6587c478bd9Sstevel@tonic-gate if (!(mdb.m_tgtflags & MDB_TGT_F_FORCE)) { 6597c478bd9Sstevel@tonic-gate die("-F must also be supplied to start kmdb " 6607c478bd9Sstevel@tonic-gate "from non-console tty\n"); 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if (mdb.m_termtype == NULL || (mdb.m_flags & 6647c478bd9Sstevel@tonic-gate MDB_FL_TERMGUESS)) { 6657c478bd9Sstevel@tonic-gate if (mdb.m_termtype != NULL) 6667c478bd9Sstevel@tonic-gate strfree(mdb.m_termtype); 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate if ((mdb.m_termtype = mdb_scf_console_term()) != 6697c478bd9Sstevel@tonic-gate NULL) 6707c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_TERMGUESS; 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate } else { 6737c478bd9Sstevel@tonic-gate /* 6747c478bd9Sstevel@tonic-gate * When on console, $TERM (if set) takes precedence over 6757c478bd9Sstevel@tonic-gate * the SMF setting. 6767c478bd9Sstevel@tonic-gate */ 6777c478bd9Sstevel@tonic-gate if (mdb.m_termtype == NULL && (mdb.m_termtype = 6787c478bd9Sstevel@tonic-gate mdb_scf_console_term()) != NULL) 6797c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_TERMGUESS; 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate control_kmdb(Kflag); 6837c478bd9Sstevel@tonic-gate terminate(0); 6847c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate /* 6887c478bd9Sstevel@tonic-gate * If standard input appears to have tty attributes, attempt to 6897c478bd9Sstevel@tonic-gate * initialize a terminal i/o backend on top of stdin and stdout. 6907c478bd9Sstevel@tonic-gate */ 6917c478bd9Sstevel@tonic-gate ttylike = (IOP_CTL(in_io, TCGETS, &tios) == 0); 6927c478bd9Sstevel@tonic-gate if (ttylike) { 6937c478bd9Sstevel@tonic-gate if ((mdb.m_term = mdb_termio_create(mdb.m_termtype, 6947c478bd9Sstevel@tonic-gate in_io, out_io)) == NULL) { 6957c478bd9Sstevel@tonic-gate if (!(mdb.m_flags & MDB_FL_EXEC)) { 6967c478bd9Sstevel@tonic-gate warn("term init failed: command-line editing " 6977c478bd9Sstevel@tonic-gate "and prompt will not be available\n"); 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate } else { 7007c478bd9Sstevel@tonic-gate in_io = mdb.m_term; 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate mdb.m_in = mdb_iob_create(in_io, MDB_IOB_RDONLY); 7057c478bd9Sstevel@tonic-gate if (mdb.m_term != NULL) { 7067c478bd9Sstevel@tonic-gate mdb_iob_setpager(mdb.m_out, mdb.m_term); 7077c478bd9Sstevel@tonic-gate if (mdb.m_flags & MDB_FL_PAGER) 7087c478bd9Sstevel@tonic-gate mdb_iob_setflags(mdb.m_out, MDB_IOB_PGENABLE); 7097c478bd9Sstevel@tonic-gate else 7107c478bd9Sstevel@tonic-gate mdb_iob_clrflags(mdb.m_out, MDB_IOB_PGENABLE); 7117c478bd9Sstevel@tonic-gate } else if (ttylike) 7127c478bd9Sstevel@tonic-gate mdb_iob_setflags(mdb.m_in, MDB_IOB_TTYLIKE); 7137c478bd9Sstevel@tonic-gate else 7147c478bd9Sstevel@tonic-gate mdb_iob_setbuf(mdb.m_in, mdb_alloc(1, UM_SLEEP), 1); 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate mdb_pservice_init(); 7177c478bd9Sstevel@tonic-gate mdb_lex_reset(); 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate if ((mdb.m_shell = getenv("SHELL")) == NULL) 7207c478bd9Sstevel@tonic-gate mdb.m_shell = "/bin/sh"; 7217c478bd9Sstevel@tonic-gate 722a576ab5bSrab /* 723a576ab5bSrab * If the debugger state is to be inherited from a previous instance, 724a576ab5bSrab * restore it now prior to path evaluation so that %R is updated. 725a576ab5bSrab */ 726a576ab5bSrab if ((p = getenv(MDB_CONFIG_ENV_VAR)) != NULL) { 727a576ab5bSrab mdb_set_config(p); 728a576ab5bSrab (void) unsetenv(MDB_CONFIG_ENV_VAR); 729a576ab5bSrab } 730a576ab5bSrab 731a576ab5bSrab /* 732a576ab5bSrab * Path evaluation part 1: Create the initial module path to allow 733a576ab5bSrab * the target constructor to load a support module. Then expand 734a576ab5bSrab * any command-line arguments that modify the paths. 735a576ab5bSrab */ 736a576ab5bSrab if (Iflag != NULL) 737a576ab5bSrab mdb_set_ipath(Iflag); 738a576ab5bSrab else 739a576ab5bSrab mdb_set_ipath(MDB_DEF_IPATH); 740a576ab5bSrab 741a576ab5bSrab if (Lflag != NULL) 742a576ab5bSrab mdb_set_lpath(Lflag); 743a576ab5bSrab else 744a576ab5bSrab mdb_set_lpath(MDB_DEF_LPATH); 745a576ab5bSrab 746a576ab5bSrab if (mdb_get_prompt() == NULL && !(mdb.m_flags & MDB_FL_ADB)) 747a576ab5bSrab (void) mdb_set_prompt(MDB_DEF_PROMPT); 748a576ab5bSrab 7497c478bd9Sstevel@tonic-gate if (tgt_ctor == mdb_kvm_tgt_create) { 7507c478bd9Sstevel@tonic-gate if (pidarg != NULL) { 7517c478bd9Sstevel@tonic-gate warn("-p and -k options are mutually exclusive\n"); 7527c478bd9Sstevel@tonic-gate terminate(2); 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate if (tgt_argc == 0) 7567c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = "/dev/ksyms"; 7577c478bd9Sstevel@tonic-gate if (tgt_argc == 1 && strisnum(tgt_argv[0]) == 0) { 7587c478bd9Sstevel@tonic-gate if (mdb.m_tgtflags & MDB_TGT_F_ALLOWIO) 7597c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = "/dev/allkmem"; 7607c478bd9Sstevel@tonic-gate else 7617c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = "/dev/kmem"; 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate if (pidarg != NULL) { 7667c478bd9Sstevel@tonic-gate if (tgt_argc != 0) { 7677c478bd9Sstevel@tonic-gate warn("-p may not be used with other arguments\n"); 7687c478bd9Sstevel@tonic-gate terminate(2); 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate if (proc_arg_psinfo(pidarg, PR_ARG_PIDS, NULL, &status) == -1) { 7717c478bd9Sstevel@tonic-gate die("cannot attach to %s: %s\n", 7727c478bd9Sstevel@tonic-gate pidarg, Pgrab_error(status)); 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate if (strchr(pidarg, '/') != NULL) 7757c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(object, MAXPATHLEN, 7767c478bd9Sstevel@tonic-gate "%s/object/a.out", pidarg); 7777c478bd9Sstevel@tonic-gate else 7787c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(object, MAXPATHLEN, 7797c478bd9Sstevel@tonic-gate "/proc/%s/object/a.out", pidarg); 7807c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = object; 7817c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = pidarg; 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate /* 7857c478bd9Sstevel@tonic-gate * Find the first argument that is not a special "-" token. If one is 7867c478bd9Sstevel@tonic-gate * found, we will examine this file and make some inferences below. 7877c478bd9Sstevel@tonic-gate */ 7887c478bd9Sstevel@tonic-gate for (c = 0; c < tgt_argc && strcmp(tgt_argv[c], "-") == 0; c++) 7897c478bd9Sstevel@tonic-gate continue; 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate if (c < tgt_argc) { 7927c478bd9Sstevel@tonic-gate Elf32_Ehdr ehdr; 7937c478bd9Sstevel@tonic-gate mdb_io_t *io; 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate /* 7967c478bd9Sstevel@tonic-gate * If special "-" tokens preceded an argument, shift the entire 7977c478bd9Sstevel@tonic-gate * argument list to the left to remove the leading "-" args. 7987c478bd9Sstevel@tonic-gate */ 7997c478bd9Sstevel@tonic-gate if (c > 0) { 8007c478bd9Sstevel@tonic-gate bcopy(&tgt_argv[c], tgt_argv, 8017c478bd9Sstevel@tonic-gate sizeof (const char *) * (tgt_argc - c)); 8027c478bd9Sstevel@tonic-gate tgt_argc -= c; 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate /* 8067c478bd9Sstevel@tonic-gate * If we just have an object file name, and that file doesn't 8077c478bd9Sstevel@tonic-gate * exist, and it's a string of digits, infer it to be a 8087c478bd9Sstevel@tonic-gate * sequence number referring to a pair of crash dump files. 8097c478bd9Sstevel@tonic-gate */ 8107c478bd9Sstevel@tonic-gate if (tgt_argc == 1 && access(tgt_argv[0], F_OK) == -1 && 8117c478bd9Sstevel@tonic-gate strisnum(tgt_argv[0])) { 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate size_t len = strlen(tgt_argv[0]) + 8; 8147c478bd9Sstevel@tonic-gate const char *object = tgt_argv[0]; 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate tgt_argv[0] = mdb_alloc(len, UM_SLEEP); 8177c478bd9Sstevel@tonic-gate tgt_argv[1] = mdb_alloc(len, UM_SLEEP); 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate (void) strcpy((char *)tgt_argv[0], "unix."); 8207c478bd9Sstevel@tonic-gate (void) strcat((char *)tgt_argv[0], object); 8217c478bd9Sstevel@tonic-gate (void) strcpy((char *)tgt_argv[1], "vmcore."); 8227c478bd9Sstevel@tonic-gate (void) strcat((char *)tgt_argv[1], object); 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate tgt_argc = 2; 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate /* 8287c478bd9Sstevel@tonic-gate * We need to open the object file in order to determine its 8297c478bd9Sstevel@tonic-gate * ELF class and potentially re-exec ourself. 8307c478bd9Sstevel@tonic-gate */ 8317c478bd9Sstevel@tonic-gate if ((io = mdb_fdio_create_path(NULL, tgt_argv[0], 8327c478bd9Sstevel@tonic-gate O_RDONLY, 0)) == NULL) 8337c478bd9Sstevel@tonic-gate die("failed to open %s", tgt_argv[0]); 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate /* 8367c478bd9Sstevel@tonic-gate * If the target is unknown or is not the rawfile target, do 8377c478bd9Sstevel@tonic-gate * a gelf_check to determine if the file is an ELF file. If 8387c478bd9Sstevel@tonic-gate * it is not and the target is unknown, use the rawfile tgt. 8397c478bd9Sstevel@tonic-gate * Otherwise an ELF-based target is needed, so we must abort. 8407c478bd9Sstevel@tonic-gate */ 8417c478bd9Sstevel@tonic-gate if (tgt_ctor != mdb_rawfile_tgt_create && 8427c478bd9Sstevel@tonic-gate mdb_gelf_check(io, &ehdr, ET_NONE) == -1) { 8437c478bd9Sstevel@tonic-gate if (tgt_ctor != NULL) { 8447c478bd9Sstevel@tonic-gate (void) mdb_gelf_check(io, &ehdr, ET_EXEC); 8457c478bd9Sstevel@tonic-gate mdb_io_destroy(io); 8467c478bd9Sstevel@tonic-gate terminate(1); 8477c478bd9Sstevel@tonic-gate } else 8487c478bd9Sstevel@tonic-gate tgt_ctor = mdb_rawfile_tgt_create; 8497c478bd9Sstevel@tonic-gate } 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate mdb_io_destroy(io); 8527c478bd9Sstevel@tonic-gate 853a576ab5bSrab if (identify_xvm_file(tgt_argv[0], &longmode) == 1 && 854a576ab5bSrab !fflag) { 855a576ab5bSrab #ifdef _LP64 856a576ab5bSrab if (!longmode) 857a576ab5bSrab goto reexec; 858a576ab5bSrab #else 859a576ab5bSrab if (longmode) 860a576ab5bSrab goto reexec; 861a576ab5bSrab #endif 862a576ab5bSrab tgt_ctor = mdb_kvm_tgt_create; 863a576ab5bSrab goto tcreate; 864a576ab5bSrab } 865a576ab5bSrab 8667c478bd9Sstevel@tonic-gate if (tgt_ctor == mdb_rawfile_tgt_create) 8677c478bd9Sstevel@tonic-gate goto tcreate; /* skip re-exec and just create target */ 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate /* 8707c478bd9Sstevel@tonic-gate * The object file turned out to be a user core file (ET_CORE), 8717c478bd9Sstevel@tonic-gate * and no other arguments were specified, swap 0 and 1. The 8727c478bd9Sstevel@tonic-gate * proc target will infer the executable for us. 8737c478bd9Sstevel@tonic-gate */ 8747c478bd9Sstevel@tonic-gate if (ehdr.e_type == ET_CORE) { 8757c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = tgt_argv[0]; 8767c478bd9Sstevel@tonic-gate tgt_argv[0] = NULL; 8777c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create; 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate /* 8817c478bd9Sstevel@tonic-gate * If tgt_argv[1] is filled in, open it up and determine if it 8827c478bd9Sstevel@tonic-gate * is a vmcore file. If it is, gelf_check will fail and we 8837c478bd9Sstevel@tonic-gate * set tgt_ctor to 'kvm'; otherwise we use the default. 8847c478bd9Sstevel@tonic-gate */ 8857c478bd9Sstevel@tonic-gate if (tgt_argc > 1 && strcmp(tgt_argv[1], "-") != 0 && 8867c478bd9Sstevel@tonic-gate tgt_argv[0] != NULL && pidarg == NULL) { 8877c478bd9Sstevel@tonic-gate Elf32_Ehdr chdr; 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate if (access(tgt_argv[1], F_OK) == -1) 8907c478bd9Sstevel@tonic-gate die("failed to access %s", tgt_argv[1]); 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate if ((io = mdb_fdio_create_path(NULL, tgt_argv[1], 8937c478bd9Sstevel@tonic-gate O_RDONLY, 0)) == NULL) 8947c478bd9Sstevel@tonic-gate die("failed to open %s", tgt_argv[1]); 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate if (mdb_gelf_check(io, &chdr, ET_NONE) == -1) 8977c478bd9Sstevel@tonic-gate tgt_ctor = mdb_kvm_tgt_create; 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate mdb_io_destroy(io); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate /* 9037c478bd9Sstevel@tonic-gate * At this point, we've read the ELF header for either an 9047c478bd9Sstevel@tonic-gate * object file or core into ehdr. If the class does not match 9057c478bd9Sstevel@tonic-gate * ours, attempt to exec the mdb of the appropriate class. 9067c478bd9Sstevel@tonic-gate */ 9077c478bd9Sstevel@tonic-gate #ifdef _LP64 908843e1988Sjohnlev if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 909843e1988Sjohnlev goto reexec; 9107c478bd9Sstevel@tonic-gate #else 911843e1988Sjohnlev if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 912843e1988Sjohnlev goto reexec; 9137c478bd9Sstevel@tonic-gate #endif 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate tcreate: 9177c478bd9Sstevel@tonic-gate if (tgt_ctor == NULL) 9187c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create; 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate tgt = mdb_tgt_create(tgt_ctor, mdb.m_tgtflags, tgt_argc, tgt_argv); 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate if (tgt == NULL) { 9237c478bd9Sstevel@tonic-gate if (errno == EINVAL) 9247c478bd9Sstevel@tonic-gate usage(2); /* target can return EINVAL to get usage */ 9257c478bd9Sstevel@tonic-gate if (errno == EMDB_TGT) 9267c478bd9Sstevel@tonic-gate terminate(1); /* target already printed error msg */ 9277c478bd9Sstevel@tonic-gate die("failed to initialize target"); 9287c478bd9Sstevel@tonic-gate } 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate mdb_tgt_activate(tgt); 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate mdb_create_loadable_disasms(); 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate if (Vflag != NULL && mdb_dis_select(Vflag) == -1) 9357c478bd9Sstevel@tonic-gate warn("invalid disassembler mode -- %s\n", Vflag); 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate if (Rflag && mdb.m_term != NULL) 9397c478bd9Sstevel@tonic-gate warn("Using proto area %s\n", mdb.m_root); 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate /* 9427c478bd9Sstevel@tonic-gate * If the target was successfully constructed and -O was specified, 9437c478bd9Sstevel@tonic-gate * we now attempt to enter piggy-mode for debugging jurassic problems. 9447c478bd9Sstevel@tonic-gate */ 9457c478bd9Sstevel@tonic-gate if (Oflag) { 9467c478bd9Sstevel@tonic-gate pcinfo_t pci; 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate (void) strcpy(pci.pc_clname, "RT"); 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate if (priocntl(P_LWPID, P_MYID, PC_GETCID, (caddr_t)&pci) != -1) { 9517c478bd9Sstevel@tonic-gate pcparms_t pcp; 9527c478bd9Sstevel@tonic-gate rtparms_t *rtp = (rtparms_t *)pcp.pc_clparms; 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate rtp->rt_pri = 35; 9557c478bd9Sstevel@tonic-gate rtp->rt_tqsecs = 0; 9567c478bd9Sstevel@tonic-gate rtp->rt_tqnsecs = RT_TQDEF; 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate pcp.pc_cid = pci.pc_cid; 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate if (priocntl(P_LWPID, P_MYID, PC_SETPARMS, 9617c478bd9Sstevel@tonic-gate (caddr_t)&pcp) == -1) { 9627c478bd9Sstevel@tonic-gate warn("failed to set RT parameters"); 9637c478bd9Sstevel@tonic-gate Oflag = 0; 9647c478bd9Sstevel@tonic-gate } 9657c478bd9Sstevel@tonic-gate } else { 9667c478bd9Sstevel@tonic-gate warn("failed to get RT class id"); 9677c478bd9Sstevel@tonic-gate Oflag = 0; 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { 9717c478bd9Sstevel@tonic-gate warn("failed to lock address space"); 9727c478bd9Sstevel@tonic-gate Oflag = 0; 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate if (Oflag) 9767c478bd9Sstevel@tonic-gate mdb_printf("%s: oink, oink!\n", mdb.m_pname); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate /* 9807c478bd9Sstevel@tonic-gate * Path evaluation part 2: Re-evaluate the path now that the target 9817c478bd9Sstevel@tonic-gate * is ready (and thus we have access to the real platform string). 9827c478bd9Sstevel@tonic-gate * Do this before reading ~/.mdbrc to allow path modifications prior 9837c478bd9Sstevel@tonic-gate * to performing module auto-loading. 9847c478bd9Sstevel@tonic-gate */ 9857c478bd9Sstevel@tonic-gate mdb_set_ipath(mdb.m_ipathstr); 9867c478bd9Sstevel@tonic-gate mdb_set_lpath(mdb.m_lpathstr); 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate if (!Sflag && (p = getenv("HOME")) != NULL) { 9897c478bd9Sstevel@tonic-gate char rcpath[MAXPATHLEN]; 9907c478bd9Sstevel@tonic-gate mdb_io_t *rc_io; 9917c478bd9Sstevel@tonic-gate int fd; 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(rcpath, MAXPATHLEN, "%s/.mdbrc", p); 9947c478bd9Sstevel@tonic-gate fd = open64(rcpath, O_RDONLY); 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate if (fd >= 0 && (rc_io = mdb_fdio_create_named(fd, rcpath))) { 9977c478bd9Sstevel@tonic-gate mdb_iob_t *iob = mdb_iob_create(rc_io, MDB_IOB_RDONLY); 9987c478bd9Sstevel@tonic-gate mdb_iob_t *old = mdb.m_in; 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate mdb.m_in = iob; 10017c478bd9Sstevel@tonic-gate (void) mdb_run(); 10027c478bd9Sstevel@tonic-gate mdb.m_in = old; 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate if (!(mdb.m_flags & MDB_FL_NOMODS)) 10077c478bd9Sstevel@tonic-gate mdb_module_load_all(0); 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGINT, int_handler, NULL); 10107c478bd9Sstevel@tonic-gate while ((status = mdb_run()) == MDB_ERR_ABORT || 10117c478bd9Sstevel@tonic-gate status == MDB_ERR_OUTPUT) { 10127c478bd9Sstevel@tonic-gate /* 10137c478bd9Sstevel@tonic-gate * If a write failed on stdout, give up. A more informative 10147c478bd9Sstevel@tonic-gate * error message will already have been printed by mdb_run(). 10157c478bd9Sstevel@tonic-gate */ 10167c478bd9Sstevel@tonic-gate if (status == MDB_ERR_OUTPUT && 10177c478bd9Sstevel@tonic-gate mdb_iob_getflags(mdb.m_out) & MDB_IOB_ERR) { 10187c478bd9Sstevel@tonic-gate mdb_warn("write to stdout failed, exiting\n"); 10197c478bd9Sstevel@tonic-gate break; 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate continue; 10227c478bd9Sstevel@tonic-gate } 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate terminate((status == MDB_ERR_QUIT || status == 0) ? 0 : 1); 10257c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 10267c478bd9Sstevel@tonic-gate return (0); 1027843e1988Sjohnlev 1028843e1988Sjohnlev reexec: 1029843e1988Sjohnlev if ((p = strrchr(execname, '/')) == NULL) 1030843e1988Sjohnlev die("cannot determine absolute pathname\n"); 1031843e1988Sjohnlev #ifdef _LP64 1032843e1988Sjohnlev #ifdef __sparc 1033843e1988Sjohnlev (void) strcpy(p, "/../sparcv7/"); 1034843e1988Sjohnlev #else 1035843e1988Sjohnlev (void) strcpy(p, "/../i86/"); 1036843e1988Sjohnlev #endif 1037843e1988Sjohnlev #else 1038843e1988Sjohnlev #ifdef __sparc 1039843e1988Sjohnlev (void) strcpy(p, "/../sparcv9/"); 1040843e1988Sjohnlev #else 1041843e1988Sjohnlev (void) strcpy(p, "/../amd64/"); 1042843e1988Sjohnlev #endif 1043843e1988Sjohnlev #endif 1044843e1988Sjohnlev (void) strcat(p, mdb.m_pname); 1045843e1988Sjohnlev 1046843e1988Sjohnlev if (mdb.m_term != NULL) 1047843e1988Sjohnlev (void) IOP_CTL(in_io, TCSETSW, &tios); 1048843e1988Sjohnlev 1049843e1988Sjohnlev (void) putenv("_MDB_EXEC=1"); 1050843e1988Sjohnlev (void) execv(execname, argv); 1051843e1988Sjohnlev 1052843e1988Sjohnlev /* 1053843e1988Sjohnlev * If execv fails, suppress ENOEXEC. Experience shows the most common 1054843e1988Sjohnlev * reason is that the machine is booted under a 32-bit kernel, in which 1055843e1988Sjohnlev * case it is clearer to only print the message below. 1056843e1988Sjohnlev */ 1057843e1988Sjohnlev if (errno != ENOEXEC) 1058843e1988Sjohnlev warn("failed to exec %s", execname); 1059843e1988Sjohnlev #ifdef _LP64 1060843e1988Sjohnlev die("64-bit %s cannot debug 32-bit program %s\n", 1061843e1988Sjohnlev mdb.m_pname, tgt_argv[0] ? 1062843e1988Sjohnlev tgt_argv[0] : tgt_argv[1]); 1063843e1988Sjohnlev #else 1064843e1988Sjohnlev die("32-bit %s cannot debug 64-bit program %s\n", 1065843e1988Sjohnlev mdb.m_pname, tgt_argv[0] ? 1066843e1988Sjohnlev tgt_argv[0] : tgt_argv[1]); 1067843e1988Sjohnlev #endif 1068843e1988Sjohnlev 1069843e1988Sjohnlev goto tcreate; 10707c478bd9Sstevel@tonic-gate } 1071