1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <mdb/mdb_debug.h> 30 #include <mdb/mdb_err.h> 31 #include <mdb/mdb_io.h> 32 #include <mdb/mdb_lex.h> 33 #include <mdb/mdb.h> 34 35 #include <libproc.h> 36 #include <libctf.h> 37 #include <rtld_db.h> 38 #include <strings.h> 39 #include <stdarg.h> 40 41 typedef struct dbg_mode { 42 const char *m_name; 43 const char *m_desc; 44 uint_t m_bits; 45 } dbg_mode_t; 46 47 static const dbg_mode_t dbg_modetab[] = { 48 { "cmdbuf", "debug command editing buffer", MDB_DBG_CMDBUF }, 49 #ifdef YYDEBUG 50 { "parser", "debug parser internals", MDB_DBG_PARSER }, 51 #endif 52 { "help", "display this listing", MDB_DBG_HELP }, 53 { "module", "debug module processing", MDB_DBG_MODULE }, 54 { "dcmd", "debug dcmd processing", MDB_DBG_DCMD }, 55 { "elf", "debug ELF file processing", MDB_DBG_ELF }, 56 { "mach", "debug machine-dependent code", MDB_DBG_MACH }, 57 { "shell", "debug shell escapes", MDB_DBG_SHELL }, 58 { "kmod", "debug kernel module processing", MDB_DBG_KMOD }, 59 { "walk", "debug walk callback processing", MDB_DBG_WALK }, 60 { "umem", "debug memory management", MDB_DBG_UMEM }, 61 { "dstk", "debug execution stack", MDB_DBG_DSTK }, 62 { "tgt", "debug target backends", MDB_DBG_TGT }, 63 { "psvc", "debug proc_service clients", MDB_DBG_PSVC }, 64 { "proc", "debug libproc internals", MDB_DBG_PROC }, 65 { "ctf", "debug libctf internals", MDB_DBG_CTF }, 66 { "dpi", "debugger/PROM interface (kmdb only)", MDB_DBG_DPI }, 67 { "kdi", "kernel/debugger interface (kmdb only)", MDB_DBG_KDI }, 68 { "callb", "debug callback invocations", MDB_DBG_CALLB }, 69 { "all", "set all debug modes", (uint_t)~MDB_DBG_HELP }, 70 { "none", "unset all debug modes", 0 }, 71 { NULL, 0 } 72 }; 73 74 static const char dbg_prefix[] = "mdb DEBUG: "; 75 76 /*PRINTFLIKE2*/ 77 void 78 mdb_dprintf(uint_t mode, const char *format, ...) 79 { 80 if ((mdb.m_debug & mode) == mode && mdb.m_err != NULL) { 81 va_list alist; 82 83 mdb_iob_puts(mdb.m_err, dbg_prefix); 84 va_start(alist, format); 85 mdb_iob_vprintf(mdb.m_err, format, alist); 86 va_end(alist); 87 } 88 } 89 90 void 91 mdb_dvprintf(uint_t mode, const char *format, va_list alist) 92 { 93 if ((mdb.m_debug & mode) == mode && format != NULL && *format != '\0' && 94 mdb.m_err != NULL) { 95 mdb_iob_puts(mdb.m_err, dbg_prefix); 96 mdb_iob_vprintf(mdb.m_err, format, alist); 97 if (format[strlen(format) - 1] != '\n') 98 mdb_iob_nl(mdb.m_err); 99 } 100 } 101 102 uint_t 103 mdb_dstr2mode(const char *s) 104 { 105 const dbg_mode_t *mp; 106 const char *name; 107 char dstr[256]; 108 109 uint_t bits = 0; 110 111 if (s == NULL) 112 return (0); 113 114 (void) strncpy(dstr, s, sizeof (dstr)); 115 dstr[sizeof (dstr) - 1] = '\0'; 116 117 for (name = strtok(dstr, ","); name; name = strtok(NULL, ",")) { 118 for (mp = dbg_modetab; mp->m_name != NULL; mp++) { 119 if (strcmp(name, mp->m_name) == 0) { 120 if (mp->m_bits != 0) 121 bits |= mp->m_bits; 122 else 123 bits = 0; 124 break; 125 } 126 } 127 128 if (mp->m_name == NULL) 129 warn("unknown debug option \"%s\"\n", name); 130 } 131 132 if (bits & MDB_DBG_HELP) { 133 warn("Debugging tokens:\n"); 134 for (mp = dbg_modetab; mp->m_name != NULL; mp++) 135 warn("\t%s: %s\n", mp->m_name, mp->m_desc); 136 } 137 138 return (bits); 139 } 140 141 void 142 mdb_dmode(uint_t bits) 143 { 144 int *libproc_debugp, *libctf_debugp; 145 void (*rd_logp)(const int); 146 147 if ((libproc_debugp = dlsym(RTLD_SELF, "_libproc_debug")) != NULL) 148 *libproc_debugp = (bits & MDB_DBG_PROC) != 0; 149 150 if ((libctf_debugp = dlsym(RTLD_SELF, "_libctf_debug")) != NULL) 151 *libctf_debugp = (bits & MDB_DBG_CTF) != 0; 152 153 if ((rd_logp = (void (*)())dlsym(RTLD_SELF, "rd_log")) != NULL) 154 rd_logp((bits & MDB_DBG_PSVC) != 0); 155 156 mdb_lex_debug(bits & MDB_DBG_PARSER); 157 mdb.m_debug = bits; 158 } 159 160 #ifdef DEBUG 161 int 162 mdb_dassert(const char *expr, const char *file, int line) 163 { 164 fail("\"%s\", line %d: assertion failed: %s\n", file, line, expr); 165 /*NOTREACHED*/ 166 return (0); 167 } 168 #endif 169 170 /* 171 * Function to convert mdb longjmp codes (see <mdb/mdb.h>) into a string for 172 * debugging routines. 173 */ 174 const char * 175 mdb_err2str(int err) 176 { 177 static const char *const errtab[] = { 178 "0", "PARSE", "NOMEM", "PAGER", "SIGINT", 179 "QUIT", "ASSERT", "API", "ABORT", "OUTPUT" 180 }; 181 182 static char buf[32]; 183 184 if (err >= 0 && err < sizeof (errtab) / sizeof (errtab[0])) 185 return (errtab[err]); 186 187 (void) mdb_iob_snprintf(buf, sizeof (buf), "ERR#%d", err); 188 return (buf); 189 } 190