[docs] Enable documentation for utils.
[mono.git] / mono / utils / mono-error.c
1 /**
2  * \file
3  * Error handling code
4  *
5  * Authors:
6  *      Rodrigo Kumpera    (rkumpera@novell.com)
7  * Copyright 2009 Novell, Inc (http://www.novell.com)
8  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
9  */
10 #include <glib.h>
11
12 #include <config.h>
13 #include "mono-error.h"
14 #include "mono-error-internals.h"
15
16 #include <mono/metadata/exception.h>
17 #include <mono/metadata/exception-internals.h>
18 #include <mono/metadata/debug-helpers.h>
19 #include <mono/metadata/object-internals.h>
20
21 #define set_error_messagev() do { \
22         if (!(error->full_message = g_strdup_vprintf (msg_format, args))) \
23                         error->flags |= MONO_ERROR_INCOMPLETE; \
24 } while (0)
25
26 #define set_error_message() do { \
27         va_list args; \
28         va_start (args, msg_format); \
29         set_error_messagev();        \
30         va_end (args); \
31 } while (0)
32
33 static void
34 mono_error_set_generic_errorv (MonoError *oerror, const char *name_space, const char *name, const char *msg_format, va_list args);
35
36 static gboolean
37 is_managed_exception (MonoErrorInternal *error)
38 {
39         return (error->error_code == MONO_ERROR_EXCEPTION_INSTANCE);
40 }
41
42 static gboolean
43 is_boxed (MonoErrorInternal *error)
44 {
45         return ((error->flags & MONO_ERROR_MEMPOOL_BOXED) != 0);
46 }
47
48 static void
49 mono_error_prepare (MonoErrorInternal *error)
50 {
51         /* mono_error_set_* after a mono_error_cleanup without an intervening init */
52         g_assert (error->error_code != MONO_ERROR_CLEANUP_CALLED_SENTINEL);
53         if (error->error_code != MONO_ERROR_NONE)
54                 return;
55
56         error->type_name = error->assembly_name = error->member_name = error->full_message = error->exception_name_space = error->exception_name = error->full_message_with_fields = error->first_argument = NULL;
57         error->exn.klass = NULL;
58 }
59
60 static MonoClass*
61 get_class (MonoErrorInternal *error)
62 {
63         MonoClass *klass = NULL;
64         if (is_managed_exception (error))
65                 klass = mono_object_class (mono_gchandle_get_target (error->exn.instance_handle));
66         else
67                 klass = error->exn.klass;
68         return klass;
69 }
70
71 static const char*
72 get_type_name (MonoErrorInternal *error)
73 {
74         if (error->type_name)
75                 return error->type_name;
76         MonoClass *klass = get_class (error);
77         if (klass)
78                 return klass->name;
79         return "<unknown type>";
80 }
81
82 static const char*
83 get_assembly_name (MonoErrorInternal *error)
84 {
85         if (error->assembly_name)
86                 return error->assembly_name;
87         MonoClass *klass = get_class (error);
88         if (klass && klass->image)
89                 return klass->image->name;
90         return "<unknown assembly>";
91 }
92
93 void
94 mono_error_init_flags (MonoError *oerror, unsigned short flags)
95 {
96         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
97         g_assert (sizeof (MonoError) == sizeof (MonoErrorInternal));
98
99         error->error_code = MONO_ERROR_NONE;
100         error->flags = flags;
101 }
102
103 /**
104  * mono_error_init:
105  * @error: Pointer to MonoError struct to initialize
106  *
107  * Any function which takes a MonoError for purposes of reporting an error
108  * is required to call either this or mono_error_init_flags on entry.
109  */
110 void
111 mono_error_init (MonoError *error)
112 {
113         mono_error_init_flags (error, 0);
114 }
115
116 void
117 mono_error_cleanup (MonoError *oerror)
118 {
119         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
120         short int orig_error_code = error->error_code;
121         gboolean free_strings = error->flags & MONO_ERROR_FREE_STRINGS;
122         gboolean has_instance_handle = is_managed_exception (error);
123
124         /* Two cleanups in a row without an intervening init. */
125         g_assert (orig_error_code != MONO_ERROR_CLEANUP_CALLED_SENTINEL);
126         /* Mempool stored error shouldn't be cleaned up */
127         g_assert (!is_boxed (error));
128
129         /* Mark it as cleaned up. */
130         error->error_code = MONO_ERROR_CLEANUP_CALLED_SENTINEL;
131         error->flags = 0;
132
133         if (orig_error_code == MONO_ERROR_NONE)
134                 return;
135
136
137         if (has_instance_handle)
138                 mono_gchandle_free (error->exn.instance_handle);
139
140
141         g_free ((char*)error->full_message);
142         g_free ((char*)error->full_message_with_fields);
143         error->full_message = NULL;
144         error->full_message_with_fields = NULL;
145         if (!free_strings) //no memory was allocated
146                 return;
147
148         g_free ((char*)error->type_name);
149         g_free ((char*)error->assembly_name);
150         g_free ((char*)error->member_name);
151         g_free ((char*)error->exception_name_space);
152         g_free ((char*)error->exception_name);
153         g_free ((char*)error->first_argument);
154         error->type_name = error->assembly_name = error->member_name = error->exception_name_space = error->exception_name = error->first_argument = NULL;
155         error->exn.klass = NULL;
156
157 }
158
159 gboolean
160 mono_error_ok (MonoError *error)
161 {
162         return error->error_code == MONO_ERROR_NONE;
163 }
164
165 void
166 mono_error_assert_ok_pos (MonoError *error, const char* filename, int lineno)
167 {
168         if (mono_error_ok (error))
169                 return;
170
171         g_error ("%s:%d: %s\n", filename, lineno, mono_error_get_message (error));
172 }
173
174 unsigned short
175 mono_error_get_error_code (MonoError *error)
176 {
177         return error->error_code;
178 }
179
180 /*Return a pointer to the internal error message, might be NULL.
181 Caller should not release it.*/
182 const char*
183 mono_error_get_message (MonoError *oerror)
184 {
185         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
186         if (error->error_code == MONO_ERROR_NONE)
187                 return NULL;
188         if (error->full_message_with_fields)
189                 return error->full_message_with_fields;
190
191         error->full_message_with_fields = g_strdup_printf ("%s assembly:%s type:%s member:%s",
192                 error->full_message,
193                 get_assembly_name (error),
194                 get_type_name (error),
195                 error->member_name ? error->member_name : "<none>");
196
197         return error->full_message_with_fields ? error->full_message_with_fields : error->full_message;
198 }
199
200 /*
201  * Inform that this error has heap allocated strings.
202  * The strings will be duplicated if @dup_strings is TRUE
203  * otherwise they will just be free'd in mono_error_cleanup.
204  */
205 void
206 mono_error_dup_strings (MonoError *oerror, gboolean dup_strings)
207 {
208 #define DUP_STR(field) do { if (error->field) {\
209         if (!(error->field = g_strdup (error->field))) \
210                 error->flags |= MONO_ERROR_INCOMPLETE; \
211         }} while (0);
212
213         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
214         error->flags |= MONO_ERROR_FREE_STRINGS;
215
216         if (dup_strings) {
217                 DUP_STR (type_name);
218                 DUP_STR (assembly_name);
219                 DUP_STR (member_name);
220                 DUP_STR (exception_name_space);
221                 DUP_STR (exception_name);
222                 DUP_STR (first_argument);
223         }
224 #undef DUP_STR
225 }
226
227 void
228 mono_error_set_error (MonoError *oerror, int error_code, const char *msg_format, ...)
229 {
230         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
231         mono_error_prepare (error);
232
233         error->error_code = error_code;
234         set_error_message ();
235 }
236
237 static void
238 mono_error_set_assembly_name (MonoError *oerror, const char *assembly_name)
239 {
240         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
241         g_assert (error->error_code != MONO_ERROR_NONE);
242
243         error->assembly_name = assembly_name;
244 }
245
246 static void
247 mono_error_set_member_name (MonoError *oerror, const char *member_name)
248 {
249         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
250
251         error->member_name = member_name;
252 }
253
254 static void
255 mono_error_set_type_name (MonoError *oerror, const char *type_name)
256 {
257         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
258
259         error->type_name = type_name;
260 }
261
262 static void
263 mono_error_set_class (MonoError *oerror, MonoClass *klass)
264 {
265         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
266
267         if (is_managed_exception (error))
268                 return;
269         error->exn.klass = klass;       
270 }
271
272 static void
273 mono_error_set_corlib_exception (MonoError *oerror, const char *name_space, const char *name)
274 {
275         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
276
277         error->exception_name_space = name_space;
278         error->exception_name = name;
279 }
280
281
282 void
283 mono_error_set_assembly_load (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
284 {
285         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
286         mono_error_prepare (error);
287
288         error->error_code = MONO_ERROR_FILE_NOT_FOUND;
289         mono_error_set_assembly_name (oerror, assembly_name);
290
291         set_error_message ();
292 }
293
294
295 void
296 mono_error_set_assembly_load_simple (MonoError *oerror, const char *assembly_name, gboolean refection_only)
297 {
298         if (refection_only)
299                 mono_error_set_assembly_load (oerror, assembly_name, "Cannot resolve dependency to assembly because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.");
300         else
301                 mono_error_set_assembly_load (oerror, assembly_name, "Could not load file or assembly '%s' or one of its dependencies.", assembly_name);
302 }
303
304 void
305 mono_error_set_type_load_class (MonoError *oerror, MonoClass *klass, const char *msg_format, ...)
306 {
307         va_list args;
308         va_start (args, msg_format);
309         mono_error_vset_type_load_class (oerror, klass, msg_format, args);
310         va_end (args);
311 }
312
313 void
314 mono_error_vset_type_load_class (MonoError *oerror, MonoClass *klass, const char *msg_format, va_list args)
315 {
316         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
317         mono_error_prepare (error);
318
319         error->error_code = MONO_ERROR_TYPE_LOAD;
320         mono_error_set_class (oerror, klass);
321         set_error_messagev ();
322 }
323
324 /*
325  * Different than other functions, this one here assumes that type_name and assembly_name to have been allocated just for us.
326  * Which means mono_error_cleanup will free them.
327  */
328 void
329 mono_error_set_type_load_name (MonoError *oerror, const char *type_name, const char *assembly_name, const char *msg_format, ...)
330 {
331         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
332         mono_error_prepare (error);
333
334         error->error_code = MONO_ERROR_TYPE_LOAD;
335         mono_error_set_type_name (oerror, type_name);
336         mono_error_set_assembly_name (oerror, assembly_name);
337         mono_error_dup_strings (oerror, FALSE);
338         set_error_message ();
339 }
340
341 void
342 mono_error_set_method_load (MonoError *oerror, MonoClass *klass, const char *method_name, const char *msg_format, ...)
343 {
344         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
345         mono_error_prepare (error);
346
347         error->error_code = MONO_ERROR_MISSING_METHOD;
348         mono_error_set_class (oerror, klass);
349         mono_error_set_member_name (oerror, method_name);
350         set_error_message ();
351 }
352
353 void
354 mono_error_set_field_load (MonoError *oerror, MonoClass *klass, const char *field_name, const char *msg_format, ...)
355 {
356         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
357         mono_error_prepare (error);
358
359         error->error_code = MONO_ERROR_MISSING_FIELD;
360         mono_error_set_class (oerror, klass);
361         mono_error_set_member_name (oerror, field_name);
362         set_error_message ();   
363 }
364
365 void
366 mono_error_set_bad_image_name (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
367 {
368         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
369         mono_error_prepare (error);
370
371         error->error_code = MONO_ERROR_BAD_IMAGE;
372         mono_error_set_assembly_name (oerror, assembly_name);
373         set_error_message ();
374 }
375
376 void
377 mono_error_set_bad_image (MonoError *oerror, MonoImage *image, const char *msg_format, ...)
378 {
379         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
380         mono_error_prepare (error);
381
382         error->error_code = MONO_ERROR_BAD_IMAGE;
383         error->assembly_name = image ? mono_image_get_name (image) : "<no_image>";
384         set_error_message ();
385 }
386
387 void
388 mono_error_set_generic_errorv (MonoError *oerror, const char *name_space, const char *name, const char *msg_format, va_list args)
389 {
390         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
391         mono_error_prepare (error);
392
393         error->error_code = MONO_ERROR_GENERIC;
394         mono_error_set_corlib_exception (oerror, name_space, name);
395         set_error_messagev ();
396 }
397
398 void
399 mono_error_set_generic_error (MonoError *oerror, const char * name_space, const char *name, const char *msg_format, ...)
400 {
401         va_list args;
402         va_start (args, msg_format);
403         mono_error_set_generic_errorv (oerror, name_space, name, msg_format, args);
404         va_end (args);
405 }
406
407 /**
408  * mono_error_set_not_implemented:
409  *
410  * System.NotImplementedException
411  */
412 void
413 mono_error_set_not_implemented (MonoError *oerror, const char *msg_format, ...)
414 {
415         va_list args;
416         va_start (args, msg_format);
417         mono_error_set_generic_errorv (oerror, "System", "NotImplementedException", msg_format, args);
418         va_end (args);
419 }
420
421 /**
422  * mono_error_set_execution_engine:
423  *
424  * System.ExecutionEngineException
425  */
426 void
427 mono_error_set_execution_engine (MonoError *oerror, const char *msg_format, ...)
428 {
429         va_list args;
430         va_start (args, msg_format);
431         mono_error_set_generic_errorv (oerror, "System", "ExecutionEngineException", msg_format, args);
432         va_end (args);
433 }
434
435 /**
436  * mono_error_set_not_supported:
437  *
438  * System.NotSupportedException
439  */
440 void
441 mono_error_set_not_supported (MonoError *oerror, const char *msg_format, ...)
442 {
443         va_list args;
444         va_start (args, msg_format);
445         mono_error_set_generic_errorv (oerror, "System", "NotSupportedException", msg_format, args);
446         va_end (args);
447 }
448
449 /**
450  * mono_error_set_invalid_operation:
451  *
452  * System.InvalidOperationException
453  */
454 void
455 mono_error_set_invalid_operation (MonoError *oerror, const char *msg_format, ...)
456 {
457         va_list args;
458         va_start (args, msg_format);
459         mono_error_set_generic_errorv (oerror, "System", "InvalidOperationException", msg_format, args);
460         va_end (args);
461 }
462
463 void
464 mono_error_set_invalid_program (MonoError *oerror, const char *msg_format, ...)
465 {
466         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
467
468         mono_error_prepare (error);
469         error->error_code = MONO_ERROR_INVALID_PROGRAM;
470
471         set_error_message ();
472 }
473
474 void
475 mono_error_set_exception_instance (MonoError *oerror, MonoException *exc)
476 {
477         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
478
479         mono_error_prepare (error);
480         error->error_code = MONO_ERROR_EXCEPTION_INSTANCE;
481         error->exn.instance_handle = mono_gchandle_new (exc ? &exc->object : NULL, FALSE);
482 }
483
484 void
485 mono_error_set_exception_handle (MonoError *oerror, MonoExceptionHandle exc)
486 {
487         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
488
489         mono_error_prepare (error);
490         error->error_code = MONO_ERROR_EXCEPTION_INSTANCE;
491         error->exn.instance_handle = mono_gchandle_from_handle (MONO_HANDLE_CAST(MonoObject, exc), FALSE);
492 }
493
494 void
495 mono_error_set_out_of_memory (MonoError *oerror, const char *msg_format, ...)
496 {
497         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
498         mono_error_prepare (error);
499
500         error->error_code = MONO_ERROR_OUT_OF_MEMORY;
501
502         set_error_message ();
503 }
504
505 void
506 mono_error_set_argument (MonoError *oerror, const char *argument, const char *msg_format, ...)
507 {
508         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
509         mono_error_prepare (error);
510
511         error->error_code = MONO_ERROR_ARGUMENT;
512         error->first_argument = argument;
513
514         set_error_message ();
515 }
516
517 void
518 mono_error_set_argument_null (MonoError *oerror, const char *argument, const char *msg_format, ...)
519 {
520         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
521         mono_error_prepare (error);
522
523         error->error_code = MONO_ERROR_ARGUMENT_NULL;
524         error->first_argument = argument;
525
526         set_error_message ();
527 }
528
529 void
530 mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char *msg_format, ...)
531 {
532         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
533         mono_error_prepare (error);
534
535         error->error_code = MONO_ERROR_NOT_VERIFIABLE;
536         if (method) {
537                 mono_error_set_class (oerror, method->klass);
538                 mono_error_set_member_name (oerror, mono_method_full_name (method, 1));
539         }
540
541         set_error_message ();
542 }
543
544
545 static MonoString*
546 get_type_name_as_mono_string (MonoErrorInternal *error, MonoDomain *domain, MonoError *error_out)
547 {
548         MonoString* res = NULL;
549
550         if (error->type_name) {
551                 res = mono_string_new (domain, error->type_name);
552                 
553         } else {
554                 MonoClass *klass = get_class (error);
555                 if (klass) {
556                         char *name = mono_type_full_name (&klass->byval_arg);
557                         if (name) {
558                                 res = mono_string_new (domain, name);
559                                 g_free (name);
560                         }
561                 }
562         }
563         if (!res)
564                 mono_error_set_out_of_memory (error_out, "Could not allocate type name");
565         return res;
566 }
567
568 static void
569 set_message_on_exception (MonoException *exception, MonoErrorInternal *error, MonoError *error_out)
570 {
571         MonoString *msg = mono_string_new (mono_domain_get (), error->full_message);
572         if (msg)
573                 MONO_OBJECT_SETREF (exception, message, msg);
574         else
575                 mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
576 }
577
578 /*Can fail with out-of-memory*/
579 MonoException*
580 mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
581 {
582         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
583
584         MonoException* exception = NULL;
585         MonoString *assembly_name = NULL, *type_name = NULL, *method_name = NULL, *field_name = NULL, *msg = NULL;
586         MonoDomain *domain = mono_domain_get ();
587
588         error_init (error_out);
589
590         switch (error->error_code) {
591         case MONO_ERROR_NONE:
592                 return NULL;
593
594         case MONO_ERROR_MISSING_METHOD:
595                 if ((error->type_name || error->exn.klass) && error->member_name) {
596                         type_name = get_type_name_as_mono_string (error, domain, error_out);
597                         if (!mono_error_ok (error_out))
598                                 break;
599
600                         method_name = mono_string_new (domain, error->member_name);
601                         if (!method_name) {
602                                 mono_error_set_out_of_memory (error_out, "Could not allocate method name");
603                                 break;
604                         }
605
606                         exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name, error_out);
607                         if (exception)
608                                 set_message_on_exception (exception, error, error_out);
609                 } else {
610                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", error->full_message);
611                 }
612                 break;
613
614         case MONO_ERROR_MISSING_FIELD:
615                 if ((error->type_name || error->exn.klass) && error->member_name) {
616                         type_name = get_type_name_as_mono_string (error, domain, error_out);
617                         if (!mono_error_ok (error_out))
618                                 break;
619                         
620                         field_name = mono_string_new (domain, error->member_name);
621                         if (!field_name) {
622                                 mono_error_set_out_of_memory (error_out, "Could not allocate field name");
623                                 break;
624                         }
625                         
626                         exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name, error_out);
627                         if (exception)
628                                 set_message_on_exception (exception, error, error_out);
629                 } else {
630                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", error->full_message);
631                 }
632                 break;
633
634         case MONO_ERROR_TYPE_LOAD:
635                 if ((error->type_name && error->assembly_name) || error->exn.klass) {
636                         type_name = get_type_name_as_mono_string (error, domain, error_out);
637                         if (!mono_error_ok (error_out))
638                                 break;
639
640                         if (error->assembly_name) {
641                                 assembly_name = mono_string_new (domain, error->assembly_name);
642                                 if (!assembly_name) {
643                                         mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
644                                         break;
645                                 }
646                         }
647
648                         exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name, error_out);
649                         if (exception && error->full_message != NULL && strcmp (error->full_message, ""))
650                                 set_message_on_exception (exception, error, error_out);
651                 } else {
652                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", error->full_message);
653                 }
654                 break;
655
656         case MONO_ERROR_FILE_NOT_FOUND:
657         case MONO_ERROR_BAD_IMAGE:
658                 if (error->assembly_name) {
659                         msg = mono_string_new (domain, error->full_message);
660                         if (!msg) {
661                                 mono_error_set_out_of_memory (error_out, "Could not allocate message");
662                                 break;
663                         }
664
665                         if (error->assembly_name) {
666                                 assembly_name = mono_string_new (domain, error->assembly_name);
667                                 if (!assembly_name) {
668                                         mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
669                                         break;
670                                 }
671                         }
672
673                         if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
674                                 exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name, error_out);
675                         else
676                                 exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name, error_out);
677                 } else {
678                         if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
679                                 exception = mono_exception_from_name_msg (mono_get_corlib (), "System.IO", "FileNotFoundException", error->full_message);
680                         else
681                                 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "BadImageFormatException", error->full_message);
682                 }
683                 break;
684
685         case MONO_ERROR_OUT_OF_MEMORY:
686                 exception = mono_get_exception_out_of_memory ();
687                 break;
688
689         case MONO_ERROR_ARGUMENT:
690                 exception = mono_get_exception_argument (error->first_argument, error->full_message);
691                 break;
692
693         case MONO_ERROR_ARGUMENT_NULL:
694                 exception = mono_get_exception_argument_null (error->first_argument);
695                 break;
696
697         case MONO_ERROR_NOT_VERIFIABLE: {
698                 char *type_name = NULL, *message;
699                 if (error->exn.klass) {
700                         type_name = mono_type_get_full_name (error->exn.klass);
701                         if (!type_name) {
702                                 mono_error_set_out_of_memory (error_out, "Could not allocate message");
703                                 break;
704                         }
705                 }
706                 message = g_strdup_printf ("Error in %s:%s %s", type_name, error->member_name, error->full_message);
707                 if (!message) {
708                         g_free (type_name);
709                         mono_error_set_out_of_memory (error_out, "Could not allocate message");
710                         break;  
711                 }
712                 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", message);
713                 g_free (message);
714                 g_free (type_name);
715                 break;
716         }
717         case MONO_ERROR_GENERIC:
718                 if (!error->exception_name_space || !error->exception_name)
719                         mono_error_set_execution_engine (error_out, "MonoError with generic error but no exception name was supplied");
720                 else
721                         exception = mono_exception_from_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, error->full_message);
722                 break;
723
724         case MONO_ERROR_EXCEPTION_INSTANCE:
725                 exception = (MonoException*) mono_gchandle_get_target (error->exn.instance_handle);
726                 break;
727
728         case MONO_ERROR_CLEANUP_CALLED_SENTINEL:
729                 mono_error_set_execution_engine (error_out, "MonoError reused after mono_error_cleanup");
730                 break;
731
732         case MONO_ERROR_INVALID_PROGRAM: {
733                 gboolean lacks_message = error->flags & MONO_ERROR_INCOMPLETE;
734                 if (lacks_message)
735                         return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
736                 else
737                         return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", error->full_message);
738         }
739         default:
740                 mono_error_set_execution_engine (error_out, "Invalid error-code %d", error->error_code);
741         }
742
743         if (!mono_error_ok (error_out))
744                 return NULL;
745         if (!exception)
746                 mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
747         return exception;
748 }
749
750 /*
751 Convert this MonoError to an exception if it's faulty or return NULL.
752 The error object is cleant after.
753 */
754
755 MonoException*
756 mono_error_convert_to_exception (MonoError *target_error)
757 {
758         MonoError error;
759         MonoException *ex;
760
761         /* Mempool stored error shouldn't be cleaned up */
762         g_assert (!is_boxed ((MonoErrorInternal*)target_error));
763
764         if (mono_error_ok (target_error))
765                 return NULL;
766
767         ex = mono_error_prepare_exception (target_error, &error);
768         if (!mono_error_ok (&error)) {
769                 MonoError second_chance;
770                 /*Try to produce the exception for the second error. FIXME maybe we should log about the original one*/
771                 ex = mono_error_prepare_exception (&error, &second_chance);
772
773                 g_assert (mono_error_ok (&second_chance)); /*We can't reasonable handle double faults, maybe later.*/
774                 mono_error_cleanup (&error);
775         }
776         mono_error_cleanup (target_error);
777         return ex;
778 }
779
780 void
781 mono_error_move (MonoError *dest, MonoError *src)
782 {
783         memcpy (dest, src, sizeof (MonoErrorInternal));
784         error_init (src);
785 }
786
787 /**
788  * mono_error_box:
789  * @ierror: The input error that will be boxed.
790  * @image: The mempool of this image will hold the boxed error.
791  *
792  * Creates a new boxed error in the given mempool from MonoError.
793  * It does not alter ierror, so you still have to clean it up with
794  * mono_error_cleanup or mono_error_convert_to_exception or another such function.
795  *
796  * Returns the boxed error, or NULL if the mempool could not allocate.
797  */
798 MonoErrorBoxed*
799 mono_error_box (const MonoError *ierror, MonoImage *image)
800 {
801         MonoErrorInternal *from = (MonoErrorInternal*)ierror;
802         /* Don't know how to box a gchandle */
803         g_assert (!is_managed_exception (from));
804         MonoErrorBoxed* box = mono_image_alloc (image, sizeof (MonoErrorBoxed));
805         box->image = image;
806         mono_error_init_flags (&box->error, MONO_ERROR_MEMPOOL_BOXED);
807         MonoErrorInternal *to = (MonoErrorInternal*)&box->error;
808
809 #define DUP_STR(field) do {                                             \
810                 if (from->field) {                                      \
811                         if (!(to->field = mono_image_strdup (image, from->field))) \
812                                 to->flags |= MONO_ERROR_INCOMPLETE;     \
813                 } else {                                                \
814                         to->field = NULL;                               \
815                 }                                                       \
816         } while (0)
817
818         to->error_code = from->error_code;
819         DUP_STR (type_name);
820         DUP_STR (assembly_name);
821         DUP_STR (member_name);
822         DUP_STR (exception_name_space);
823         DUP_STR (exception_name);
824         DUP_STR (full_message);
825         DUP_STR (full_message_with_fields);
826         DUP_STR (first_argument);
827         to->exn.klass = from->exn.klass;
828
829 #undef DUP_STR
830         
831         return box;
832 }
833
834
835 /**
836  * mono_error_set_from_boxed:
837  * @oerror: The error that will be set to the contents of the box.
838  * @box: A mempool-allocated error.
839  *
840  * Sets the error condition in the oerror from the contents of the
841  * given boxed error.  Does not alter the boxed error, so it can be
842  * used in a future call to mono_error_set_from_boxed as needed.  The
843  * oerror should've been previously initialized with mono_error_init,
844  * as usual.
845  *
846  * Returns TRUE on success or FALSE on failure.
847  */
848 gboolean
849 mono_error_set_from_boxed (MonoError *oerror, const MonoErrorBoxed *box)
850 {
851         MonoErrorInternal* to = (MonoErrorInternal*)oerror;
852         MonoErrorInternal* from = (MonoErrorInternal*)&box->error;
853         g_assert (!is_managed_exception (from));
854
855         mono_error_prepare (to);
856         to->flags |= MONO_ERROR_FREE_STRINGS;
857 #define DUP_STR(field)  do {                                            \
858                 if (from->field) {                                      \
859                         if (!(to->field = g_strdup (from->field)))      \
860                                 to->flags |= MONO_ERROR_INCOMPLETE;     \
861                 } else {                                                \
862                         to->field = NULL;                               \
863                 }                                                       \
864         } while (0)
865
866         to->error_code = from->error_code;
867         DUP_STR (type_name);
868         DUP_STR (assembly_name);
869         DUP_STR (member_name);
870         DUP_STR (exception_name_space);
871         DUP_STR (exception_name);
872         DUP_STR (full_message);
873         DUP_STR (full_message_with_fields);
874         DUP_STR (first_argument);
875         to->exn.klass = from->exn.klass;
876                   
877 #undef DUP_STR
878         return (to->flags & MONO_ERROR_INCOMPLETE) == 0 ;
879 }