Beispiel #1
0
MonoMethod*
mono_method_desc_search_in_image (MonoMethodDesc *desc, MonoImage *image)
{
	MonoClass *klass;
	const MonoTableInfo *methods;
	MonoMethod *method;
	int i;

	/* Handle short names for system classes */
	if (!desc->name_space && image == mono_defaults.corlib) {
		klass = find_system_class (desc->klass);
		if (klass)
			return mono_method_desc_search_in_class (desc, klass);
	}

	if (desc->name_space && desc->klass) {
		klass = mono_class_try_load_from_name (image, desc->name_space, desc->klass);
		if (!klass)
			return NULL;
		return mono_method_desc_search_in_class (desc, klass);
	}

	/* FIXME: Is this call necessary?  We don't use its result. */
	mono_image_get_table_info (image, MONO_TABLE_TYPEDEF);
	methods = mono_image_get_table_info (image, MONO_TABLE_METHOD);
	for (i = 0; i < mono_table_info_get_rows (methods); ++i) {
		MonoError error;
		guint32 token = mono_metadata_decode_row_col (methods, i, MONO_METHOD_NAME);
		const char *n = mono_metadata_string_heap (image, token);

		if (strcmp (n, desc->name))
			continue;
		method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
		if (!method) {
			mono_error_cleanup (&error);
			continue;
		}
		if (mono_method_desc_full_match (desc, method))
			return method;
	}
	return NULL;
}
Beispiel #2
0
MonoDebugLocalsInfo*
mono_ppdb_lookup_locals (MonoDebugMethodInfo *minfo)
{
	MonoPPDBFile *ppdb = minfo->handle->ppdb;
	MonoImage *image = ppdb->image;
	MonoTableInfo *tables = image->tables;
	MonoMethod *method = minfo->method;
	guint32 cols [MONO_LOCALSCOPE_SIZE];
	guint32 locals_cols [MONO_LOCALVARIABLE_SIZE];
	int i, lindex, sindex, method_idx, start_scope_idx, scope_idx, locals_idx, locals_end_idx, nscopes;
	MonoDebugLocalsInfo *res;
	MonoMethodSignature *sig;

	if (!method->token)
		return NULL;

	sig = mono_method_signature (method);
	if (!sig)
		return NULL;

	method_idx = mono_metadata_token_index (method->token);

	start_scope_idx = mono_metadata_localscope_from_methoddef (image, method_idx);

	if (!start_scope_idx)
		return NULL;

	/* Compute number of locals and scopes */
	scope_idx = start_scope_idx;
	mono_metadata_decode_row (&tables [MONO_TABLE_LOCALSCOPE], scope_idx-1, cols, MONO_LOCALSCOPE_SIZE);
	locals_idx = cols [MONO_LOCALSCOPE_VARIABLELIST];

	// https://github.com/dotnet/roslyn/blob/2ae8d5fed96ab3f1164031f9b4ac827f53289159/docs/specs/PortablePdb-Metadata.md#LocalScopeTable
	//
	// The variableList attribute in the pdb metadata table is a contiguous array that starts at a
	// given offset (locals_idx) above and
	//
	// """
	// continues to the smaller of:
	//
	// the last row of the LocalVariable table
	// the next run of LocalVariables, found by inspecting the VariableList of the next row in this LocalScope table.
	// """
	// this endpoint becomes locals_end_idx below

	// March to the last scope that is in this method
	while (scope_idx <= tables [MONO_TABLE_LOCALSCOPE].rows) {
		mono_metadata_decode_row (&tables [MONO_TABLE_LOCALSCOPE], scope_idx-1, cols, MONO_LOCALSCOPE_SIZE);
		if (cols [MONO_LOCALSCOPE_METHOD] != method_idx)
			break;
		scope_idx ++;
	}
	// The number of scopes is the difference in the indices
	// for the first and last scopes
	nscopes = scope_idx - start_scope_idx;

	// Ends with "the last row of the LocalVariable table"
	// this happens if the above loop marched one past the end
	// of the rows
	if (scope_idx > tables [MONO_TABLE_LOCALSCOPE].rows) {
		locals_end_idx = tables [MONO_TABLE_LOCALVARIABLE].rows + 1;
	} else {
		// Ends with "the next run of LocalVariables,
		// found by inspecting the VariableList of the next row in this LocalScope table."
		locals_end_idx = cols [MONO_LOCALSCOPE_VARIABLELIST];
	}

	res = g_new0 (MonoDebugLocalsInfo, 1);
	res->num_blocks = nscopes;
	res->code_blocks = g_new0 (MonoDebugCodeBlock, res->num_blocks);
	res->num_locals = locals_end_idx - locals_idx;
	res->locals = g_new0 (MonoDebugLocalVar, res->num_locals);

	lindex = 0;
	for (sindex = 0; sindex < nscopes; ++sindex) {
		scope_idx = start_scope_idx + sindex;
		mono_metadata_decode_row (&tables [MONO_TABLE_LOCALSCOPE], scope_idx-1, cols, MONO_LOCALSCOPE_SIZE);

		locals_idx = cols [MONO_LOCALSCOPE_VARIABLELIST];
		if (scope_idx == tables [MONO_TABLE_LOCALSCOPE].rows) {
			locals_end_idx = tables [MONO_TABLE_LOCALVARIABLE].rows + 1;
		} else {
			locals_end_idx = mono_metadata_decode_row_col (&tables [MONO_TABLE_LOCALSCOPE], scope_idx-1 + 1, MONO_LOCALSCOPE_VARIABLELIST);
		}

		res->code_blocks [sindex].start_offset = cols [MONO_LOCALSCOPE_STARTOFFSET];
		res->code_blocks [sindex].end_offset = cols [MONO_LOCALSCOPE_STARTOFFSET] + cols [MONO_LOCALSCOPE_LENGTH];

		//printf ("Scope: %s %d %d %d-%d\n", mono_method_full_name (method, 1), cols [MONO_LOCALSCOPE_STARTOFFSET], cols [MONO_LOCALSCOPE_LENGTH], locals_idx, locals_end_idx);

		for (i = locals_idx; i < locals_end_idx; ++i) {
			mono_metadata_decode_row (&tables [MONO_TABLE_LOCALVARIABLE], i - 1, locals_cols, MONO_LOCALVARIABLE_SIZE);

			res->locals [lindex].name = g_strdup (mono_metadata_string_heap (image, locals_cols [MONO_LOCALVARIABLE_NAME]));
			res->locals [lindex].index = locals_cols [MONO_LOCALVARIABLE_INDEX];
			res->locals [lindex].block = &res->code_blocks [sindex];
			lindex ++;

			//printf ("\t %s %d\n", mono_metadata_string_heap (image, locals_cols [MONO_LOCALVARIABLE_NAME]), locals_cols [MONO_LOCALVARIABLE_INDEX]);
		}
	}

	return res;
}