[sgen] Exclusive write on binary protocol file
[mono.git] / mono / utils / mono-error.c
1 /*
2  * mono-error.c: Error handling code
3  *
4  * Authors:
5  *      Rodrigo Kumpera    (rkumpera@novell.com)
6  * Copyright 2009 Novell, Inc (http://www.novell.com)
7  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
8  */
9 #include <glib.h>
10
11 #include "mono-error.h"
12 #include "mono-error-internals.h"
13
14 #include <mono/metadata/exception.h>
15 #include <mono/metadata/debug-helpers.h>
16 #include <mono/metadata/object-internals.h>
17
18 #define set_error_messagev() do { \
19         if (!(error->full_message = g_strdup_vprintf (msg_format, args))) \
20                         error->flags |= MONO_ERROR_INCOMPLETE; \
21 } while (0)
22
23 #define set_error_message() do { \
24         va_list args; \
25         va_start (args, msg_format); \
26         set_error_messagev();        \
27         va_end (args); \
28 } while (0)
29
30 static void
31 mono_error_set_generic_errorv (MonoError *oerror, const char *name_space, const char *name, const char *msg_format, va_list args);
32
33 static gboolean
34 is_managed_exception (MonoErrorInternal *error)
35 {
36         return (error->error_code == MONO_ERROR_EXCEPTION_INSTANCE);
37 }
38
39 static void
40 mono_error_prepare (MonoErrorInternal *error)
41 {
42         if (error->error_code != MONO_ERROR_NONE)
43                 return;
44
45         error->type_name = error->assembly_name = error->member_name = error->full_message = error->exception_name_space = error->exception_name = error->full_message_with_fields = error->first_argument = NULL;
46         error->exn.klass = NULL;
47 }
48
49 static MonoClass*
50 get_class (MonoErrorInternal *error)
51 {
52         MonoClass *klass = NULL;
53         if (is_managed_exception (error))
54                 klass = mono_object_class (mono_gchandle_get_target (error->exn.instance_handle));
55         else
56                 klass = error->exn.klass;
57         return klass;
58 }
59
60 static const char*
61 get_type_name (MonoErrorInternal *error)
62 {
63         if (error->type_name)
64                 return error->type_name;
65         MonoClass *klass = get_class (error);
66         if (klass)
67                 return klass->name;
68         return "<unknown type>";
69 }
70
71 static const char*
72 get_assembly_name (MonoErrorInternal *error)
73 {
74         if (error->assembly_name)
75                 return error->assembly_name;
76         MonoClass *klass = get_class (error);
77         if (klass && klass->image)
78                 return klass->image->name;
79         return "<unknown assembly>";
80 }
81
82 void
83 mono_error_init_flags (MonoError *oerror, unsigned short flags)
84 {
85         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
86         g_assert (sizeof (MonoError) == sizeof (MonoErrorInternal));
87
88         error->error_code = MONO_ERROR_NONE;
89         error->flags = flags;
90 }
91
92 /**
93  * mono_error_init:
94  * @error: Pointer to MonoError struct to initialize
95  *
96  * Any function which takes a MonoError for purposes of reporting an error
97  * is required to call either this or mono_error_init_flags on entry.
98  */
99 void
100 mono_error_init (MonoError *error)
101 {
102         mono_error_init_flags (error, 0);
103 }
104
105 void
106 mono_error_cleanup (MonoError *oerror)
107 {
108         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
109         if (error->error_code == MONO_ERROR_NONE)
110                 return;
111
112         if (is_managed_exception (error))
113                 mono_gchandle_free (error->exn.instance_handle);
114
115         g_free ((char*)error->full_message);
116         g_free ((char*)error->full_message_with_fields);
117         if (!(error->flags & MONO_ERROR_FREE_STRINGS)) //no memory was allocated
118                 return;
119
120         g_free ((char*)error->type_name);
121         g_free ((char*)error->assembly_name);
122         g_free ((char*)error->member_name);
123         g_free ((char*)error->exception_name_space);
124         g_free ((char*)error->exception_name);
125         g_free ((char*)error->first_argument);
126 }
127
128 gboolean
129 mono_error_ok (MonoError *error)
130 {
131         return error->error_code == MONO_ERROR_NONE;
132 }
133
134 void
135 mono_error_assert_ok_pos (MonoError *error, const char* filename, int lineno)
136 {
137         if (mono_error_ok (error))
138                 return;
139
140         g_error ("%s:%d: %s\n", filename, lineno, mono_error_get_message (error));
141 }
142
143 unsigned short
144 mono_error_get_error_code (MonoError *error)
145 {
146         return error->error_code;
147 }
148
149 /*Return a pointer to the internal error message, might be NULL.
150 Caller should not release it.*/
151 const char*
152 mono_error_get_message (MonoError *oerror)
153 {
154         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
155         if (error->error_code == MONO_ERROR_NONE)
156                 return NULL;
157         if (error->full_message_with_fields)
158                 return error->full_message_with_fields;
159
160         error->full_message_with_fields = g_strdup_printf ("%s assembly:%s type:%s member:%s",
161                 error->full_message,
162                 get_assembly_name (error),
163                 get_type_name (error),
164                 error->member_name ? error->member_name : "<none>");
165
166         return error->full_message_with_fields ? error->full_message_with_fields : error->full_message;
167 }
168
169 /*
170  * Inform that this error has heap allocated strings.
171  * The strings will be duplicated if @dup_strings is TRUE
172  * otherwise they will just be free'd in mono_error_cleanup.
173  */
174 void
175 mono_error_dup_strings (MonoError *oerror, gboolean dup_strings)
176 {
177 #define DUP_STR(field) do { if (error->field) {\
178         if (!(error->field = g_strdup (error->field))) \
179                 error->flags |= MONO_ERROR_INCOMPLETE; \
180         }} while (0);
181
182         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
183         error->flags |= MONO_ERROR_FREE_STRINGS;
184
185         if (dup_strings) {
186                 DUP_STR (type_name);
187                 DUP_STR (assembly_name);
188                 DUP_STR (member_name);
189                 DUP_STR (exception_name_space);
190                 DUP_STR (exception_name);
191                 DUP_STR (first_argument);
192         }
193 #undef DUP_STR
194 }
195
196 void
197 mono_error_set_error (MonoError *oerror, int error_code, const char *msg_format, ...)
198 {
199         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
200         mono_error_prepare (error);
201
202         error->error_code = error_code;
203         set_error_message ();
204 }
205
206 static void
207 mono_error_set_assembly_name (MonoError *oerror, const char *assembly_name)
208 {
209         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
210         g_assert (error->error_code != MONO_ERROR_NONE);
211
212         error->assembly_name = assembly_name;
213 }
214
215 static void
216 mono_error_set_member_name (MonoError *oerror, const char *member_name)
217 {
218         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
219
220         error->member_name = member_name;
221 }
222
223 static void
224 mono_error_set_type_name (MonoError *oerror, const char *type_name)
225 {
226         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
227
228         error->type_name = type_name;
229 }
230
231 static void
232 mono_error_set_class (MonoError *oerror, MonoClass *klass)
233 {
234         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
235
236         if (is_managed_exception (error))
237                 return;
238         error->exn.klass = klass;       
239 }
240
241 static void
242 mono_error_set_corlib_exception (MonoError *oerror, const char *name_space, const char *name)
243 {
244         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
245
246         error->exception_name_space = name_space;
247         error->exception_name = name;
248 }
249
250
251 void
252 mono_error_set_assembly_load (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
253 {
254         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
255         mono_error_prepare (error);
256
257         error->error_code = MONO_ERROR_FILE_NOT_FOUND;
258         mono_error_set_assembly_name (oerror, assembly_name);
259
260         set_error_message ();
261 }
262
263
264 void
265 mono_error_set_assembly_load_simple (MonoError *oerror, const char *assembly_name, gboolean refection_only)
266 {
267         if (refection_only)
268                 mono_error_set_assembly_load (oerror, assembly_name, "Cannot resolve dependency to assembly because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.");
269         else
270                 mono_error_set_assembly_load (oerror, assembly_name, "Could not load file or assembly or one of its dependencies.");
271 }
272
273 void
274 mono_error_set_type_load_class (MonoError *oerror, MonoClass *klass, const char *msg_format, ...)
275 {
276         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
277         mono_error_prepare (error);
278
279         error->error_code = MONO_ERROR_TYPE_LOAD;
280         mono_error_set_class (oerror, klass);
281         set_error_message ();
282 }
283
284 /*
285  * Different than other functions, this one here assumes that type_name and assembly_name to have been allocated just for us.
286  * Which means mono_error_cleanup will free them.
287  */
288 void
289 mono_error_set_type_load_name (MonoError *oerror, const char *type_name, const char *assembly_name, const char *msg_format, ...)
290 {
291         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
292         mono_error_prepare (error);
293
294         error->error_code = MONO_ERROR_TYPE_LOAD;
295         mono_error_set_type_name (oerror, type_name);
296         mono_error_set_assembly_name (oerror, assembly_name);
297         mono_error_dup_strings (oerror, FALSE);
298         set_error_message ();
299 }
300
301 void
302 mono_error_set_method_load (MonoError *oerror, MonoClass *klass, const char *method_name, const char *msg_format, ...)
303 {
304         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
305         mono_error_prepare (error);
306
307         error->error_code = MONO_ERROR_MISSING_METHOD;
308         mono_error_set_class (oerror, klass);
309         mono_error_set_member_name (oerror, method_name);
310         set_error_message ();
311 }
312
313 void
314 mono_error_set_field_load (MonoError *oerror, MonoClass *klass, const char *field_name, const char *msg_format, ...)
315 {
316         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
317         mono_error_prepare (error);
318
319         error->error_code = MONO_ERROR_MISSING_FIELD;
320         mono_error_set_class (oerror, klass);
321         mono_error_set_member_name (oerror, field_name);
322         set_error_message ();   
323 }
324
325 void
326 mono_error_set_bad_image_name (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
327 {
328         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
329         mono_error_prepare (error);
330
331         error->error_code = MONO_ERROR_BAD_IMAGE;
332         mono_error_set_assembly_name (oerror, assembly_name);
333         set_error_message ();
334 }
335
336 void
337 mono_error_set_bad_image (MonoError *oerror, MonoImage *image, const char *msg_format, ...)
338 {
339         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
340         mono_error_prepare (error);
341
342         error->error_code = MONO_ERROR_BAD_IMAGE;
343         error->assembly_name = image ? mono_image_get_name (image) : "<no_image>";
344         set_error_message ();
345 }
346
347 void
348 mono_error_set_generic_errorv (MonoError *oerror, const char *name_space, const char *name, const char *msg_format, va_list args)
349 {
350         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
351         mono_error_prepare (error);
352
353         error->error_code = MONO_ERROR_GENERIC;
354         mono_error_set_corlib_exception (oerror, name_space, name);
355         set_error_messagev ();
356 }
357
358 void
359 mono_error_set_generic_error (MonoError *oerror, const char * name_space, const char *name, const char *msg_format, ...)
360 {
361         va_list args;
362         va_start (args, msg_format);
363         mono_error_set_generic_errorv (oerror, name_space, name, msg_format, args);
364         va_end (args);
365 }
366
367 /**
368  * mono_error_set_not_implemented:
369  *
370  * System.NotImplementedException
371  */
372 void
373 mono_error_set_not_implemented (MonoError *oerror, const char *msg_format, ...)
374 {
375         va_list args;
376         va_start (args, msg_format);
377         mono_error_set_generic_errorv (oerror, "System", "NotImplementedException", msg_format, args);
378         va_end (args);
379 }
380
381 /**
382  * mono_error_set_execution_engine:
383  *
384  * System.ExecutionEngineException
385  */
386 void
387 mono_error_set_execution_engine (MonoError *oerror, const char *msg_format, ...)
388 {
389         va_list args;
390         va_start (args, msg_format);
391         mono_error_set_generic_errorv (oerror, "System", "ExecutionEngineException", msg_format, args);
392         va_end (args);
393 }
394
395 /**
396  * mono_error_set_not_supported:
397  *
398  * System.NotSupportedException
399  */
400 void
401 mono_error_set_not_supported (MonoError *oerror, const char *msg_format, ...)
402 {
403         va_list args;
404         va_start (args, msg_format);
405         mono_error_set_generic_errorv (oerror, "System", "NotSupportedException", msg_format, args);
406         va_end (args);
407 }
408
409 /**
410  * mono_error_set_invalid_operation:
411  *
412  * System.InvalidOperationException
413  */
414 void
415 mono_error_set_invalid_operation (MonoError *oerror, const char *msg_format, ...)
416 {
417         va_list args;
418         va_start (args, msg_format);
419         mono_error_set_generic_errorv (oerror, "System", "InvalidOperationException", msg_format, args);
420         va_end (args);
421 }
422
423 void
424 mono_error_set_exception_instance (MonoError *oerror, MonoException *exc)
425 {
426         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
427
428         mono_error_prepare (error);
429         error->error_code = MONO_ERROR_EXCEPTION_INSTANCE;
430         error->exn.instance_handle = mono_gchandle_new (exc ? &exc->object : NULL, FALSE);
431 }
432
433 void
434 mono_error_set_out_of_memory (MonoError *oerror, const char *msg_format, ...)
435 {
436         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
437         mono_error_prepare (error);
438
439         error->error_code = MONO_ERROR_OUT_OF_MEMORY;
440
441         set_error_message ();
442 }
443
444 void
445 mono_error_set_argument (MonoError *oerror, const char *argument, const char *msg_format, ...)
446 {
447         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
448         mono_error_prepare (error);
449
450         error->error_code = MONO_ERROR_ARGUMENT;
451         error->first_argument = argument;
452
453         set_error_message ();
454 }
455
456 void
457 mono_error_set_argument_null (MonoError *oerror, const char *argument, const char *msg_format, ...)
458 {
459         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
460         mono_error_prepare (error);
461
462         error->error_code = MONO_ERROR_ARGUMENT_NULL;
463         error->first_argument = argument;
464
465         set_error_message ();
466 }
467
468 void
469 mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char *msg_format, ...)
470 {
471         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
472         mono_error_prepare (error);
473
474         error->error_code = MONO_ERROR_NOT_VERIFIABLE;
475         if (method) {
476                 mono_error_set_class (oerror, method->klass);
477                 mono_error_set_member_name (oerror, mono_method_full_name (method, 1));
478         }
479
480         set_error_message ();
481 }
482
483
484 static MonoString*
485 get_type_name_as_mono_string (MonoErrorInternal *error, MonoDomain *domain, MonoError *error_out)
486 {
487         MonoString* res = NULL;
488
489         if (error->type_name) {
490                 res = mono_string_new (domain, error->type_name);
491                 
492         } else {
493                 MonoClass *klass = get_class (error);
494                 if (klass) {
495                         char *name = mono_type_full_name (&klass->byval_arg);
496                         if (name) {
497                                 res = mono_string_new (domain, name);
498                                 g_free (name);
499                         }
500                 }
501         }
502         if (!res)
503                 mono_error_set_out_of_memory (error_out, "Could not allocate type name");
504         return res;
505 }
506
507 static void
508 set_message_on_exception (MonoException *exception, MonoErrorInternal *error, MonoError *error_out)
509 {
510         MonoString *msg = mono_string_new (mono_domain_get (), error->full_message);
511         if (msg)
512                 MONO_OBJECT_SETREF (exception, message, msg);
513         else
514                 mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
515 }
516
517 /*Can fail with out-of-memory*/
518 MonoException*
519 mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
520 {
521         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
522
523         MonoException* exception = NULL;
524         MonoString *assembly_name = NULL, *type_name = NULL, *method_name = NULL, *field_name = NULL, *msg = NULL;
525         MonoDomain *domain = mono_domain_get ();
526
527         mono_error_init (error_out);
528
529         switch (error->error_code) {
530         case MONO_ERROR_NONE:
531                 return NULL;
532
533         case MONO_ERROR_MISSING_METHOD:
534                 if ((error->type_name || error->exn.klass) && error->member_name) {
535                         type_name = get_type_name_as_mono_string (error, domain, error_out);
536                         if (!mono_error_ok (error_out))
537                                 break;
538
539                         method_name = mono_string_new (domain, error->member_name);
540                         if (!method_name) {
541                                 mono_error_set_out_of_memory (error_out, "Could not allocate method name");
542                                 break;
543                         }
544
545                         exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name);
546                         if (exception)
547                                 set_message_on_exception (exception, error, error_out);
548                 } else {
549                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", error->full_message);
550                 }
551                 break;
552
553         case MONO_ERROR_MISSING_FIELD:
554                 if ((error->type_name || error->exn.klass) && error->member_name) {
555                         type_name = get_type_name_as_mono_string (error, domain, error_out);
556                         if (!mono_error_ok (error_out))
557                                 break;
558                         
559                         field_name = mono_string_new (domain, error->member_name);
560                         if (!field_name) {
561                                 mono_error_set_out_of_memory (error_out, "Could not allocate field name");
562                                 break;
563                         }
564                         
565                         exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name);
566                         if (exception)
567                                 set_message_on_exception (exception, error, error_out);
568                 } else {
569                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", error->full_message);
570                 }
571                 break;
572
573         case MONO_ERROR_TYPE_LOAD:
574                 if ((error->type_name && error->assembly_name) || error->exn.klass) {
575                         type_name = get_type_name_as_mono_string (error, domain, error_out);
576                         if (!mono_error_ok (error_out))
577                                 break;
578
579                         if (error->assembly_name) {
580                                 assembly_name = mono_string_new (domain, error->assembly_name);
581                                 if (!assembly_name) {
582                                         mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
583                                         break;
584                                 }
585                         }
586
587                         exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name);
588                         if (exception)
589                                 set_message_on_exception (exception, error, error_out);
590                 } else {
591                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", error->full_message);
592                 }
593                 break;
594
595         case MONO_ERROR_FILE_NOT_FOUND:
596         case MONO_ERROR_BAD_IMAGE:
597                 if (error->assembly_name) {
598                         msg = mono_string_new (domain, error->full_message);
599                         if (!msg) {
600                                 mono_error_set_out_of_memory (error_out, "Could not allocate message");
601                                 break;
602                         }
603
604                         if (error->assembly_name) {
605                                 assembly_name = mono_string_new (domain, error->assembly_name);
606                                 if (!assembly_name) {
607                                         mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
608                                         break;
609                                 }
610                         }
611
612                         if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
613                                 exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name);
614                         else
615                                 exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name);
616                 } else {
617                         if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
618                                 exception = mono_exception_from_name_msg (mono_get_corlib (), "System.IO", "FileNotFoundException", error->full_message);
619                         else
620                                 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "BadImageFormatException", error->full_message);
621                 }
622                 break;
623
624         case MONO_ERROR_OUT_OF_MEMORY:
625                 exception = mono_get_exception_out_of_memory ();
626                 break;
627
628         case MONO_ERROR_ARGUMENT:
629                 exception = mono_get_exception_argument (error->first_argument, error->full_message);
630                 break;
631
632         case MONO_ERROR_ARGUMENT_NULL:
633                 exception = mono_get_exception_argument_null (error->first_argument);
634                 break;
635
636         case MONO_ERROR_NOT_VERIFIABLE: {
637                 char *type_name = NULL, *message;
638                 if (error->exn.klass) {
639                         type_name = mono_type_get_full_name (error->exn.klass);
640                         if (!type_name) {
641                                 mono_error_set_out_of_memory (error_out, "Could not allocate message");
642                                 break;
643                         }
644                 }
645                 message = g_strdup_printf ("Error in %s:%s %s", type_name, error->member_name, error->full_message);
646                 if (!message) {
647                         g_free (type_name);
648                         mono_error_set_out_of_memory (error_out, "Could not allocate message");
649                         break;  
650                 }
651                 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", message);
652                 g_free (message);
653                 g_free (type_name);
654                 break;
655         }
656         case MONO_ERROR_GENERIC:
657                 if (!error->exception_name_space || !error->exception_name)
658                         mono_error_set_execution_engine (error_out, "MonoError with generic error but no exception name was supplied");
659                 else
660                         exception = mono_exception_from_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, error->full_message);
661                 break;
662
663         case MONO_ERROR_EXCEPTION_INSTANCE:
664                 exception = (MonoException*) mono_gchandle_get_target (error->exn.instance_handle);
665                 break;
666
667         default:
668                 mono_error_set_execution_engine (error_out, "Invalid error-code %d", error->error_code);
669         }
670
671         if (!mono_error_ok (error_out))
672                 return NULL;
673         if (!exception)
674                 mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
675         return exception;
676 }
677
678 /*
679 Convert this MonoError to an exception if it's faulty or return NULL.
680 The error object is cleant after.
681 */
682
683 MonoException*
684 mono_error_convert_to_exception (MonoError *target_error)
685 {
686         MonoError error;
687         MonoException *ex;
688
689         if (mono_error_ok (target_error))
690                 return NULL;
691
692         ex = mono_error_prepare_exception (target_error, &error);
693         if (!mono_error_ok (&error)) {
694                 MonoError second_chance;
695                 /*Try to produce the exception for the second error. FIXME maybe we should log about the original one*/
696                 ex = mono_error_prepare_exception (&error, &second_chance);
697
698                 g_assert (mono_error_ok (&second_chance)); /*We can't reasonable handle double faults, maybe later.*/
699                 mono_error_cleanup (&error);
700         }
701         mono_error_cleanup (target_error);
702         return ex;
703 }
704
705 void
706 mono_error_move (MonoError *dest, MonoError *src)
707 {
708         memcpy (dest, src, sizeof (MonoErrorInternal));
709         mono_error_init (src);
710 }