static ncaiError ncai_fill_module(ncaiModule* modulePtr, native_module_t* src) { ncaiError error; ncaiModule module; error = ncai_alloc_module(&module); if ( error != NCAI_ERROR_NONE) return error; module->info->segments = (ncaiSegmentInfo*)ncai_alloc(sizeof(ncaiSegmentInfo)*src->seg_count); if (module->info->segments == NULL) { ncai_dealloc_module(module); return NCAI_ERROR_OUT_OF_MEMORY; } module->info->kind = NCAI_MODULE_OTHER; module->info->segment_count = src->seg_count; size_t pathsize = strlen(src->filename) + 1; module->info->filename = (char*)ncai_alloc(pathsize); if (module->info->filename == NULL) { ncai_dealloc_module(module); return NCAI_ERROR_OUT_OF_MEMORY; } memcpy(module->info->filename, src->filename, pathsize); module->info->name = ncai_parse_module_name(module->info->filename); if (module->info->name == NULL) { ncai_dealloc_module(module); return NCAI_ERROR_OUT_OF_MEMORY; } for (size_t i = 0; i < src->seg_count; i++) { if (src->segments[i].type == SEGMENT_TYPE_CODE) module->info->segments[i].kind = NCAI_SEGMENT_CODE; else if (src->segments[i].type == SEGMENT_TYPE_DATA) module->info->segments[i].kind = NCAI_SEGMENT_DATA; else module->info->segments[i].kind = NCAI_SEGMENT_UNKNOWN; module->info->segments[i].base_address = src->segments[i].base; module->info->segments[i].size = src->segments[i].size; } module->isAlive = true; *modulePtr = module; return NCAI_ERROR_NONE; }
static ncaiError ncai_get_module_info(ncaiModule module, ncaiModuleInfo *info_ptr) { ncaiModuleInfo mod_info; ncaiSegmentInfo* seg_info = NULL; seg_info = (ncaiSegmentInfo*)ncai_alloc(sizeof(ncaiSegmentInfo)* (module->info->segment_count)); if (seg_info == NULL) return NCAI_ERROR_OUT_OF_MEMORY; for (size_t i = 0; i < module->info->segment_count; i++) { seg_info[i] = module->info->segments[i]; } mod_info.kind = module->info->kind; mod_info.name = strdup(module->info->name); assert(mod_info.name); mod_info.filename = strdup(module->info->filename); assert(mod_info.filename); mod_info.segment_count = module->info->segment_count; mod_info.segments = seg_info; *info_ptr = mod_info; return NCAI_ERROR_NONE; }
char* ncai_parse_module_name(char* filepath) { size_t length = 0; char* filename = strrchr(filepath, '/'); filename = filename ? (filename + 1) : filepath; char* dot_so = strstr(filename, ".so"); if (dot_so != NULL) // We have shared library, cut off 'lib' too { if (memcmp(filename, "lib", 3) == 0) filename += 3; length = dot_so - filename; } else { dot_so = strstr(filename, ".exe"); if (dot_so != NULL) length = dot_so - filename; else length = strlen(filename); } char* ret = (char*)ncai_alloc(length + 1); if (ret) { memcpy(ret, filename, length); ret[length] = '\0'; } return ret; }
ncaiError ncai_add_event_to_thread(ncaiEnv *env, ncaiEventKind event_type, ncaiThread event_thread) { NCAIEnv *p_env = (NCAIEnv *)env; ncaiEventThread *et =p_env->event_threads[event_type - NCAI_MIN_EVENT_TYPE_VAL]; // Find out if this environment is already registered // on this thread on this event type while (et != NULL) { if (et->thread == event_thread) return NCAI_ERROR_NONE; et = et->next; } ncaiEventThread *newet; newet = (ncaiEventThread *) ncai_alloc(sizeof(ncaiEventThread)); if (newet == NULL) return NCAI_ERROR_OUT_OF_MEMORY; newet->thread = event_thread; LMAutoUnlock aulock(p_env->env_lock); //ncai env general lock newet->next = p_env->event_threads[event_type - NCAI_MIN_EVENT_TYPE_VAL]; p_env->event_threads[event_type - NCAI_MIN_EVENT_TYPE_VAL] = newet; return NCAI_ERROR_NONE; }
//allocates the memory for module, except for segments - those must be allocated, when the segments information is known. static ncaiError ncai_alloc_module(ncaiModule* dest) { assert(dest); ncaiModule module = (ncaiModule)ncai_alloc(sizeof(_ncaiModule)); if (module == NULL) return NCAI_ERROR_OUT_OF_MEMORY; module->next = NULL; module->info = (ncaiModuleInfo*)ncai_alloc(sizeof(ncaiModuleInfo)); if (module->info == NULL) { ncai_free(module); return NCAI_ERROR_OUT_OF_MEMORY; } *dest = module; return NCAI_ERROR_NONE; }
ncaiError JNICALL ncaiGetThreadInfo(ncaiEnv *env, ncaiThread thread, ncaiThreadInfo *info_ptr) { TRACE2("ncai.thread", "ncaiGetThreadsInfo called"); SuspendEnabledChecker sec; if (env == NULL) return NCAI_ERROR_INVALID_ENVIRONMENT; if (info_ptr == NULL) return NCAI_ERROR_NULL_POINTER; if (thread == NULL) return NCAI_ERROR_INVALID_THREAD; hythread_t hythread = reinterpret_cast<hythread_t>(thread); if (!ncai_thread_is_alive(hythread)) return NCAI_ERROR_THREAD_NOT_ALIVE; jthread java_thread = jthread_get_java_thread(hythread); if (java_thread != NULL) { JNIEnv* jni_env = jthread_get_vm_thread(hythread)->jni_env; jclass cl = GetObjectClass(jni_env, java_thread); jmethodID id = jni_env->GetMethodID(cl, "getName","()Ljava/lang/String;"); jstring name = jni_env->CallObjectMethod(java_thread, id); info_ptr->name = (char *)jni_env->GetStringUTFChars(name, NULL); info_ptr->kind = NCAI_THREAD_JAVA; return NCAI_ERROR_NONE; } info_ptr->kind = NCAI_THREAD_VM_INTERNAL; const char* name_int = "native_0x"; size_t name_len = strlen(name_int) + 4 + 1; info_ptr->name = (char*)ncai_alloc(name_len); assert(info_ptr->name); sprintf(info_ptr->name, "%s%04X", name_int, hythread_get_id(hythread)); return NCAI_ERROR_NONE; }
static ncaiError ncai_transform_modules_to_array(ncaiModule list, ncaiModule** retArray, int count) { ncaiModule* array; array = (ncaiModule*) ncai_alloc(sizeof(ncaiModule) * count); if (array == NULL) return NCAI_ERROR_OUT_OF_MEMORY; int i = 0; for (ncaiModule current = list; current != NULL; i++, current = current->next) { array[i] = current; } *retArray = array; return NCAI_ERROR_NONE; }
ncaiError JNICALL ncaiGetAllThreads(ncaiEnv *env, jint *count_ptr, ncaiThread **threads_ptr) { TRACE2("ncai.thread", "GetAllThreads called"); SuspendEnabledChecker sec; if (env == NULL) return NCAI_ERROR_INVALID_ENVIRONMENT; if (threads_ptr == NULL || count_ptr == NULL) return NCAI_ERROR_NULL_POINTER; hythread_group_t* groups; int group_count; IDATA status; int i, res_count = 0; status = hythread_group_get_list(&groups, &group_count); if (status != TM_ERROR_NONE) return NCAI_ERROR_INTERNAL; for (i = 0; i < group_count; i++) { hythread_t cur_thread; hythread_iterator_t iterator = hythread_iterator_create(groups[i]); while (iterator && (cur_thread = hythread_iterator_next(&iterator))) { if (ncai_thread_is_alive(cur_thread)) res_count++; } hythread_iterator_release(&iterator); } ncaiThread* res_threads = (ncaiThread*)ncai_alloc(sizeof(void*)*res_count); if (res_threads == NULL) return NCAI_ERROR_OUT_OF_MEMORY; int index = 0; for (i = 0; i < group_count; i++) { hythread_t cur_thread; hythread_iterator_t iterator = hythread_iterator_create(groups[i]); while (iterator && (cur_thread = hythread_iterator_next(&iterator))) { if (index >= res_count) break; // some threads were created between two cycles if (!ncai_thread_is_alive(cur_thread)) continue; res_threads[index] = (ncaiThread)cur_thread; ++index; } hythread_iterator_release(&iterator); } *threads_ptr = res_threads; *count_ptr = index; return NCAI_ERROR_NONE; }