예제 #1
0
파일: mop.c 프로젝트: mono/mono-oprofile
static void
mop_jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result)
{
	static int n = 0;
	char* name = mono_method_full_name (method, TRUE);

	char* start = mono_jit_info_get_code_start (jinfo);
	int len = mono_jit_info_get_code_size (jinfo);
	int i;
	
	JitRange * jr;
	jr = mop_get_jit_range (start);
	
	for (i = 0; name [i]; ++i) {
		if (!isalnum (name [i]))
			name [i] = '_';
	}
	
	fprintf (assm, ".section vm%d\n", jr->rangenum);
	fprintf (assm, ".org %p\n", (char*)start - (char*)jr->start);
	fprintf (assm, "%s%d:\n", name, ++n);

	for (i = 0; i < len; i ++) {
		fprintf (assm, ".byte %d; ", start [i]);
	}
	fprintf (assm, "\n\n\n");

	g_free (name);
}
예제 #2
0
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);
	}
}
예제 #3
0
void CPipeServer::GetJitInfo()
{
	void *domain=(void *)ReadQword();
	void *address=(void *)ReadQword();
	void *jitinfo=mono_jit_info_table_find(domain, address);
	WriteQword((UINT_PTR)jitinfo);
	if (jitinfo)
	{
		WriteQword((UINT_PTR)mono_jit_info_get_method(jitinfo));
		WriteQword((UINT_PTR)mono_jit_info_get_code_start(jitinfo));
		WriteDword((UINT_PTR)mono_jit_info_get_code_size(jitinfo));
	}
}
예제 #4
0
파일: xmono.cpp 프로젝트: 0bj3ct/xmono
/*监控需要hook的函数*/
static void profile_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) {
    if (result == MONO_PROFILE_FAILED) return;
    if (mono_method_get_token (method) == 0) return;                /*一般是动态生成的marshall*/
    uint32_t iflags;
    int flag = mono_method_get_flags (method, &iflags);
    if (iflags != 0) return;                                        /*iflags非0 一般是一些native和特殊的method实现*/
    if (mono_jit_info_get_code_size (jinfo) < 4) return;            /*代码段太小, 无法hook*/

    void *p = mono_jit_info_get_code_start (jinfo);
    if (p == 0) {
        LOGD ("function code size is null");
        return;
    }

        /*测试jit函数是否是mov r12, sp*/
    if (*(uint32_t*)p != 0xE1A0C00D)
         LOGD ("exception func : %s , %p", mono_method_get_name (method), p);

    /*TODO : 增加可配置的image和函数列表*/
    if (strcmp (get_method_image_name (method), "Assembly-CSharp") != 0) return;
    if (strcmp (mono_method_get_name (method), ".ctor") == 0) return;
    if (strcmp (mono_method_get_name (method), ".cctor") == 0) return;
    if (strcmp (mono_method_get_name (method), "set") == 0) return;
    if (strcmp (mono_method_get_name (method), "get") == 0) return;
    if (strcmp (mono_method_get_name (method), "Update") == 0) return;
    if (strcmp (mono_method_get_name (method), "LateUpdate") == 0) return;
    if (strcmp (mono_method_get_name (method), "OnGUI") == 0) return;

    /*TODO : 需要一个容器来存储还未编译, 但又想hook的函数*/

    bool donthook = false;
    pthread_mutex_lock (&replace_mutex);
    if (replace_method_dict.find (method) != replace_method_dict.end ())
        donthook = true;
    pthread_mutex_unlock (&replace_mutex);
    if (donthook) return;

    char *hook = specific_hook (p, method, (void*)func_trace);
    if (hook == 0) {
        /*将失败的hook也放到一个表里面*/
        LOGD ("hook err : %s", mono_method_get_name (method));
        return;
    }
    pthread_mutex_lock (&hooked_mutex);
    hooked_method_dict[method] = new HookInfo(jinfo, hook);
    pthread_mutex_unlock (&hooked_mutex);
    LOGD ("hook func : %s , %p", mono_method_get_name (method), p);
    return;
}
예제 #5
0
파일: xmono.cpp 프로젝트: 0bj3ct/xmono
static void replace_method (Package *pkg) {
    xmono::ReplaceMethodReq req;
    xmono::ReplaceMethodRsp rsp;
    std::string str((char*)pkg->body, pkg->all_len - sizeof (Package));
    if (!req.ParseFromString (str)) {
        LOGD ("xmono::ReplaceMethodReq ParseFromString err!");
        return;
    }
    std::string err;
    void *p, *old_p;
    uint8_t *code;
    int code_size;
    MonoMethodHeader *mh;
    MonoThread *thread;
    MonoMethod *new_method;
    MonoDomain *domain;
    MonoMethod * method = get_method_with_token (req.image_name ().c_str (), req.method_token ());
    if (!method) {
        rsp.set_err (false);
        rsp.set_msg (helper_last_err ());
        goto replace_method_end;
    }
    domain = mono_domain_get_by_id (req.domain_id ());
    if (!domain) {
        rsp.set_err (false);
        rsp.set_msg ("can not get the domain from id");
        goto replace_method_end;
    }
    mh = mono_method_get_header (method);
    if (req.ex_size () != mono_method_header_get_num_clauses (mh)) {
        rsp.set_err (false);
        rsp.set_msg ("ex size != mono_method_header_clauses size!");
        goto replace_method_end;
    }
    for (int i = 0; i < req.ex_size (); i++) {
        xmono::ReplaceMethodReq_ExceptionClause const &e = req.ex (i);
        void *iter = 0;
        MonoExceptionClause *clauses = &mh->clauses[i];
        MonoExceptionClause *old_e = (MonoExceptionClause*)iter;
        old_e->try_offset = e.try_offset ();
        old_e->try_len = e.try_len ();
        old_e->handler_offset = e.handler_offset ();
        old_e->handler_len = e.handler_len ();
    }
    code = new uint8_t[req.new_code ().size ()];
    memcpy (code, req.new_code ().c_str (), req.new_code ().size ());
    mh->code = code;
    mh->code_size = req.new_code ().size ();
    thread = mono_thread_attach (domain);
    /*128 是一个估计值, 在未来可能不稳定, 但当前只能如此*/
    new_method = (MonoMethod*)calloc (128, 1); /*这个地方用malloc优于用new*/
    memcpy (new_method, method, 128);

    pthread_mutex_lock (&replace_mutex);
    replace_method_dict[new_method] = true;
    pthread_mutex_unlock (&replace_mutex);

    p = mono_compile_method (new_method);
    memcpy (hooked_method_dict[method]->specific_hook + 4, &p, 4);

    pthread_mutex_lock (&hooked_mutex);
    old_p = mono_jit_info_get_code_start (hooked_method_dict[method]->jinfo);
    pthread_mutex_unlock (&hooked_mutex);

    mono_thread_detach (thread);
    LOGD ("compile method, new ptr : %p, old ptr : %p", p, old_p);
    rsp.set_err (true);
    rsp.set_msg ("replace_method successful.");
replace_method_end:
    std::string out;
    rsp.SerializeToString (&out);
    ecmd_send (XMONO_ID_REPLACE_METHOD_RSP, (uint8_t const*)out.c_str (), out.size ());
    return;
}