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