baaa2af993a468c4cc8eed506c3d82e3c419bb79
[mono.git] / mono / metadata / exception.c
1 /*
2  * exception.c: Exception handling
3  *
4  * Authors:
5  *      Paolo Molaro    (lupus@ximian.com)
6  *      Dietmar Maurer  (dietmar@ximian.com)
7  *      Dick Porter     (dick@ximian.com)
8  *      Miguel de Icaza (miguel@ximian.com)
9  *
10  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
13  */
14
15 #include <glib.h>
16 #include <config.h>
17 #include <mono/metadata/environment.h>
18 #include <mono/metadata/exception.h>
19 #include <mono/metadata/exception-internals.h>
20
21 #include <mono/metadata/object-internals.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/appdomain.h>
24 #include <mono/metadata/mono-debug.h>
25 #include <mono/utils/mono-error-internals.h>
26 #include <mono/utils/mono-logger-internals.h>
27 #include <string.h>
28
29 #ifdef HAVE_EXECINFO_H
30 #include <execinfo.h>
31 #endif
32
33 static MonoUnhandledExceptionFunc unhandled_exception_hook = NULL;
34 static gpointer unhandled_exception_hook_data = NULL;
35
36 /**
37  * mono_exception_from_name:
38  * @image: the Mono image where to look for the class
39  * @name_space: the namespace for the class
40  * @name: class name
41  *
42  * Creates an exception of the given namespace/name class in the
43  * current domain.
44  *
45  * Returns: the initialized exception instance.
46  */
47 MonoException *
48 mono_exception_from_name (MonoImage *image, const char *name_space,
49                           const char *name)
50 {
51         return mono_exception_from_name_domain (mono_domain_get (), image, name_space, name);
52 }
53
54 /**
55  * mono_exception_from_name_domain:
56  * @domain: Domain where the return object will be created.
57  * @image: the Mono image where to look for the class
58  * @name_space: the namespace for the class
59  * @name: class name
60  *
61  * Creates an exception object of the given namespace/name class on
62  * the given domain.
63  *
64  * Returns: the initialized exception instance.
65  */
66 MonoException *
67 mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, 
68                                  const char* name_space, const char *name)
69 {
70         MonoError error;
71         MonoClass *klass;
72         MonoObject *o;
73         MonoDomain *caller_domain = mono_domain_get ();
74
75         klass = mono_class_load_from_name (image, name_space, name);
76
77         o = mono_object_new_checked (domain, klass, &error);
78         mono_error_assert_ok (&error);
79
80         if (domain != caller_domain)
81                 mono_domain_set_internal (domain);
82         mono_runtime_object_init_checked (o, &error);
83         mono_error_assert_ok (&error);
84
85         if (domain != caller_domain)
86                 mono_domain_set_internal (caller_domain);
87
88         return (MonoException *)o;
89 }
90
91
92 /**
93  * mono_exception_from_token:
94  * @image: the Mono image where to look for the class
95  * @token: The type token of the class
96  *
97  * Creates an exception of the type given by @token.
98  *
99  * Returns: the initialized exception instance.
100  */
101 MonoException *
102 mono_exception_from_token (MonoImage *image, guint32 token)
103 {
104         MonoError error;
105         MonoClass *klass;
106         MonoObject *o;
107
108         klass = mono_class_get_checked (image, token, &error);
109         mono_error_assert_ok (&error);
110
111         o = mono_object_new_checked (mono_domain_get (), klass, &error);
112         mono_error_assert_ok (&error);
113         
114         mono_runtime_object_init_checked (o, &error);
115         mono_error_assert_ok (&error);
116
117         return (MonoException *)o;
118 }
119
120 static MonoException *
121 create_exception_two_strings (MonoClass *klass, MonoString *a1, MonoString *a2, MonoError *error)
122 {
123         MonoDomain *domain = mono_domain_get ();
124         MonoMethod *method = NULL;
125         MonoObject *o;
126         int count = 1;
127         gpointer args [2];
128         gpointer iter;
129         MonoMethod *m;
130
131         if (a2 != NULL)
132                 count++;
133         
134         o = mono_object_new_checked (domain, klass, error);
135         mono_error_assert_ok (error);
136
137         iter = NULL;
138         while ((m = mono_class_get_methods (klass, &iter))) {
139                 MonoMethodSignature *sig;
140                 
141                 if (strcmp (".ctor", mono_method_get_name (m)))
142                         continue;
143                 sig = mono_method_signature (m);
144                 if (sig->param_count != count)
145                         continue;
146
147                 if (sig->params [0]->type != MONO_TYPE_STRING)
148                         continue;
149                 if (count == 2 && sig->params [1]->type != MONO_TYPE_STRING)
150                         continue;
151                 method = m;
152                 break;
153         }
154
155         args [0] = a1;
156         args [1] = a2;
157
158         mono_runtime_invoke_checked (method, o, args, error);
159         return_val_if_nok (error, NULL);
160
161         return (MonoException *) o;
162 }
163
164 /**
165  * mono_exception_from_name_two_strings:
166  * @image: the Mono image where to look for the class
167  * @name_space: the namespace for the class
168  * @name: class name
169  * @a1: first string argument to pass
170  * @a2: second string argument to pass
171  *
172  * Creates an exception from a constructor that takes two string
173  * arguments.
174  *
175  * Returns: the initialized exception instance.
176  */
177 MonoException *
178 mono_exception_from_name_two_strings (MonoImage *image, const char *name_space,
179                                       const char *name, MonoString *a1, MonoString *a2)
180 {
181         MonoError error;
182         MonoException *ret;
183
184         ret = mono_exception_from_name_two_strings_checked (image, name_space, name, a1, a2, &error);
185         mono_error_cleanup (&error);
186         return ret;
187 }
188
189 /**
190  * mono_exception_from_name_two_strings_checked:
191  * @image: the Mono image where to look for the class
192  * @name_space: the namespace for the class
193  * @name: class name
194  * @a1: first string argument to pass
195  * @a2: second string argument to pass
196  * @error: set on error
197  *
198  * Creates an exception from a constructor that takes two string
199  * arguments.
200  *
201  * Returns: the initialized exception instance. On failure returns
202  * NULL and sets @error.
203  */
204 MonoException *
205 mono_exception_from_name_two_strings_checked (MonoImage *image, const char *name_space,
206                                               const char *name, MonoString *a1, MonoString *a2,
207                                               MonoError *error)
208 {
209         MonoClass *klass;
210
211         mono_error_init (error);
212         klass = mono_class_load_from_name (image, name_space, name);
213
214         return create_exception_two_strings (klass, a1, a2, error);
215 }
216
217 /**
218  * mono_exception_from_name_msg:
219  * @image: the Mono image where to look for the class
220  * @name_space: the namespace for the class
221  * @name: class name
222  * @msg: the message to embed inside the exception
223  *
224  * Creates an exception and initializes its message field.
225  *
226  * Returns: the initialized exception instance.
227  */
228 MonoException *
229 mono_exception_from_name_msg (MonoImage *image, const char *name_space,
230                               const char *name, const char *msg)
231 {
232         MonoException *ex;
233
234         ex = mono_exception_from_name (image, name_space, name);
235
236         if (msg)
237                 MONO_OBJECT_SETREF (ex, message, mono_string_new (mono_object_get_domain ((MonoObject*)ex), msg));
238
239         return ex;
240 }
241
242 /**
243  * mono_exception_from_token_two_strings:
244  *
245  *   Same as mono_exception_from_name_two_strings, but lookup the exception class using
246  * IMAGE and TOKEN.
247  */
248 MonoException *
249 mono_exception_from_token_two_strings (MonoImage *image, guint32 token,
250                                                                            MonoString *a1, MonoString *a2)
251 {
252         MonoError error;
253         MonoException *ret;
254         ret = mono_exception_from_token_two_strings_checked (image, token, a1, a2, &error);
255         mono_error_cleanup (&error);
256         return ret;
257 }
258
259 /**
260  * mono_exception_from_token_two_strings_checked:
261  *
262  *   Same as mono_exception_from_name_two_strings, but lookup the exception class using
263  * IMAGE and TOKEN.
264  */
265 MonoException *
266 mono_exception_from_token_two_strings_checked (MonoImage *image, guint32 token,
267                                                MonoString *a1, MonoString *a2,
268                                                MonoError *error)
269 {
270         MonoClass *klass;
271
272         mono_error_init (error);
273
274         klass = mono_class_get_checked (image, token, error);
275         mono_error_assert_ok (error); /* FIXME handle the error. */
276
277         return create_exception_two_strings (klass, a1, a2, error);
278 }
279
280 /**
281  * mono_get_exception_divide_by_zero:
282  *
283  * Returns: a new instance of the `System.DivideByZeroException`
284  */
285 MonoException *
286 mono_get_exception_divide_by_zero ()
287 {
288         return mono_exception_from_name (mono_get_corlib (), "System",
289                                          "DivideByZeroException");
290 }
291
292 /**
293  * mono_get_exception_security:
294  *
295  * Returns: a new instance of the `System.Security.SecurityException`
296  */
297 MonoException *
298 mono_get_exception_security ()
299 {
300         return mono_exception_from_name (mono_get_corlib (), "System.Security",
301                                          "SecurityException");
302 }
303
304 /**
305  * mono_get_exception_thread_abort:
306  *
307  * Returns: a new instance of the `System.Threading.ThreadAbortException`
308  */
309 MonoException *
310 mono_get_exception_thread_abort ()
311 {
312         return mono_exception_from_name (mono_get_corlib (), "System.Threading",
313                                          "ThreadAbortException");
314 }
315
316 /**
317  * mono_get_exception_thread_interrupted:
318  *
319  * Returns: a new instance of the `System.Threading.ThreadInterruptedException`
320  */
321 MonoException *
322 mono_get_exception_thread_interrupted ()
323 {
324         return mono_exception_from_name (mono_get_corlib (), "System.Threading",
325                                          "ThreadInterruptedException");
326 }
327
328 /**
329  * mono_get_exception_arithmetic:
330  *
331  * Returns: a new instance of the `System.ArithmeticException`
332  */
333 MonoException *
334 mono_get_exception_arithmetic ()
335 {
336         return mono_exception_from_name (mono_get_corlib (), "System",
337                                          "ArithmeticException");
338 }
339
340 /**
341  * mono_get_exception_overflow:
342  *
343  * Returns: a new instance of the `System.OverflowException`
344  */
345 MonoException *
346 mono_get_exception_overflow ()
347 {
348         return mono_exception_from_name (mono_get_corlib (), "System",
349                                          "OverflowException");
350 }
351
352 /**
353  * mono_get_exception_null_reference:
354  *
355  * Returns: a new instance of the `System.NullReferenceException`
356  */
357 MonoException *
358 mono_get_exception_null_reference ()
359 {
360         return mono_exception_from_name (mono_get_corlib (), "System",
361                                          "NullReferenceException");
362 }
363
364 /**
365  * mono_get_exception_execution_engine:
366  * @msg: the message to pass to the user
367  *
368  * Returns: a new instance of the `System.ExecutionEngineException`
369  */
370 MonoException *
371 mono_get_exception_execution_engine (const char *msg)
372 {
373         return mono_exception_from_name_msg (mono_get_corlib (), "System", "ExecutionEngineException", msg);
374 }
375
376 /**
377  * mono_get_exception_serialization:
378  * @msg: the message to pass to the user
379  *
380  * Returns: a new instance of the `System.Runtime.Serialization.SerializationException`
381  */
382 MonoException *
383 mono_get_exception_serialization (const char *msg)
384 {
385         return mono_exception_from_name_msg (mono_get_corlib (), "System.Runtime.Serialization", "SerializationException", msg);
386 }
387
388 /**
389  * mono_get_exception_invalid_cast:
390  *
391  * Returns: a new instance of the `System.InvalidCastException`
392  */
393 MonoException *
394 mono_get_exception_invalid_cast ()
395 {
396         return mono_exception_from_name (mono_get_corlib (), "System", "InvalidCastException");
397 }
398
399 /**
400  * mono_get_exception_invalid_operation:
401  * @msg: the message to pass to the user
402  *
403  * Returns: a new instance of the `System.InvalidOperationException`
404  */
405 MonoException *
406 mono_get_exception_invalid_operation (const char *msg)
407 {
408         return mono_exception_from_name_msg (mono_get_corlib (), "System",
409                                         "InvalidOperationException", msg);
410 }
411
412 /**
413  * mono_get_exception_index_out_of_range:
414  *
415  * Returns: a new instance of the `System.IndexOutOfRangeException`
416  */
417 MonoException *
418 mono_get_exception_index_out_of_range ()
419 {
420         return mono_exception_from_name (mono_get_corlib (), "System",
421                                          "IndexOutOfRangeException");
422 }
423
424 /**
425  * mono_get_exception_array_type_mismatch:
426  *
427  * Returns: a new instance of the `System.ArrayTypeMismatchException`
428  */
429 MonoException *
430 mono_get_exception_array_type_mismatch ()
431 {
432         return mono_exception_from_name (mono_get_corlib (), "System",
433                                          "ArrayTypeMismatchException");
434 }
435
436 /**
437  * mono_get_exception_type_load:
438  * @class_name: the name of the class that could not be loaded
439  * @assembly_name: the assembly where the class was looked up.
440  *
441  * Returns: a new instance of the `System.TypeLoadException`
442  */
443 MonoException *
444 mono_get_exception_type_load (MonoString *class_name, char *assembly_name)
445 {
446         MonoString *s = assembly_name ? mono_string_new (mono_domain_get (), assembly_name) : mono_string_new (mono_domain_get (), "");
447
448         MonoError error;
449         MonoException *ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System",
450                                                                    "TypeLoadException", class_name, s, &error);
451         mono_error_assert_ok (&error);
452         return ret;
453 }
454
455 /**
456  * mono_get_exception_not_implemented:
457  * @msg: the message to pass to the user
458  *
459  * Returns: a new instance of the `System.NotImplementedException`
460  */
461 MonoException *
462 mono_get_exception_not_implemented (const char *msg)
463 {
464         return mono_exception_from_name_msg (mono_get_corlib (), "System", "NotImplementedException", msg);
465 }
466
467 /**
468  * mono_get_exception_not_supported:
469  * @msg: the message to pass to the user
470  *
471  * Returns: a new instance of the `System.NotSupportedException`
472  */
473 MonoException *
474 mono_get_exception_not_supported (const char *msg)
475 {
476         return mono_exception_from_name_msg (mono_get_corlib (), "System", "NotSupportedException", msg);
477 }
478
479 /**
480  * mono_get_exception_missing_method:
481  * @class_name: the class where the lookup was performed.
482  * @member_name: the name of the missing method.
483  *
484  * Returns: a new instance of the `System.MissingMethodException`
485  */
486 MonoException *
487 mono_get_exception_missing_method (const char *class_name, const char *member_name)
488 {
489         MonoString *s1 = mono_string_new (mono_domain_get (), class_name);
490         MonoString *s2 = mono_string_new (mono_domain_get (), member_name);
491
492         MonoError error;
493         MonoException *ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System",
494                                                                            "MissingMethodException", s1, s2, &error);
495         mono_error_assert_ok (&error);
496         return ret;
497 }
498
499 /**
500  * mono_get_exception_missing_field:
501  * @class_name: the class where the lookup was performed
502  * @member_name: the name of the missing method.
503  *
504  * Returns: a new instance of the `System.MissingFieldException`
505  */
506 MonoException *
507 mono_get_exception_missing_field (const char *class_name, const char *member_name)
508 {
509         MonoString *s1 = mono_string_new (mono_domain_get (), class_name);
510         MonoString *s2 = mono_string_new (mono_domain_get (), member_name);
511
512         MonoError error;
513         MonoException *ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System",
514                                                                    "MissingFieldException", s1, s2, &error);
515         mono_error_assert_ok (&error);
516         return ret;
517 }
518
519 /**
520  * mono_get_exception_argument_null:
521  * @arg: the name of the argument that is null
522  *
523  * Returns: a new instance of the `System.ArgumentNullException`
524  */
525 MonoException*
526 mono_get_exception_argument_null (const char *arg)
527 {
528         MonoException *ex;
529
530         ex = mono_exception_from_name ( 
531                 mono_get_corlib (), "System", "ArgumentNullException");
532
533         if (arg) {
534                 MonoArgumentException *argex = (MonoArgumentException *)ex;
535                 MONO_OBJECT_SETREF (argex, param_name, mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg));
536         }
537         
538         return ex;
539 }
540
541 /**
542  * mono_get_exception_argument:
543  * @arg: the name of the invalid argument.
544  *
545  * Returns: a new instance of the `System.ArgumentException`
546  */
547 MonoException *
548 mono_get_exception_argument (const char *arg, const char *msg)
549 {
550         MonoException *ex;
551
552         ex = mono_exception_from_name_msg (
553                 mono_get_corlib (), "System", "ArgumentException", msg);
554
555         if (arg) {
556                 MonoArgumentException *argex = (MonoArgumentException *)ex;
557                 MONO_OBJECT_SETREF (argex, param_name, mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg));
558         }
559         
560         return ex;
561 }
562
563 /**
564  * mono_get_exception_argument_out_of_range:
565  * @arg: the name of the out of range argument.
566  *
567  * Returns: a new instance of the `System.ArgumentOutOfRangeException`
568  */
569 MonoException *
570 mono_get_exception_argument_out_of_range (const char *arg)
571 {
572         MonoException *ex;
573
574         ex = mono_exception_from_name (
575                 mono_get_corlib (), "System", "ArgumentOutOfRangeException");
576
577         if (arg) {
578                 MonoArgumentException *argex = (MonoArgumentException *)ex;
579                 MONO_OBJECT_SETREF (argex, param_name, mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg));
580         }
581         
582         return ex;
583 }
584
585 /**
586  * mono_get_exception_thread_state:
587  * @msg: the message to present to the user
588  *
589  * Returns: a new instance of the `System.Threading.ThreadStateException`
590  */
591 MonoException *
592 mono_get_exception_thread_state (const char *msg)
593 {
594         return mono_exception_from_name_msg (
595                 mono_get_corlib (), "System.Threading", "ThreadStateException", msg);
596 }
597
598 /**
599  * mono_get_exception_io:
600  * @msg: the message to present to the user
601  *
602  * Returns: a new instance of the `System.IO.IOException`
603  */
604 MonoException *
605 mono_get_exception_io (const char *msg)
606 {
607         return mono_exception_from_name_msg ( 
608                 mono_get_corlib (), "System.IO", "IOException", msg);
609 }
610
611 /**
612  * mono_get_exception_file_not_found:
613  * @fname: the name of the file not found.
614  *
615  * Returns: a new instance of the `System.IO.FileNotFoundException`
616  */
617 MonoException *
618 mono_get_exception_file_not_found (MonoString *fname)
619 {
620         MonoError error;
621         MonoException *ret = mono_exception_from_name_two_strings_checked (
622                 mono_get_corlib (), "System.IO", "FileNotFoundException", fname, fname, &error);
623         mono_error_assert_ok (&error);
624         return ret;
625 }
626
627 /**
628  * mono_get_exception_file_not_found2:
629  * @msg: an informative message for the user.
630  * @fname: the name of the file not found.
631  *
632  * Returns: a new instance of the `System.IO.FileNotFoundException`
633  */
634 MonoException *
635 mono_get_exception_file_not_found2 (const char *msg, MonoString *fname)
636 {
637         MonoString *s = msg ? mono_string_new (mono_domain_get (), msg) : NULL;
638
639         MonoError error;
640         MonoException *ret = mono_exception_from_name_two_strings_checked (
641                 mono_get_corlib (), "System.IO", "FileNotFoundException", s, fname, &error);
642         mono_error_assert_ok (&error);
643         return ret;
644 }
645
646 /**
647  * mono_get_exception_type_initialization:
648  * @type_name: the name of the type that failed to initialize.
649  * @inner: the inner exception.
650  *
651  * Returns: a new instance of the `System.TypeInitializationException`
652  */
653 MonoException *
654 mono_get_exception_type_initialization (const gchar *type_name, MonoException *inner)
655 {
656         MonoError error;
657         MonoException *ret = mono_get_exception_type_initialization_checked (type_name, inner, &error);
658         if (!is_ok (&error)) {
659                 mono_error_cleanup (&error);
660                 return NULL;
661         }
662
663         return ret;
664 }
665
666 MonoException *
667 mono_get_exception_type_initialization_checked (const gchar *type_name, MonoException *inner, MonoError *error)
668 {
669         MonoClass *klass;
670         gpointer args [2];
671         MonoObject *exc;
672         MonoMethod *method;
673         gpointer iter;
674
675         klass = mono_class_load_from_name (mono_get_corlib (), "System", "TypeInitializationException");
676
677         mono_class_init (klass);
678
679         iter = NULL;
680         while ((method = mono_class_get_methods (klass, &iter))) {
681                 if (!strcmp (".ctor", mono_method_get_name (method))) {
682                         MonoMethodSignature *sig = mono_method_signature (method);
683
684                         if (sig->param_count == 2 && sig->params [0]->type == MONO_TYPE_STRING && mono_class_from_mono_type (sig->params [1]) == mono_defaults.exception_class)
685                                 break;
686                 }
687                 method = NULL;
688         }
689         g_assert (method);
690
691         args [0] = mono_string_new (mono_domain_get (), type_name);
692         args [1] = inner;
693
694         exc = mono_object_new_checked (mono_domain_get (), klass, error);
695         mono_error_assert_ok (error);
696
697         mono_runtime_invoke_checked (method, exc, args, error);
698         return_val_if_nok (error, NULL);
699
700         return (MonoException *) exc;
701 }
702
703 /**
704  * mono_get_exception_synchronization_lock:
705  * @inner: the inner exception.
706  *
707  * Returns: a new instance of the `System.SynchronizationLockException`
708  */
709 MonoException *
710 mono_get_exception_synchronization_lock (const char *msg)
711 {
712         return mono_exception_from_name_msg (mono_get_corlib (), "System.Threading", "SynchronizationLockException", msg);
713 }
714
715 /**
716  * mono_get_exception_cannot_unload_appdomain:
717  * @inner: the inner exception.
718  *
719  * Returns: a new instance of the `System.CannotUnloadAppDomainException`
720  */
721 MonoException *
722 mono_get_exception_cannot_unload_appdomain (const char *msg)
723 {
724         return mono_exception_from_name_msg (mono_get_corlib (), "System", "CannotUnloadAppDomainException", msg);
725 }
726
727 /**
728  * mono_get_exception_appdomain_unloaded
729  *
730  * Returns: a new instance of the `System.AppDomainUnloadedException`
731  */
732 MonoException *
733 mono_get_exception_appdomain_unloaded (void)
734 {
735         return mono_exception_from_name (mono_get_corlib (), "System", "AppDomainUnloadedException");
736 }
737
738 /**
739  * mono_get_exception_bad_image_format:
740  * @msg: an informative message for the user.
741  *
742  * Returns: a new instance of the `System.BadImageFormatException`
743  */
744 MonoException *
745 mono_get_exception_bad_image_format (const char *msg)
746 {
747         return mono_exception_from_name_msg (mono_get_corlib (), "System", "BadImageFormatException", msg);
748 }       
749
750 /**
751  * mono_get_exception_bad_image_format2:
752  * @msg: an informative message for the user.
753  * @fname: The full name of the file with the invalid image.
754  *
755  * Returns: a new instance of the `System.BadImageFormatException`
756  */
757 MonoException *
758 mono_get_exception_bad_image_format2 (const char *msg, MonoString *fname)
759 {
760         MonoString *s = msg ? mono_string_new (mono_domain_get (), msg) : NULL;
761
762         MonoError error;
763         MonoException *ret = mono_exception_from_name_two_strings_checked (
764                 mono_get_corlib (), "System", "BadImageFormatException", s, fname, &error);
765         mono_error_assert_ok (&error);
766         return ret;
767 }
768
769 /**
770  * mono_get_exception_stack_overflow:
771  *
772  * Returns: a new instance of the `System.StackOverflowException`
773  */
774 MonoException *
775 mono_get_exception_stack_overflow (void)
776 {
777         return mono_exception_from_name (mono_get_corlib (), "System", "StackOverflowException");       
778 }
779
780 /**
781  * mono_get_exception_out_of_memory:
782  *
783  * Returns: a new instance of the `System.OutOfMemoryException`
784  */
785 MonoException *
786 mono_get_exception_out_of_memory (void)
787 {
788         return mono_exception_from_name (mono_get_corlib (), "System", "OutOfMemoryException");
789 }
790
791 /**
792  * mono_get_exception_field_access:
793  *
794  * Returns: a new instance of the `System.FieldAccessException`
795  */
796 MonoException *
797 mono_get_exception_field_access (void)
798 {
799         return mono_exception_from_name (mono_get_corlib (), "System", "FieldAccessException");
800 }
801
802 /**
803  * mono_get_exception_field_access2:
804  * @msg: an informative message for the user.
805  *
806  * Returns: a new instance of the `System.FieldAccessException`
807  */
808 MonoException *
809 mono_get_exception_field_access_msg (const char *msg)
810 {
811         return mono_exception_from_name_msg (mono_get_corlib (), "System", "FieldAccessException", msg);
812 }
813
814 /**
815  * mono_get_exception_method_access:
816  *
817  * Returns: a new instance of the `System.MethodAccessException`
818  */
819 MonoException *
820 mono_get_exception_method_access (void)
821 {
822         return mono_exception_from_name (mono_get_corlib (), "System", "MethodAccessException");
823 }
824
825 /**
826  * mono_get_exception_method_access2:
827  * @msg: an informative message for the user.
828  *
829  * Returns: a new instance of the `System.MethodAccessException`
830  */
831 MonoException *
832 mono_get_exception_method_access_msg (const char *msg)
833 {
834         return mono_exception_from_name_msg (mono_get_corlib (), "System", "MethodAccessException", msg);
835 }
836
837 /**
838  * mono_get_exception_reflection_type_load:
839  * @types: an array of types that were defined in the moduled loaded.
840  * @exceptions: an array of exceptions that were thrown during the type loading.
841  *
842  * Returns: a new instance of the `System.Reflection.ReflectionTypeLoadException`
843  */
844 MonoException *
845 mono_get_exception_reflection_type_load (MonoArray *types_raw, MonoArray *exceptions_raw)
846 {
847         HANDLE_FUNCTION_ENTER ();
848         MonoError error;
849         MONO_HANDLE_DCL (MonoArray, types);
850         MONO_HANDLE_DCL (MonoArray, exceptions);
851         MonoExceptionHandle ret = mono_get_exception_reflection_type_load_checked (types, exceptions, &error);
852         if (is_ok (&error)) {
853                 mono_error_cleanup (&error);
854                 ret = MONO_HANDLE_CAST (MonoException, NULL_HANDLE);
855                 goto leave;
856         }
857
858 leave:
859         HANDLE_FUNCTION_RETURN_OBJ (ret);
860
861 }
862
863 MonoExceptionHandle
864 mono_get_exception_reflection_type_load_checked (MonoArrayHandle types, MonoArrayHandle exceptions, MonoError *error)
865 {
866         MonoClass *klass;
867         MonoMethod *method;
868         gpointer iter;
869
870         mono_error_init (error);
871
872         klass = mono_class_load_from_name (mono_get_corlib (), "System.Reflection", "ReflectionTypeLoadException");
873
874         mono_class_init (klass);
875
876         /* Find the Type[], Exception[] ctor */
877         iter = NULL;
878         while ((method = mono_class_get_methods (klass, &iter))) {
879                 if (!strcmp (".ctor", mono_method_get_name (method))) {
880                         MonoMethodSignature *sig = mono_method_signature (method);
881
882                         if (sig->param_count == 2 && sig->params [0]->type == MONO_TYPE_SZARRAY && sig->params [1]->type == MONO_TYPE_SZARRAY)
883                                 break;
884                 }
885                 method = NULL;
886         }
887         g_assert (method);
888
889         MonoExceptionHandle exc = MONO_HANDLE_NEW (MonoException, mono_object_new_checked (mono_domain_get (), klass, error));
890         mono_error_assert_ok (error);
891
892         gpointer args [2];
893         args [0] = MONO_HANDLE_RAW (types);
894         args [1] = MONO_HANDLE_RAW (exceptions);
895
896         mono_runtime_invoke_checked (method, MONO_HANDLE_RAW (exc), args, error);
897         return_val_if_nok (error, MONO_HANDLE_CAST (MonoException, NULL_HANDLE));
898
899         return exc;
900 }
901
902 MonoException *
903 mono_get_exception_runtime_wrapped (MonoObject *wrapped_exception)
904 {
905         MonoError error;
906         MonoException *ret = mono_get_exception_runtime_wrapped_checked (wrapped_exception, &error);
907         if (!is_ok (&error)) {
908                 mono_error_cleanup (&error);
909                 return NULL;
910         }
911
912         return ret;
913 }
914
915 MonoException *
916 mono_get_exception_runtime_wrapped_checked (MonoObject *wrapped_exception, MonoError *error)
917 {
918         MonoClass *klass;
919         MonoObject *o;
920         MonoMethod *method;
921         MonoDomain *domain = mono_domain_get ();
922         gpointer params [16];
923
924         klass = mono_class_load_from_name (mono_get_corlib (), "System.Runtime.CompilerServices", "RuntimeWrappedException");
925
926         o = mono_object_new_checked (domain, klass, error);
927         mono_error_assert_ok (error);
928         g_assert (o != NULL);
929
930         method = mono_class_get_method_from_name (klass, ".ctor", 1);
931         g_assert (method);
932
933         params [0] = wrapped_exception;
934
935         mono_runtime_invoke_checked (method, o, params, error);
936         return_val_if_nok (error, NULL);
937
938         return (MonoException *)o;
939 }       
940
941 static gboolean
942 append_frame_and_continue (MonoMethod *method, gpointer ip, size_t native_offset, gboolean managed, gpointer user_data)
943 {
944         MonoDomain *domain = mono_domain_get ();
945         GString *text = (GString*)user_data;
946
947         if (method) {
948                 char *msg = mono_debug_print_stack_frame (method, native_offset, domain);
949                 g_string_append_printf (text, "%s\n", msg);
950                 g_free (msg);
951         } else {
952                 g_string_append_printf (text, "<unknown native frame 0x%x>\n", ip);
953         }
954
955         return FALSE;
956 }
957
958 char *
959 mono_exception_get_managed_backtrace (MonoException *exc)
960 {
961         GString *text;
962
963         text = g_string_new_len (NULL, 20);
964
965         if (!mono_get_eh_callbacks ()->mono_exception_walk_trace (exc, append_frame_and_continue, text))
966                 g_string_append (text, "managed backtrace not available\n");
967
968         return g_string_free (text, FALSE);
969 }
970
971 char *
972 mono_exception_handle_get_native_backtrace (MonoExceptionHandle exc)
973 {
974 #ifdef HAVE_BACKTRACE_SYMBOLS
975         MonoDomain *domain;
976         MonoArrayHandle arr = MONO_HANDLE_NEW(MonoArray, NULL);
977         int i, len;
978         GString *text;
979         char **messages;
980
981         MONO_HANDLE_GET (arr, exc, native_trace_ips);
982
983         if (MONO_HANDLE_IS_NULL(arr))
984                 return g_strdup ("");
985         domain = mono_domain_get ();
986         len = mono_array_handle_length (arr);
987         text = g_string_new_len (NULL, len * 20);
988         uint32_t gchandle;
989         void *addr = MONO_ARRAY_HANDLE_PIN (arr, gpointer, 0, &gchandle);
990         MONO_ENTER_GC_SAFE;
991         messages = backtrace_symbols (addr, len);
992         MONO_EXIT_GC_SAFE;
993         mono_gchandle_free (gchandle);
994
995         for (i = 0; i < len; ++i) {
996                 gpointer ip;
997                 MONO_HANDLE_ARRAY_GETVAL (ip, arr, gpointer, i);
998                 MonoJitInfo *ji = mono_jit_info_table_find (mono_domain_get (), (char *)ip);
999                 if (ji) {
1000                         char *msg = mono_debug_print_stack_frame (mono_jit_info_get_method (ji), (char*)ip - (char*)ji->code_start, domain);
1001                         g_string_append_printf (text, "%s\n", msg);
1002                         g_free (msg);
1003                 } else {
1004                         g_string_append_printf (text, "%s\n", messages [i]);
1005                 }
1006         }
1007
1008         g_free (messages);
1009         return g_string_free (text, FALSE);
1010 #else
1011         return g_strdup ("");
1012 #endif
1013 }
1014
1015 MonoStringHandle
1016 ves_icall_Mono_Runtime_GetNativeStackTrace (MonoExceptionHandle exc, MonoError *error)
1017 {
1018         char *trace;
1019         MonoStringHandle res;
1020         mono_error_init (error);
1021
1022         if (!exc) {
1023                 mono_error_set_argument_null (error, "exception", "");
1024                 return NULL_HANDLE_STRING;
1025         }
1026
1027         trace = mono_exception_handle_get_native_backtrace (exc);
1028         res = mono_string_new_handle (mono_domain_get (), trace, error);
1029         g_free (trace);
1030         return res;
1031 }
1032
1033 /**
1034  * mono_error_raise_exception:
1035  * @target_error: the exception to raise
1036  *
1037  * Raises the exception of @target_error.
1038  * Does nothing if @target_error has a success error code.
1039  * Aborts in case of a double fault. This happens when it can't recover from an error caused by trying
1040  * to construct the first exception object.
1041  * The error object @target_error is cleaned up.
1042 */
1043 void
1044 mono_error_raise_exception (MonoError *target_error)
1045 {
1046         MonoException *ex = mono_error_convert_to_exception (target_error);
1047         if (ex)
1048                 mono_raise_exception (ex);
1049 }
1050
1051 /**
1052  * mono_error_set_pending_exception:
1053  * @error: The error
1054  *
1055  *
1056  * If @error is set, convert it to an exception and set the pending exception for the current icall.
1057  * Returns TRUE if @error was set, or FALSE otherwise, so that you can write:
1058  *    if (mono_error_set_pending_exception (error)) {
1059  *      { ... cleanup code ... }
1060  *      return;
1061  *    }
1062  */
1063 gboolean
1064 mono_error_set_pending_exception (MonoError *error)
1065 {
1066         MonoException *ex = mono_error_convert_to_exception (error);
1067         if (ex) {
1068                 mono_set_pending_exception (ex);
1069                 return TRUE;
1070         } else {
1071                 return FALSE;
1072         }
1073 }
1074
1075 void
1076 mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, void *user_data)
1077 {
1078         unhandled_exception_hook = func;
1079         unhandled_exception_hook_data = user_data;
1080 }
1081
1082 void
1083 mono_invoke_unhandled_exception_hook (MonoObject *exc)
1084 {
1085         if (unhandled_exception_hook) {
1086                 unhandled_exception_hook (exc, unhandled_exception_hook_data);
1087         } else {
1088                 MonoError inner_error;
1089                 MonoObject *other = NULL;
1090                 MonoString *str = mono_object_try_to_string (exc, &other, &inner_error);
1091                 char *msg = NULL;
1092                 
1093                 if (str && is_ok (&inner_error)) {
1094                         msg = mono_string_to_utf8_checked (str, &inner_error);
1095                         if (!is_ok (&inner_error)) {
1096                                 msg = g_strdup_printf ("Nested exception while formatting original exception");
1097                                 mono_error_cleanup (&inner_error);
1098                         }
1099                 } else if (other) {
1100                         char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc);
1101                         char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other);
1102
1103                         msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n",
1104                                 original_backtrace, nested_backtrace);
1105
1106                         g_free (original_backtrace);
1107                         g_free (nested_backtrace);
1108                 } else {
1109                         msg = g_strdup ("Nested exception trying to figure out what went wrong");
1110                 }
1111                 mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
1112                 g_free (msg);
1113 #if defined(HOST_IOS)
1114                 g_assertion_message ("Terminating runtime due to unhandled exception");
1115 #else
1116                 exit (mono_environment_exitcode_get ());
1117 #endif
1118         }
1119
1120         g_assert_not_reached ();
1121 }