/** * mono_debug_print_stack_frame: * @native_offset: Native offset within the @method's machine code. * * Conventient wrapper around mono_debug_lookup_source_location() which can be * used if you only want to use the location to print a stack frame. */ gchar * mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain) { MonoDebugSourceLocation *location; gchar *fname, *ptr, *res; int offset; fname = mono_method_full_name (method, TRUE); for (ptr = fname; *ptr; ptr++) { if (*ptr == ':') *ptr = '.'; } location = mono_debug_lookup_source_location (method, native_offset, domain); if (!location) { if (mono_debug_initialized) { mono_debugger_lock (); offset = il_offset_from_address (method, domain, native_offset); mono_debugger_unlock (); } else { offset = -1; } if (offset < 0) res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset); else res = g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname, offset, native_offset); g_free (fname); return res; } res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset, location->source_file, location->row); g_free (fname); mono_debug_free_source_location (location); return res; }
static inline gchar *build_hint_from_stack (MonoDomain *domain, void **stack, gint stack_entries) { gchar *hint; MonoMethod *method, *selectedMethod; MonoAssembly *assembly; MonoImage *image; MonoDebugSourceLocation *location; MonoStackBacktraceInfo *info; gboolean use_full_trace; char *methodName; gint i, native_offset, firstAvailable; selectedMethod = NULL; firstAvailable = -1; use_full_trace = FALSE; native_offset = -1; for (i = 0; i < stack_entries; i++) { info = (MonoStackBacktraceInfo*) stack [i]; method = info ? info->method : NULL; if (!method || method->wrapper_type != MONO_WRAPPER_NONE) continue; if (firstAvailable == -1) firstAvailable = i; image = method->klass->image; assembly = image->assembly; if ((assembly && assembly->in_gac) || ignore_frame (method)) continue; selectedMethod = method; native_offset = info->native_offset; break; } if (!selectedMethod) { /* All the frames were from assemblies installed in GAC. Find first frame that is * not in the ignore list */ for (i = 0; i < stack_entries; i++) { info = (MonoStackBacktraceInfo*) stack [i]; method = info ? info->method : NULL; if (!method || ignore_frame (method)) continue; selectedMethod = method; native_offset = info->native_offset; break; } if (!selectedMethod) use_full_trace = TRUE; } hint = NULL; if (use_full_trace) { GString *trace = g_string_new ("Full trace:\n"); for (i = firstAvailable; i < stack_entries; i++) { info = (MonoStackBacktraceInfo*) stack [i]; method = info ? info->method : NULL; if (!method || method->wrapper_type != MONO_WRAPPER_NONE) continue; location = mono_debug_lookup_source_location (method, info->native_offset, domain); methodName = mono_method_full_name (method, TRUE); if (location) { append_report (&trace, LOCATION_INDENT "%s in %s:%u\n", methodName, location->source_file, location->row); mono_debug_free_source_location (location); } else append_report (&trace, LOCATION_INDENT "%s\n", methodName); g_free (methodName); } if (trace) { if (trace->len) hint = g_string_free (trace, FALSE); else g_string_free (trace, TRUE); } } else { location = mono_debug_lookup_source_location (selectedMethod, native_offset, domain); methodName = mono_method_full_name (selectedMethod, TRUE); if (location) { hint = g_strdup_printf (LOCATION_INDENT "%s in %s:%u\n", methodName, location->source_file, location->row); mono_debug_free_source_location (location); } else hint = g_strdup_printf (LOCATION_INDENT "%s\n", methodName); g_free (methodName); } return hint; }
static void method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) { if (result == MONO_PROFILE_OK) { int i; MonoDebugSourceLocation *sourceLoc; MonoDebugMethodInfo *methodDebugInfo; MonoDebugMethodJitInfo *dmji; MonoClass *klass = mono_method_get_class (method); char *signature = mono_signature_get_desc (mono_method_signature (method), TRUE); char *name = g_strdup_printf ("%s(%s)", mono_method_get_name (method), signature); char *classname = g_strdup_printf ("%s%s%s", mono_class_get_namespace (klass), mono_class_get_namespace (klass)[0] != 0 ? "::" : "", mono_class_get_name (klass)); gpointer code_start = mono_jit_info_get_code_start (jinfo); int code_size = mono_jit_info_get_code_size (jinfo); iJIT_Method_Load vtuneMethod; memset(&vtuneMethod, 0, sizeof(vtuneMethod)); vtuneMethod.method_id = iJIT_GetNewMethodID(); vtuneMethod.method_name = name; vtuneMethod.method_load_address = code_start; vtuneMethod.method_size = code_size; vtuneMethod.class_file_name = classname; dmji = mono_debug_find_method (method, mono_domain_get()); if (dmji != NULL) { vtuneMethod.line_number_size = dmji->num_line_numbers; vtuneMethod.line_number_table = (vtuneMethod.line_number_size != 0) ? (LineNumberInfo*)malloc(sizeof(LineNumberInfo) * vtuneMethod.line_number_size) : NULL; for (i = 0; i < dmji->num_line_numbers; ++i) { sourceLoc = mono_debug_lookup_source_location (method, dmji->line_numbers[i].native_offset, mono_domain_get()); if (sourceLoc == NULL) { free(vtuneMethod.line_number_table); vtuneMethod.line_number_table = NULL; vtuneMethod.line_number_size = 0; break; } if (i == 0) vtuneMethod.source_file_name = strdup(sourceLoc->source_file); vtuneMethod.line_number_table[i].Offset = dmji->line_numbers[i].native_offset; vtuneMethod.line_number_table[i].LineNumber = sourceLoc->row; mono_debug_free_source_location (sourceLoc); } mono_debug_free_method_jit_info (dmji); } iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod); if (vtuneMethod.source_file_name != NULL) free(vtuneMethod.source_file_name); if (vtuneMethod.line_number_table != NULL) free(vtuneMethod.line_number_table); g_free (signature); g_free (name); g_free (classname); } }