In mono/metadata:
[mono.git] / mono / utils / mono-error.c
blob0ee5c420ecf216c0b3aa395e36fec721a1a003c5
1 /*
2 * mono-error.c: Error handling code
4 * Authors:
5 * Rodrigo Kumpera (rkumpera@novell.com)
6 * Copyright 2009 Novell, Inc (http://www.novell.com)
7 */
8 #include <glib.h>
10 #include "mono-error.h"
11 #include "mono-error-internals.h"
13 #include <mono/metadata/exception.h>
14 #include <mono/metadata/object-internals.h>
15 #include <mono/metadata/debug-helpers.h>
17 #define mono_internal_error_get_message(E) ((E)->full_message ? (E)->full_message : (E)->message)
19 #define set_error_message() do { \
20 va_list args; \
21 va_start (args, msg_format); \
22 if (g_vsnprintf (error->message, sizeof (error->message), msg_format, args) >= sizeof (error->message)) {\
23 if (!(error->full_message = g_strdup_vprintf (msg_format, args))) \
24 error->flags |= MONO_ERROR_INCOMPLETE; \
25 } \
26 va_end (args); \
27 } while (0)
29 static void
30 mono_error_prepare (MonoErrorInternal *error)
32 if (error->error_code != MONO_ERROR_NONE)
33 return;
35 error->type_name = error->assembly_name = error->member_name = error->full_message = error->exception_name_space = error->exception_name = NULL;
36 error->klass = NULL;
37 error->message [0] = 0;
40 void
41 mono_error_init_flags (MonoError *oerror, unsigned short flags)
43 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
44 g_assert (sizeof (MonoError) == sizeof (MonoErrorInternal));
46 error->error_code = MONO_ERROR_NONE;
47 error->flags = flags;
50 void
51 mono_error_init (MonoError *error)
53 mono_error_init_flags (error, 0);
56 void
57 mono_error_cleanup (MonoError *oerror)
59 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
60 if (error->error_code == MONO_ERROR_NONE)
61 return;
63 g_free ((char*)error->full_message);
64 if (!(error->flags & MONO_ERROR_FREE_STRINGS)) //no memory was allocated
65 return;
67 g_free ((char*)error->type_name);
68 g_free ((char*)error->assembly_name);
69 g_free ((char*)error->member_name);
70 g_free ((char*)error->exception_name_space);
71 g_free ((char*)error->exception_name);
74 gboolean
75 mono_error_ok (MonoError *error)
77 return error->error_code == MONO_ERROR_NONE;
80 unsigned short
81 mono_error_get_error_code (MonoError *error)
83 return error->error_code;
86 /*Return a pointer to the internal error message, might be NULL.
87 Caller should not release it.*/
88 const char*
89 mono_error_get_message (MonoError *oerror)
91 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
92 if (error->error_code == MONO_ERROR_NONE)
93 return NULL;
94 return mono_internal_error_get_message (error);
98 * Inform that this error has heap allocated strings.
99 * The strings will be duplicated if @dup_strings is TRUE
100 * otherwise they will just be free'd in mono_error_cleanup.
102 void
103 mono_error_dup_strings (MonoError *oerror, gboolean dup_strings)
105 #define DUP_STR(field) do { if (error->field) {\
106 if (!(error->field = g_strdup (error->field))) \
107 error->flags |= MONO_ERROR_INCOMPLETE; \
108 }} while (0);
110 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
111 error->flags |= MONO_ERROR_FREE_STRINGS;
113 if (dup_strings) {
114 DUP_STR (type_name);
115 DUP_STR (assembly_name);
116 DUP_STR (member_name);
117 DUP_STR (exception_name_space);
118 DUP_STR (exception_name);
120 #undef DUP_STR
123 void
124 mono_error_set_error (MonoError *oerror, int error_code, const char *msg_format, ...)
126 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
127 mono_error_prepare (error);
129 error->error_code = error_code;
130 set_error_message ();
133 static void
134 mono_error_set_assembly_name (MonoError *oerror, const char *assembly_name)
136 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
137 g_assert (error->error_code != MONO_ERROR_NONE);
139 error->assembly_name = assembly_name;
142 static void
143 mono_error_set_member_name (MonoError *oerror, const char *member_name)
145 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
147 error->member_name = member_name;
150 static void
151 mono_error_set_type_name (MonoError *oerror, const char *type_name)
153 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
155 error->type_name = type_name;
158 static void
159 mono_error_set_class (MonoError *oerror, MonoClass *klass)
161 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
163 error->klass = klass;
166 static void
167 mono_error_set_corlib_exception (MonoError *oerror, const char *name_space, const char *name)
169 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
171 error->exception_name_space = name_space;
172 error->exception_name = name;
176 void
177 mono_error_set_assembly_load (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
179 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
180 mono_error_prepare (error);
182 error->error_code = MONO_ERROR_FILE_NOT_FOUND;
183 mono_error_set_assembly_name (oerror, assembly_name);
185 set_error_message ();
188 void
189 mono_error_set_type_load_class (MonoError *oerror, MonoClass *klass, const char *msg_format, ...)
191 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
192 mono_error_prepare (error);
194 error->error_code = MONO_ERROR_TYPE_LOAD;
195 mono_error_set_class (oerror, klass);
196 set_error_message ();
199 void
200 mono_error_set_type_load_name (MonoError *oerror, const char *type_name, const char *assembly_name, const char *msg_format, ...)
202 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
203 mono_error_prepare (error);
205 error->error_code = MONO_ERROR_TYPE_LOAD;
206 mono_error_set_type_name (oerror, type_name);
207 mono_error_set_assembly_name (oerror, assembly_name);
208 set_error_message ();
211 void
212 mono_error_set_method_load (MonoError *oerror, MonoClass *klass, const char *method_name, const char *msg_format, ...)
214 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
215 mono_error_prepare (error);
217 error->error_code = MONO_ERROR_MISSING_METHOD;
218 mono_error_set_class (oerror, klass);
219 mono_error_set_member_name (oerror, method_name);
220 set_error_message ();
223 void
224 mono_error_set_field_load (MonoError *oerror, MonoClass *klass, const char *field_name, const char *msg_format, ...)
226 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
227 mono_error_prepare (error);
229 error->error_code = MONO_ERROR_MISSING_FIELD;
230 mono_error_set_class (oerror, klass);
231 mono_error_set_member_name (oerror, field_name);
232 set_error_message ();
235 void
236 mono_error_set_bad_image (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
238 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
239 mono_error_prepare (error);
241 error->error_code = MONO_ERROR_BAD_IMAGE;
242 mono_error_set_assembly_name (oerror, assembly_name);
243 set_error_message ();
246 void
247 mono_error_set_generic_error (MonoError *oerror, const char * name_space, const char *name, const char *msg_format, ...)
249 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
250 mono_error_prepare (error);
252 error->error_code = MONO_ERROR_GENERIC;
253 mono_error_set_corlib_exception (oerror, name_space, name);
254 set_error_message ();
257 void
258 mono_error_set_out_of_memory (MonoError *oerror, const char *msg_format, ...)
260 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
261 va_list args;
262 mono_error_prepare (error);
264 error->error_code = MONO_ERROR_OUT_OF_MEMORY;
265 va_start (args, msg_format);
266 g_vsnprintf (error->message, sizeof (error->message), msg_format, args);
267 va_end (args);
270 static MonoString*
271 get_type_name_as_mono_string (MonoErrorInternal *error, MonoDomain *domain, MonoError *error_out)
273 MonoString* res = NULL;
275 if (error->type_name) {
276 res = mono_string_new (domain, error->type_name);
278 } else if (error->klass) {
279 char *name = mono_type_full_name (&error->klass->byval_arg);
280 if (name) {
281 res = mono_string_new (domain, name);
282 g_free (name);
285 if (!res)
286 mono_error_set_out_of_memory (error_out, "Could not allocate type name");
287 return res;
290 static void
291 set_message_on_exception (MonoException *exception, MonoErrorInternal *error, MonoError *error_out)
293 MonoString *msg = mono_string_new (mono_domain_get (), mono_internal_error_get_message (error));
294 if (msg)
295 MONO_OBJECT_SETREF (exception, message, msg);
296 else
297 mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
300 MonoException*
301 mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
303 MonoErrorInternal *error = (MonoErrorInternal*)oerror;
305 MonoException* exception = NULL;
306 MonoString *assembly_name = NULL, *type_name = NULL, *method_name = NULL, *field_name = NULL, *msg = NULL;
307 MonoDomain *domain = mono_domain_get ();
310 switch (error->error_code) {
311 case MONO_ERROR_NONE:
312 return NULL;
314 case MONO_ERROR_MISSING_METHOD:
315 if ((error->type_name || error->klass) && error->member_name) {
316 type_name = get_type_name_as_mono_string (error, domain, error_out);
317 if (!mono_error_ok (error_out))
318 break;
320 method_name = mono_string_new (domain, error->member_name);
321 if (!method_name) {
322 mono_error_set_out_of_memory (error_out, "Could not allocate method name");
323 break;
326 exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name);
327 if (exception)
328 set_message_on_exception (exception, error, error_out);
329 } else {
330 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", mono_internal_error_get_message (error));
332 break;
334 case MONO_ERROR_MISSING_FIELD:
335 if ((error->type_name || error->klass) && error->member_name) {
336 type_name = get_type_name_as_mono_string (error, domain, error_out);
337 if (!mono_error_ok (error_out))
338 break;
340 field_name = mono_string_new (domain, error->member_name);
341 if (!field_name) {
342 mono_error_set_out_of_memory (error_out, "Could not allocate field name");
343 break;
346 exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name);
347 if (exception)
348 set_message_on_exception (exception, error, error_out);
349 } else {
350 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", mono_internal_error_get_message (error));
352 break;
354 case MONO_ERROR_TYPE_LOAD:
355 if (error->type_name || error->assembly_name) {
356 type_name = get_type_name_as_mono_string (error, domain, error_out);
357 if (!mono_error_ok (error_out))
358 break;
360 if (error->assembly_name) {
361 assembly_name = mono_string_new (domain, error->assembly_name);
362 if (!assembly_name) {
363 mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
364 break;
368 exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name);
369 if (exception)
370 set_message_on_exception (exception, error, error_out);
371 } else {
372 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", mono_internal_error_get_message (error));
374 break;
376 case MONO_ERROR_FILE_NOT_FOUND:
377 case MONO_ERROR_BAD_IMAGE:
378 if (error->assembly_name) {
379 msg = mono_string_new (domain, mono_internal_error_get_message (error));
380 if (!msg) {
381 mono_error_set_out_of_memory (error_out, "Could not allocate message");
382 break;
385 if (error->assembly_name) {
386 assembly_name = mono_string_new (domain, error->assembly_name);
387 if (!assembly_name) {
388 mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
389 break;
393 if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
394 exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name);
395 else
396 exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name);
397 } else {
398 if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
399 exception = mono_exception_from_name_msg (mono_get_corlib (), "System.IO", "FileNotFoundException", mono_internal_error_get_message (error));
400 else
401 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "BadImageFormatException", mono_internal_error_get_message (error));
403 break;
405 case MONO_ERROR_OUT_OF_MEMORY:
406 exception = mono_get_exception_out_of_memory ();
407 break;
409 case MONO_ERROR_GENERIC:
410 if (!error->exception_name_space || !error->exception_name)
411 mono_error_set_generic_error (error_out, "System", "ExecutionEngineException", "MonoError with generic error but no exception name was supplied");
412 else
413 exception = mono_exception_from_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, mono_internal_error_get_message (error));
414 break;
416 default:
417 mono_error_set_generic_error (error_out, "System", "ExecutionEngineException", "Invalid error-code %d", error->error_code);
420 if (!mono_error_ok (error_out))
421 return NULL;
422 if (!exception)
423 mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
424 return exception;