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