gint ves_icall_System_IO_FSW_SupportsFSW (void) { #if HAVE_KQUEUE return 3; #else MonoDl *fam_module; int lib_used = 4; /* gamin */ int inotify_instance; char *err; inotify_instance = ves_icall_System_IO_InotifyWatcher_GetInotifyInstance (); if (inotify_instance != -1) { close (inotify_instance); return 5; /* inotify */ } fam_module = mono_dl_open ("libgamin-1.so", MONO_DL_LAZY, NULL); if (fam_module == NULL) { lib_used = 2; /* FAM */ fam_module = mono_dl_open ("libfam.so", MONO_DL_LAZY, NULL); } if (fam_module == NULL) return 0; err = mono_dl_symbol (fam_module, "FAMNextEvent", (gpointer *) &FAMNextEvent); g_free (err); if (FAMNextEvent == NULL) return 0; return lib_used; #endif }
static char * mono_extension_handle_native_sigsegv_libunwind (void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info) { char *dl_err; int unw_err; unw_init_local_t unw_init_local_fn; unw_get_reg_t unw_get_reg_fn; unw_get_proc_name_t unw_get_proc_name_fn; unw_step_t unw_step_fn; unw_cursor_t cursor; size_t frames = 0; MonoDl *dl = mono_dl_open ("libunwind.so", MONO_DL_LAZY, &dl_err); if (!dl) return dl_err; LOAD_SYM (dl, dl_err, UNW_OBJ (init_local), unw_init_local_fn); LOAD_SYM (dl, dl_err, UNW_OBJ (get_reg), unw_get_reg_fn); LOAD_SYM (dl, dl_err, UNW_OBJ (get_proc_name), unw_get_proc_name_fn); LOAD_SYM (dl, dl_err, UNW_OBJ (step), unw_step_fn); if ((unw_err = unw_init_local_fn (&cursor, ctx))) { mono_dl_close (dl); return g_strdup_printf ("unw_init_local () returned %d", unw_err); } do { int reg_err; unw_word_t ip, off; char name [FUNC_NAME_LENGTH]; if ((reg_err = unw_get_reg_fn (&cursor, UNW_REG_IP, &ip))) { mono_runtime_printf_err ("unw_get_reg (UNW_REG_IP) returned %d", reg_err); break; } reg_err = unw_get_proc_name_fn (&cursor, name, FUNC_NAME_LENGTH, &off); if (reg_err == -UNW_ENOINFO) strcpy (name, "???"); mono_runtime_printf_err (" at %s+%zu [0x%zx]", name, off, ip); unw_err = unw_step_fn (&cursor); frames++; } while (unw_err > 0 && frames < FRAMES_TO_UNWIND); if (unw_err < 0) mono_runtime_printf_err ("unw_step () returned %d", unw_err); mono_dl_close (dl); return NULL; }
static gboolean load_embedded_profiler (const char *desc, const char *name) { char *err = NULL; char *symbol; MonoDl *pmodule = NULL; gboolean result; /* * Some profilers (such as ours) may need to call back into the runtime * from their sampling callback (which is called in async-signal context). * They need to be able to know that all references back to the runtime * have been resolved; otherwise, calling runtime functions may result in * invoking the dynamic linker which is not async-signal-safe. Passing * MONO_DL_EAGER will ask the dynamic linker to resolve everything upfront. */ pmodule = mono_dl_open (NULL, MONO_DL_EAGER, &err); if (!pmodule) { g_warning ("Could not open main executable (%s)", err); g_free (err); return FALSE; } symbol = g_strdup_printf (INITIALIZER_NAME "_%s", name); result = load_profiler (pmodule, desc, symbol); g_free (symbol); return result; }
/** * mono_profiler_load: * @desc: arguments to configure the profiler * * Invoke this method to initialize the profiler. This will drive the * loading of the internal ("default") or any external profilers. * * This routine is invoked by Mono's driver, but must be called manually * if you embed Mono into your application. */ void mono_profiler_load (const char *desc) { mono_gc_base_init (); #ifndef DISABLE_PROFILER if (!desc || (strcmp ("default", desc) == 0) || (strncmp (desc, "default:", 8) == 0)) { mono_profiler_install_simple (desc); return; } #else if (!desc) { desc = "default"; } #endif { MonoDl *pmodule = NULL; const char* col = strchr (desc, ':'); char* libname; char* path; char *mname; char *err; void *iter; if (col != NULL) { mname = g_memdup (desc, col - desc + 1); mname [col - desc] = 0; } else { mname = g_strdup (desc); } libname = g_strdup_printf ("mono-profiler-%s", mname); iter = NULL; err = NULL; while ((path = mono_dl_build_path (NULL, libname, &iter))) { g_free (err); pmodule = mono_dl_open (path, MONO_DL_LAZY, &err); if (pmodule) { ProfilerInitializer func; if ((err = mono_dl_symbol (pmodule, INITIALIZER_NAME, (gpointer *)&func))) { g_warning ("Cannot find initializer function %s in profiler module: %s (%s)", INITIALIZER_NAME, libname, err); g_free (err); err = NULL; } else { func (desc); } break; } g_free (path); } if (!pmodule) { g_warning ("Error loading profiler module '%s': %s", libname, err); g_free (err); } g_free (libname); g_free (mname); g_free (path); } }
static MonoDl* try_load (const char *lib_name, char *dir, int flags, char **err) { gpointer iter; MonoDl *runtime_lib; char *path; iter = NULL; *err = NULL; while ((path = mono_dl_build_path (dir, lib_name, &iter))) { g_free (*err); runtime_lib = mono_dl_open (path, flags, err); g_free (path); if (runtime_lib) return runtime_lib; } return NULL; }
static gboolean load_profiler_from_directory (const char *directory, const char *libname, const char *desc) { MonoDl *pmodule = NULL; char* path; char *err; void *iter; iter = NULL; err = NULL; while ((path = mono_dl_build_path (directory, libname, &iter))) { pmodule = mono_dl_open (path, MONO_DL_LAZY, &err); g_free (path); g_free (err); if (pmodule) return load_profiler (pmodule, desc, INITIALIZER_NAME); } return FALSE; }
static gboolean load_embedded_profiler (const char *desc, const char *name) { char *err = NULL; char *symbol; MonoDl *pmodule = NULL; gboolean result; pmodule = mono_dl_open (NULL, MONO_DL_LAZY, &err); if (!pmodule) { g_warning ("Could not open main executable (%s)", err); g_free (err); return FALSE; } symbol = g_strdup_printf (INITIALIZER_NAME "_%s", name); result = load_profiler (pmodule, desc, symbol); g_free (symbol); return result; }
// TODO: Much of the library loading code here is custom. It would be better to merge this with mono-dl static gboolean load_profiler_from_directory (const char *directory, const char *libname, const char *desc) { MonoDl *pmodule = NULL; char* path; char *err; void *iter; mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler %s from %s (desc %s)", libname, directory, desc); iter = NULL; err = NULL; while ((path = mono_dl_build_path (directory, libname, &iter))) { pmodule = mono_dl_open (path, MONO_DL_EAGER, &err); mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler: %s, %ssuccessful, err: %s", path, pmodule?"":"not ", err); g_free (path); g_free (err); if (pmodule) return load_profiler (pmodule, desc, INITIALIZER_NAME); } return FALSE; }
static char * mono_extension_handle_native_sigsegv_libcorkscrew (void *ctx, MONO_SIG_HANDLER_INFO_TYPE *info) { #if defined (__arm__) || defined (__i386__) char *dl_err; get_backtrace_symbols_t get_backtrace_symbols; free_backtrace_symbols_t free_backtrace_symbols; unwind_backtrace_signal_arch_t unwind_backtrace_signal_arch; acquire_my_map_info_list_t acquire_my_map_info_list; release_my_map_info_list_t release_my_map_info_list; backtrace_frame_t frames [FRAMES_TO_UNWIND]; backtrace_symbol_t symbols [FRAMES_TO_UNWIND]; map_info_t *map_info; ssize_t frames_unwound; size_t i; MonoDl *dl = mono_dl_open ("libcorkscrew.so", MONO_DL_LAZY, &dl_err); if (!dl) return dl_err; LOAD_SYM (dl, dl_err, get_backtrace_symbols, get_backtrace_symbols); LOAD_SYM (dl, dl_err, free_backtrace_symbols, free_backtrace_symbols); LOAD_SYM (dl, dl_err, unwind_backtrace_signal_arch, unwind_backtrace_signal_arch); LOAD_SYM (dl, dl_err, acquire_my_map_info_list, acquire_my_map_info_list); LOAD_SYM (dl, dl_err, release_my_map_info_list, release_my_map_info_list); map_info = acquire_my_map_info_list (); frames_unwound = unwind_backtrace_signal_arch (info, ctx, map_info, frames, 0, FRAMES_TO_UNWIND); release_my_map_info_list (map_info); if (frames_unwound == -1) { mono_dl_close (dl); return g_strdup ("unwind_backtrace_signal_arch () returned -1"); } get_backtrace_symbols (frames, frames_unwound, symbols); for (i = 0; i < frames_unwound; i++) { backtrace_frame_t *frame = frames + i; backtrace_symbol_t *symbol = symbols + i; const char *name = symbol->demangled_name ? symbol->demangled_name : (symbol->symbol_name ? symbol->symbol_name : "???"); uintptr_t off = symbol->relative_pc - symbol->relative_symbol_addr; uintptr_t ip = frame->absolute_pc; mono_runtime_printf_err (" at %s+%zu [0x%zx]", name, off, ip); } free_backtrace_symbols (symbols, frames_unwound); mono_dl_close (dl); return NULL; #else return g_strdup ("libcorkscrew is only supported on 32-bit ARM/x86"); #endif }