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