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); }
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); } }
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)); } }
/*监控需要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; }