/** * mono_debug_lookup_source_location: * @address: Native offset within the @method's machine code. * * Lookup the source code corresponding to the machine instruction located at * native offset @address within @method. * * The returned `MonoDebugSourceLocation' contains both file / line number * information and the corresponding IL offset. It must be freed by * mono_debug_free_source_location(). */ MonoDebugSourceLocation * mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDomain *domain) { MonoDebugMethodInfo *minfo; MonoDebugSourceLocation *location; gint32 offset; if (mono_debug_format == MONO_DEBUG_FORMAT_NONE) return NULL; mono_debugger_lock (); minfo = _mono_debug_lookup_method (method); if (!minfo || !minfo->handle || !minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) { mono_debugger_unlock (); return NULL; } offset = il_offset_from_address (method, domain, address); if (offset < 0) { mono_debugger_unlock (); return NULL; } location = mono_debug_symfile_lookup_location (minfo, offset); mono_debugger_unlock (); return location; }
/** * mono_debug_lookup_source_location_by_il: * * Same as mono_debug_lookup_source_location but take an IL_OFFSET argument. */ MonoDebugSourceLocation * mono_debug_lookup_source_location_by_il (MonoMethod *method, guint32 il_offset, MonoDomain *domain) { MonoDebugMethodInfo *minfo; MonoDebugSourceLocation *location; if (mono_debug_format == MONO_DEBUG_FORMAT_NONE) return NULL; mono_debugger_lock (); minfo = mono_debug_lookup_method_internal (method); if (!minfo || !minfo->handle) { mono_debugger_unlock (); return NULL; } if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) { mono_debugger_unlock (); return NULL; } if (minfo->handle->ppdb) location = mono_ppdb_lookup_location (minfo, il_offset); else location = mono_debug_symfile_lookup_location (minfo, il_offset); mono_debugger_unlock (); return location; }
/** * mono_profiler_coverage_get: * @prof: The profiler handle, installed with mono_profiler_install * @method: the method to gather information from. * @func: A routine that will be called back with the results * * If the MONO_PROFILER_INS_COVERAGE flag was active during JIT compilation * it is posisble to obtain coverage information about a give method. * * The function @func will be invoked repeatedly with instances of the * MonoProfileCoverageEntry structure. */ void mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileCoverageFunc func) { MonoError error; MonoProfileCoverageInfo* info = NULL; int i, offset; guint32 code_size; const unsigned char *start, *end, *cil_code; MonoMethodHeader *header; MonoProfileCoverageEntry entry; MonoDebugMethodInfo *debug_minfo; mono_profiler_coverage_lock (); if (coverage_hash) info = (MonoProfileCoverageInfo *)g_hash_table_lookup (coverage_hash, method); mono_profiler_coverage_unlock (); if (!info) return; header = mono_method_get_header_checked (method, &error); mono_error_assert_ok (&error); start = mono_method_header_get_code (header, &code_size, NULL); debug_minfo = mono_debug_lookup_method (method); end = start + code_size; for (i = 0; i < info->entries; ++i) { cil_code = info->data [i].cil_code; if (cil_code && cil_code >= start && cil_code < end) { char *fname = NULL; offset = cil_code - start; entry.iloffset = offset; entry.method = method; entry.counter = info->data [i].count; entry.line = entry.col = 1; entry.filename = NULL; if (debug_minfo) { MonoDebugSourceLocation *location; location = mono_debug_symfile_lookup_location (debug_minfo, offset); if (location) { entry.line = location->row; entry.col = location->column; entry.filename = fname = g_strdup (location->source_file); mono_debug_free_source_location (location); } } func (prof, &entry); g_free (fname); } } mono_metadata_free_mh (header); }
MonoDebugSourceLocation * mono_debug_method_lookup_location (MonoDebugMethodInfo *minfo, int il_offset) { MonoDebugSourceLocation *location; mono_debugger_lock (); if (minfo->handle->ppdb) location = mono_ppdb_lookup_location (minfo, il_offset); else location = mono_debug_symfile_lookup_location (minfo, il_offset); mono_debugger_unlock (); return location; }
/* * 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 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 (method); 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_symfile_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 */ }