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);
	}
}
Exemple #2
0
/**
 * 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);
}
Exemple #3
0
/**
 * mono_debug_print_stack_frame:
 * \param native_offset Native offset within the \p method's machine code.
 * Conventient wrapper around \c 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 && get_seq_point)
			offset = get_seq_point (domain, method, native_offset);

		if (offset < 0)
			res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
		else {
			char *mvid = mono_guid_to_string_minimal ((uint8_t*)m_class_get_image (method->klass)->heap_guid.data);
			char *aotid = mono_runtime_get_aotid ();
			if (aotid)
				res = g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname, offset, mvid, aotid);
			else
				res = g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname, offset, mvid);

			g_free (aotid);
			g_free (mvid);
		}
		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;
}
Exemple #4
0
/**
 * 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;
}
Exemple #5
0
/*
 * 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 */
}
Exemple #6
0
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;
}