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