void vfail(const char *format, va_list alist) { extern const char *volatile _mdb_abort_str; static char buf[256]; static int nfail; if (_mdb_abort_str == NULL) { _mdb_abort_str = buf; /* Do this first so we don't recurse */ (void) mdb_iob_vsnprintf(buf, sizeof (buf), format, alist); nfail = 1; } /* * We'll try to print failure messages twice. Any more than that, * and we're probably hitting an assertion or some other problem in * the printing routines, and will recurse until we run out of stack. */ if (nfail++ < 3) { mdb_iob_printf(mdb.m_err, "%s ABORT: ", mdb.m_pname); mdb_iob_vprintf(mdb.m_err, format, alist); mdb_iob_flush(mdb.m_err); (void) mdb_signal_blockall(); (void) mdb_signal_raise(SIGABRT); (void) mdb_signal_unblock(SIGABRT); } exit(1); }
/*ARGSUSED*/ static void flt_handler(int sig, siginfo_t *sip, ucontext_t *ucp, void *data) { static const struct rlimit rl = { (rlim_t)RLIM_INFINITY, (rlim_t)RLIM_INFINITY }; const mdb_idcmd_t *idcp = NULL; if (mdb.m_frame != NULL && mdb.m_frame->f_cp != NULL) idcp = mdb.m_frame->f_cp->c_dcmd; if (sip != NULL) bcopy(sip, &_mdb_abort_info, sizeof (_mdb_abort_info)); if (ucp != NULL) bcopy(ucp, &_mdb_abort_ctx, sizeof (_mdb_abort_ctx)); _mdb_abort_info.si_signo = sig; (void) mdb_signal_sethandler(sig, SIG_DFL, NULL); /* * If there is no current dcmd, or the current dcmd comes from a * builtin module, we don't allow resume and always core dump. */ if (idcp == NULL || idcp->idc_modp == NULL || idcp->idc_modp == &mdb.m_rmod || idcp->idc_modp->mod_hdl == NULL) goto dump; if (mdb.m_term != NULL) { struct frame *fr = (struct frame *) (ucp->uc_mcontext.gregs[STACK_REGISTER] + STACK_BIAS); char signame[SIG2STR_MAX]; int i = 1; char c; if (sig2str(sig, signame) == -1) { mdb_iob_printf(mdb.m_err, "\n*** %s: received signal %d at:\n", mdb.m_pname, sig); } else { mdb_iob_printf(mdb.m_err, "\n*** %s: received signal %s at:\n", mdb.m_pname, signame); } if (ucp->uc_mcontext.gregs[REG_PC] != 0) print_frame(ucp->uc_mcontext.gregs[REG_PC], i++); while (fr != NULL && valid_frame(fr) && fr->fr_savpc != 0) { print_frame(fr->fr_savpc, i++); fr = (struct frame *) ((uintptr_t)fr->fr_savfp + STACK_BIAS); } query: mdb_iob_printf(mdb.m_err, "\n%s: (c)ore dump, (q)uit, " "(r)ecover, or (s)top for debugger [cqrs]? ", mdb.m_pname); mdb_iob_flush(mdb.m_err); for (;;) { if (IOP_READ(mdb.m_term, &c, sizeof (c)) != sizeof (c)) goto dump; switch (c) { case 'c': case 'C': (void) setrlimit(RLIMIT_CORE, &rl); mdb_iob_printf(mdb.m_err, "\n%s: attempting " "to dump core ...\n", mdb.m_pname); goto dump; case 'q': case 'Q': mdb_iob_discard(mdb.m_out); mdb_iob_nl(mdb.m_err); (void) mdb_signal_unblockall(); terminate(1); /*NOTREACHED*/ case 'r': case 'R': mdb_iob_printf(mdb.m_err, "\n%s: unloading " "module '%s' ...\n", mdb.m_pname, idcp->idc_modp->mod_name); (void) mdb_module_unload( idcp->idc_modp->mod_name, 0); (void) mdb_signal_sethandler(sig, flt_handler, NULL); _mdb_abort_rcount++; mdb.m_intr = 0; mdb.m_pend = 0; (void) mdb_signal_unblockall(); longjmp(mdb.m_frame->f_pcb, MDB_ERR_ABORT); /*NOTREACHED*/ case 's': case 'S': mdb_iob_printf(mdb.m_err, "\n%s: " "attempting to stop pid %d ...\n", mdb.m_pname, (int)getpid()); /* * Stop ourself; if this fails or we are * subsequently continued, ask again. */ (void) mdb_signal_raise(SIGSTOP); (void) mdb_signal_unblockall(); goto query; } } } dump: if (SI_FROMUSER(sip)) { (void) mdb_signal_block(sig); (void) mdb_signal_raise(sig); } (void) sigfillset(&ucp->uc_sigmask); (void) sigdelset(&ucp->uc_sigmask, sig); if (_mdb_abort_str == NULL) _mdb_abort_str = "fatal signal received"; ucp->uc_flags |= UC_SIGMASK; (void) setcontext(ucp); }