/* * mono_save_xdebug_info: * * Emit debugging info for METHOD into an assembly file which can be assembled * and loaded into gdb to provide debugging info for JITted code. * LOCKING: Acquires the loader lock. */ void mono_save_xdebug_info (MonoCompile *cfg) { MonoDebugMethodJitInfo *dmji; if (use_gdb_interface) { mono_loader_lock (); if (!xdebug_syms) xdebug_syms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); /* * gdb is not designed to handle 1000s of symbol files (one per method). So we * group them into groups of 100. */ if ((xdebug_method_count % 100) == 0) mono_xdebug_flush (); xdebug_method_count ++; dmji = mono_debug_find_method (cfg->jit_info->method, mono_domain_get ());; mono_dwarf_writer_emit_method (xdebug_writer, cfg, cfg->jit_info->method, NULL, NULL, cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, dmji); mono_debug_free_method_jit_info (dmji); #if 0 /* * Emit a symbol for the code by emitting it at the beginning of the text * segment, and setting the text segment to have an absolute address. * This symbol can be used to set breakpoints in gdb. * FIXME: This doesn't work when multiple methods are emitted into the same file. */ sym = get_debug_sym (cfg->jit_info->method, "", xdebug_syms); img_writer_emit_section_change (w, ".text", 0); if (!xdebug_text_addr) { xdebug_text_addr = cfg->jit_info->code_start; img_writer_set_section_addr (w, (gssize)xdebug_text_addr); } img_writer_emit_global_with_size (w, sym, cfg->jit_info->code_size, TRUE); img_writer_emit_label (w, sym); img_writer_emit_bytes (w, cfg->jit_info->code_start, cfg->jit_info->code_size); g_free (sym); #endif mono_loader_unlock (); } else { if (!xdebug_writer) return; mono_loader_lock (); dmji = mono_debug_find_method (cfg->jit_info->method, mono_domain_get ());; mono_dwarf_writer_emit_method (xdebug_writer, cfg, cfg->jit_info->method, NULL, NULL, cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, dmji); mono_debug_free_method_jit_info (dmji); fflush (xdebug_fp); mono_loader_unlock (); } }
void mono_debug_close_method (MonoCompile *cfg) { MiniDebugMethodInfo *info; MonoDebugMethodJitInfo *jit; MonoMethodHeader *header; MonoMethodSignature *sig; MonoDebugMethodAddress *debug_info; MonoMethod *method; int i; info = (MiniDebugMethodInfo *) cfg->debug_info; if (!info || !info->jit) { if (info) g_free (info); return; } method = cfg->method; header = mono_method_get_header (method); sig = mono_method_signature (method); jit = info->jit; jit->code_start = cfg->native_code; jit->epilogue_begin = cfg->epilog_begin; jit->code_size = cfg->code_len; if (jit->epilogue_begin) record_line_number (info, jit->epilogue_begin, header->code_size); jit->num_params = sig->param_count; jit->params = g_new0 (MonoDebugVarInfo, jit->num_params); for (i = 0; i < jit->num_locals; i++) write_variable (cfg->locals [i], &jit->locals [i]); if (sig->hasthis) { jit->this_var = g_new0 (MonoDebugVarInfo, 1); write_variable (cfg->args [0], jit->this_var); } for (i = 0; i < jit->num_params; i++) write_variable (cfg->args [i + sig->hasthis], &jit->params [i]); jit->num_line_numbers = info->line_numbers->len; jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers); for (i = 0; i < jit->num_line_numbers; i++) jit->line_numbers [i] = g_array_index (info->line_numbers, MonoDebugLineNumberEntry, i); debug_info = mono_debug_add_method (cfg->method_to_register, jit, cfg->domain); mono_debug_add_vg_method (method, jit); mono_debugger_check_breakpoints (method, debug_info); mono_debug_free_method_jit_info (jit); g_array_free (info->line_numbers, TRUE); g_free (info); }
static void method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) { if (result == MONO_PROFILE_OK) { int i; MonoDebugSourceLocation *sourceLoc; 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) { g_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) g_free (vtuneMethod.source_file_name); if (vtuneMethod.line_number_table != NULL) g_free (vtuneMethod.line_number_table); g_free (signature); g_free (name); g_free (classname); } }
static gint32 il_offset_from_address (MonoMethod *method, MonoDomain *domain, guint32 native_offset) { MonoDebugMethodJitInfo *jit; int i; jit = find_method (method, domain); if (!jit || !jit->line_numbers) goto cleanup_and_fail; for (i = jit->num_line_numbers - 1; i >= 0; i--) { MonoDebugLineNumberEntry lne = jit->line_numbers [i]; if (lne.native_offset <= native_offset) { mono_debug_free_method_jit_info (jit); return lne.il_offset; } } cleanup_and_fail: mono_debug_free_method_jit_info (jit); return -1; }
void mono_debug_close_method (MonoCompile *cfg) { MiniDebugMethodInfo *info; MonoDebugMethodJitInfo *jit; MonoMethodHeader *header; MonoMethodSignature *sig; MonoMethod *method; int i; info = (MiniDebugMethodInfo *) cfg->debug_info; if (!info || !info->jit) { if (info) g_free (info); return; } method = cfg->method; header = cfg->header; sig = mono_method_signature (method); jit = info->jit; jit->code_start = cfg->native_code; jit->epilogue_begin = cfg->epilog_begin; jit->code_size = cfg->code_len; jit->has_var_info = mini_debug_options.mdb_optimizations || MONO_CFG_PROFILE_CALL_CONTEXT (cfg); if (jit->epilogue_begin) record_line_number (info, jit->epilogue_begin, header->code_size); if (jit->has_var_info) { jit->num_params = sig->param_count; jit->params = g_new0 (MonoDebugVarInfo, jit->num_params); for (i = 0; i < jit->num_locals; i++) write_variable (cfg->locals [i], &jit->locals [i]); if (sig->hasthis) { jit->this_var = g_new0 (MonoDebugVarInfo, 1); write_variable (cfg->args [0], jit->this_var); } for (i = 0; i < jit->num_params; i++) write_variable (cfg->args [i + sig->hasthis], &jit->params [i]); if (cfg->gsharedvt_info_var) { jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1); jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1); write_variable (cfg->gsharedvt_info_var, jit->gsharedvt_info_var); write_variable (cfg->gsharedvt_locals_var, jit->gsharedvt_locals_var); } } jit->num_line_numbers = info->line_numbers->len; jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers); for (i = 0; i < jit->num_line_numbers; i++) jit->line_numbers [i] = g_array_index (info->line_numbers, MonoDebugLineNumberEntry, i); mono_debug_add_method (cfg->method_to_register, jit, cfg->domain); mono_debug_add_vg_method (method, jit); mono_debug_free_method_jit_info (jit); mono_debug_free_method (cfg); }