*/
#include <glib.h>
+#include <config.h>
#include "mono-error.h"
#include "mono-error-internals.h"
#include <mono/metadata/exception.h>
-#include <mono/metadata/class-internals.h>
+#include <mono/metadata/exception-internals.h>
#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/object.h>
#include <mono/metadata/object-internals.h>
#define set_error_messagev() do { \
static void
mono_error_prepare (MonoErrorInternal *error)
{
+ /* mono_error_set_* after a mono_error_cleanup without an intervening init */
+ g_assert (error->error_code != MONO_ERROR_CLEANUP_CALLED_SENTINEL);
if (error->error_code != MONO_ERROR_NONE)
return;
error->flags = flags;
}
+/**
+ * mono_error_init:
+ * @error: Pointer to MonoError struct to initialize
+ *
+ * Any function which takes a MonoError for purposes of reporting an error
+ * is required to call either this or mono_error_init_flags on entry.
+ */
void
mono_error_init (MonoError *error)
{
mono_error_cleanup (MonoError *oerror)
{
MonoErrorInternal *error = (MonoErrorInternal*)oerror;
- if (error->error_code == MONO_ERROR_NONE)
+ short int orig_error_code = error->error_code;
+ gboolean free_strings = error->flags & MONO_ERROR_FREE_STRINGS;
+ gboolean has_instance_handle = is_managed_exception (error);
+
+ /* Two cleanups in a row without an intervening init. */
+ g_assert (orig_error_code != MONO_ERROR_CLEANUP_CALLED_SENTINEL);
+
+ /* Mark it as cleaned up. */
+ error->error_code = MONO_ERROR_CLEANUP_CALLED_SENTINEL;
+ error->flags = 0;
+
+ if (orig_error_code == MONO_ERROR_NONE)
return;
- if (is_managed_exception (error))
+
+ if (has_instance_handle)
mono_gchandle_free (error->exn.instance_handle);
+
g_free ((char*)error->full_message);
g_free ((char*)error->full_message_with_fields);
- if (!(error->flags & MONO_ERROR_FREE_STRINGS)) //no memory was allocated
+ error->full_message = NULL;
+ error->full_message_with_fields = NULL;
+ if (!free_strings) //no memory was allocated
return;
g_free ((char*)error->type_name);
g_free ((char*)error->exception_name_space);
g_free ((char*)error->exception_name);
g_free ((char*)error->first_argument);
+ error->type_name = error->assembly_name = error->member_name = error->exception_name_space = error->exception_name = error->first_argument = NULL;
+ error->exn.klass = NULL;
+
}
gboolean
}
/**
- * mono_error_set_execution_engine:
+ * mono_error_set_not_supported:
*
* System.NotSupportedException
*/
va_end (args);
}
+/**
+ * mono_error_set_invalid_operation:
+ *
+ * System.InvalidOperationException
+ */
void
-mono_error_set_exception_instance (MonoError *oerror, MonoException *exc)
+mono_error_set_invalid_operation (MonoError *oerror, const char *msg_format, ...)
{
- MonoErrorInternal *error = (MonoErrorInternal*)oerror;
-
- mono_error_prepare (error);
- error->error_code = MONO_ERROR_EXCEPTION_INSTANCE;
- error->exn.instance_handle = mono_gchandle_new (exc ? &exc->object : NULL, FALSE);
+ va_list args;
+ va_start (args, msg_format);
+ mono_error_set_generic_errorv (oerror, "System", "InvalidOperationException", msg_format, args);
+ va_end (args);
}
void
-mono_error_set_from_loader_error (MonoError *oerror)
+mono_error_set_invalid_program (MonoError *oerror, const char *msg_format, ...)
{
- MonoLoaderError *loader_error = mono_loader_get_last_error ();
MonoErrorInternal *error = (MonoErrorInternal*)oerror;
- gboolean dup_strings = TRUE;
mono_error_prepare (error);
+ error->error_code = MONO_ERROR_INVALID_PROGRAM;
- if (!loader_error) {
- mono_error_set_execution_engine (oerror, "Runtime tried to produce a mono-error from an empty loader-error");
- return;
- }
-
- switch (loader_error->exception_type) {
- case MONO_EXCEPTION_NONE:
- mono_error_set_execution_engine (oerror, "Runtime tried to produce a mono-error from a non-error loader-error");
- break;
-
- case MONO_EXCEPTION_INVALID_PROGRAM:
- mono_error_set_generic_error (oerror, "System", "InvalidProgramException", "Failed for unknown reasons.");
- break;
-
- case MONO_EXCEPTION_UNVERIFIABLE_IL:
- mono_error_set_generic_error (oerror, "System.Security", "VerificationException", "Failed for unknown reasons.");
- break;
-
- case MONO_EXCEPTION_MISSING_METHOD:
- error->error_code = MONO_ERROR_MISSING_METHOD;
- mono_error_set_type_name (oerror, loader_error->class_name);
- mono_error_set_member_name (oerror, loader_error->member_name);
- error->full_message = g_strdup ("Failed for unknown reasons.");
- break;
-
- case MONO_EXCEPTION_MISSING_FIELD:
- mono_error_set_field_load (oerror, loader_error->klass, loader_error->member_name, "Failed for unknown reasons.");
- break;
-
- case MONO_EXCEPTION_TYPE_LOAD:
- mono_error_set_type_load_name (oerror, g_strdup (loader_error->class_name), g_strdup (loader_error->assembly_name), "Failed for unknown reasons.");
- dup_strings = FALSE;
- break;
-
- case MONO_EXCEPTION_FILE_NOT_FOUND:
- mono_error_set_assembly_load_simple (oerror, loader_error->assembly_name, loader_error->ref_only);
- break;
-
- case MONO_EXCEPTION_METHOD_ACCESS:
- mono_error_set_generic_error (oerror, "System", "MethodAccessException", "Failed for unknown reasons.");
- break;
-
- case MONO_EXCEPTION_FIELD_ACCESS:
- mono_error_set_generic_error (oerror, "System", "FieldAccessException", "Failed for unknown reasons.");
- break;
-
- case MONO_EXCEPTION_OBJECT_SUPPLIED:
- case MONO_EXCEPTION_GENERIC_SHARING_FAILED:
- mono_error_set_execution_engine (oerror, "Runtime tried to produce a mono-error from JIT internal error %d", loader_error->exception_type);
- break;
-
- case MONO_EXCEPTION_BAD_IMAGE:
- mono_error_set_bad_image_name (oerror, "<unknown>", "%s", loader_error->msg);
- break;
-
- case MONO_EXCEPTION_OUT_OF_MEMORY:
- mono_error_set_out_of_memory (oerror, "Failed for unknown reasons.");
- break;
-
- default:
- mono_error_set_execution_engine (oerror, "Runtime tried to produce an unknown loader-error %d", loader_error->exception_type);
- break;
- }
-
- mono_error_dup_strings (oerror, dup_strings);
- mono_loader_clear_error ();
+ set_error_message ();
}
void
-mono_loader_set_error_from_mono_error (MonoError *oerror)
+mono_error_set_exception_instance (MonoError *oerror, MonoException *exc)
{
MonoErrorInternal *error = (MonoErrorInternal*)oerror;
- switch (error->error_code) {
- case MONO_ERROR_MISSING_METHOD:
- mono_loader_set_error_method_load (get_type_name (error), error->member_name);
- break;
- case MONO_ERROR_MISSING_FIELD:
- mono_loader_set_error_field_load (error->exn.klass, error->member_name);
- break;
- case MONO_ERROR_TYPE_LOAD:
- mono_loader_set_error_type_load (get_type_name (error), get_assembly_name (error));
- break;
- case MONO_ERROR_FILE_NOT_FOUND:
- /* XXX can't recover if it's ref only or not */
- mono_loader_set_error_assembly_load (get_assembly_name (error), FALSE);
- break;
- case MONO_ERROR_BAD_IMAGE:
- mono_loader_set_error_bad_image (g_strdup (error->full_message));
- break;
- case MONO_ERROR_EXCEPTION_INSTANCE:
- mono_loader_set_error_bad_image (g_strdup_printf ("Non translatable error"));
- default:
- mono_loader_set_error_bad_image (g_strdup_printf ("Non translatable error: %s", error->full_message));
- }
+ mono_error_prepare (error);
+ error->error_code = MONO_ERROR_EXCEPTION_INSTANCE;
+ error->exn.instance_handle = mono_gchandle_new (exc ? &exc->object : NULL, FALSE);
}
void
break;
}
- exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name);
+ exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name, error_out);
if (exception)
set_message_on_exception (exception, error, error_out);
} else {
break;
}
- exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name);
+ exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name, error_out);
if (exception)
set_message_on_exception (exception, error, error_out);
} else {
}
}
- exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name);
+ exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name, error_out);
if (exception)
set_message_on_exception (exception, error, error_out);
} else {
}
if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
- exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name);
+ exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name, error_out);
else
- exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name);
+ exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name, error_out);
} else {
if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
exception = mono_exception_from_name_msg (mono_get_corlib (), "System.IO", "FileNotFoundException", error->full_message);
exception = (MonoException*) mono_gchandle_get_target (error->exn.instance_handle);
break;
+ case MONO_ERROR_CLEANUP_CALLED_SENTINEL:
+ mono_error_set_execution_engine (error_out, "MonoError reused after mono_error_cleanup");
+ break;
+
+ case MONO_ERROR_INVALID_PROGRAM: {
+ gboolean lacks_message = error->flags & MONO_ERROR_INCOMPLETE;
+ if (lacks_message)
+ return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
+ else
+ return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", error->full_message);
+ }
default:
mono_error_set_execution_engine (error_out, "Invalid error-code %d", error->error_code);
}