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 /* 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 27*1320caf7SBryan Cantrill /* 28*1320caf7SBryan Cantrill * Copyright (c) 2013, Joyent, Inc. All rights reserved. 29*1320caf7SBryan Cantrill */ 30*1320caf7SBryan 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 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 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 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 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 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 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 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] " 3267c478bd9Sstevel@tonic-gate "[-R root] [-V dis-version] [object [core] | core | suffix]\n\n", 3277c478bd9Sstevel@tonic-gate mdb.m_pname); 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate mdb_iob_puts(mdb.m_err, 3307c478bd9Sstevel@tonic-gate "\t-f force raw file debugging mode\n" 3317c478bd9Sstevel@tonic-gate "\t-k force kernel debugging mode\n" 3327c478bd9Sstevel@tonic-gate "\t-m disable demand-loading of module symbols\n" 3337c478bd9Sstevel@tonic-gate "\t-o set specified debugger option (+o to unset)\n" 3347c478bd9Sstevel@tonic-gate "\t-p attach to specified process-id\n" 3357c478bd9Sstevel@tonic-gate "\t-s set symbol matching distance\n" 3367c478bd9Sstevel@tonic-gate "\t-u force user program debugging mode\n" 3377c478bd9Sstevel@tonic-gate "\t-w enable write mode\n" 3387c478bd9Sstevel@tonic-gate "\t-y send terminal initialization sequences for tty mode\n" 3397c478bd9Sstevel@tonic-gate "\t-A disable automatic loading of mdb modules\n" 3407c478bd9Sstevel@tonic-gate "\t-F enable forcible takeover mode\n" 3417c478bd9Sstevel@tonic-gate "\t-K stop operating system and enter live kernel debugger\n" 3427c478bd9Sstevel@tonic-gate "\t-M preload all module symbols\n" 3437c478bd9Sstevel@tonic-gate "\t-I set initial path for macro files\n" 3447c478bd9Sstevel@tonic-gate "\t-L set initial path for module libs\n" 3457c478bd9Sstevel@tonic-gate "\t-P set command-line prompt\n" 3467c478bd9Sstevel@tonic-gate "\t-R set root directory for pathname expansion\n" 3477c478bd9Sstevel@tonic-gate "\t-S suppress processing of ~/.mdbrc file\n" 3487c478bd9Sstevel@tonic-gate "\t-U unload live kernel debugger\n" 3497c478bd9Sstevel@tonic-gate "\t-W enable I/O-mapped memory access (kernel only)\n" 3507c478bd9Sstevel@tonic-gate "\t-V set disassembler version\n"); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate terminate(status); 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate static char * 3567c478bd9Sstevel@tonic-gate mdb_scf_console_term(void) 3577c478bd9Sstevel@tonic-gate { 3587c478bd9Sstevel@tonic-gate scf_simple_prop_t *prop; 3597c478bd9Sstevel@tonic-gate char *term = NULL; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate if ((prop = scf_simple_prop_get(NULL, 3627c478bd9Sstevel@tonic-gate "svc:/system/console-login:default", "ttymon", 3637c478bd9Sstevel@tonic-gate "terminal_type")) == NULL) 3647c478bd9Sstevel@tonic-gate return (NULL); 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate if (scf_simple_prop_type(prop) == SCF_TYPE_ASTRING && 3677c478bd9Sstevel@tonic-gate (term = scf_simple_prop_next_astring(prop)) != NULL) 3687c478bd9Sstevel@tonic-gate term = strdup(term); 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate scf_simple_prop_free(prop); 3717c478bd9Sstevel@tonic-gate return (term); 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate 374a576ab5bSrab /* 375a576ab5bSrab * Unpleasant hack: we might be debugging a hypervisor domain dump. 376a576ab5bSrab * Earlier versions use a non-ELF file. Later versions are ELF, but are 377a576ab5bSrab * /always/ ELF64, so our standard ehdr check isn't good enough. Since 378a576ab5bSrab * we don't want to know too much about the file format, we'll ask 379a576ab5bSrab * mdb_kb. 380a576ab5bSrab */ 381a576ab5bSrab #ifdef __x86 382a576ab5bSrab static int 383a576ab5bSrab identify_xvm_file(const char *file, int *longmode) 384a576ab5bSrab { 385a576ab5bSrab int (*identify)(const char *, int *); 386a576ab5bSrab 387a576ab5bSrab if (mdb_module_load("mdb_kb", MDB_MOD_GLOBAL | MDB_MOD_SILENT) != 0) 388a576ab5bSrab return (0); 389a576ab5bSrab 390a576ab5bSrab identify = (int (*)())dlsym(RTLD_NEXT, "xkb_identify"); 391a576ab5bSrab 392a576ab5bSrab if (identify == NULL) 393a576ab5bSrab return (0); 394a576ab5bSrab 395a576ab5bSrab return (identify(file, longmode)); 396a576ab5bSrab } 397a576ab5bSrab #else 398a576ab5bSrab /*ARGSUSED*/ 399a576ab5bSrab static int 400a576ab5bSrab identify_xvm_file(const char *file, int *longmode) 401a576ab5bSrab { 402a576ab5bSrab return (0); 403a576ab5bSrab } 404a576ab5bSrab #endif /* __x86 */ 405a576ab5bSrab 4067c478bd9Sstevel@tonic-gate int 4077c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char *envp[]) 4087c478bd9Sstevel@tonic-gate { 409ca3e8d88SDave Plauger extern int mdb_kvm_is_compressed_dump(mdb_io_t *); 410*1320caf7SBryan Cantrill extern int mdb_kvm_is_dump(mdb_io_t *); 4117c478bd9Sstevel@tonic-gate mdb_tgt_ctor_f *tgt_ctor = NULL; 412*1320caf7SBryan Cantrill const char **tgt_argv = alloca((argc + 2) * sizeof (char *)); 4137c478bd9Sstevel@tonic-gate int tgt_argc = 0; 4147c478bd9Sstevel@tonic-gate mdb_tgt_t *tgt; 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate char object[MAXPATHLEN], execname[MAXPATHLEN]; 4177c478bd9Sstevel@tonic-gate mdb_io_t *in_io, *out_io, *err_io, *null_io; 4187c478bd9Sstevel@tonic-gate struct termios tios; 4197c478bd9Sstevel@tonic-gate int status, c; 4207c478bd9Sstevel@tonic-gate char *p; 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate const char *Iflag = NULL, *Lflag = NULL, *Vflag = NULL, *pidarg = NULL; 423843e1988Sjohnlev int fflag = 0, Kflag = 0, Rflag = 0, Sflag = 0, Oflag = 0, Uflag = 0; 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate int ttylike; 426a576ab5bSrab int longmode = 0; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate stack_t sigstack; 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate if (realpath(getexecname(), execname) == NULL) { 4317c478bd9Sstevel@tonic-gate (void) strncpy(execname, argv[0], MAXPATHLEN); 4327c478bd9Sstevel@tonic-gate execname[MAXPATHLEN - 1] = '\0'; 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate mdb_create(execname, argv[0]); 4367c478bd9Sstevel@tonic-gate bzero(tgt_argv, argc * sizeof (char *)); 4377c478bd9Sstevel@tonic-gate argv[0] = (char *)mdb.m_pname; 4387c478bd9Sstevel@tonic-gate _mdb_self_fd = open("/proc/self/as", O_RDONLY); 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate mdb.m_env = envp; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate out_io = mdb_fdio_create(STDOUT_FILENO); 4437c478bd9Sstevel@tonic-gate mdb.m_out = mdb_iob_create(out_io, MDB_IOB_WRONLY); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate err_io = mdb_fdio_create(STDERR_FILENO); 4467c478bd9Sstevel@tonic-gate mdb.m_err = mdb_iob_create(err_io, MDB_IOB_WRONLY); 4477c478bd9Sstevel@tonic-gate mdb_iob_clrflags(mdb.m_err, MDB_IOB_AUTOWRAP); 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate null_io = mdb_nullio_create(); 4507c478bd9Sstevel@tonic-gate mdb.m_null = mdb_iob_create(null_io, MDB_IOB_WRONLY); 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate in_io = mdb_fdio_create(STDIN_FILENO); 4537c478bd9Sstevel@tonic-gate if ((mdb.m_termtype = getenv("TERM")) != NULL) { 4547c478bd9Sstevel@tonic-gate mdb.m_termtype = strdup(mdb.m_termtype); 4557c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_TERMGUESS; 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate mdb.m_term = NULL; 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate mdb_dmode(mdb_dstr2mode(getenv("MDB_DEBUG"))); 4607c478bd9Sstevel@tonic-gate mdb.m_pgid = getpgrp(); 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate if (getenv("_MDB_EXEC") != NULL) 4637c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_EXEC; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate /* 4667c478bd9Sstevel@tonic-gate * Setup an alternate signal stack. When tearing down pipelines in 4677c478bd9Sstevel@tonic-gate * terminate(), we may have to destroy the stack of the context in 4687c478bd9Sstevel@tonic-gate * which we are currently executing the signal handler. 4697c478bd9Sstevel@tonic-gate */ 4707c478bd9Sstevel@tonic-gate sigstack.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, 4717c478bd9Sstevel@tonic-gate MAP_PRIVATE | MAP_ANON, -1, 0); 4727c478bd9Sstevel@tonic-gate if (sigstack.ss_sp == MAP_FAILED) 4737c478bd9Sstevel@tonic-gate die("could not allocate signal stack"); 4747c478bd9Sstevel@tonic-gate sigstack.ss_size = SIGSTKSZ; 4757c478bd9Sstevel@tonic-gate sigstack.ss_flags = 0; 4767c478bd9Sstevel@tonic-gate if (sigaltstack(&sigstack, NULL) != 0) 4777c478bd9Sstevel@tonic-gate die("could not set signal stack"); 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGPIPE, SIG_IGN, NULL); 4807c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGQUIT, SIG_IGN, NULL); 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGILL, flt_handler, NULL); 4837c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGTRAP, flt_handler, NULL); 4847c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGIOT, flt_handler, NULL); 4857c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGEMT, flt_handler, NULL); 4867c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGFPE, flt_handler, NULL); 4877c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGBUS, flt_handler, NULL); 4887c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGSEGV, flt_handler, NULL); 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGHUP, (mdb_signal_f *)terminate, NULL); 4917c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGTERM, (mdb_signal_f *)terminate, NULL); 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate for (mdb.m_rdvers = RD_VERSION; mdb.m_rdvers > 0; mdb.m_rdvers--) { 4947c478bd9Sstevel@tonic-gate if (rd_init(mdb.m_rdvers) == RD_OK) 4957c478bd9Sstevel@tonic-gate break; 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate for (mdb.m_ctfvers = CTF_VERSION; mdb.m_ctfvers > 0; mdb.m_ctfvers--) { 4997c478bd9Sstevel@tonic-gate if (ctf_version(mdb.m_ctfvers) != -1) 5007c478bd9Sstevel@tonic-gate break; 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate if ((p = getenv("HISTSIZE")) != NULL && strisnum(p)) { 5047c478bd9Sstevel@tonic-gate mdb.m_histlen = strtoi(p); 5057c478bd9Sstevel@tonic-gate if (mdb.m_histlen < 1) 5067c478bd9Sstevel@tonic-gate mdb.m_histlen = 1; 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate while (optind < argc) { 5107c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, 5117c478bd9Sstevel@tonic-gate "fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) { 5127c478bd9Sstevel@tonic-gate switch (c) { 5137c478bd9Sstevel@tonic-gate case 'f': 514843e1988Sjohnlev fflag++; 5157c478bd9Sstevel@tonic-gate tgt_ctor = mdb_rawfile_tgt_create; 5167c478bd9Sstevel@tonic-gate break; 5177c478bd9Sstevel@tonic-gate case 'k': 5187c478bd9Sstevel@tonic-gate tgt_ctor = mdb_kvm_tgt_create; 5197c478bd9Sstevel@tonic-gate break; 5207c478bd9Sstevel@tonic-gate case 'm': 5217c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_NOLOAD; 5227c478bd9Sstevel@tonic-gate mdb.m_tgtflags &= ~MDB_TGT_F_PRELOAD; 5237c478bd9Sstevel@tonic-gate break; 5247c478bd9Sstevel@tonic-gate case 'o': 5257c478bd9Sstevel@tonic-gate if (!mdb_set_options(optarg, TRUE)) 5267c478bd9Sstevel@tonic-gate terminate(2); 5277c478bd9Sstevel@tonic-gate break; 5287c478bd9Sstevel@tonic-gate case 'p': 5297c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create; 5307c478bd9Sstevel@tonic-gate pidarg = optarg; 5317c478bd9Sstevel@tonic-gate break; 5327c478bd9Sstevel@tonic-gate case 's': 5337c478bd9Sstevel@tonic-gate if (!strisnum(optarg)) { 5347c478bd9Sstevel@tonic-gate warn("expected integer following -s\n"); 5357c478bd9Sstevel@tonic-gate terminate(2); 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate mdb.m_symdist = (size_t)(uint_t)strtoi(optarg); 5387c478bd9Sstevel@tonic-gate break; 5397c478bd9Sstevel@tonic-gate case 'u': 5407c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create; 5417c478bd9Sstevel@tonic-gate break; 5427c478bd9Sstevel@tonic-gate case 'w': 5437c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_RDWR; 5447c478bd9Sstevel@tonic-gate break; 5457c478bd9Sstevel@tonic-gate case 'y': 5467c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_USECUP; 5477c478bd9Sstevel@tonic-gate break; 5487c478bd9Sstevel@tonic-gate case 'A': 5497c478bd9Sstevel@tonic-gate (void) mdb_set_options("nomods", TRUE); 5507c478bd9Sstevel@tonic-gate break; 5517c478bd9Sstevel@tonic-gate case 'C': 5527c478bd9Sstevel@tonic-gate (void) mdb_set_options("noctf", TRUE); 5537c478bd9Sstevel@tonic-gate break; 5547c478bd9Sstevel@tonic-gate case 'D': 5557c478bd9Sstevel@tonic-gate mdb_dmode(mdb_dstr2mode(optarg)); 5567c478bd9Sstevel@tonic-gate break; 5577c478bd9Sstevel@tonic-gate case 'F': 5587c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_FORCE; 5597c478bd9Sstevel@tonic-gate break; 5607c478bd9Sstevel@tonic-gate case 'I': 5617c478bd9Sstevel@tonic-gate Iflag = optarg; 5627c478bd9Sstevel@tonic-gate break; 5637c478bd9Sstevel@tonic-gate case 'L': 5647c478bd9Sstevel@tonic-gate Lflag = optarg; 5657c478bd9Sstevel@tonic-gate break; 5667c478bd9Sstevel@tonic-gate case 'K': 5677c478bd9Sstevel@tonic-gate Kflag++; 5687c478bd9Sstevel@tonic-gate break; 5697c478bd9Sstevel@tonic-gate case 'M': 5707c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_PRELOAD; 5717c478bd9Sstevel@tonic-gate mdb.m_tgtflags &= ~MDB_TGT_F_NOLOAD; 5727c478bd9Sstevel@tonic-gate break; 5737c478bd9Sstevel@tonic-gate case 'O': 5747c478bd9Sstevel@tonic-gate Oflag++; 5757c478bd9Sstevel@tonic-gate break; 5767c478bd9Sstevel@tonic-gate case 'P': 5777c478bd9Sstevel@tonic-gate if (!mdb_set_prompt(optarg)) 5787c478bd9Sstevel@tonic-gate terminate(2); 5797c478bd9Sstevel@tonic-gate break; 5807c478bd9Sstevel@tonic-gate case 'R': 5817c478bd9Sstevel@tonic-gate (void) strncpy(mdb.m_root, optarg, MAXPATHLEN); 5827c478bd9Sstevel@tonic-gate mdb.m_root[MAXPATHLEN - 1] = '\0'; 5837c478bd9Sstevel@tonic-gate Rflag++; 5847c478bd9Sstevel@tonic-gate break; 5857c478bd9Sstevel@tonic-gate case 'S': 5867c478bd9Sstevel@tonic-gate Sflag++; 5877c478bd9Sstevel@tonic-gate break; 5887c478bd9Sstevel@tonic-gate case 'U': 5897c478bd9Sstevel@tonic-gate Uflag++; 5907c478bd9Sstevel@tonic-gate break; 5917c478bd9Sstevel@tonic-gate case 'V': 5927c478bd9Sstevel@tonic-gate Vflag = optarg; 5937c478bd9Sstevel@tonic-gate break; 5947c478bd9Sstevel@tonic-gate case 'W': 5957c478bd9Sstevel@tonic-gate mdb.m_tgtflags |= MDB_TGT_F_ALLOWIO; 5967c478bd9Sstevel@tonic-gate break; 5977c478bd9Sstevel@tonic-gate case '?': 5987c478bd9Sstevel@tonic-gate if (optopt == '?') 5997c478bd9Sstevel@tonic-gate usage(0); 6007c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 6017c478bd9Sstevel@tonic-gate default: 6027c478bd9Sstevel@tonic-gate usage(2); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate if (optind < argc) { 6077c478bd9Sstevel@tonic-gate const char *arg = argv[optind++]; 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate if (arg[0] == '+' && strlen(arg) == 2) { 6107c478bd9Sstevel@tonic-gate if (arg[1] != 'o') { 6117c478bd9Sstevel@tonic-gate warn("illegal option -- %s\n", arg); 6127c478bd9Sstevel@tonic-gate terminate(2); 6137c478bd9Sstevel@tonic-gate } 6147c478bd9Sstevel@tonic-gate if (optind >= argc) { 6157c478bd9Sstevel@tonic-gate warn("option requires an argument -- " 6167c478bd9Sstevel@tonic-gate "%s\n", arg); 6177c478bd9Sstevel@tonic-gate terminate(2); 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate if (!mdb_set_options(argv[optind++], FALSE)) 6207c478bd9Sstevel@tonic-gate terminate(2); 6217c478bd9Sstevel@tonic-gate } else 6227c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = arg; 6237c478bd9Sstevel@tonic-gate } 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate 6269acbbeafSnn if (rd_ctl(RD_CTL_SET_HELPPATH, (void *)mdb.m_root) != RD_OK) { 6279acbbeafSnn warn("cannot set librtld_db helper path to %s\n", mdb.m_root); 6289acbbeafSnn terminate(2); 6299acbbeafSnn } 6309acbbeafSnn 6317c478bd9Sstevel@tonic-gate if (mdb.m_debug & MDB_DBG_HELP) 6327c478bd9Sstevel@tonic-gate terminate(0); /* Quit here if we've printed out the tokens */ 6337c478bd9Sstevel@tonic-gate 6349acbbeafSnn 6357c478bd9Sstevel@tonic-gate if (Iflag != NULL && strchr(Iflag, ';') != NULL) { 6367c478bd9Sstevel@tonic-gate warn("macro path cannot contain semicolons\n"); 6377c478bd9Sstevel@tonic-gate terminate(2); 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate if (Lflag != NULL && strchr(Lflag, ';') != NULL) { 6417c478bd9Sstevel@tonic-gate warn("module path cannot contain semicolons\n"); 6427c478bd9Sstevel@tonic-gate terminate(2); 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate if (Kflag || Uflag) { 6467c478bd9Sstevel@tonic-gate char *nm; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate if (tgt_ctor != NULL || Iflag != NULL) { 6497c478bd9Sstevel@tonic-gate warn("neither -f, -k, -p, -u, nor -I " 6507c478bd9Sstevel@tonic-gate "may be used with -K\n"); 6517c478bd9Sstevel@tonic-gate usage(2); 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate if (Lflag != NULL) 6557c478bd9Sstevel@tonic-gate mdb_set_lpath(Lflag); 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate if ((nm = ttyname(STDIN_FILENO)) == NULL || 6587c478bd9Sstevel@tonic-gate strcmp(nm, "/dev/console") != 0) { 6597c478bd9Sstevel@tonic-gate /* 6607c478bd9Sstevel@tonic-gate * Due to the consequences of typing mdb -K instead of 6617c478bd9Sstevel@tonic-gate * mdb -k on a tty other than /dev/console, we require 6627c478bd9Sstevel@tonic-gate * -F when starting kmdb from a tty other than 6637c478bd9Sstevel@tonic-gate * /dev/console. 6647c478bd9Sstevel@tonic-gate */ 6657c478bd9Sstevel@tonic-gate if (!(mdb.m_tgtflags & MDB_TGT_F_FORCE)) { 6667c478bd9Sstevel@tonic-gate die("-F must also be supplied to start kmdb " 6677c478bd9Sstevel@tonic-gate "from non-console tty\n"); 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate if (mdb.m_termtype == NULL || (mdb.m_flags & 6717c478bd9Sstevel@tonic-gate MDB_FL_TERMGUESS)) { 6727c478bd9Sstevel@tonic-gate if (mdb.m_termtype != NULL) 6737c478bd9Sstevel@tonic-gate strfree(mdb.m_termtype); 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate if ((mdb.m_termtype = mdb_scf_console_term()) != 6767c478bd9Sstevel@tonic-gate NULL) 6777c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_TERMGUESS; 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate } else { 6807c478bd9Sstevel@tonic-gate /* 6817c478bd9Sstevel@tonic-gate * When on console, $TERM (if set) takes precedence over 6827c478bd9Sstevel@tonic-gate * the SMF setting. 6837c478bd9Sstevel@tonic-gate */ 6847c478bd9Sstevel@tonic-gate if (mdb.m_termtype == NULL && (mdb.m_termtype = 6857c478bd9Sstevel@tonic-gate mdb_scf_console_term()) != NULL) 6867c478bd9Sstevel@tonic-gate mdb.m_flags |= MDB_FL_TERMGUESS; 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate control_kmdb(Kflag); 6907c478bd9Sstevel@tonic-gate terminate(0); 6917c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate /* 6957c478bd9Sstevel@tonic-gate * If standard input appears to have tty attributes, attempt to 6967c478bd9Sstevel@tonic-gate * initialize a terminal i/o backend on top of stdin and stdout. 6977c478bd9Sstevel@tonic-gate */ 6987c478bd9Sstevel@tonic-gate ttylike = (IOP_CTL(in_io, TCGETS, &tios) == 0); 6997c478bd9Sstevel@tonic-gate if (ttylike) { 7007c478bd9Sstevel@tonic-gate if ((mdb.m_term = mdb_termio_create(mdb.m_termtype, 7017c478bd9Sstevel@tonic-gate in_io, out_io)) == NULL) { 7027c478bd9Sstevel@tonic-gate if (!(mdb.m_flags & MDB_FL_EXEC)) { 7037c478bd9Sstevel@tonic-gate warn("term init failed: command-line editing " 7047c478bd9Sstevel@tonic-gate "and prompt will not be available\n"); 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate } else { 7077c478bd9Sstevel@tonic-gate in_io = mdb.m_term; 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate mdb.m_in = mdb_iob_create(in_io, MDB_IOB_RDONLY); 7127c478bd9Sstevel@tonic-gate if (mdb.m_term != NULL) { 7137c478bd9Sstevel@tonic-gate mdb_iob_setpager(mdb.m_out, mdb.m_term); 7147c478bd9Sstevel@tonic-gate if (mdb.m_flags & MDB_FL_PAGER) 7157c478bd9Sstevel@tonic-gate mdb_iob_setflags(mdb.m_out, MDB_IOB_PGENABLE); 7167c478bd9Sstevel@tonic-gate else 7177c478bd9Sstevel@tonic-gate mdb_iob_clrflags(mdb.m_out, MDB_IOB_PGENABLE); 7187c478bd9Sstevel@tonic-gate } else if (ttylike) 7197c478bd9Sstevel@tonic-gate mdb_iob_setflags(mdb.m_in, MDB_IOB_TTYLIKE); 7207c478bd9Sstevel@tonic-gate else 7217c478bd9Sstevel@tonic-gate mdb_iob_setbuf(mdb.m_in, mdb_alloc(1, UM_SLEEP), 1); 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate mdb_pservice_init(); 7247c478bd9Sstevel@tonic-gate mdb_lex_reset(); 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate if ((mdb.m_shell = getenv("SHELL")) == NULL) 7277c478bd9Sstevel@tonic-gate mdb.m_shell = "/bin/sh"; 7287c478bd9Sstevel@tonic-gate 729a576ab5bSrab /* 730a576ab5bSrab * If the debugger state is to be inherited from a previous instance, 731a576ab5bSrab * restore it now prior to path evaluation so that %R is updated. 732a576ab5bSrab */ 733a576ab5bSrab if ((p = getenv(MDB_CONFIG_ENV_VAR)) != NULL) { 734a576ab5bSrab mdb_set_config(p); 735a576ab5bSrab (void) unsetenv(MDB_CONFIG_ENV_VAR); 736a576ab5bSrab } 737a576ab5bSrab 738a576ab5bSrab /* 739a576ab5bSrab * Path evaluation part 1: Create the initial module path to allow 740a576ab5bSrab * the target constructor to load a support module. Then expand 741a576ab5bSrab * any command-line arguments that modify the paths. 742a576ab5bSrab */ 743a576ab5bSrab if (Iflag != NULL) 744a576ab5bSrab mdb_set_ipath(Iflag); 745a576ab5bSrab else 746a576ab5bSrab mdb_set_ipath(MDB_DEF_IPATH); 747a576ab5bSrab 748a576ab5bSrab if (Lflag != NULL) 749a576ab5bSrab mdb_set_lpath(Lflag); 750a576ab5bSrab else 751a576ab5bSrab mdb_set_lpath(MDB_DEF_LPATH); 752a576ab5bSrab 753a576ab5bSrab if (mdb_get_prompt() == NULL && !(mdb.m_flags & MDB_FL_ADB)) 754a576ab5bSrab (void) mdb_set_prompt(MDB_DEF_PROMPT); 755a576ab5bSrab 7567c478bd9Sstevel@tonic-gate if (tgt_ctor == mdb_kvm_tgt_create) { 7577c478bd9Sstevel@tonic-gate if (pidarg != NULL) { 7587c478bd9Sstevel@tonic-gate warn("-p and -k options are mutually exclusive\n"); 7597c478bd9Sstevel@tonic-gate terminate(2); 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate if (tgt_argc == 0) 7637c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = "/dev/ksyms"; 7647c478bd9Sstevel@tonic-gate if (tgt_argc == 1 && strisnum(tgt_argv[0]) == 0) { 7657c478bd9Sstevel@tonic-gate if (mdb.m_tgtflags & MDB_TGT_F_ALLOWIO) 7667c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = "/dev/allkmem"; 7677c478bd9Sstevel@tonic-gate else 7687c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = "/dev/kmem"; 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate if (pidarg != NULL) { 7737c478bd9Sstevel@tonic-gate if (tgt_argc != 0) { 7747c478bd9Sstevel@tonic-gate warn("-p may not be used with other arguments\n"); 7757c478bd9Sstevel@tonic-gate terminate(2); 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate if (proc_arg_psinfo(pidarg, PR_ARG_PIDS, NULL, &status) == -1) { 7787c478bd9Sstevel@tonic-gate die("cannot attach to %s: %s\n", 7797c478bd9Sstevel@tonic-gate pidarg, Pgrab_error(status)); 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate if (strchr(pidarg, '/') != NULL) 7827c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(object, MAXPATHLEN, 7837c478bd9Sstevel@tonic-gate "%s/object/a.out", pidarg); 7847c478bd9Sstevel@tonic-gate else 7857c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(object, MAXPATHLEN, 7867c478bd9Sstevel@tonic-gate "/proc/%s/object/a.out", pidarg); 7877c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = object; 7887c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = pidarg; 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate /* 7927c478bd9Sstevel@tonic-gate * Find the first argument that is not a special "-" token. If one is 7937c478bd9Sstevel@tonic-gate * found, we will examine this file and make some inferences below. 7947c478bd9Sstevel@tonic-gate */ 7957c478bd9Sstevel@tonic-gate for (c = 0; c < tgt_argc && strcmp(tgt_argv[c], "-") == 0; c++) 7967c478bd9Sstevel@tonic-gate continue; 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate if (c < tgt_argc) { 7997c478bd9Sstevel@tonic-gate Elf32_Ehdr ehdr; 8007c478bd9Sstevel@tonic-gate mdb_io_t *io; 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate /* 8037c478bd9Sstevel@tonic-gate * If special "-" tokens preceded an argument, shift the entire 8047c478bd9Sstevel@tonic-gate * argument list to the left to remove the leading "-" args. 8057c478bd9Sstevel@tonic-gate */ 8067c478bd9Sstevel@tonic-gate if (c > 0) { 8077c478bd9Sstevel@tonic-gate bcopy(&tgt_argv[c], tgt_argv, 8087c478bd9Sstevel@tonic-gate sizeof (const char *) * (tgt_argc - c)); 8097c478bd9Sstevel@tonic-gate tgt_argc -= c; 8107c478bd9Sstevel@tonic-gate } 8117c478bd9Sstevel@tonic-gate 812ffd958e4SJosef 'Jeff' Sipek if (fflag) 813ffd958e4SJosef 'Jeff' Sipek goto tcreate; /* skip re-exec and just create target */ 814ffd958e4SJosef 'Jeff' Sipek 8157c478bd9Sstevel@tonic-gate /* 8167c478bd9Sstevel@tonic-gate * If we just have an object file name, and that file doesn't 8177c478bd9Sstevel@tonic-gate * exist, and it's a string of digits, infer it to be a 8187c478bd9Sstevel@tonic-gate * sequence number referring to a pair of crash dump files. 8197c478bd9Sstevel@tonic-gate */ 8207c478bd9Sstevel@tonic-gate if (tgt_argc == 1 && access(tgt_argv[0], F_OK) == -1 && 8217c478bd9Sstevel@tonic-gate strisnum(tgt_argv[0])) { 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate size_t len = strlen(tgt_argv[0]) + 8; 8247c478bd9Sstevel@tonic-gate const char *object = tgt_argv[0]; 8257c478bd9Sstevel@tonic-gate 826*1320caf7SBryan Cantrill tgt_argv[0] = alloca(len); 827*1320caf7SBryan Cantrill tgt_argv[1] = alloca(len); 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate (void) strcpy((char *)tgt_argv[0], "unix."); 8307c478bd9Sstevel@tonic-gate (void) strcat((char *)tgt_argv[0], object); 8317c478bd9Sstevel@tonic-gate (void) strcpy((char *)tgt_argv[1], "vmcore."); 8327c478bd9Sstevel@tonic-gate (void) strcat((char *)tgt_argv[1], object); 8337c478bd9Sstevel@tonic-gate 834ca3e8d88SDave Plauger if (access(tgt_argv[0], F_OK) == -1 && 835*1320caf7SBryan Cantrill access(tgt_argv[1], F_OK) != -1) { 836*1320caf7SBryan Cantrill /* 837*1320caf7SBryan Cantrill * If we have a vmcore but not a unix file, 838*1320caf7SBryan Cantrill * set the symbol table to be the vmcore to 839*1320caf7SBryan Cantrill * force libkvm to extract it out of the dump. 840*1320caf7SBryan Cantrill */ 841*1320caf7SBryan Cantrill tgt_argv[0] = tgt_argv[1]; 842*1320caf7SBryan Cantrill } else if (access(tgt_argv[0], F_OK) == -1 && 843ca3e8d88SDave Plauger access(tgt_argv[1], F_OK) == -1) { 844ca3e8d88SDave Plauger (void) strcpy((char *)tgt_argv[1], "vmdump."); 845ca3e8d88SDave Plauger (void) strcat((char *)tgt_argv[1], object); 846ca3e8d88SDave Plauger if (access(tgt_argv[1], F_OK) == 0) { 847ca3e8d88SDave Plauger mdb_iob_printf(mdb.m_err, 848ca3e8d88SDave Plauger "cannot open compressed dump; " 849ca3e8d88SDave Plauger "decompress using savecore -f %s\n", 850ca3e8d88SDave Plauger tgt_argv[1]); 851ca3e8d88SDave Plauger terminate(0); 852ca3e8d88SDave Plauger } 853ca3e8d88SDave Plauger } 854ca3e8d88SDave Plauger 8557c478bd9Sstevel@tonic-gate tgt_argc = 2; 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate /* 8597c478bd9Sstevel@tonic-gate * We need to open the object file in order to determine its 8607c478bd9Sstevel@tonic-gate * ELF class and potentially re-exec ourself. 8617c478bd9Sstevel@tonic-gate */ 8627c478bd9Sstevel@tonic-gate if ((io = mdb_fdio_create_path(NULL, tgt_argv[0], 8637c478bd9Sstevel@tonic-gate O_RDONLY, 0)) == NULL) 8647c478bd9Sstevel@tonic-gate die("failed to open %s", tgt_argv[0]); 8657c478bd9Sstevel@tonic-gate 866ca3e8d88SDave Plauger if (tgt_argc == 1) { 867ca3e8d88SDave Plauger if (mdb_kvm_is_compressed_dump(io)) { 868*1320caf7SBryan Cantrill /* 869*1320caf7SBryan Cantrill * We have a single vmdump.N compressed dump 870*1320caf7SBryan Cantrill * file; give a helpful message. 871*1320caf7SBryan Cantrill */ 872ca3e8d88SDave Plauger mdb_iob_printf(mdb.m_err, 873ca3e8d88SDave Plauger "cannot open compressed dump; " 874ca3e8d88SDave Plauger "decompress using savecore -f %s\n", 875ca3e8d88SDave Plauger tgt_argv[0]); 876ca3e8d88SDave Plauger terminate(0); 877*1320caf7SBryan Cantrill } else if (mdb_kvm_is_dump(io)) { 878*1320caf7SBryan Cantrill /* 879*1320caf7SBryan Cantrill * We have an uncompressed dump as our only 880*1320caf7SBryan Cantrill * argument; specify the dump as the symbol 881*1320caf7SBryan Cantrill * table to force libkvm to dig it out of the 882*1320caf7SBryan Cantrill * dump. 883*1320caf7SBryan Cantrill */ 884*1320caf7SBryan Cantrill tgt_argv[tgt_argc++] = tgt_argv[0]; 885ca3e8d88SDave Plauger } 886ca3e8d88SDave Plauger } 887ca3e8d88SDave Plauger 8887c478bd9Sstevel@tonic-gate /* 8897c478bd9Sstevel@tonic-gate * If the target is unknown or is not the rawfile target, do 8907c478bd9Sstevel@tonic-gate * a gelf_check to determine if the file is an ELF file. If 8917c478bd9Sstevel@tonic-gate * it is not and the target is unknown, use the rawfile tgt. 8927c478bd9Sstevel@tonic-gate * Otherwise an ELF-based target is needed, so we must abort. 8937c478bd9Sstevel@tonic-gate */ 894ffd958e4SJosef 'Jeff' Sipek if (mdb_gelf_check(io, &ehdr, ET_NONE) == -1) { 8957c478bd9Sstevel@tonic-gate if (tgt_ctor != NULL) { 8967c478bd9Sstevel@tonic-gate (void) mdb_gelf_check(io, &ehdr, ET_EXEC); 8977c478bd9Sstevel@tonic-gate mdb_io_destroy(io); 8987c478bd9Sstevel@tonic-gate terminate(1); 8997c478bd9Sstevel@tonic-gate } else 9007c478bd9Sstevel@tonic-gate tgt_ctor = mdb_rawfile_tgt_create; 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate mdb_io_destroy(io); 9047c478bd9Sstevel@tonic-gate 905ffd958e4SJosef 'Jeff' Sipek if (identify_xvm_file(tgt_argv[0], &longmode) == 1) { 906a576ab5bSrab #ifdef _LP64 907a576ab5bSrab if (!longmode) 908a576ab5bSrab goto reexec; 909a576ab5bSrab #else 910a576ab5bSrab if (longmode) 911a576ab5bSrab goto reexec; 912a576ab5bSrab #endif 913a576ab5bSrab tgt_ctor = mdb_kvm_tgt_create; 914a576ab5bSrab goto tcreate; 915a576ab5bSrab } 916a576ab5bSrab 9177c478bd9Sstevel@tonic-gate /* 9187c478bd9Sstevel@tonic-gate * The object file turned out to be a user core file (ET_CORE), 9197c478bd9Sstevel@tonic-gate * and no other arguments were specified, swap 0 and 1. The 9207c478bd9Sstevel@tonic-gate * proc target will infer the executable for us. 9217c478bd9Sstevel@tonic-gate */ 9227c478bd9Sstevel@tonic-gate if (ehdr.e_type == ET_CORE) { 9237c478bd9Sstevel@tonic-gate tgt_argv[tgt_argc++] = tgt_argv[0]; 9247c478bd9Sstevel@tonic-gate tgt_argv[0] = NULL; 9257c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create; 9267c478bd9Sstevel@tonic-gate } 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate /* 9297c478bd9Sstevel@tonic-gate * If tgt_argv[1] is filled in, open it up and determine if it 9307c478bd9Sstevel@tonic-gate * is a vmcore file. If it is, gelf_check will fail and we 9317c478bd9Sstevel@tonic-gate * set tgt_ctor to 'kvm'; otherwise we use the default. 9327c478bd9Sstevel@tonic-gate */ 9337c478bd9Sstevel@tonic-gate if (tgt_argc > 1 && strcmp(tgt_argv[1], "-") != 0 && 9347c478bd9Sstevel@tonic-gate tgt_argv[0] != NULL && pidarg == NULL) { 9357c478bd9Sstevel@tonic-gate Elf32_Ehdr chdr; 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate if (access(tgt_argv[1], F_OK) == -1) 9387c478bd9Sstevel@tonic-gate die("failed to access %s", tgt_argv[1]); 9397c478bd9Sstevel@tonic-gate 940ca3e8d88SDave Plauger /* *.N case: drop vmdump.N from the list */ 941ca3e8d88SDave Plauger if (tgt_argc == 3) { 942ca3e8d88SDave Plauger if ((io = mdb_fdio_create_path(NULL, 943ca3e8d88SDave Plauger tgt_argv[2], O_RDONLY, 0)) == NULL) 944ca3e8d88SDave Plauger die("failed to open %s", tgt_argv[2]); 945ca3e8d88SDave Plauger if (mdb_kvm_is_compressed_dump(io)) 946ca3e8d88SDave Plauger tgt_argv[--tgt_argc] = NULL; 947ca3e8d88SDave Plauger mdb_io_destroy(io); 948ca3e8d88SDave Plauger } 949ca3e8d88SDave Plauger 9507c478bd9Sstevel@tonic-gate if ((io = mdb_fdio_create_path(NULL, tgt_argv[1], 9517c478bd9Sstevel@tonic-gate O_RDONLY, 0)) == NULL) 9527c478bd9Sstevel@tonic-gate die("failed to open %s", tgt_argv[1]); 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate if (mdb_gelf_check(io, &chdr, ET_NONE) == -1) 9557c478bd9Sstevel@tonic-gate tgt_ctor = mdb_kvm_tgt_create; 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate mdb_io_destroy(io); 9587c478bd9Sstevel@tonic-gate } 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate /* 9617c478bd9Sstevel@tonic-gate * At this point, we've read the ELF header for either an 9627c478bd9Sstevel@tonic-gate * object file or core into ehdr. If the class does not match 9637c478bd9Sstevel@tonic-gate * ours, attempt to exec the mdb of the appropriate class. 9647c478bd9Sstevel@tonic-gate */ 9657c478bd9Sstevel@tonic-gate #ifdef _LP64 966843e1988Sjohnlev if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 967843e1988Sjohnlev goto reexec; 9687c478bd9Sstevel@tonic-gate #else 969843e1988Sjohnlev if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 970843e1988Sjohnlev goto reexec; 9717c478bd9Sstevel@tonic-gate #endif 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate tcreate: 9757c478bd9Sstevel@tonic-gate if (tgt_ctor == NULL) 9767c478bd9Sstevel@tonic-gate tgt_ctor = mdb_proc_tgt_create; 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate tgt = mdb_tgt_create(tgt_ctor, mdb.m_tgtflags, tgt_argc, tgt_argv); 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate if (tgt == NULL) { 9817c478bd9Sstevel@tonic-gate if (errno == EINVAL) 9827c478bd9Sstevel@tonic-gate usage(2); /* target can return EINVAL to get usage */ 9837c478bd9Sstevel@tonic-gate if (errno == EMDB_TGT) 9847c478bd9Sstevel@tonic-gate terminate(1); /* target already printed error msg */ 9857c478bd9Sstevel@tonic-gate die("failed to initialize target"); 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate mdb_tgt_activate(tgt); 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate mdb_create_loadable_disasms(); 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate if (Vflag != NULL && mdb_dis_select(Vflag) == -1) 9937c478bd9Sstevel@tonic-gate warn("invalid disassembler mode -- %s\n", Vflag); 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate if (Rflag && mdb.m_term != NULL) 9977c478bd9Sstevel@tonic-gate warn("Using proto area %s\n", mdb.m_root); 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate /* 10007c478bd9Sstevel@tonic-gate * If the target was successfully constructed and -O was specified, 10017c478bd9Sstevel@tonic-gate * we now attempt to enter piggy-mode for debugging jurassic problems. 10027c478bd9Sstevel@tonic-gate */ 10037c478bd9Sstevel@tonic-gate if (Oflag) { 10047c478bd9Sstevel@tonic-gate pcinfo_t pci; 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate (void) strcpy(pci.pc_clname, "RT"); 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate if (priocntl(P_LWPID, P_MYID, PC_GETCID, (caddr_t)&pci) != -1) { 10097c478bd9Sstevel@tonic-gate pcparms_t pcp; 10107c478bd9Sstevel@tonic-gate rtparms_t *rtp = (rtparms_t *)pcp.pc_clparms; 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate rtp->rt_pri = 35; 10137c478bd9Sstevel@tonic-gate rtp->rt_tqsecs = 0; 10147c478bd9Sstevel@tonic-gate rtp->rt_tqnsecs = RT_TQDEF; 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate pcp.pc_cid = pci.pc_cid; 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate if (priocntl(P_LWPID, P_MYID, PC_SETPARMS, 10197c478bd9Sstevel@tonic-gate (caddr_t)&pcp) == -1) { 10207c478bd9Sstevel@tonic-gate warn("failed to set RT parameters"); 10217c478bd9Sstevel@tonic-gate Oflag = 0; 10227c478bd9Sstevel@tonic-gate } 10237c478bd9Sstevel@tonic-gate } else { 10247c478bd9Sstevel@tonic-gate warn("failed to get RT class id"); 10257c478bd9Sstevel@tonic-gate Oflag = 0; 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { 10297c478bd9Sstevel@tonic-gate warn("failed to lock address space"); 10307c478bd9Sstevel@tonic-gate Oflag = 0; 10317c478bd9Sstevel@tonic-gate } 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate if (Oflag) 10347c478bd9Sstevel@tonic-gate mdb_printf("%s: oink, oink!\n", mdb.m_pname); 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate /* 10387c478bd9Sstevel@tonic-gate * Path evaluation part 2: Re-evaluate the path now that the target 10397c478bd9Sstevel@tonic-gate * is ready (and thus we have access to the real platform string). 10407c478bd9Sstevel@tonic-gate * Do this before reading ~/.mdbrc to allow path modifications prior 10417c478bd9Sstevel@tonic-gate * to performing module auto-loading. 10427c478bd9Sstevel@tonic-gate */ 10437c478bd9Sstevel@tonic-gate mdb_set_ipath(mdb.m_ipathstr); 10447c478bd9Sstevel@tonic-gate mdb_set_lpath(mdb.m_lpathstr); 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate if (!Sflag && (p = getenv("HOME")) != NULL) { 10477c478bd9Sstevel@tonic-gate char rcpath[MAXPATHLEN]; 10487c478bd9Sstevel@tonic-gate mdb_io_t *rc_io; 10497c478bd9Sstevel@tonic-gate int fd; 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(rcpath, MAXPATHLEN, "%s/.mdbrc", p); 10527c478bd9Sstevel@tonic-gate fd = open64(rcpath, O_RDONLY); 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate if (fd >= 0 && (rc_io = mdb_fdio_create_named(fd, rcpath))) { 10557c478bd9Sstevel@tonic-gate mdb_iob_t *iob = mdb_iob_create(rc_io, MDB_IOB_RDONLY); 10567c478bd9Sstevel@tonic-gate mdb_iob_t *old = mdb.m_in; 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate mdb.m_in = iob; 10597c478bd9Sstevel@tonic-gate (void) mdb_run(); 10607c478bd9Sstevel@tonic-gate mdb.m_in = old; 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate if (!(mdb.m_flags & MDB_FL_NOMODS)) 10657c478bd9Sstevel@tonic-gate mdb_module_load_all(0); 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate (void) mdb_signal_sethandler(SIGINT, int_handler, NULL); 10687c478bd9Sstevel@tonic-gate while ((status = mdb_run()) == MDB_ERR_ABORT || 10697c478bd9Sstevel@tonic-gate status == MDB_ERR_OUTPUT) { 10707c478bd9Sstevel@tonic-gate /* 10717c478bd9Sstevel@tonic-gate * If a write failed on stdout, give up. A more informative 10727c478bd9Sstevel@tonic-gate * error message will already have been printed by mdb_run(). 10737c478bd9Sstevel@tonic-gate */ 10747c478bd9Sstevel@tonic-gate if (status == MDB_ERR_OUTPUT && 10757c478bd9Sstevel@tonic-gate mdb_iob_getflags(mdb.m_out) & MDB_IOB_ERR) { 10767c478bd9Sstevel@tonic-gate mdb_warn("write to stdout failed, exiting\n"); 10777c478bd9Sstevel@tonic-gate break; 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate continue; 10807c478bd9Sstevel@tonic-gate } 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate terminate((status == MDB_ERR_QUIT || status == 0) ? 0 : 1); 10837c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 10847c478bd9Sstevel@tonic-gate return (0); 1085843e1988Sjohnlev 1086843e1988Sjohnlev reexec: 1087843e1988Sjohnlev if ((p = strrchr(execname, '/')) == NULL) 1088843e1988Sjohnlev die("cannot determine absolute pathname\n"); 1089843e1988Sjohnlev #ifdef _LP64 1090843e1988Sjohnlev #ifdef __sparc 1091843e1988Sjohnlev (void) strcpy(p, "/../sparcv7/"); 1092843e1988Sjohnlev #else 1093843e1988Sjohnlev (void) strcpy(p, "/../i86/"); 1094843e1988Sjohnlev #endif 1095843e1988Sjohnlev #else 1096843e1988Sjohnlev #ifdef __sparc 1097843e1988Sjohnlev (void) strcpy(p, "/../sparcv9/"); 1098843e1988Sjohnlev #else 1099843e1988Sjohnlev (void) strcpy(p, "/../amd64/"); 1100843e1988Sjohnlev #endif 1101843e1988Sjohnlev #endif 1102843e1988Sjohnlev (void) strcat(p, mdb.m_pname); 1103843e1988Sjohnlev 1104843e1988Sjohnlev if (mdb.m_term != NULL) 1105843e1988Sjohnlev (void) IOP_CTL(in_io, TCSETSW, &tios); 1106843e1988Sjohnlev 1107843e1988Sjohnlev (void) putenv("_MDB_EXEC=1"); 1108843e1988Sjohnlev (void) execv(execname, argv); 1109843e1988Sjohnlev 1110843e1988Sjohnlev /* 1111843e1988Sjohnlev * If execv fails, suppress ENOEXEC. Experience shows the most common 1112843e1988Sjohnlev * reason is that the machine is booted under a 32-bit kernel, in which 1113843e1988Sjohnlev * case it is clearer to only print the message below. 1114843e1988Sjohnlev */ 1115843e1988Sjohnlev if (errno != ENOEXEC) 1116843e1988Sjohnlev warn("failed to exec %s", execname); 1117843e1988Sjohnlev #ifdef _LP64 1118843e1988Sjohnlev die("64-bit %s cannot debug 32-bit program %s\n", 1119843e1988Sjohnlev mdb.m_pname, tgt_argv[0] ? 1120843e1988Sjohnlev tgt_argv[0] : tgt_argv[1]); 1121843e1988Sjohnlev #else 1122843e1988Sjohnlev die("32-bit %s cannot debug 64-bit program %s\n", 1123843e1988Sjohnlev mdb.m_pname, tgt_argv[0] ? 1124843e1988Sjohnlev tgt_argv[0] : tgt_argv[1]); 1125843e1988Sjohnlev #endif 1126843e1988Sjohnlev 1127843e1988Sjohnlev goto tcreate; 11287c478bd9Sstevel@tonic-gate } 1129