Esempio n. 1
0
static void
foreach_method (const gpointer key, const gpointer val, gpointer user_data)
{
	MonoMethod *method = key;
	MonoClass *klass = user_data;
	if (method->klass != klass)
		return;
	/* FIXME: ensure it's the correct token */
	fprintf (outf, "M:0x%x\n", mono_metadata_token_index (method->token));
}
Esempio n. 2
0
static void
foreach_field (const gpointer key, const gpointer val, gpointer user_data)
{
	MonoClassField *field = key;
	MonoClass *klass = user_data;
	int idx;
	if (field->parent != klass)
		return;
	idx = mono_metadata_token_index (mono_class_get_field_token (field));
	fprintf (outf, "F:0x%x\n", idx);
}
Esempio n. 3
0
static void
foreach_type (const gpointer key, const gpointer val, gpointer user_data)
{
	MonoClass *klass = key;
	MonoImage *image = user_data;
	if (klass->image != image)
		return;
	if (klass->rank || klass->byval_arg.type == MONO_TYPE_PTR)
		return;
	fprintf (outf, "T:0x%x\n", mono_metadata_token_index (klass->type_token));
	g_hash_table_foreach (method_table, foreach_method, klass);
	g_hash_table_foreach (field_table, foreach_field, klass);
}
Esempio n. 4
0
// for parent_type see HasCustomDebugInformation table at
// https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md
static const char*
lookup_custom_debug_information (MonoImage* image, guint32 token, uint8_t parent_type, guint8* guid)
{
	MonoTableInfo *tables = image->tables;
	MonoTableInfo *table = &tables[MONO_TABLE_CUSTOMDEBUGINFORMATION];
	locator_t loc;

	if (!table->base)
		return 0;

	loc.idx = (mono_metadata_token_index (token) << 5) | parent_type;
	loc.col_idx = MONO_CUSTOMDEBUGINFORMATION_PARENT;
	loc.t = table;

	if (!mono_binary_search (&loc, table->base, table->rows, table->row_size, table_locator))
		return NULL;
	// Great we found one of possibly many CustomDebugInformations of this entity they are distinguished by KIND guid
	// First try on this index found by binary search...(it's most likeley to be only one and binary search found the one we want)
	if (compare_guid (guid, (guint8*)mono_metadata_guid_heap (image, mono_metadata_decode_row_col (table, loc.result, MONO_CUSTOMDEBUGINFORMATION_KIND))))
		return mono_metadata_blob_heap (image, mono_metadata_decode_row_col (table, loc.result, MONO_CUSTOMDEBUGINFORMATION_VALUE));

	// Move forward from binary found index, until parent token differs
	for (int i = loc.result + 1; i < table->rows; i++)
	{
		if (mono_metadata_decode_row_col (table, i, MONO_CUSTOMDEBUGINFORMATION_PARENT) != loc.idx)
			break;
		if (compare_guid (guid, (guint8*)mono_metadata_guid_heap (image, mono_metadata_decode_row_col (table, i, MONO_CUSTOMDEBUGINFORMATION_KIND))))
			return mono_metadata_blob_heap (image, mono_metadata_decode_row_col (table, i, MONO_CUSTOMDEBUGINFORMATION_VALUE));
	}

	// Move backward from binary found index, until parent token differs
	for (int i = loc.result - 1; i >= 0; i--) {
		if (mono_metadata_decode_row_col (table, i, MONO_CUSTOMDEBUGINFORMATION_PARENT) != loc.idx)
			break;
		if (compare_guid (guid, (guint8*)mono_metadata_guid_heap (image, mono_metadata_decode_row_col (table, i, MONO_CUSTOMDEBUGINFORMATION_KIND))))
			return mono_metadata_blob_heap (image, mono_metadata_decode_row_col (table, i, MONO_CUSTOMDEBUGINFORMATION_VALUE));
	}
	return NULL;
}
Esempio n. 5
0
static const unsigned char*
dis_one (GString *str, MonoDisHelper *dh, MonoMethod *method, const unsigned char *ip, const unsigned char *end)
{
	MonoMethodHeader *header = mono_method_get_header (method);
	const MonoOpcode *opcode;
	guint32 label, token;
	gint32 sval;
	int i;
	char *tmp;
	const unsigned char* il_code = mono_method_header_get_code (header, NULL, NULL);

	label = ip - il_code;
	if (dh->indenter) {
		tmp = dh->indenter (dh, method, label);
		g_string_append (str, tmp);
		g_free (tmp);
	}
	if (dh->label_format)
		g_string_append_printf (str, dh->label_format, label);
	
	i = mono_opcode_value (&ip, end);
	ip++;
	opcode = &mono_opcodes [i];
	g_string_append_printf (str, "%-10s", mono_opcode_name (i));

	switch (opcode->argument) {
	case MonoInlineNone:
		break;
	case MonoInlineType:
	case MonoInlineField:
	case MonoInlineMethod:
	case MonoInlineTok:
	case MonoInlineSig:
		token = read32 (ip);
		if (dh->tokener) {
			tmp = dh->tokener (dh, method, token);
			g_string_append (str, tmp);
			g_free (tmp);
		} else {
			g_string_append_printf (str, "0x%08x", token);
		}
		ip += 4;
		break;
	case MonoInlineString: {
		const char *blob;
		char *s;
		size_t len2;
		char *blob2 = NULL;

		if (!image_is_dynamic (method->klass->image) && !method_is_dynamic (method)) {
			token = read32 (ip);
			blob = mono_metadata_user_string (method->klass->image, mono_metadata_token_index (token));

			len2 = mono_metadata_decode_blob_size (blob, &blob);
			len2 >>= 1;

#ifdef NO_UNALIGNED_ACCESS
			/* The blob might not be 2 byte aligned */
			blob2 = g_malloc ((len2 * 2) + 1);
			memcpy (blob2, blob, len2 * 2);
#else
			blob2 = (char*)blob;
#endif

#if G_BYTE_ORDER != G_LITTLE_ENDIAN
			{
				guint16 *buf = g_new (guint16, len2 + 1);
				int i;

				for (i = 0; i < len2; ++i)
					buf [i] = GUINT16_FROM_LE (((guint16*)blob2) [i]);
				s = g_utf16_to_utf8 (buf, len2, NULL, NULL, NULL);
				g_free (buf);
			}
#else
				s = g_utf16_to_utf8 ((gunichar2*)blob2, len2, NULL, NULL, NULL);
#endif

			g_string_append_printf (str, "\"%s\"", s);
			g_free (s);
			if (blob != blob2)
				g_free (blob2);
		}
		ip += 4;
		break;
	}
	case MonoInlineVar:
		g_string_append_printf (str, "%d", read16 (ip));
		ip += 2;
		break;
	case MonoShortInlineVar:
		g_string_append_printf (str, "%d", (*ip));
		ip ++;
		break;
	case MonoInlineBrTarget:
		sval = read32 (ip);
		ip += 4;
		if (dh->label_target)
			g_string_append_printf (str, dh->label_target, ip + sval - il_code);
		else
			g_string_append_printf (str, "%d", sval);
		break;
	case MonoShortInlineBrTarget:
		sval = *(const signed char*)ip;
		ip ++;
		if (dh->label_target)
			g_string_append_printf (str, dh->label_target, ip + sval - il_code);
		else
			g_string_append_printf (str, "%d", sval);
		break;
	case MonoInlineSwitch: {
		const unsigned char *end;
		sval = read32 (ip);
		ip += 4;
		end = ip + sval * 4;
		g_string_append_c (str, '(');
		for (i = 0; i < sval; ++i) {
			if (i > 0)
				g_string_append (str, ", ");
			label = read32 (ip);
			if (dh->label_target)
				g_string_append_printf (str, dh->label_target, end + label - il_code);
			else
				g_string_append_printf (str, "%d", label);
			ip += 4;
		}
		g_string_append_c (str, ')');
		break;
	}
	case MonoInlineR: {
		double r;
		readr8 (ip, &r);
		g_string_append_printf (str, "%g", r);
		ip += 8;
		break;
	}
	case MonoShortInlineR: {
		float r;
		readr4 (ip, &r);
		g_string_append_printf (str, "%g", r);
		ip += 4;
		break;
	}
	case MonoInlineI:
		g_string_append_printf (str, "%d", (gint32)read32 (ip));
		ip += 4;
		break;
	case MonoShortInlineI:
		g_string_append_printf (str, "%d", *(const signed char*)ip);
		ip ++;
		break;
	case MonoInlineI8:
		ip += 8;
		break;
	default:
		g_assert_not_reached ();
	}
Esempio n. 6
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;
}
Esempio n. 7
0
void
mono_ppdb_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points)
{
	MonoPPDBFile *ppdb = minfo->handle->ppdb;
	MonoImage *image = ppdb->image;
	MonoMethod *method = minfo->method;
	MonoTableInfo *tables = image->tables;
	guint32 cols [MONO_METHODBODY_SIZE];
	const char *ptr;
	const char *end;
	MonoDebugSourceInfo *docinfo;
	int i, method_idx, size, docidx, iloffset, delta_il, delta_lines, delta_cols, start_line, start_col, adv_line, adv_col;
	gboolean first = TRUE, first_non_hidden = TRUE;
	GArray *sps;
	MonoSymSeqPoint sp;
	GPtrArray *sfiles = NULL;
	GPtrArray *sindexes = NULL;

	if (source_file)
		*source_file = NULL;
	if (source_file_list)
		*source_file_list = NULL;
	if (source_files)
		*source_files = NULL;
	if (seq_points)
		*seq_points = NULL;
	if (n_seq_points)
		*n_seq_points = 0;

	if (source_file_list)
		*source_file_list = sfiles = g_ptr_array_new ();
	if (source_files)
		sindexes = g_ptr_array_new ();

	if (!method->token)
		return;

	method_idx = mono_metadata_token_index (method->token);

	mono_metadata_decode_row (&tables [MONO_TABLE_METHODBODY], method_idx-1, cols, MONO_METHODBODY_SIZE);

	docidx = cols [MONO_METHODBODY_DOCUMENT];

	if (!cols [MONO_METHODBODY_SEQ_POINTS])
		return;

	ptr = mono_metadata_blob_heap (image, cols [MONO_METHODBODY_SEQ_POINTS]);
	size = mono_metadata_decode_blob_size (ptr, &ptr);
	end = ptr + size;

	sps = g_array_new (FALSE, TRUE, sizeof (MonoSymSeqPoint));

	/* Header */
	/* LocalSignature */
	mono_metadata_decode_value (ptr, &ptr);
	if (docidx == 0)
		docidx = mono_metadata_decode_value (ptr, &ptr);
	docinfo = get_docinfo (ppdb, image, docidx);

	if (sfiles)
		g_ptr_array_add (sfiles, docinfo);

	if (source_file)
		*source_file = g_strdup (docinfo->source_file);

	iloffset = 0;
	start_line = 0;
	start_col = 0;
	while (ptr < end) {
		delta_il = mono_metadata_decode_value (ptr, &ptr);
		if (!first && delta_il == 0) {
			/* subsequent-document-record */
			docidx = mono_metadata_decode_value (ptr, &ptr);
			docinfo = get_docinfo (ppdb, image, docidx);
			if (sfiles)
				g_ptr_array_add (sfiles, docinfo);
			continue;
		}
		iloffset += delta_il;
		first = FALSE;

		delta_lines = mono_metadata_decode_value (ptr, &ptr);
		if (delta_lines == 0)
			delta_cols = mono_metadata_decode_value (ptr, &ptr);
		else
			delta_cols = mono_metadata_decode_signed_value (ptr, &ptr);

		if (delta_lines == 0 && delta_cols == 0) {
			/* Hidden sequence point */
			continue;
		}

		if (first_non_hidden) {
			start_line = mono_metadata_decode_value (ptr, &ptr);
			start_col = mono_metadata_decode_value (ptr, &ptr);
		} else {
			adv_line = mono_metadata_decode_signed_value (ptr, &ptr);
			adv_col = mono_metadata_decode_signed_value (ptr, &ptr);
			start_line += adv_line;
			start_col += adv_col;
		}
		first_non_hidden = FALSE;

		memset (&sp, 0, sizeof (sp));
		sp.il_offset = iloffset;
		sp.line = start_line;
		sp.column = start_col;
		sp.end_line = start_line + delta_lines;
		sp.end_column = start_col + delta_cols;

		g_array_append_val (sps, sp);
		if (source_files)
			g_ptr_array_add (sindexes, GUINT_TO_POINTER (sfiles->len - 1));
	}

	if (n_seq_points) {
		*n_seq_points = sps->len;
		g_assert (seq_points);
		*seq_points = g_new (MonoSymSeqPoint, sps->len);
		memcpy (*seq_points, sps->data, sps->len * sizeof (MonoSymSeqPoint));
	}

	if (source_files) {
		*source_files = g_new (int, sps->len);
		for (i = 0; i < sps->len; ++i)
			(*source_files)[i] = GPOINTER_TO_INT (g_ptr_array_index (sindexes, i));
		g_ptr_array_free (sindexes, TRUE);
	}

	g_array_free (sps, TRUE);
}
Esempio n. 8
0
/**
 * mono_ppdb_lookup_location:
 * \param minfo A \c MonoDebugMethodInfo which can be retrieved by mono_debug_lookup_method().
 * \param offset IL offset within the corresponding method's CIL code.
 *
 * This function is similar to mono_debug_lookup_location(), but we
 * already looked up the method and also already did the
 * native address -> IL offset mapping.
 */
MonoDebugSourceLocation *
mono_ppdb_lookup_location (MonoDebugMethodInfo *minfo, uint32_t offset)
{
	MonoPPDBFile *ppdb = minfo->handle->ppdb;
	MonoImage *image = ppdb->image;
	MonoMethod *method = minfo->method;
	MonoTableInfo *tables = image->tables;
	guint32 cols [MONO_METHODBODY_SIZE];
	const char *ptr;
	const char *end;
	char *docname;
	int idx, size, docidx, iloffset, delta_il, delta_lines, delta_cols, start_line, start_col, adv_line, adv_col;
	gboolean first = TRUE, first_non_hidden = TRUE;
	MonoDebugSourceLocation *location;

	if (!method->token)
		return NULL;

	idx = mono_metadata_token_index (method->token);

	mono_metadata_decode_row (&tables [MONO_TABLE_METHODBODY], idx-1, cols, MONO_METHODBODY_SIZE);

	docidx = cols [MONO_METHODBODY_DOCUMENT];

	if (!cols [MONO_METHODBODY_SEQ_POINTS])
		return NULL;
	ptr = mono_metadata_blob_heap (image, cols [MONO_METHODBODY_SEQ_POINTS]);
	size = mono_metadata_decode_blob_size (ptr, &ptr);
	end = ptr + size;

	/* Header */
	/* LocalSignature */
	mono_metadata_decode_value (ptr, &ptr);
	if (docidx == 0)
		docidx = mono_metadata_decode_value (ptr, &ptr);
	docname = get_docname (ppdb, image, docidx);

	iloffset = 0;
	start_line = 0;
	start_col = 0;
	while (ptr < end) {
		delta_il = mono_metadata_decode_value (ptr, &ptr);
		if (!first && delta_il == 0) {
			/* document-record */
			docidx = mono_metadata_decode_value (ptr, &ptr);
			docname = get_docname (ppdb, image, docidx);
			continue;
		}
		if (!first && iloffset + delta_il > offset)
			break;
		iloffset += delta_il;
		first = FALSE;

		delta_lines = mono_metadata_decode_value (ptr, &ptr);
		if (delta_lines == 0)
			delta_cols = mono_metadata_decode_value (ptr, &ptr);
		else
			delta_cols = mono_metadata_decode_signed_value (ptr, &ptr);
		if (delta_lines == 0 && delta_cols == 0)
			/* hidden-sequence-point-record */
			continue;
		if (first_non_hidden) {
			start_line = mono_metadata_decode_value (ptr, &ptr);
			start_col = mono_metadata_decode_value (ptr, &ptr);
		} else {
			adv_line = mono_metadata_decode_signed_value (ptr, &ptr);
			adv_col = mono_metadata_decode_signed_value (ptr, &ptr);
			start_line += adv_line;
			start_col += adv_col;
		}
		first_non_hidden = FALSE;
	}

	location = g_new0 (MonoDebugSourceLocation, 1);
	location->source_file = docname;
	location->row = start_line;
	location->il_offset = iloffset;

	return location;
}