Beispiel #1
0
void CPipeServer::GetILCode()
{
	void *methodheader=(void *)ReadQword();
	UINT32 code;
	void *result=mono_method_header_get_code(methodheader, &code, NULL);
	WriteQword((UINT_PTR)result);
	WriteDword(code);
}
Beispiel #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);
}
Beispiel #3
0
void CPipeServer::DisassembleMethod()
{
	void *method=(void *)ReadQword();
	void *methodheader=mono_method_get_header(method);
	UINT32 codesize, maxstack;
	void *ilcode=mono_method_header_get_code(methodheader, &codesize, &maxstack);
	char *disassembly=mono_disasm_code(NULL, method, ilcode, (void *)((UINT_PTR)ilcode+codesize));

	WriteWord(strlen(disassembly));
	Write(disassembly, strlen(disassembly));
	g_free(disassembly);
}
Beispiel #4
0
static void disasm_method (Package *pkg) {
    xmono::DisasmMethodReq req;
    xmono::DisasmMethodRsp rsp;
    std::string str((char*)pkg->body, pkg->all_len - sizeof (Package)); //Fixme : 修复头部all_len是总长的问题
    if (!req.ParseFromString (str)) {
        LOGD ("xmono::DisasmMethodReq ParseFromString err!");
        return;
    }
    std::string err("");
    MonoMethod *method = get_method_with_token (req.image_name ().c_str (), req.method_token ());
    if (!method) err += helper_last_err ();
    MonoImage *image = mono_image_loaded (req.image_name ().c_str ());
    if (!image) err += "  image : " + req.image_name () + " can not be find!";
    if (image && method) {
        MemWriter writer(4096);
        char const *mname = mono_method_full_name (method, 1);
        if (mname) {
            writer.sprintf ("//[%s]%s[%08X]\n", get_method_image_name (method), mname, mono_method_get_token (method));
            g_free (mname);
        }
        MonoMethodHeader *header = mono_method_get_header (method);
        disassemble_cil (image, header, &writer); /*Fixme : disassemble_cil需要在失败时返回更多信息*/
        rsp.set_err (true);
        LOGD ("writer : %s", writer.getBuffPtr ());
        std::string s((char*)writer.getBuffPtr (), writer.getBuffSize ());
        rsp.set_disasm_code (s);
        //这部分只是测试用的
        uint32_t asm_size = 0;
        uint8_t const *p = mono_method_header_get_code (header, &asm_size, 0);
        std::string asm_code ((char const*)p, asm_size);
        rsp.set_asm_code (asm_code);
    } else {
        rsp.set_err (false);
        rsp.set_err_str (err);
    }
    std::string out;
    rsp.SerializeToString (&out);
    ecmd_send (XMONO_ID_DISASM_METHOD_RSP, (uint8_t const*)out.c_str (), out.size ());
    return;
}
Beispiel #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 ();
	}
Beispiel #6
0
static void
add_types_from_method (MonoMethod *method) {
	const MonoOpcode *opcode;
	MonoMethodHeader *header;
	const unsigned char *ip, *il_code_end;
	gpointer val = NULL, oldkey = NULL;
	int i, n;
	guint32 token;
	MonoClass *klass;
	MonoClassField *field;
	MonoCustomAttrInfo* cattrs;
	MonoType** locals;
	gpointer exc_iter;
	MonoExceptionClause clause;

	if (g_hash_table_lookup_extended (method_table, method, &oldkey, &val))
		return;
	g_hash_table_insert (method_table, method, NULL);

	g_assert (method->klass);

	if (verbose > 1)
		g_print ("#processing method: %s\n", mono_method_full_name (method, TRUE));
	mono_class_init (method->klass);
	cattrs = mono_custom_attrs_from_method (method);
	handle_cattrs (cattrs);
	add_type (method->klass);
	add_types_from_signature (mono_method_signature (method));
	for (i = 0; i < mono_method_signature (method)->param_count + 1; ++i) {
		cattrs = mono_custom_attrs_from_param (method, i);
		handle_cattrs (cattrs);
	}

	if (method->flags & METHOD_ATTRIBUTE_VIRTUAL)
		virtual_methods = g_list_prepend (virtual_methods, method);

	/* if no IL code to parse, return */
	if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
		return;
	if (method->flags & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT))
		return;

	header = mono_method_get_header (method);

	locals = mono_method_header_get_locals (header, &n, NULL);
	for (i = 0; i < n; ++i) {
		klass = mono_class_from_mono_type (locals [i]);
		add_type (klass);
	}
	for (exc_iter = NULL; mono_method_header_get_clauses (header, method, &exc_iter, &clause);) {
		if (clause.flags == MONO_EXCEPTION_CLAUSE_NONE)
			add_type (clause.data.catch_class);
	}

	ip = mono_method_header_get_code (header, &n, NULL);
	il_code_end = ip + n;

	while (ip < il_code_end) {
		if (verbose > 2)
			g_print ("#%s", mono_disasm_code_one (NULL, method, ip, NULL));
		if (*ip == 0xfe) {
			++ip;
			i = *ip + 256;
		} else {
			i = *ip;
		}

		opcode = &mono_opcodes [i];

		switch (opcode->argument) {
		case MonoInlineNone:
			ip++;
			break;
		case MonoInlineType:
			token = read32 (ip + 1);
			add_type (mono_class_get (method->klass->image, token));
			ip += 5;
			break;
		case MonoInlineField: {
			token = read32 (ip + 1);
			field = mono_field_from_token (method->klass->image, token, &klass, NULL);
			add_field (field);
			add_type (klass);
			ip += 5;
			break;
		}
		case MonoInlineTok:
		case MonoInlineSig:
			/* FIXME */
		case MonoInlineString:
		case MonoShortInlineR:
		case MonoInlineBrTarget:
		case MonoInlineI:
			ip += 5;
			break;
		case MonoInlineVar:
			ip += 3;
			break;
		case MonoShortInlineVar:
		case MonoShortInlineI:
		case MonoShortInlineBrTarget:
			ip += 2;
			break;
		case MonoInlineSwitch:
			++ip;
			n = read32 (ip);
			ip += 4;
			ip += 4 * n;
			break;
		case MonoInlineI8:
		case MonoInlineR:
			ip += 9;
			break;
		case MonoInlineMethod:
			{
				MonoMethod *cm = mono_get_method (method->klass->image, read32 (ip + 1), NULL);
				add_type (cm->klass);
				add_types_from_method (cm);
			}
			ip += 5;
			break;
		default:
			g_assert_not_reached ();
		}
	}
}
Beispiel #7
0
MonoDebugMethodAddress *
mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
{
    MonoMethod *declaring;
    MonoDebugDataTable *table;
    MonoDebugMethodHeader *header;
    MonoDebugMethodAddress *address;
    MonoDebugMethodInfo *minfo;
    MonoDebugHandle *handle;
    guint8 buffer [BUFSIZ];
    guint8 *ptr, *oldptr;
    guint32 i, size, total_size, max_size;
    gboolean is_wrapper = FALSE;

    mono_debugger_lock ();

    table = lookup_data_table (domain);

    handle = _mono_debug_get_image (method->klass->image);
    minfo = _mono_debug_lookup_method (method);

    if (!minfo || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
            (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
            (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
            (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
            (method->wrapper_type != MONO_WRAPPER_NONE)) {
        is_wrapper = TRUE;
    }

    max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) +
               (25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);

    if (max_size > BUFSIZ)
        ptr = oldptr = g_malloc (max_size);
    else
        ptr = oldptr = buffer;

    write_leb128 (jit->prologue_end, ptr, &ptr);
    write_leb128 (jit->epilogue_begin, ptr, &ptr);

    write_leb128 (jit->num_line_numbers, ptr, &ptr);
    for (i = 0; i < jit->num_line_numbers; i++) {
        MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];

        write_sleb128 (lne->il_offset, ptr, &ptr);
        write_sleb128 (lne->native_offset, ptr, &ptr);
    }

    *ptr++ = jit->this_var ? 1 : 0;
    if (jit->this_var)
        write_variable (jit->this_var, ptr, &ptr);

    write_leb128 (jit->num_params, ptr, &ptr);
    for (i = 0; i < jit->num_params; i++)
        write_variable (&jit->params [i], ptr, &ptr);

    write_leb128 (jit->num_locals, ptr, &ptr);
    for (i = 0; i < jit->num_locals; i++)
        write_variable (&jit->locals [i], ptr, &ptr);

    size = ptr - oldptr;
    g_assert (size < max_size);
    total_size = size + sizeof (MonoDebugMethodAddress);

    address = (MonoDebugMethodAddress *) allocate_data_item (
                  table, MONO_DEBUG_DATA_ITEM_METHOD, total_size);

    address->header.size = total_size;
    address->header.symfile_id = handle ? handle->index : 0;
    address->header.domain_id = mono_domain_get_id (domain);
    address->header.method_id = is_wrapper ? 0 : minfo->index;
    address->header.method = method;

    address->code_start = jit->code_start;
    address->code_size = jit->code_size;

    memcpy (&address->data, oldptr, size);
    if (max_size > BUFSIZ)
        g_free (oldptr);

    declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
    header = g_hash_table_lookup (table->method_hash, declaring);

    if (!header) {
        header = &address->header;
        g_hash_table_insert (table->method_hash, declaring, header);

        if (is_wrapper) {
            const unsigned char* il_code;
            MonoMethodHeader *mheader;
            MonoDebugWrapperData *wrapper;
            guint32 il_codesize;

            mheader = mono_method_get_header (declaring);
            il_code = mono_method_header_get_code (mheader, &il_codesize, NULL);

            header->wrapper_data = wrapper = g_new0 (MonoDebugWrapperData, 1);

            wrapper->wrapper_type = method->wrapper_type;
            wrapper->method_name = mono_method_full_name (declaring, TRUE);
            wrapper->cil_code = mono_disasm_code (
                                    NULL, declaring, il_code, il_code + il_codesize);
        }
    } else {
        address->header.wrapper_data = header->wrapper_data;
        header->address_list = g_slist_prepend (header->address_list, address);
    }

    g_hash_table_insert (table->method_address_hash, method, address);

    write_data_item (table, (guint8 *) address);

    mono_debugger_unlock ();
    return address;
}
Beispiel #8
0
static gboolean
collect_coverage_for (MonoProfiler *prof, MonoMethod *method)
{
	int i;
	char *classname;
	char *fqn;
	MonoMethodHeader *header;
	gboolean has_positive, found;
	guint32 iflags, flags, code_size;
	MonoClass *klass;
	MonoImage *image;

	flags = mono_method_get_flags (method, &iflags);
	if ((iflags & 0x1000 /*METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL*/) ||
	    (flags & 0x2000 /*METHOD_ATTRIBUTE_PINVOKE_IMPL*/))
		return FALSE;

	//if (method->wrapper_type != MONO_WRAPPER_NONE)
	//	return FALSE;

	klass = mono_method_get_class (method);
	image = mono_class_get_image (klass);
	/* Hacky way of determining the executing assembly */
	if (! prof->outfile_name && (strcmp (mono_method_get_name (method), "Main") == 0)) {
		prof->outfile_name = g_strdup_printf ("%s.cov", mono_image_get_filename (image));
	}

	/* Check filters */
	if (prof->filters) {
		/* Check already filtered classes first */
		if (g_hash_table_lookup (prof->filtered_classes, klass))
			return FALSE;

		classname = mono_type_get_name (mono_class_get_type (klass));

		fqn = g_strdup_printf ("[%s]%s", mono_image_get_name (image), classname);

		// Check positive filters first
		has_positive = FALSE;
		found = FALSE;
		for (i = 0; i < prof->filters->len; ++i) {
			char *filter = g_ptr_array_index (prof->filters_as_str, i);
			if (filter [0] == '+') {
				filter = &filter [1];
				if (strstr (fqn, filter) != NULL)
					found = TRUE;
				has_positive = TRUE;
			}
		}
		if (has_positive && !found)
			return FALSE;

		for (i = 0; i < prof->filters->len; ++i) {
			// Is substring search suffices ???
//			GPatternSpec *spec = g_ptr_array_index (filters, i);
//			if (g_pattern_match_string (spec, classname)) {
			char *filter = g_ptr_array_index (prof->filters_as_str, i);
			if (filter [0] == '+')
				continue;

			// Skip '-'
			filter = &filter [1];
			if (strstr (fqn, filter) != NULL) {
				g_hash_table_insert (prof->filtered_classes, klass, klass);
				return FALSE;
			}
		}
		g_free (fqn);
		g_free (classname);
	}

	header = mono_method_get_header (method);

	mono_method_header_get_code (header, &code_size, NULL);
	if (code_size > 20000) {
		exit (1);
		g_warning ("Unable to instrument method %s:%s since it is too complex.", mono_class_get_name (klass), mono_method_get_name (method));
		return FALSE;
	}

	g_hash_table_insert (prof->methods, method, method);

	g_hash_table_insert (prof->classes, klass, klass);

	g_hash_table_insert (prof->assemblies, mono_image_get_assembly (image), mono_image_get_assembly (image));

	return TRUE;
}
Beispiel #9
0
/*反汇编method的IL*/
static char const *disil_method (MonoMethod *method) {
    MonoMethodHeader *header = mono_method_get_header (method);
    uint32_t len = 0;
    uint8_t const *code = mono_method_header_get_code (header, &len, 0);
    return mono_disasm_code (0, method, code, code + len);
}