xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_err.c (revision 64e4e50ab4bc3670a29e5691e3dd935c94f0a5d7)
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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <mdb/mdb_signal.h>
28 #include <mdb/mdb_err.h>
29 #include <mdb/mdb.h>
30 
31 #include <thread_db.h>
32 #include <rtld_db.h>
33 #include <libctf.h>
34 #include <strings.h>
35 #include <stdlib.h>
36 
37 static const char *const _mdb_errlist[] = {
38 	"unknown symbol name",				/* EMDB_NOSYM */
39 	"unknown object file name",			/* EMDB_NOOBJ */
40 	"no mapping for address",			/* EMDB_NOMAP */
41 	"unknown dcmd name",				/* EMDB_NODCMD */
42 	"unknown walk name",				/* EMDB_NOWALK */
43 	"dcmd name already in use",			/* EMDB_DCMDEXISTS */
44 	"walk name already in use",			/* EMDB_WALKEXISTS */
45 	"no support for platform",			/* EMDB_NOPLAT */
46 	"no process active",				/* EMDB_NOPROC */
47 	"specified name is too long",			/* EMDB_NAME2BIG */
48 	"specified name contains illegal characters",	/* EMDB_NAMEBAD */
49 	"failed to allocate needed memory",		/* EMDB_ALLOC */
50 	"specified module is not loaded",		/* EMDB_NOMOD */
51 	"cannot unload built-in module",		/* EMDB_BUILTINMOD */
52 	"no walk is currently active",			/* EMDB_NOWCB */
53 	"invalid walk state argument",			/* EMDB_BADWCB */
54 	"walker does not accept starting address",	/* EMDB_NOWALKLOC */
55 	"walker requires starting address",		/* EMDB_NOWALKGLOB */
56 	"failed to initialize walk",			/* EMDB_WALKINIT */
57 	"walker cannot be layered on itself",		/* EMDB_WALKLOOP */
58 	"i/o stream is read-only",			/* EMDB_IORO */
59 	"i/o stream is write-only",			/* EMDB_IOWO */
60 	"no symbol corresponds to address",		/* EMDB_NOSYMADDR */
61 	"unknown disassembler name",			/* EMDB_NODIS */
62 	"disassembler name already in use",		/* EMDB_DISEXISTS */
63 	"no such software event specifier",		/* EMDB_NOSESPEC */
64 	"no such xdata available",			/* EMDB_NOXD */
65 	"xdata name already in use",			/* EMDB_XDEXISTS */
66 	"operation not supported by target",		/* EMDB_TGTNOTSUP */
67 	"target is not open for writing",		/* EMDB_TGTRDONLY */
68 	"invalid register name",			/* EMDB_BADREG */
69 	"no register set available for thread",		/* EMDB_NOREGS */
70 	"stack address is not properly aligned",	/* EMDB_STKALIGN */
71 	"no executable file is open",			/* EMDB_NOEXEC */
72 	"failed to evaluate command",			/* EMDB_EVAL */
73 	"command cancelled by user",			/* EMDB_CANCEL */
74 	"only %lu of %lu bytes could be read",		/* EMDB_PARTIAL */
75 	"dcmd failed",					/* EMDB_DCFAIL */
76 	"improper dcmd usage",				/* EMDB_DCUSAGE */
77 	"target error",					/* EMDB_TGT */
78 	"invalid system call number",			/* EMDB_BADSYSNUM */
79 	"invalid signal number",			/* EMDB_BADSIGNUM */
80 	"invalid fault number",				/* EMDB_BADFLTNUM */
81 	"target is currently executing",		/* EMDB_TGTBUSY */
82 	"target has completed execution",		/* EMDB_TGTZOMB */
83 	"target is a core file",			/* EMDB_TGTCORE */
84 	"debugger lost control of target",		/* EMDB_TGTLOST */
85 	"libthread_db call failed unexpectedly",	/* EMDB_TDB */
86 	"failed to dlopen library",			/* EMDB_RTLD */
87 	"librtld_db call failed unexpectedly",		/* EMDB_RTLD_DB */
88 	"runtime linker data not available",		/* EMDB_NORTLD */
89 	"invalid thread identifier",			/* EMDB_NOTHREAD */
90 	"event specifier disabled",			/* EMDB_SPECDIS */
91 	"unknown link map id",				/* EMDB_NOLMID */
92 	"failed to determine return address",		/* EMDB_NORETADDR */
93 	"watchpoint size exceeds address space limit",	/* EMDB_WPRANGE */
94 	"conflict with existing watchpoint",		/* EMDB_WPDUP */
95 	"address not aligned on an instruction boundary", /* EMDB_BPALIGN */
96 	"library is missing demangler entry point",	/* EMDB_NODEM */
97 	"cannot read past current end of file",		/* EMDB_EOF */
98 	"no symbolic debug information available for module", /* EMDB_NOCTF */
99 	"libctf call failed unexpectedly",		/* EMDB_CTF */
100 	"thread local storage has not yet been allocated", /* EMDB_TLS */
101 	"object does not support thread local storage",	/* EMDB_NOTLS */
102 	"no such member of structure or union",		/* EMDB_CTFNOMEMB */
103 	"inappropriate context for action",		/* EMDB_CTX */
104 	"module incompatible with target",		/* EMDB_INCOMPAT */
105 	"operation not supported by target on this platform",
106 							/* EMDB_TGTHWNOTSUP */
107 	"kmdb is not loaded",				/* EMDB_KINACTIVE */
108 	"kmdb is loading",				/* EMDB_KACTIVATING */
109 	"kmdb is already loaded",			/* EMDB_KACTIVE */
110 	"kmdb is unloading",				/* EMDB_KDEACTIVATING */
111 	"kmdb could not be loaded",			/* EMDB_KNOLOAD */
112 	"boot-loaded kmdb cannot be unloaded",		/* EMDB_KNOUNLOAD */
113 	"too many enabled watchpoints for this machine", /* EMDB_WPTOOMANY */
114 	"DTrace is active",				/* EMDB_DTACTIVE */
115 	"boot-loaded module cannot be unloaded",	/* EMDB_KMODNOUNLOAD */
116 	"stack frame pointer is invalid",		/* EMDB_STKFRAME */
117 	"unexpected short write"			/* EMDB_SHORTWRITE */
118 
119 };
120 
121 static const int _mdb_nerr = sizeof (_mdb_errlist) / sizeof (_mdb_errlist[0]);
122 
123 static size_t errno_rbytes;	/* EMDB_PARTIAL actual bytes read */
124 static size_t errno_nbytes;	/* EMDB_PARTIAL total bytes requested */
125 static int errno_libctf;	/* EMDB_CTF underlying error code */
126 #ifndef _KMDB
127 static int errno_rtld_db;	/* EMDB_RTLD_DB underlying error code */
128 #endif
129 
130 const char *
mdb_strerror(int err)131 mdb_strerror(int err)
132 {
133 	static char buf[256];
134 	const char *str;
135 
136 	if (err >= EMDB_BASE && (err - EMDB_BASE) < _mdb_nerr)
137 		str = _mdb_errlist[err - EMDB_BASE];
138 	else
139 		str = strerror(err);
140 
141 	switch (err) {
142 	case EMDB_PARTIAL:
143 		(void) mdb_iob_snprintf(buf, sizeof (buf), str,
144 		    errno_rbytes, errno_nbytes);
145 		str = buf;
146 		break;
147 
148 #ifndef _KMDB
149 	case EMDB_RTLD_DB:
150 		if (rd_errstr(errno_rtld_db) != NULL)
151 			str = rd_errstr(errno_rtld_db);
152 		break;
153 #endif
154 
155 	case EMDB_CTF:
156 		if (ctf_errmsg(errno_libctf) != NULL)
157 			str = ctf_errmsg(errno_libctf);
158 		break;
159 	}
160 
161 	return (str ? str : "unknown error");
162 }
163 
164 void
vwarn(const char * format,va_list alist)165 vwarn(const char *format, va_list alist)
166 {
167 	int err = errno;
168 
169 	mdb_iob_printf(mdb.m_err, "%s: ", mdb.m_pname);
170 	mdb_iob_vprintf(mdb.m_err, format, alist);
171 
172 	if (strchr(format, '\n') == NULL)
173 		mdb_iob_printf(mdb.m_err, ": %s\n", mdb_strerror(err));
174 }
175 
176 void
vdie(const char * format,va_list alist)177 vdie(const char *format, va_list alist)
178 {
179 	vwarn(format, alist);
180 	mdb_destroy();
181 	exit(1);
182 }
183 
184 void
vfail(const char * format,va_list alist)185 vfail(const char *format, va_list alist)
186 {
187 	extern const char *volatile _mdb_abort_str;
188 	static char buf[256];
189 	static int nfail;
190 
191 	if (_mdb_abort_str == NULL) {
192 		_mdb_abort_str = buf; /* Do this first so we don't recurse */
193 		(void) mdb_iob_vsnprintf(buf, sizeof (buf), format, alist);
194 
195 		nfail = 1;
196 	}
197 
198 	/*
199 	 * We'll try to print failure messages twice.  Any more than that,
200 	 * and we're probably hitting an assertion or some other problem in
201 	 * the printing routines, and will recurse until we run out of stack.
202 	 */
203 	if (nfail++ < 3) {
204 		mdb_iob_printf(mdb.m_err, "%s ABORT: ", mdb.m_pname);
205 		mdb_iob_vprintf(mdb.m_err, format, alist);
206 		mdb_iob_flush(mdb.m_err);
207 
208 		(void) mdb_signal_blockall();
209 		(void) mdb_signal_raise(SIGABRT);
210 		(void) mdb_signal_unblock(SIGABRT);
211 	}
212 
213 	exit(1);
214 }
215 
216 /*PRINTFLIKE1*/
217 void
warn(const char * format,...)218 warn(const char *format, ...)
219 {
220 	va_list alist;
221 
222 	va_start(alist, format);
223 	vwarn(format, alist);
224 	va_end(alist);
225 }
226 
227 /*PRINTFLIKE1*/
228 void
die(const char * format,...)229 die(const char *format, ...)
230 {
231 	va_list alist;
232 
233 	va_start(alist, format);
234 	vdie(format, alist);
235 	va_end(alist);
236 }
237 
238 /*PRINTFLIKE1*/
239 void
fail(const char * format,...)240 fail(const char *format, ...)
241 {
242 	va_list alist;
243 
244 	va_start(alist, format);
245 	vfail(format, alist);
246 	va_end(alist);
247 }
248 
249 int
set_errbytes(size_t rbytes,size_t nbytes)250 set_errbytes(size_t rbytes, size_t nbytes)
251 {
252 	errno_rbytes = rbytes;
253 	errno_nbytes = nbytes;
254 	errno = EMDB_PARTIAL;
255 	return (-1);
256 }
257 
258 int
set_errno(int err)259 set_errno(int err)
260 {
261 	errno = err;
262 	return (-1);
263 }
264 
265 int
ctf_to_errno(int err)266 ctf_to_errno(int err)
267 {
268 	errno_libctf = err;
269 	return (EMDB_CTF);
270 }
271 
272 #ifndef _KMDB
273 /*
274  * The libthread_db interface is a superfund site and provides no strerror
275  * equivalent for us to call: we try to provide some sensible handling for its
276  * garbage bin of error return codes here.  First of all, we don't bother
277  * interpreting all of the possibilities, since many of them aren't even used
278  * in the implementation anymore.  We try to map thread_db errors we may see
279  * to UNIX errnos or mdb errnos as appropriate.
280  */
281 int
tdb_to_errno(int err)282 tdb_to_errno(int err)
283 {
284 	switch (err) {
285 	case TD_OK:
286 	case TD_PARTIALREG:
287 		return (0);
288 	case TD_NOCAPAB:
289 		return (ENOTSUP);
290 	case TD_BADPH:
291 	case TD_BADTH:
292 	case TD_BADSH:
293 	case TD_BADTA:
294 	case TD_BADKEY:
295 	case TD_NOEVENT:
296 		return (EINVAL);
297 	case TD_NOFPREGS:
298 	case TD_NOXREGS:
299 		return (EMDB_NOREGS);
300 	case TD_NOTHR:
301 		return (EMDB_NOTHREAD);
302 	case TD_MALLOC:
303 		return (EMDB_ALLOC);
304 	case TD_TLSDEFER:
305 		return (EMDB_TLS);
306 	case TD_NOTLS:
307 		return (EMDB_NOTLS);
308 	case TD_DBERR:
309 	case TD_ERR:
310 	default:
311 		return (EMDB_TDB);
312 	}
313 }
314 
315 int
rdb_to_errno(int err)316 rdb_to_errno(int err)
317 {
318 	errno_rtld_db = err;
319 	return (EMDB_RTLD_DB);
320 }
321 #endif /* _KMDB */
322