xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_debug.c (revision defc4c8acfa01dba1ef3c13ca0cafccfcede51c0)
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