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