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