예제 #1
0
/*
 * mono_opcode_value_and_size:
 *
 * Returns the size of the opcode starting at *@ip, or -1 on error.
 * Value is the opcode number. 
*/
int
mono_opcode_value_and_size (const unsigned char **ip, const unsigned char *end, int *value)
{
	const unsigned char *start = *ip, *p;
	int i = *value = mono_opcode_value (ip, end);
	int size = 0; 
	if (i < 0 || i >= MONO_CEE_LAST)
		return -1;
	p = *ip;

	switch (mono_opcodes [i].argument) {
	case MonoInlineNone:
		size = 1;
		break;
	case MonoInlineString:
	case MonoInlineType:
	case MonoInlineField:
	case MonoInlineMethod:
	case MonoInlineTok:
	case MonoInlineSig:
	case MonoShortInlineR:
	case MonoInlineI:
	case MonoInlineBrTarget:
		size = 5;
		break;
	case MonoInlineVar:
		size = 3;
		break;
	case MonoShortInlineVar:
	case MonoShortInlineI:
	case MonoShortInlineBrTarget:
		size = 2;
		break;
	case MonoInlineR:
	case MonoInlineI8:
		size = 9;
		break;
	case MonoInlineSwitch: {
		guint32 entries;
		if (ADDP_IS_GREATER_OR_OVF (p, 5, end))
			return -1;
		entries = read32 (p + 1);
		if (entries >= (0xFFFFFFFFU / 4))
			return -1;
		size = 4 + 4 * entries;
		break;
	}
	default:
		g_error ("Invalid opcode %d argument %d max opcode %d\n", i, mono_opcodes [i].argument, MONO_CEE_LAST);
	}

	if (ADDP_IS_GREATER_OR_OVF (p, size, end))
		return -1;

	return (p - start) + size;
}
예제 #2
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 ();
	}