/* Convert this MonoError to an exception if it's faulty or return NULL. The error object is cleant after. */ MonoException* mono_error_convert_to_exception (MonoError *target_error) { ERROR_DECL (error); MonoException *ex; /* Mempool stored error shouldn't be cleaned up */ g_assert (!is_boxed ((MonoErrorInternal*)target_error)); if (mono_error_ok (target_error)) return NULL; ex = mono_error_prepare_exception (target_error, error); if (!mono_error_ok (error)) { ERROR_DECL (second_chance); /*Try to produce the exception for the second error. FIXME maybe we should log about the original one*/ ex = mono_error_prepare_exception (error, second_chance); // We cannot reasonably handle double faults, maybe later. g_assert (mono_error_ok (second_chance)); mono_error_cleanup (error); } mono_error_cleanup (target_error); return ex; }
void mono_error_set_argument_out_of_range (MonoError *error, const char *name) { ERROR_DECL (error_creating_exception); mono_error_set_exception_handle (error, mono_new_exception_argument_out_of_range (name, error_creating_exception)); mono_error_cleanup (error_creating_exception); }
void mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, host_mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow, gboolean preserve_ips) { ERROR_DECL (error); MonoContext ctx; /* adjust eip so that it point into the call instruction */ eip -= 4; setup_context (&ctx); /*printf ("stack in throw: %p\n", esp);*/ MONO_CONTEXT_SET_BP (&ctx, esp); MONO_CONTEXT_SET_IP (&ctx, eip); memcpy (&ctx.regs, int_regs, sizeof (host_mgreg_t) * MONO_MAX_IREGS); memcpy (&ctx.fregs, fp_regs, sizeof (double) * MONO_MAX_FREGS); if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) { MonoException *mono_ex = (MonoException*)exc; if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; } else if (preserve_ips) { mono_ex->caught_in_unmanaged = TRUE; } } mono_error_assert_ok (error); mono_handle_exception (&ctx, exc); mono_restore_context (&ctx); g_assert_not_reached (); }
static void throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow, gboolean preserve_ips) { ERROR_DECL (error); MonoContext ctx; static void (*restore_context) (MonoContext *); gpointer *window; if (!restore_context) restore_context = mono_get_restore_context (); window = MONO_SPARC_WINDOW_ADDR (sp); ctx.sp = (gpointer*)sp; ctx.ip = ip; ctx.fp = (gpointer*)(MONO_SPARC_WINDOW_ADDR (sp) [sparc_i6 - 16]); if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) { MonoException *mono_ex = (MonoException*)exc; if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; } else (preserve_ips) { mono_ex->caught_in_unmanaged = NULL; } }
/* Used by mono_error_prepare_exception - it sets its own error on mono_string_new_checked failure. */ static MonoStringHandle string_new_cleanup (MonoDomain *domain, const char *text) { ERROR_DECL (ignored_err); MonoStringHandle result = mono_string_new_handle (domain, text, ignored_err); mono_error_cleanup (ignored_err); return result; }
/** * mono_get_exception_argument_internal: * \param type the actual type * \param arg the name of the argument that is invalid or null, etc. * \param msg optional message * \returns a new instance of the \c System.ArgumentException or derived */ static MonoException* mono_get_exception_argument_internal (const char *type, const char *arg, const char *msg) { HANDLE_FUNCTION_ENTER (); ERROR_DECL (error); MonoExceptionHandle ex = mono_exception_new_argument_internal (type, arg, msg, error); mono_error_cleanup (error); HANDLE_FUNCTION_RETURN_OBJ (ex); }
/** * mono_get_exception_file_not_found: * \param fname the name of the file not found. * \returns a new instance of the \c System.IO.FileNotFoundException */ MonoException * mono_get_exception_file_not_found (MonoString *fname_raw) { HANDLE_FUNCTION_ENTER (); ERROR_DECL (error); MONO_HANDLE_DCL (MonoString, fname); MonoExceptionHandle ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System.IO", "FileNotFoundException", fname, fname, error); mono_error_assert_ok (error); HANDLE_FUNCTION_RETURN_OBJ (ret); }
/** * mono_exception_from_name_domain: * \param domain Domain where the return object will be created. * \param image the Mono image where to look for the class * \param name_space the namespace for the class * \param name class name * * Creates an exception object of the given namespace/name class on * the given domain. * * \returns the initialized exception instance. */ MonoException * mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, const char* name_space, const char *name) { HANDLE_FUNCTION_ENTER (); ERROR_DECL (error); MonoExceptionHandle ret = mono_exception_new_by_name_domain (domain, image, name_space, name, error); mono_error_assert_ok (error); HANDLE_FUNCTION_RETURN_OBJ (ret); }
/** * mono_exception_from_token_two_strings: * * Same as mono_exception_from_name_two_strings, but lookup the exception class using * IMAGE and TOKEN. */ MonoException * mono_exception_from_token_two_strings (MonoImage *image, guint32 token, MonoString *arg1_raw, MonoString *arg2_raw) { HANDLE_FUNCTION_ENTER (); ERROR_DECL (error); MONO_HANDLE_DCL (MonoString, arg1); MONO_HANDLE_DCL (MonoString, arg2); MonoExceptionHandle ret = mono_exception_from_token_two_strings_checked (image, token, arg1, arg2, error); mono_error_cleanup (error); HANDLE_FUNCTION_RETURN_OBJ (ret); }
/** * mono_exception_from_name_two_strings: * \param image the Mono image where to look for the class * \param name_space the namespace for the class * \param name class name * \param a1 first string argument to pass * \param a2 second string argument to pass * * Creates an exception from a constructor that takes two string * arguments. * * \returns the initialized exception instance. */ MonoException * mono_exception_from_name_two_strings (MonoImage *image, const char *name_space, const char *name, MonoString *a1_raw, MonoString *a2_raw) { HANDLE_FUNCTION_ENTER (); ERROR_DECL (error); MONO_HANDLE_DCL (MonoString, a1); MONO_HANDLE_DCL (MonoString, a2); MonoExceptionHandle ret = mono_exception_from_name_two_strings_checked (image, name_space, name, a1, a2, error); mono_error_cleanup (error); HANDLE_FUNCTION_RETURN_OBJ (ret); }
static MonoClass *test_mono_class_from_name (MonoImage *image, const char *name_space, const char *name) { ERROR_DECL (error); MonoClass *klass; klass = mono_class_from_name_checked (image, name_space, name, error); mono_error_cleanup (error); /* FIXME Don't swallow the error */ return klass; }
/** * mono_get_exception_runtime_wrapped: */ MonoException * mono_get_exception_runtime_wrapped (MonoObject *wrapped_exception_raw) { HANDLE_FUNCTION_ENTER (); ERROR_DECL (error); MONO_HANDLE_DCL (MonoObject, wrapped_exception); MonoExceptionHandle ret = mono_get_exception_runtime_wrapped_handle (wrapped_exception, error); if (!is_ok (error)) { mono_error_cleanup (error); ret = MONO_HANDLE_CAST (MonoException, mono_new_null ()); } HANDLE_FUNCTION_RETURN_OBJ (ret); }
/** * mono_exception_from_name_msg: * \param image the Mono image where to look for the class * \param name_space the namespace for the class * \param name class name * \param msg the message to embed inside the exception * * Creates an exception and initializes its message field. * * \returns the initialized exception instance. */ MonoException * mono_exception_from_name_msg (MonoImage *image, const char *name_space, const char *name, const char *msg) { HANDLE_FUNCTION_ENTER (); MonoExceptionHandle ex; MONO_ENTER_GC_UNSAFE; ERROR_DECL (error); ex = mono_exception_new_by_name_msg (image, name_space, name, msg, error); mono_error_cleanup (error); MONO_EXIT_GC_UNSAFE; HANDLE_FUNCTION_RETURN_OBJ (ex); }
/** * mono_get_exception_type_initialization: * \param type_name the name of the type that failed to initialize. * \param inner the inner exception. * \returns a new instance of the \c System.TypeInitializationException */ MonoException * mono_get_exception_type_initialization (const gchar *type_name, MonoException* inner_raw) { HANDLE_FUNCTION_ENTER (); MONO_HANDLE_DCL (MonoException, inner); ERROR_DECL (error); MonoExceptionHandle ret = mono_get_exception_type_initialization_handle (type_name, inner, error); if (!is_ok (error)) { ret = MONO_HANDLE_CAST (MonoException, mono_new_null ()); mono_error_cleanup (error); } HANDLE_FUNCTION_RETURN_OBJ (ret); }
/** * mono_get_exception_reflection_type_load: * \param types an array of types that were defined in the moduled loaded. * \param exceptions an array of exceptions that were thrown during the type loading. * \returns a new instance of the \c System.Reflection.ReflectionTypeLoadException */ MonoException * mono_get_exception_reflection_type_load (MonoArray *types_raw, MonoArray *exceptions_raw) { HANDLE_FUNCTION_ENTER (); ERROR_DECL (error); MONO_HANDLE_DCL (MonoArray, types); MONO_HANDLE_DCL (MonoArray, exceptions); MonoExceptionHandle ret = mono_get_exception_reflection_type_load_checked (types, exceptions, error); if (!is_ok (error)) ret = MONO_HANDLE_CAST (MonoException, mono_new_null ()); mono_error_cleanup (error); HANDLE_FUNCTION_RETURN_OBJ (ret); }
/** * mono_get_exception_file_not_found2: * \param msg an informative message for the user. * \param fname the name of the file not found. * \returns a new instance of the \c System.IO.FileNotFoundException */ MonoException * mono_get_exception_file_not_found2 (const char *msg, MonoString *fname_raw) { HANDLE_FUNCTION_ENTER (); ERROR_DECL (error); MONO_HANDLE_DCL (MonoString, fname); MonoStringHandle s = NULL_HANDLE_STRING; if (msg) { s = mono_string_new_handle (mono_domain_get (), msg, error); mono_error_assert_ok (error); } MonoExceptionHandle ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System.IO", "FileNotFoundException", s, fname, error); mono_error_assert_ok (error); HANDLE_FUNCTION_RETURN_OBJ (ret); }
/** * mono_get_exception_missing_member: * \param exception_type the specific exception type for the specific member type, i.e. field or method * \param class_name the class where the lookup was performed. * \param member_name the name of the missing method. * \returns a new instance of the \c exception_type (MissingFieldException or MissingMethodException) */ static MonoException* mono_get_exception_missing_member (const char *exception_type, const char *class_name, const char *member_name) { HANDLE_FUNCTION_ENTER (); ERROR_DECL (error); MonoDomain * const domain = mono_domain_get (); MonoStringHandle s1 = mono_string_new_handle (domain, class_name, error); mono_error_assert_ok (error); MonoStringHandle s2 = mono_string_new_handle (domain, member_name, error); mono_error_assert_ok (error); MonoExceptionHandle ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", exception_type, s1, s2, error); mono_error_assert_ok (error); HANDLE_FUNCTION_RETURN_OBJ (ret); }
static void mono_init_merp (const intptr_t crashed_pid, const char *signal, MonoStackHash *hashes, MERPStruct *merp, const char *version) { g_assert (mono_merp_enabled ()); // If these aren't set, icall wasn't made // don't do merp? / don't set the variable to use merp; g_assert (config.appBundleID); g_assert (config.appVersion); merp->bundleIDArg = config.appSignature; merp->versionArg = config.appVersion; merp->archArg = get_merp_arch (); merp->exceptionArg = parse_exception_type (signal); merp->serviceNameArg = config.appBundleID; // FIXME: Not really a posix way to associated a process with a single executable // path? Linux gets bogged down in /proc merp->servicePathArg = NULL; if (crashed_pid) { size_t servicePathSize = sizeof (gchar) * 1200; merp->servicePathArg = g_malloc0 (servicePathSize); int result = proc_pidpath (crashed_pid, (void *) merp->servicePathArg, 1200); if (result <= 0) { g_free ((void *) merp->servicePathArg); merp->servicePathArg = NULL; } } merp->moduleName = "Mono Exception"; merp->moduleVersion = version; merp->moduleOffset = 0; ERROR_DECL (error); merp->uiLidArg = ves_icall_System_Threading_Thread_current_lcid (error); mono_error_assert_ok (error); merp->osVersion = os_version_string (); // FIXME: THis is apple-only for now merp->systemManufacturer = "apple"; get_apple_model ((char *) merp->systemModel, sizeof (merp->systemModel)); merp->hashes = *hashes; }
MonoArray* ves_icall_System_Security_Principal_WindowsIdentity_GetRoles (gpointer token) { ERROR_DECL (error); MonoArray *array = NULL; MonoDomain *domain = mono_domain_get (); /* POSIX-compliant systems should use IsMemberOfGroupId or IsMemberOfGroupName */ g_warning ("WindowsIdentity._GetRoles should never be called on POSIX"); if (!array) { /* return empty array of string, i.e. string [0] */ array = mono_array_new_checked (domain, mono_get_string_class (), 0, error); mono_error_set_pending_exception (error); } return array; }
/** * mono_exception_from_token: * \param image the Mono image where to look for the class * \param token The type token of the class * * Creates an exception of the type given by \p token. * * \returns the initialized exception instance. */ MonoException * mono_exception_from_token (MonoImage *image, guint32 token) { HANDLE_FUNCTION_ENTER (); ERROR_DECL (error); MonoClass *klass; klass = mono_class_get_checked (image, token, error); mono_error_assert_ok (error); MonoObjectHandle o = mono_object_new_handle (mono_domain_get (), klass, error); mono_error_assert_ok (error); mono_runtime_object_init_handle (o, error); mono_error_assert_ok (error); HANDLE_FUNCTION_RETURN_OBJ (MONO_HANDLE_CAST (MonoException, o)); }
/** * mono_get_exception_type_load: * \param class_name the name of the class that could not be loaded * \param assembly_name the assembly where the class was looked up. * \returns a new instance of the \c System.TypeLoadException */ MonoException * mono_get_exception_type_load (MonoString *class_name_raw, char *assembly_name) { ERROR_DECL (error); HANDLE_FUNCTION_ENTER (); MONO_HANDLE_DCL (MonoString, class_name); MonoStringHandle s = NULL_HANDLE_STRING; MonoDomain * const domain = mono_domain_get (); if (assembly_name) { s = mono_string_new_handle (domain, assembly_name, error); mono_error_assert_ok (error); } else s = mono_string_empty_handle (domain); MonoExceptionHandle ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", "TypeLoadException", class_name, s, error); mono_error_assert_ok (error); HANDLE_FUNCTION_RETURN_OBJ (ret); }
/* * Context propagation is required when: * (a) the security manager is active (1.x and later) * (b) other contexts needs to be propagated (2.x and later) * * returns NULL if no context propagation is required, else the returns the * MonoMethod to call to Capture the ExecutionContext. */ MonoMethod* mono_get_context_capture_method (void) { static MonoMethod *method = NULL; if (mono_image_get_assembly (mono_defaults.corlib)->aname.major < 2) return NULL; /* older corlib revisions won't have the class (nor the method) */ MonoClass *execution_context = mono_class_try_get_execution_context_class (); if (execution_context && !method) { ERROR_DECL (error); mono_class_init_internal (execution_context); method = mono_class_get_method_from_name_checked (execution_context, "Capture", 0, 0, error); mono_error_assert_ok (error); } return method; }
static void throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean rethrow, gboolean preserve_ips) { ERROR_DECL (error); MonoContext ctx; #ifdef DEBUG_EXCEPTIONS g_print ("throw_exception: exc=%p eip=%p esp=%p rethrow=%d\n", exc, (void *)eip, (void *) esp, rethrow); #endif /* adjust eip so that it point into the call instruction */ eip -= 8; memset (&ctx, 0, sizeof (MonoContext)); /*g_print ("stack in throw: %p\n", esp);*/ memcpy (&ctx.sc_regs, (void *)(esp + MIPS_STACK_PARAM_OFFSET), sizeof (gulong) * MONO_SAVED_GREGS); memset (&ctx.sc_fpregs, 0, sizeof (mips_freg) * MONO_SAVED_FREGS); MONO_CONTEXT_SET_IP (&ctx, eip); if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) { MonoException *mono_ex = (MonoException*)exc; if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; } if (preserve_ips) { mono_ex->caught_in_unmanaged = TRUE; } } mono_error_assert_ok (error); mono_handle_exception (&ctx, exc); #ifdef DEBUG_EXCEPTIONS g_print ("throw_exception: restore to pc=%p sp=%p fp=%p ctx=%p\n", (void *) ctx.sc_pc, (void *) ctx.sc_regs[mips_sp], (void *) ctx.sc_regs[mips_fp], &ctx); #endif mono_restore_context (&ctx); g_assert_not_reached (); }
/* * mono_x86_throw_exception: * * C function called from the throw trampolines. */ void mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc, mgreg_t eip, gboolean rethrow) { ERROR_DECL (error); MonoContext ctx; ctx.esp = regs [X86_ESP]; ctx.eip = eip; ctx.ebp = regs [X86_EBP]; ctx.edi = regs [X86_EDI]; ctx.esi = regs [X86_ESI]; ctx.ebx = regs [X86_EBX]; ctx.edx = regs [X86_EDX]; ctx.ecx = regs [X86_ECX]; ctx.eax = regs [X86_EAX]; #ifdef __APPLE__ /* The OSX ABI specifies 16 byte alignment at call sites */ g_assert ((ctx.esp % MONO_ARCH_FRAME_ALIGNMENT) == 0); #endif if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) { MonoException *mono_ex = (MonoException*)exc; if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; } } mono_error_assert_ok (error); /* adjust eip so that it point into the call instruction */ ctx.eip -= 1; mono_handle_exception (&ctx, exc); mono_restore_context (&ctx); g_assert_not_reached (); }
void mono_invoke_unhandled_exception_hook (MonoObject *exc) { if (unhandled_exception_hook) { unhandled_exception_hook (exc, unhandled_exception_hook_data); } else { ERROR_DECL (inner_error); MonoObject *other = NULL; MonoString *str = mono_object_try_to_string (exc, &other, inner_error); char *msg = NULL; if (str && is_ok (inner_error)) { msg = mono_string_to_utf8_checked_internal (str, inner_error); if (!is_ok (inner_error)) { msg = g_strdup_printf ("Nested exception while formatting original exception"); mono_error_cleanup (inner_error); } } else if (other) { char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc); char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other); msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n", original_backtrace, nested_backtrace); g_free (original_backtrace); g_free (nested_backtrace); } else { msg = g_strdup ("Nested exception trying to figure out what went wrong"); } mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg); g_free (msg); #if defined(HOST_IOS) g_assertion_message ("Terminating runtime due to unhandled exception"); #else exit (mono_environment_exitcode_get ()); #endif } g_assert_not_reached (); }
__int32 STDMETHODCALLTYPE _CorExeMain(void) { ERROR_DECL (error); MonoDomain* domain; MonoAssembly* assembly; MonoImage* image; MonoMethod* method; guint32 entry; gchar* file_name; gchar* corlib_version_error; int argc; gunichar2** argvw; gchar** argv; int i; file_name = mono_get_module_file_name (NULL); init_from_coree = TRUE; domain = mono_runtime_load (file_name, NULL); corlib_version_error = (gchar*) mono_check_corlib_version (); if (corlib_version_error) { g_free (corlib_version_error); g_free (file_name); MessageBox (NULL, L"Corlib not in sync with this runtime.", NULL, MB_ICONERROR); mono_runtime_quit (); ExitProcess (1); } MonoAssemblyOpenRequest req; mono_assembly_request_prepare (&req.request, sizeof (req), MONO_ASMCTX_DEFAULT); assembly = mono_assembly_request_open (file_name, &req, NULL); mono_close_exe_image (); if (!assembly) { g_free (file_name); MessageBox (NULL, L"Cannot open assembly.", NULL, MB_ICONERROR); mono_runtime_quit (); ExitProcess (1); } image = assembly->image; entry = mono_image_get_entry_point (image); if (!entry) { g_free (file_name); MessageBox (NULL, L"Assembly doesn't have an entry point.", NULL, MB_ICONERROR); mono_runtime_quit (); ExitProcess (1); } method = mono_get_method_checked (image, entry, NULL, NULL, error); if (method == NULL) { g_free (file_name); mono_error_cleanup (error); /* FIXME don't swallow the error */ MessageBox (NULL, L"The entry point method could not be loaded.", NULL, MB_ICONERROR); mono_runtime_quit (); ExitProcess (1); } argvw = CommandLineToArgvW (GetCommandLine (), &argc); argv = g_new0 (gchar*, argc); argv [0] = file_name; for (i = 1; i < argc; ++i) argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL); LocalFree (argvw); mono_runtime_run_main_checked (method, argc, argv, error); mono_error_raise_exception_deprecated (error); /* OK, triggers unhandled exn handler */ mono_thread_manage (); mono_runtime_quit (); /* return does not terminate the process. */ ExitProcess (mono_environment_exitcode_get ()); }
/* * mono_debug_add_vg_method: * * Register symbol information for the method with valgrind */ static void mono_debug_add_vg_method (MonoMethod *method, MonoDebugMethodJitInfo *jit) { #ifdef VALGRIND_ADD_LINE_INFO ERROR_DECL (error); MonoMethodHeader *header; MonoDebugMethodInfo *minfo; int i; char *filename = NULL; guint32 address, line_number; const char *full_name; guint32 *addresses; guint32 *lines; if (!RUNNING_ON_VALGRIND) return; header = mono_method_get_header_checked (method, error); mono_error_assert_ok (error); /* FIXME don't swallow the error */ full_name = mono_method_full_name (method, TRUE); addresses = g_new0 (guint32, header->code_size + 1); lines = g_new0 (guint32, header->code_size + 1); /* * Very simple code to convert the addr->offset mappings that mono has * into [addr-addr] ->line number mappings. */ minfo = mono_debug_lookup_method (method); if (minfo) { /* Create offset->line number mapping */ for (i = 0; i < header->code_size; ++i) { MonoDebugSourceLocation *location; location = mono_debug_method_lookup_location (minfo, i); if (!location) continue; lines [i] = location.row; if (!filename) filename = location.source_file; mono_debug_free_source_location (location); } } /* Create address->offset mapping */ for (i = 0; i < jit->num_line_numbers; ++i) { MonoDebugLineNumberEntry *lne = jit->line_numbers [i]; g_assert (lne->offset <= header->code_size); if ((addresses [lne->offset] == 0) || (lne->address < addresses [lne->offset])) addresses [lne->offset] = lne->address; } /* Fill out missing addresses */ address = 0; for (i = 0; i < header->code_size; ++i) { if (addresses [i] == 0) addresses [i] = address; else address = addresses [i]; } address = 0; line_number = 0; i = 0; while (i < header->code_size) { if (lines [i] == line_number) i ++; else { if (line_number > 0) { //g_assert (addresses [i] - 1 >= address); if (addresses [i] - 1 >= address) { VALGRIND_ADD_LINE_INFO (jit->code_start + address, jit->code_start + addresses [i] - 1, filename, line_number); //printf ("[%d-%d] -> %d.\n", address, addresses [i] - 1, line_number); } } address = addresses [i]; line_number = lines [i]; } } if (line_number > 0) { VALGRIND_ADD_LINE_INFO (jit->code_start + address, jit->code_start + jit->code_size - 1, filename, line_number); //printf ("[%d-%d] -> %d.\n", address, jit->code_size - 1, line_number); } VALGRIND_ADD_SYMBOL (jit->code_start, jit->code_size, full_name); g_free (addresses); g_free (lines); mono_metadata_free_mh (header); #endif /* VALGRIND_ADD_LINE_INFO */ }
/* * actually, we might want to queue the finalize requests in a separate thread, * but we need to be careful about the execution domain of the thread... */ void mono_gc_run_finalize (void *obj, void *data) { ERROR_DECL (error); MonoObject *exc = NULL; MonoObject *o; #ifndef HAVE_SGEN_GC MonoObject *o2; #endif MonoMethod* finalizer = NULL; MonoDomain *caller_domain = mono_domain_get (); MonoDomain *domain; // This function is called from the innards of the GC, so our best alternative for now is to do polling here mono_threads_safepoint (); o = (MonoObject*)((char*)obj + GPOINTER_TO_UINT (data)); const char *o_ns = m_class_get_name_space (mono_object_class (o)); const char *o_name = m_class_get_name (mono_object_class (o)); if (mono_do_not_finalize) { if (!mono_do_not_finalize_class_names) return; size_t namespace_len = strlen (o_ns); for (int i = 0; mono_do_not_finalize_class_names [i]; ++i) { const char *name = mono_do_not_finalize_class_names [i]; if (strncmp (name, o_ns, namespace_len)) break; if (name [namespace_len] != '.') break; if (strcmp (name + namespace_len + 1, o_name)) break; return; } } if (mono_log_finalizers) g_log ("mono-gc-finalizers", G_LOG_LEVEL_DEBUG, "<%s at %p> Starting finalizer checks.", o_name, o); if (suspend_finalizers) return; domain = o->vtable->domain; #ifndef HAVE_SGEN_GC mono_domain_finalizers_lock (domain); o2 = (MonoObject *)g_hash_table_lookup (domain->finalizable_objects_hash, o); mono_domain_finalizers_unlock (domain); if (!o2) /* Already finalized somehow */ return; #endif /* make sure the finalizer is not called again if the object is resurrected */ object_register_finalizer ((MonoObject *)obj, NULL); if (mono_log_finalizers) g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Registered finalizer as processed.", o_name, o); if (o->vtable->klass == mono_defaults.internal_thread_class) { MonoInternalThread *t = (MonoInternalThread*)o; if (mono_gc_is_finalizer_internal_thread (t)) /* Avoid finalizing ourselves */ return; } if (m_class_get_image (mono_object_class (o)) == mono_defaults.corlib && !strcmp (o_name, "DynamicMethod") && finalizing_root_domain) { /* * These can't be finalized during unloading/shutdown, since that would * free the native code which can still be referenced by other * finalizers. * FIXME: This is not perfect, objects dying at the same time as * dynamic methods can still reference them even when !shutdown. */ return; } if (mono_runtime_get_no_exec ()) return; /* speedup later... and use a timeout */ /* g_print ("Finalize run on %p %s.%s\n", o, mono_object_class (o)->name_space, mono_object_class (o)->name); */ /* Use _internal here, since this thread can enter a doomed appdomain */ mono_domain_set_internal (mono_object_domain (o)); /* delegates that have a native function pointer allocated are * registered for finalization, but they don't have a Finalize * method, because in most cases it's not needed and it's just a waste. */ if (m_class_is_delegate (mono_object_class (o))) { MonoDelegate* del = (MonoDelegate*)o; if (del->delegate_trampoline) mono_delegate_free_ftnptr ((MonoDelegate*)o); mono_domain_set_internal (caller_domain); return; } finalizer = mono_class_get_finalizer (o->vtable->klass); /* If object has a CCW but has no finalizer, it was only * registered for finalization in order to free the CCW. * Else it needs the regular finalizer run. * FIXME: what to do about ressurection and suppression * of finalizer on object with CCW. */ if (mono_marshal_free_ccw (o) && !finalizer) { mono_domain_set_internal (caller_domain); return; } /* * To avoid the locking plus the other overhead of mono_runtime_invoke_checked (), * create and precompile a wrapper which calls the finalize method using * a CALLVIRT. */ if (mono_log_finalizers) g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Compiling finalizer.", o_name, o); #ifndef HOST_WASM if (!domain->finalize_runtime_invoke) { MonoMethod *finalize_method = mono_class_get_method_from_name_checked (mono_defaults.object_class, "Finalize", 0, 0, error); mono_error_assert_ok (error); MonoMethod *invoke = mono_marshal_get_runtime_invoke (finalize_method, TRUE); domain->finalize_runtime_invoke = mono_compile_method_checked (invoke, error); mono_error_assert_ok (error); /* expect this not to fail */ } RuntimeInvokeFunction runtime_invoke = (RuntimeInvokeFunction)domain->finalize_runtime_invoke; #endif mono_runtime_class_init_full (o->vtable, error); goto_if_nok (error, unhandled_error); if (G_UNLIKELY (MONO_GC_FINALIZE_INVOKE_ENABLED ())) { MONO_GC_FINALIZE_INVOKE ((unsigned long)o, mono_object_get_size_internal (o), o_ns, o_name); } if (mono_log_finalizers) g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Calling finalizer.", o_name, o); MONO_PROFILER_RAISE (gc_finalizing_object, (o)); #ifdef HOST_WASM if (finalizer) { // null finalizers work fine when using the vcall invoke as Object has an empty one gpointer params [1]; params [0] = NULL; mono_runtime_try_invoke (finalizer, o, params, &exc, error); } #else runtime_invoke (o, NULL, &exc, NULL); #endif MONO_PROFILER_RAISE (gc_finalized_object, (o)); if (mono_log_finalizers) g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o_name, o); unhandled_error: if (!is_ok (error)) exc = (MonoObject*)mono_error_convert_to_exception (error); if (exc) mono_thread_internal_unhandled_exception (exc); mono_domain_set_internal (caller_domain); }
static int dump_verify_info (MonoImage *image, int flags, gboolean valid_only) { GSList *errors, *tmp; int count = 0, verifiable = 0; const char* desc [] = { "Ok", "Error", "Warning", NULL, "CLS", NULL, NULL, NULL, "Not Verifiable" }; if (verify_code) { /* verify code */ int i; MonoTableInfo *m = &image->tables [MONO_TABLE_METHOD]; for (i = 0; i < m->rows; ++i) { MonoMethod *method; ERROR_DECL (error); method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i+1), NULL, NULL, error); if (!method) { g_print ("Warning: Cannot lookup method with token 0x%08x due to %s\n", i + 1, mono_error_get_message (error)); mono_error_cleanup (error); continue; } errors = mono_method_verify (method, flags); if (errors) { MonoClass *klass = mono_method_get_class (method); char *name = mono_type_full_name (m_class_get_byval_arg (klass)); if (mono_method_signature_internal (method) == NULL) { g_print ("In method: %s::%s(ERROR)\n", name, mono_method_get_name (method)); } else { char *sig; sig = mono_signature_get_desc (mono_method_signature_internal (method), FALSE); g_print ("In method: %s::%s(%s)\n", name, mono_method_get_name (method), sig); g_free (sig); } g_free (name); } for (tmp = errors; tmp; tmp = tmp->next) { MonoVerifyInfo *info = (MonoVerifyInfo *)tmp->data; if (info->status == MONO_VERIFY_NOT_VERIFIABLE && valid_only) continue; g_print ("%s: %s\n", desc [info->status], info->message); if (info->status == MONO_VERIFY_ERROR) { count++; verifiable = 3; } if(info->status == MONO_VERIFY_NOT_VERIFIABLE) { if (verifiable < 2) verifiable = 2; } } mono_free_verify_list (errors); } } if (count) g_print ("Error count: %d\n", count); return verifiable; }
static int verify_image_file (const char *fname) { ERROR_DECL (error); MonoImage *image; MonoTableInfo *table; MonoAssembly *assembly; MonoImageOpenStatus status; int i, count = 0; if (!strstr (fname, "mscorlib.dll")) { image = mono_image_open_raw (fname, &status); if (!image) { printf ("Could not open %s\n", fname); return 1; } if (!mono_verifier_verify_pe_data (image, error)) goto invalid_image; if (!mono_image_load_pe_data (image)) { printf ("Could not load pe data for assembly %s\n", fname); return 1; } if (!mono_verifier_verify_cli_data (image, error)) goto invalid_image; if (!mono_image_load_cli_data (image)) { printf ("Could not load cli data for assembly %s\n", fname); return 1; } if (!mono_verifier_verify_table_data (image, error)) goto invalid_image; mono_image_load_names (image); /*fake an assembly for class loading to work*/ assembly = g_new0 (MonoAssembly, 1); assembly->in_gac = FALSE; assembly->image = image; image->assembly = assembly; mono_assembly_fill_assembly_name (image, &assembly->aname); /*Finish initializing the runtime*/ mono_install_assembly_load_hook (pedump_assembly_load_hook, NULL); mono_install_assembly_search_hook (pedump_assembly_search_hook, NULL); mono_init_version ("pedump", image->version); mono_install_assembly_preload_hook (pedump_preload, GUINT_TO_POINTER (FALSE)); mono_icall_init (); mono_marshal_init (); } else { /*Finish initializing the runtime*/ mono_install_assembly_load_hook (pedump_assembly_load_hook, NULL); mono_install_assembly_search_hook (pedump_assembly_search_hook, NULL); mono_init_version ("pedump", NULL); mono_install_assembly_preload_hook (pedump_preload, GUINT_TO_POINTER (FALSE)); mono_icall_init (); mono_marshal_init (); image = mono_get_corlib (); if (!mono_verifier_verify_pe_data (image, error)) goto invalid_image; if (!mono_image_load_pe_data (image)) { printf ("Could not load pe data for assembly %s\n", fname); return 1; } if (!mono_verifier_verify_cli_data (image, error)) goto invalid_image; if (!mono_image_load_cli_data (image)) { printf ("Could not load cli data for assembly %s\n", fname); return 1; } if (!mono_verifier_verify_table_data (image, error)) goto invalid_image; } if (!verify_partial_md && !mono_verifier_verify_full_table_data (image, error)) goto invalid_image; table = &image->tables [MONO_TABLE_TYPEDEF]; for (i = 1; i <= table->rows; ++i) { ERROR_DECL (error); guint32 token = i | MONO_TOKEN_TYPE_DEF; MonoClass *klass = mono_class_get_checked (image, token, error); if (!klass) { printf ("Could not load class with token %x due to %s\n", token, mono_error_get_message (error)); mono_error_cleanup (error); continue; } mono_class_init_internal (klass); if (mono_class_has_failure (klass)) { ERROR_DECL (type_load_error); mono_error_set_for_class_failure (type_load_error, klass); printf ("Could not initialize class(0x%08x) %s.%s due to %s\n", token, m_class_get_name_space (klass), m_class_get_name (klass), mono_error_get_message (type_load_error)); mono_error_cleanup (type_load_error); ++count; } mono_class_setup_vtable (klass); if (mono_class_has_failure (klass)) { ERROR_DECL (type_load_error); mono_error_set_for_class_failure (type_load_error, klass); printf ("Could not initialize vtable of class(0x%08x) %s.%s due to %s\n", token, m_class_get_name_space (klass), m_class_get_name (klass), mono_error_get_message (type_load_error)); mono_error_cleanup (type_load_error); ++count; } } if (count) return 5; return 0; invalid_image: if (!is_ok (error)) { g_print ("FAIL: %s\n", mono_error_get_message (error)); mono_error_cleanup (error); ++count; } if (count) g_print ("Error count: %d\n", count); return 1; }