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