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