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