Merge pull request #2593 from ludovic-henry/coop-fix-native-to-managed
[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_load_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_load_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_load_from_name (mono_get_corlib (), "System", "TypeInitializationException");
587
588         mono_class_init (klass);
589
590         iter = NULL;
591         while ((method = mono_class_get_methods (klass, &iter))) {
592                 if (!strcmp (".ctor", mono_method_get_name (method))) {
593                         MonoMethodSignature *sig = mono_method_signature (method);
594
595                         if (sig->param_count == 2 && sig->params [0]->type == MONO_TYPE_STRING && mono_class_from_mono_type (sig->params [1]) == mono_defaults.exception_class)
596                                 break;
597                 }
598                 method = NULL;
599         }
600         g_assert (method);
601
602         args [0] = mono_string_new (mono_domain_get (), type_name);
603         args [1] = inner;
604
605         exc = mono_object_new_checked (mono_domain_get (), klass, &error);
606         mono_error_assert_ok (&error);
607         mono_runtime_invoke_checked (method, exc, args, &error);
608         mono_error_raise_exception (&error); /* FIXME don't raise here */
609
610         return (MonoException *) exc;
611 }
612
613 /**
614  * mono_get_exception_synchronization_lock:
615  * @inner: the inner exception.
616  *
617  * Returns: a new instance of the `System.SynchronizationLockException`
618  */
619 MonoException *
620 mono_get_exception_synchronization_lock (const char *msg)
621 {
622         return mono_exception_from_name_msg (mono_get_corlib (), "System.Threading", "SynchronizationLockException", msg);
623 }
624
625 /**
626  * mono_get_exception_cannot_unload_appdomain:
627  * @inner: the inner exception.
628  *
629  * Returns: a new instance of the `System.CannotUnloadAppDomainException`
630  */
631 MonoException *
632 mono_get_exception_cannot_unload_appdomain (const char *msg)
633 {
634         return mono_exception_from_name_msg (mono_get_corlib (), "System", "CannotUnloadAppDomainException", msg);
635 }
636
637 /**
638  * mono_get_exception_appdomain_unloaded
639  *
640  * Returns: a new instance of the `System.AppDomainUnloadedException`
641  */
642 MonoException *
643 mono_get_exception_appdomain_unloaded (void)
644 {
645         return mono_exception_from_name (mono_get_corlib (), "System", "AppDomainUnloadedException");
646 }
647
648 /**
649  * mono_get_exception_bad_image_format:
650  * @msg: an informative message for the user.
651  *
652  * Returns: a new instance of the `System.BadImageFormatException`
653  */
654 MonoException *
655 mono_get_exception_bad_image_format (const char *msg)
656 {
657         return mono_exception_from_name_msg (mono_get_corlib (), "System", "BadImageFormatException", msg);
658 }       
659
660 /**
661  * mono_get_exception_bad_image_format2:
662  * @msg: an informative message for the user.
663  * @fname: The full name of the file with the invalid image.
664  *
665  * Returns: a new instance of the `System.BadImageFormatException`
666  */
667 MonoException *
668 mono_get_exception_bad_image_format2 (const char *msg, MonoString *fname)
669 {
670         MonoString *s = msg ? mono_string_new (mono_domain_get (), msg) : NULL;
671
672         return mono_exception_from_name_two_strings (
673                 mono_get_corlib (), "System", "BadImageFormatException", s, fname);
674 }
675
676 /**
677  * mono_get_exception_stack_overflow:
678  *
679  * Returns: a new instance of the `System.StackOverflowException`
680  */
681 MonoException *
682 mono_get_exception_stack_overflow (void)
683 {
684         return mono_exception_from_name (mono_get_corlib (), "System", "StackOverflowException");       
685 }
686
687 /**
688  * mono_get_exception_out_of_memory:
689  *
690  * Returns: a new instance of the `System.OutOfMemoryException`
691  */
692 MonoException *
693 mono_get_exception_out_of_memory (void)
694 {
695         return mono_exception_from_name (mono_get_corlib (), "System", "OutOfMemoryException");
696 }
697
698 /**
699  * mono_get_exception_field_access:
700  *
701  * Returns: a new instance of the `System.FieldAccessException`
702  */
703 MonoException *
704 mono_get_exception_field_access (void)
705 {
706         return mono_exception_from_name (mono_get_corlib (), "System", "FieldAccessException");
707 }
708
709 /**
710  * mono_get_exception_field_access2:
711  * @msg: an informative message for the user.
712  *
713  * Returns: a new instance of the `System.FieldAccessException`
714  */
715 MonoException *
716 mono_get_exception_field_access_msg (const char *msg)
717 {
718         return mono_exception_from_name_msg (mono_get_corlib (), "System", "FieldAccessException", msg);
719 }
720
721 /**
722  * mono_get_exception_method_access:
723  *
724  * Returns: a new instance of the `System.MethodAccessException`
725  */
726 MonoException *
727 mono_get_exception_method_access (void)
728 {
729         return mono_exception_from_name (mono_get_corlib (), "System", "MethodAccessException");
730 }
731
732 /**
733  * mono_get_exception_method_access2:
734  * @msg: an informative message for the user.
735  *
736  * Returns: a new instance of the `System.MethodAccessException`
737  */
738 MonoException *
739 mono_get_exception_method_access_msg (const char *msg)
740 {
741         return mono_exception_from_name_msg (mono_get_corlib (), "System", "MethodAccessException", msg);
742 }
743
744 /**
745  * mono_get_exception_reflection_type_load:
746  * @types: an array of types that were defined in the moduled loaded.
747  * @exceptions: an array of exceptions that were thrown during the type loading.
748  *
749  * Returns: a new instance of the `System.Reflection.ReflectionTypeLoadException`
750  */
751 MonoException *
752 mono_get_exception_reflection_type_load (MonoArray *types, MonoArray *exceptions)
753 {
754         MonoError error;
755         MonoClass *klass;
756         gpointer args [2];
757         MonoObject *exc;
758         MonoMethod *method;
759         gpointer iter;
760
761         klass = mono_class_load_from_name (mono_get_corlib (), "System.Reflection", "ReflectionTypeLoadException");
762
763         mono_class_init (klass);
764
765         /* Find the Type[], Exception[] ctor */
766         iter = NULL;
767         while ((method = mono_class_get_methods (klass, &iter))) {
768                 if (!strcmp (".ctor", mono_method_get_name (method))) {
769                         MonoMethodSignature *sig = mono_method_signature (method);
770
771                         if (sig->param_count == 2 && sig->params [0]->type == MONO_TYPE_SZARRAY && sig->params [1]->type == MONO_TYPE_SZARRAY)
772                                 break;
773                 }
774                 method = NULL;
775         }
776         g_assert (method);
777
778         args [0] = types;
779         args [1] = exceptions;
780
781         exc = mono_object_new_checked (mono_domain_get (), klass, &error);
782         mono_error_assert_ok (&error);
783
784         mono_runtime_invoke_checked (method, exc, args, &error);
785         mono_error_raise_exception (&error); /* FIXME don't raise here */
786
787         return (MonoException *) exc;
788 }
789
790 MonoException *
791 mono_get_exception_runtime_wrapped (MonoObject *wrapped_exception)
792 {
793         MonoError error;
794         MonoClass *klass;
795         MonoObject *o;
796         MonoMethod *method;
797         MonoDomain *domain = mono_domain_get ();
798         gpointer params [16];
799
800         klass = mono_class_load_from_name (mono_get_corlib (), "System.Runtime.CompilerServices", "RuntimeWrappedException");
801
802         o = mono_object_new_checked (domain, klass, &error);
803         g_assert (o != NULL && mono_error_ok (&error)); /* FIXME don't swallow the error */
804
805         method = mono_class_get_method_from_name (klass, ".ctor", 1);
806         g_assert (method);
807
808         params [0] = wrapped_exception;
809
810         mono_runtime_invoke_checked (method, o, params, &error);
811         mono_error_raise_exception (&error); /* FIXME don't raise here */
812
813         return (MonoException *)o;
814 }       
815
816 static gboolean
817 append_frame_and_continue (MonoMethod *method, gpointer ip, size_t native_offset, gboolean managed, gpointer user_data)
818 {
819         MonoDomain *domain = mono_domain_get ();
820         GString *text = (GString*)user_data;
821
822         if (method) {
823                 char *msg = mono_debug_print_stack_frame (method, native_offset, domain);
824                 g_string_append_printf (text, "%s\n", msg);
825                 g_free (msg);
826         } else {
827                 g_string_append_printf (text, "<unknown native frame 0x%x>\n", ip);
828         }
829
830         return FALSE;
831 }
832
833 char *
834 mono_exception_get_managed_backtrace (MonoException *exc)
835 {
836         GString *text;
837
838         text = g_string_new_len (NULL, 20);
839
840         if (!mono_get_eh_callbacks ()->mono_exception_walk_trace (exc, append_frame_and_continue, text))
841                 g_string_append (text, "managed backtrace not available\n");
842
843         return g_string_free (text, FALSE);
844 }
845
846 char *
847 mono_exception_get_native_backtrace (MonoException *exc)
848 {
849 #ifdef HAVE_BACKTRACE_SYMBOLS
850         MonoDomain *domain;
851         MonoArray *arr = exc->native_trace_ips;
852         int i, len;
853         GString *text;
854         char **messages;
855
856         if (!arr)
857                 return g_strdup ("");
858         domain = mono_domain_get ();
859         len = mono_array_length (arr);
860         text = g_string_new_len (NULL, len * 20);
861         messages = backtrace_symbols (mono_array_addr (arr, gpointer, 0), len);
862
863
864         for (i = 0; i < len; ++i) {
865                 gpointer ip = mono_array_get (arr, gpointer, i);
866                 MonoJitInfo *ji = mono_jit_info_table_find (mono_domain_get (), (char *)ip);
867                 if (ji) {
868                         char *msg = mono_debug_print_stack_frame (mono_jit_info_get_method (ji), (char*)ip - (char*)ji->code_start, domain);
869                         g_string_append_printf (text, "%s\n", msg);
870                         g_free (msg);
871                 } else {
872                         g_string_append_printf (text, "%s\n", messages [i]);
873                 }
874         }
875
876         free (messages);
877         return g_string_free (text, FALSE);
878 #else
879         return g_strdup ("");
880 #endif
881 }
882
883 MonoString *
884 ves_icall_Mono_Runtime_GetNativeStackTrace (MonoException *exc)
885 {
886         char *trace;
887         MonoString *res;
888         if (!exc)
889                 mono_raise_exception (mono_get_exception_argument_null ("exception"));
890
891         trace = mono_exception_get_native_backtrace (exc);
892         res = mono_string_new (mono_domain_get (), trace);
893         g_free (trace);
894         return res;
895 }
896
897 /**
898  * mono_error_raise_exception:
899  * @target_error: the exception to raise
900  *
901  * Raises the exception of @target_error.
902  * Does nothing if @target_error has a success error code.
903  * Aborts in case of a double fault. This happens when it can't recover from an error caused by trying
904  * to construct the first exception object.
905  * The error object @target_error is cleaned up.
906 */
907 void
908 mono_error_raise_exception (MonoError *target_error)
909 {
910         MonoException *ex = mono_error_convert_to_exception (target_error);
911         if (ex)
912                 mono_raise_exception (ex);
913 }
914
915 void
916 mono_error_set_pending_exception (MonoError *error)
917 {
918         MonoException *ex = mono_error_convert_to_exception (error);
919         if (ex)
920                 mono_set_pending_exception (ex);
921 }
922