mdb_debug.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <mdb/mdb_debug.h>
#include <mdb/mdb_err.h>
#include <mdb/mdb_io.h>
#include <mdb/mdb_lex.h>
#include <mdb/mdb.h>
#include <libproc.h>
#include <libctf.h>
#include <rtld_db.h>
#include <strings.h>
#include <stdarg.h>
typedef struct dbg_mode {
const char *m_name;
const char *m_desc;
uint_t m_bits;
} dbg_mode_t;
static const dbg_mode_t dbg_modetab[] = {
{ "cmdbuf", "debug command editing buffer", MDB_DBG_CMDBUF },
#ifdef YYDEBUG
{ "parser", "debug parser internals", MDB_DBG_PARSER },
#endif
{ "help", "display this listing", MDB_DBG_HELP },
{ "module", "debug module processing", MDB_DBG_MODULE },
{ "dcmd", "debug dcmd processing", MDB_DBG_DCMD },
{ "elf", "debug ELF file processing", MDB_DBG_ELF },
{ "mach", "debug machine-dependent code", MDB_DBG_MACH },
{ "shell", "debug shell escapes", MDB_DBG_SHELL },
{ "kmod", "debug kernel module processing", MDB_DBG_KMOD },
{ "walk", "debug walk callback processing", MDB_DBG_WALK },
{ "umem", "debug memory management", MDB_DBG_UMEM },
{ "dstk", "debug execution stack", MDB_DBG_DSTK },
{ "tgt", "debug target backends", MDB_DBG_TGT },
{ "psvc", "debug proc_service clients", MDB_DBG_PSVC },
{ "proc", "debug libproc internals", MDB_DBG_PROC },
{ "ctf", "debug libctf internals", MDB_DBG_CTF },
{ "dpi", "debugger/PROM interface (kmdb only)", MDB_DBG_DPI },
{ "kdi", "kernel/debugger interface (kmdb only)", MDB_DBG_KDI },
{ "callb", "debug callback invocations", MDB_DBG_CALLB },
{ "all", "set all debug modes", (uint_t)~MDB_DBG_HELP },
{ "none", "unset all debug modes", 0 },
{ NULL, 0 }
};
static const char dbg_prefix[] = "mdb DEBUG: ";
/*PRINTFLIKE2*/
void
mdb_dprintf(uint_t mode, const char *format, ...)
{
if ((mdb.m_debug & mode) == mode && mdb.m_err != NULL) {
va_list alist;
mdb_iob_puts(mdb.m_err, dbg_prefix);
va_start(alist, format);
mdb_iob_vprintf(mdb.m_err, format, alist);
va_end(alist);
}
}
void
mdb_dvprintf(uint_t mode, const char *format, va_list alist)
{
if ((mdb.m_debug & mode) == mode && format != NULL && *format != '\0' &&
mdb.m_err != NULL) {
mdb_iob_puts(mdb.m_err, dbg_prefix);
mdb_iob_vprintf(mdb.m_err, format, alist);
if (format[strlen(format) - 1] != '\n')
mdb_iob_nl(mdb.m_err);
}
}
uint_t
mdb_dstr2mode(const char *s)
{
const dbg_mode_t *mp;
const char *name;
char dstr[256];
uint_t bits = 0;
if (s == NULL)
return (0);
(void) strncpy(dstr, s, sizeof (dstr));
dstr[sizeof (dstr) - 1] = '\0';
for (name = strtok(dstr, ","); name; name = strtok(NULL, ",")) {
for (mp = dbg_modetab; mp->m_name != NULL; mp++) {
if (strcmp(name, mp->m_name) == 0) {
if (mp->m_bits != 0)
bits |= mp->m_bits;
else
bits = 0;
break;
}
}
if (mp->m_name == NULL)
warn("unknown debug option \"%s\"\n", name);
}
if (bits & MDB_DBG_HELP) {
warn("Debugging tokens:\n");
for (mp = dbg_modetab; mp->m_name != NULL; mp++)
warn("\t%s: %s\n", mp->m_name, mp->m_desc);
}
return (bits);
}
void
mdb_dmode(uint_t bits)
{
int *libproc_debugp, *libctf_debugp;
void (*rd_logp)(const int);
if ((libproc_debugp = dlsym(RTLD_SELF, "_libproc_debug")) != NULL)
*libproc_debugp = (bits & MDB_DBG_PROC) != 0;
if ((libctf_debugp = dlsym(RTLD_SELF, "_libctf_debug")) != NULL)
*libctf_debugp = (bits & MDB_DBG_CTF) != 0;
if ((rd_logp = (void (*)())dlsym(RTLD_SELF, "rd_log")) != NULL)
rd_logp((bits & MDB_DBG_PSVC) != 0);
mdb_lex_debug(bits & MDB_DBG_PARSER);
mdb.m_debug = bits;
}
#ifdef DEBUG
int
mdb_dassert(const char *expr, const char *file, int line)
{
fail("\"%s\", line %d: assertion failed: %s\n", file, line, expr);
/*NOTREACHED*/
return (0);
}
#endif
/*
* Function to convert mdb longjmp codes (see <mdb/mdb.h>) into a string for
* debugging routines.
*/
const char *
mdb_err2str(int err)
{
static const char *const errtab[] = {
"0", "PARSE", "NOMEM", "PAGER", "SIGINT",
"QUIT", "ASSERT", "API", "ABORT", "OUTPUT"
};
static char buf[32];
if (err >= 0 && err < sizeof (errtab) / sizeof (errtab[0]))
return (errtab[err]);
(void) mdb_iob_snprintf(buf, sizeof (buf), "ERR#%d", err);
return (buf);
}