1a864dc36Sdarran /*
2a864dc36Sdarran  * CDDL HEADER START
3a864dc36Sdarran  *
4a864dc36Sdarran  * The contents of this file are subject to the terms of the
5a864dc36Sdarran  * Common Development and Distribution License (the "License").
6a864dc36Sdarran  * You may not use this file except in compliance with the License.
7a864dc36Sdarran  *
8a864dc36Sdarran  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9a864dc36Sdarran  * or http://www.opensolaris.org/os/licensing.
10a864dc36Sdarran  * See the License for the specific language governing permissions
11a864dc36Sdarran  * and limitations under the License.
12a864dc36Sdarran  *
13a864dc36Sdarran  * When distributing Covered Code, include this CDDL HEADER in each
14a864dc36Sdarran  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15a864dc36Sdarran  * If applicable, add the following below this CDDL HEADER, with the
16a864dc36Sdarran  * fields enclosed by brackets "[]" replaced with your own identifying
17a864dc36Sdarran  * information: Portions Copyright [yyyy] [name of copyright owner]
18a864dc36Sdarran  *
19a864dc36Sdarran  * CDDL HEADER END
20a864dc36Sdarran  */
21*920211a7Schristos 
22a864dc36Sdarran /*
23a252d550Shaad  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24a864dc36Sdarran  * Use is subject to license terms.
25a864dc36Sdarran  */
26a864dc36Sdarran 
27*920211a7Schristos /*
28*920211a7Schristos  * Copyright (c) 2012 by Delphix. All rights reserved.
29*920211a7Schristos  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
30*920211a7Schristos  */
31*920211a7Schristos 
32*920211a7Schristos #include <string.h>
33a864dc36Sdarran #include <strings.h>
34a864dc36Sdarran #include <dt_impl.h>
35a864dc36Sdarran 
36a864dc36Sdarran static const struct {
37a864dc36Sdarran 	int err;
38a864dc36Sdarran 	const char *msg;
39a864dc36Sdarran } _dt_errlist[] = {
40a864dc36Sdarran 	{ EDT_VERSION,	"Client requested version newer than library" },
41a864dc36Sdarran 	{ EDT_VERSINVAL, "Version is not properly formatted or is too large" },
42a864dc36Sdarran 	{ EDT_VERSUNDEF, "Requested version is not supported by compiler" },
43a864dc36Sdarran 	{ EDT_VERSREDUCED, "Requested version conflicts with earlier setting" },
44a864dc36Sdarran 	{ EDT_CTF,	"Unexpected libctf error" },
45a864dc36Sdarran 	{ EDT_COMPILER, "Error in D program compilation" },
46a864dc36Sdarran 	{ EDT_NOTUPREG,	"Insufficient tuple registers to generate code" },
47a864dc36Sdarran 	{ EDT_NOMEM,	"Memory allocation failure" },
48a864dc36Sdarran 	{ EDT_INT2BIG,	"Integer constant table limit exceeded" },
49a864dc36Sdarran 	{ EDT_STR2BIG,	"String constant table limit exceeded" },
50a864dc36Sdarran 	{ EDT_NOMOD,	"Unknown module name" },
51a864dc36Sdarran 	{ EDT_NOPROV,	"Unknown provider name" },
52a864dc36Sdarran 	{ EDT_NOPROBE,	"No probe matches description" },
53a864dc36Sdarran 	{ EDT_NOSYM,	"Unknown symbol name" },
54a864dc36Sdarran 	{ EDT_NOSYMADDR, "No symbol corresponds to address" },
55a864dc36Sdarran 	{ EDT_NOTYPE,	"Unknown type name" },
56a864dc36Sdarran 	{ EDT_NOVAR,	"Unknown variable name" },
57a864dc36Sdarran 	{ EDT_NOAGG,	"Unknown aggregation name" },
58a864dc36Sdarran 	{ EDT_BADSCOPE,	"Improper use of scoping operator in type name" },
59a864dc36Sdarran 	{ EDT_BADSPEC,	"Overspecified probe description" },
60a864dc36Sdarran 	{ EDT_BADSPCV,	"Undefined macro variable in probe description" },
61a864dc36Sdarran 	{ EDT_BADID,	"Unknown probe identifier" },
62a864dc36Sdarran 	{ EDT_NOTLOADED, "Module is no longer loaded" },
63a864dc36Sdarran 	{ EDT_NOCTF,	"Module does not contain any CTF data" },
64a864dc36Sdarran 	{ EDT_DATAMODEL, "Module and program data models do not match" },
65a864dc36Sdarran 	{ EDT_DIFVERS,	"Library uses newer DIF version than kernel" },
66a864dc36Sdarran 	{ EDT_BADAGG,	"Unknown aggregating action" },
67a864dc36Sdarran 	{ EDT_FIO,	"Error occurred while reading from input stream" },
68a864dc36Sdarran 	{ EDT_DIFINVAL,	"DIF program content is invalid" },
69a864dc36Sdarran 	{ EDT_DIFSIZE,	"DIF program exceeds maximum program size" },
70a864dc36Sdarran 	{ EDT_DIFFAULT,	"DIF program contains invalid pointer" },
71a864dc36Sdarran 	{ EDT_BADPROBE,	"Invalid probe specification" },
72a864dc36Sdarran 	{ EDT_BADPGLOB, "Probe description has too many globbing characters" },
73a864dc36Sdarran 	{ EDT_NOSCOPE,	"Declaration scope stack underflow" },
74a864dc36Sdarran 	{ EDT_NODECL,	"Declaration stack underflow" },
75a864dc36Sdarran 	{ EDT_DMISMATCH, "Data record list does not match statement" },
76a864dc36Sdarran 	{ EDT_DOFFSET,	"Data record offset exceeds buffer boundary" },
77a864dc36Sdarran 	{ EDT_DALIGN,	"Data record has inappropriate alignment" },
78a864dc36Sdarran 	{ EDT_BADOPTNAME, "Invalid option name" },
79a864dc36Sdarran 	{ EDT_BADOPTVAL, "Invalid value for specified option" },
80a864dc36Sdarran 	{ EDT_BADOPTCTX, "Option cannot be used from within a D program" },
81a864dc36Sdarran 	{ EDT_CPPFORK,	"Failed to fork preprocessor" },
82a864dc36Sdarran 	{ EDT_CPPEXEC,	"Failed to exec preprocessor" },
83a864dc36Sdarran 	{ EDT_CPPENT,	"Preprocessor not found" },
84a864dc36Sdarran 	{ EDT_CPPERR,	"Preprocessor failed to process input program" },
85a864dc36Sdarran 	{ EDT_SYMOFLOW,	"Symbol table identifier space exhausted" },
86a864dc36Sdarran 	{ EDT_ACTIVE,	"Operation illegal when tracing is active" },
87a864dc36Sdarran 	{ EDT_DESTRUCTIVE, "Destructive actions not allowed" },
88a864dc36Sdarran 	{ EDT_NOANON,	"No anonymous tracing state" },
89a864dc36Sdarran 	{ EDT_ISANON,	"Can't claim anonymous state and enable probes" },
90a864dc36Sdarran 	{ EDT_ENDTOOBIG, "END enablings exceed size of principal buffer" },
91a864dc36Sdarran 	{ EDT_NOCONV,	"Failed to load type for printf conversion" },
92a864dc36Sdarran 	{ EDT_BADCONV,	"Incomplete printf conversion" },
93a864dc36Sdarran 	{ EDT_BADERROR,	"Invalid library ERROR action" },
94a864dc36Sdarran 	{ EDT_ERRABORT,	"Abort due to error" },
95a864dc36Sdarran 	{ EDT_DROPABORT, "Abort due to drop" },
96a864dc36Sdarran 	{ EDT_DIRABORT,	"Abort explicitly directed" },
97a864dc36Sdarran 	{ EDT_BADRVAL,	"Invalid return value from callback" },
98a864dc36Sdarran 	{ EDT_BADNORMAL, "Invalid normalization" },
99a864dc36Sdarran 	{ EDT_BUFTOOSMALL, "Enabling exceeds size of buffer" },
100a864dc36Sdarran 	{ EDT_BADTRUNC, "Invalid truncation" },
101a864dc36Sdarran 	{ EDT_BUSY, "DTrace cannot be used when kernel debugger is active" },
102a864dc36Sdarran 	{ EDT_ACCESS, "DTrace requires additional privileges" },
103a864dc36Sdarran 	{ EDT_NOENT, "DTrace device not available on system" },
104a864dc36Sdarran 	{ EDT_BRICKED, "Abort due to systemic unresponsiveness" },
105a864dc36Sdarran 	{ EDT_HARDWIRE, "Failed to load language definitions" },
106a864dc36Sdarran 	{ EDT_ELFVERSION, "libelf is out-of-date with respect to libdtrace" },
107a864dc36Sdarran 	{ EDT_NOBUFFERED, "Attempt to buffer output without handler" },
108a864dc36Sdarran 	{ EDT_UNSTABLE, "Description matched an unstable set of probes" },
109a864dc36Sdarran 	{ EDT_BADSETOPT, "Invalid setopt() library action" },
110a864dc36Sdarran 	{ EDT_BADSTACKPC, "Invalid stack program counter size" },
111a864dc36Sdarran 	{ EDT_BADAGGVAR, "Invalid aggregation variable identifier" },
112a252d550Shaad 	{ EDT_OVERSION,	"Client requested deprecated version of library" },
113*920211a7Schristos 	{ EDT_ENABLING_ERR, "Failed to enable probe" },
114*920211a7Schristos 	{ EDT_NOPROBES, "No probe sites found for declared provider" },
115*920211a7Schristos 	{ EDT_CANTLOAD, "Failed to load module" },
116a864dc36Sdarran };
117a864dc36Sdarran 
118a864dc36Sdarran static const int _dt_nerr = sizeof (_dt_errlist) / sizeof (_dt_errlist[0]);
119a864dc36Sdarran 
120a864dc36Sdarran const char *
dtrace_errmsg(dtrace_hdl_t * dtp,int error)121a864dc36Sdarran dtrace_errmsg(dtrace_hdl_t *dtp, int error)
122a864dc36Sdarran {
123a864dc36Sdarran 	const char *str;
124a864dc36Sdarran 	int i;
125a864dc36Sdarran 
126a864dc36Sdarran 	if (error == EDT_COMPILER && dtp != NULL && dtp->dt_errmsg[0] != '\0')
127a864dc36Sdarran 		str = dtp->dt_errmsg;
128a864dc36Sdarran 	else if (error == EDT_CTF && dtp != NULL && dtp->dt_ctferr != 0)
129a864dc36Sdarran 		str = ctf_errmsg(dtp->dt_ctferr);
130a864dc36Sdarran 	else if (error >= EDT_BASE && (error - EDT_BASE) < _dt_nerr) {
131a864dc36Sdarran 		for (i = 0; i < _dt_nerr; i++) {
132a864dc36Sdarran 			if (_dt_errlist[i].err == error)
133a864dc36Sdarran 				return (_dt_errlist[i].msg);
134a864dc36Sdarran 		}
135a864dc36Sdarran 		str = NULL;
136a864dc36Sdarran 	} else
137a864dc36Sdarran 		str = strerror(error);
138a864dc36Sdarran 
139a864dc36Sdarran 	return (str ? str : "Unknown error");
140a864dc36Sdarran }
141a864dc36Sdarran 
142a864dc36Sdarran int
dtrace_errno(dtrace_hdl_t * dtp)143a864dc36Sdarran dtrace_errno(dtrace_hdl_t *dtp)
144a864dc36Sdarran {
145a864dc36Sdarran 	return (dtp->dt_errno);
146a864dc36Sdarran }
147a864dc36Sdarran 
148*920211a7Schristos #ifdef illumos
149a864dc36Sdarran int
dt_set_errno(dtrace_hdl_t * dtp,int err)150a864dc36Sdarran dt_set_errno(dtrace_hdl_t *dtp, int err)
151a864dc36Sdarran {
152a864dc36Sdarran 	dtp->dt_errno = err;
153a864dc36Sdarran 	return (-1);
154a864dc36Sdarran }
155bb8023b5Sdarran #else
156bb8023b5Sdarran int
_dt_set_errno(dtrace_hdl_t * dtp,int err,const char * errfile,int errline)157bb8023b5Sdarran _dt_set_errno(dtrace_hdl_t *dtp, int err, const char *errfile, int errline)
158bb8023b5Sdarran {
159bb8023b5Sdarran 	dtp->dt_errno = err;
160bb8023b5Sdarran 	dtp->dt_errfile = errfile;
161bb8023b5Sdarran 	dtp->dt_errline = errline;
162bb8023b5Sdarran 	return (-1);
163bb8023b5Sdarran }
164bb8023b5Sdarran 
dt_get_errloc(dtrace_hdl_t * dtp,const char ** p_errfile,int * p_errline)165bb8023b5Sdarran void dt_get_errloc(dtrace_hdl_t *dtp, const char **p_errfile, int *p_errline)
166bb8023b5Sdarran {
167bb8023b5Sdarran 	*p_errfile = dtp->dt_errfile;
168bb8023b5Sdarran 	*p_errline = dtp->dt_errline;
169bb8023b5Sdarran }
170bb8023b5Sdarran #endif
171a864dc36Sdarran 
172a864dc36Sdarran void
dt_set_errmsg(dtrace_hdl_t * dtp,const char * errtag,const char * region,const char * filename,int lineno,const char * format,va_list ap)173a864dc36Sdarran dt_set_errmsg(dtrace_hdl_t *dtp, const char *errtag, const char *region,
174a864dc36Sdarran     const char *filename, int lineno, const char *format, va_list ap)
175a864dc36Sdarran {
176a864dc36Sdarran 	size_t len, n;
177a864dc36Sdarran 	char *p, *s;
178a864dc36Sdarran 
179a864dc36Sdarran 	s = dtp->dt_errmsg;
180a864dc36Sdarran 	n = sizeof (dtp->dt_errmsg);
181a864dc36Sdarran 
182a864dc36Sdarran 	if (errtag != NULL && (yypcb->pcb_cflags & DTRACE_C_ETAGS))
183a864dc36Sdarran 		(void) snprintf(s, n, "[%s] ", errtag);
184a864dc36Sdarran 	else
185a864dc36Sdarran 		s[0] = '\0';
186a864dc36Sdarran 
187a864dc36Sdarran 	len = strlen(dtp->dt_errmsg);
188a864dc36Sdarran 	s = dtp->dt_errmsg + len;
189a864dc36Sdarran 	n = sizeof (dtp->dt_errmsg) - len;
190a864dc36Sdarran 
191a864dc36Sdarran 	if (filename == NULL)
192a864dc36Sdarran 		filename = dtp->dt_filetag;
193a864dc36Sdarran 
194a864dc36Sdarran 	if (filename != NULL)
195a864dc36Sdarran 		(void) snprintf(s, n, "\"%s\", line %d: ", filename, lineno);
196a864dc36Sdarran 	else if (lineno != 0)
197a864dc36Sdarran 		(void) snprintf(s, n, "line %d: ", lineno);
198a864dc36Sdarran 	else if (region != NULL)
199a864dc36Sdarran 		(void) snprintf(s, n, "in %s: ", region);
200a864dc36Sdarran 
201a864dc36Sdarran 	len = strlen(dtp->dt_errmsg);
202a864dc36Sdarran 	s = dtp->dt_errmsg + len;
203a864dc36Sdarran 	n = sizeof (dtp->dt_errmsg) - len;
204a864dc36Sdarran 	(void) vsnprintf(s, n, format, ap);
205a864dc36Sdarran 
206a864dc36Sdarran 	if ((p = strrchr(dtp->dt_errmsg, '\n')) != NULL)
207a864dc36Sdarran 		*p = '\0'; /* remove trailing \n from message buffer */
208a864dc36Sdarran 
209a864dc36Sdarran 	dtp->dt_errtag = errtag;
210a864dc36Sdarran }
211a864dc36Sdarran 
212a864dc36Sdarran /*ARGSUSED*/
213a864dc36Sdarran const char *
dtrace_faultstr(dtrace_hdl_t * dtp,int fault)214a864dc36Sdarran dtrace_faultstr(dtrace_hdl_t *dtp, int fault)
215a864dc36Sdarran {
216a864dc36Sdarran 	int i;
217a864dc36Sdarran 
218a864dc36Sdarran 	static const struct {
219a864dc36Sdarran 		int code;
220a864dc36Sdarran 		const char *str;
221a864dc36Sdarran 	} faults[] = {
222a864dc36Sdarran 		{ DTRACEFLT_BADADDR,	"invalid address" },
223a864dc36Sdarran 		{ DTRACEFLT_BADALIGN,	"invalid alignment" },
224a864dc36Sdarran 		{ DTRACEFLT_ILLOP,	"illegal operation" },
225a864dc36Sdarran 		{ DTRACEFLT_DIVZERO,	"divide-by-zero" },
226a864dc36Sdarran 		{ DTRACEFLT_NOSCRATCH,	"out of scratch space" },
227a864dc36Sdarran 		{ DTRACEFLT_KPRIV,	"invalid kernel access" },
228a864dc36Sdarran 		{ DTRACEFLT_UPRIV,	"invalid user access" },
229a864dc36Sdarran 		{ DTRACEFLT_TUPOFLOW,	"tuple stack overflow" },
230a864dc36Sdarran 		{ DTRACEFLT_BADSTACK,	"bad stack" },
231a864dc36Sdarran 		{ DTRACEFLT_LIBRARY,	"library-level fault" },
232a864dc36Sdarran 		{ 0,			NULL }
233a864dc36Sdarran 	};
234a864dc36Sdarran 
235a864dc36Sdarran 	for (i = 0; faults[i].str != NULL; i++) {
236a864dc36Sdarran 		if (faults[i].code == fault)
237a864dc36Sdarran 			return (faults[i].str);
238a864dc36Sdarran 	}
239a864dc36Sdarran 
240a864dc36Sdarran 	return ("unknown fault");
241a864dc36Sdarran }
242