/* * Given an object ID obtained from the debugger front end, return a * strong, global reference to that object (or NULL if the object * has been collected). The reference can then be used for JNI and * JVMTI calls. Caller is resposible for deleting the returned reference. */ jobject commonRef_idToRef(JNIEnv *env, jlong id) { jobject ref; ref = NULL; debugMonitorEnter(gdata->refLock); { RefNode *node; node = findNodeByID(env, id); if (node != NULL) { if (node->isStrong) { saveGlobalRef(env, node->ref, &ref); } else { jobject lref; lref = JNI_FUNC_PTR(env,NewLocalRef)(env, node->ref); if ( lref == NULL ) { /* Object was GC'd shortly after we found the node */ deleteNodeByID(env, node->seqNum, ALL_REFS); } else { saveGlobalRef(env, node->ref, &ref); JNI_FUNC_PTR(env,DeleteLocalRef)(env, lref); } } } } debugMonitorExit(gdata->refLock); return ref; }
jvmtiError eventFilter_setExceptionOnlyFilter(HandlerNode *node, jint index, jclass exceptionClass, jboolean caught, jboolean uncaught) { JNIEnv *env = getEnv(); ExceptionFilter *filter = &FILTER(node, index).u.ExceptionOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if (NODE_EI(node) != EI_EXCEPTION) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } filter->exception = NULL; if (exceptionClass != NULL) { /* Create a class ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, exceptionClass, &(filter->exception)); } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ExceptionOnly); filter->caught = caught; filter->uncaught = uncaught; return JVMTI_ERROR_NONE; }
jvmtiError eventFilter_setStepFilter(HandlerNode *node, jint index, jthread thread, jint size, jint depth) { jvmtiError error; JNIEnv *env = getEnv(); StepFilter *filter = &FILTER(node, index).u.Step; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if (NODE_EI(node) != EI_SINGLE_STEP) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } /* Create a thread ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, thread, &(filter->thread)); error = stepControl_beginStep(env, filter->thread, size, depth, node); if (error != JVMTI_ERROR_NONE) { tossGlobalRef(env, &(filter->thread)); return error; } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Step); filter->depth = depth; filter->size = size; return JVMTI_ERROR_NONE; }
jvmtiError eventFilter_setLocationOnlyFilter(HandlerNode *node, jint index, jclass clazz, jmethodID method, jlocation location) { JNIEnv *env = getEnv(); LocationFilter *filter = &FILTER(node, index).u.LocationOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if ((NODE_EI(node) != EI_BREAKPOINT) && (NODE_EI(node) != EI_FIELD_ACCESS) && (NODE_EI(node) != EI_FIELD_MODIFICATION) && (NODE_EI(node) != EI_SINGLE_STEP) && (NODE_EI(node) != EI_EXCEPTION)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } /* Create a class ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, clazz, &(filter->clazz)); FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(LocationOnly); filter->method = method; filter->location = location; return JVMTI_ERROR_NONE; }
void eventHelper_recordFrameEvent(jint id, jbyte suspendPolicy, EventIndex ei, jthread thread, jclass clazz, jmethodID method, jlocation location, int needReturnValue, jvalue returnValue, struct bag *eventBag) { JNIEnv *env = getEnv(); FrameEventCommandSingle *frameCommand; CommandSingle *command = bagAdd(eventBag); jvmtiError err = JVMTI_ERROR_NONE; if (command == NULL) { EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"bagAdd(eventBag)"); } command->singleKind = COMMAND_SINGLE_FRAME_EVENT; frameCommand = &command->u.frameEventCommand; frameCommand->suspendPolicy = suspendPolicy; frameCommand->id = id; frameCommand->ei = ei; saveGlobalRef(env, thread, &(frameCommand->thread)); saveGlobalRef(env, clazz, &(frameCommand->clazz)); frameCommand->method = method; frameCommand->location = location; if (needReturnValue) { err = methodReturnType(method, &frameCommand->typeKey); JDI_ASSERT(err == JVMTI_ERROR_NONE); /* * V or B C D F I J S Z L <classname> ; [ ComponentType */ if (isObjectTag(frameCommand->typeKey) && returnValue.l != NULL) { saveGlobalRef(env, returnValue.l, &(frameCommand->returnValue.l)); } else { frameCommand->returnValue = returnValue; } } else { /* This is not a JDWP METHOD_EXIT_WITH_RETURN_VALUE request, * so signal this by setting typeKey = 0 which is not * a legal typekey. */ frameCommand->typeKey = 0; } }
void eventHelper_suspendThread(jbyte sessionID, jthread thread) { JNIEnv *env = getEnv(); HelperCommand *command = jvmtiAllocate(sizeof(*command)); if (command == NULL) { EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"HelperCommmand"); } (void)memset(command, 0, sizeof(*command)); command->commandKind = COMMAND_SUSPEND_THREAD; command->sessionID = sessionID; saveGlobalRef(env, thread, &(command->u.suspendThread.thread)); enqueueCommand(command, JNI_TRUE, JNI_FALSE); }
/* * This, currently, cannot go through the normal event handling code * because the JVMTI event does not contain a thread. */ void eventHelper_reportVMInit(JNIEnv *env, jbyte sessionID, jthread thread, jbyte suspendPolicy) { HelperCommand *command = jvmtiAllocate(sizeof(*command)); if (command == NULL) { EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"HelperCommmand"); } (void)memset(command, 0, sizeof(*command)); command->commandKind = COMMAND_REPORT_VM_INIT; command->sessionID = sessionID; saveGlobalRef(env, thread, &(command->u.reportVMInit.thread)); command->u.reportVMInit.suspendPolicy = suspendPolicy; enqueueCommand(command, JNI_TRUE, JNI_FALSE); }
void eventHelper_reportInvokeDone(jbyte sessionID, jthread thread) { JNIEnv *env = getEnv(); HelperCommand *command = jvmtiAllocate(sizeof(*command)); if (command == NULL) { EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"HelperCommand"); } (void)memset(command, 0, sizeof(*command)); command->commandKind = COMMAND_REPORT_INVOKE_DONE; command->sessionID = sessionID; saveGlobalRef(env, thread, &(command->u.reportInvokeDone.thread)); enqueueCommand(command, JNI_TRUE, JNI_FALSE); }
/* * Given an object ID obtained from the debugger front end, return a * strong, global reference to that object (or NULL if the object * has been collected). The reference can then be used for JNI and * JVMTI calls. Caller is resposible for deleting the returned reference. */ jobject commonRef_idToRef(jlong id) { JNIEnv *env = getEnv(); jobject ref = NULL; RefNode *node; debugMonitorEnter(refLock); node = findNodeByID(env, id); if (node != NULL) { saveGlobalRef(env, node->ref, &ref); } debugMonitorExit(refLock); return ref; }
jvmtiError eventFilter_setThreadOnlyFilter(HandlerNode *node, jint index, jthread thread) { JNIEnv *env = getEnv(); ThreadFilter *filter = &FILTER(node, index).u.ThreadOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if (NODE_EI(node) == EI_GC_FINISH) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } /* Create a thread ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, thread, &(filter->thread)); FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ThreadOnly); return JVMTI_ERROR_NONE; }
jvmtiError eventFilter_setInstanceOnlyFilter(HandlerNode *node, jint index, jobject instance) { JNIEnv *env = getEnv(); InstanceFilter *filter = &FILTER(node, index).u.InstanceOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } filter->instance = NULL; if (instance != NULL) { /* Create an object ref that will live beyond * the end of this call */ saveGlobalRef(env, instance, &(filter->instance)); } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(InstanceOnly); return JVMTI_ERROR_NONE; }
jvmtiError eventFilter_setFieldOnlyFilter(HandlerNode *node, jint index, jclass clazz, jfieldID field) { JNIEnv *env = getEnv(); FieldFilter *filter = &FILTER(node, index).u.FieldOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if ((NODE_EI(node) != EI_FIELD_ACCESS) && (NODE_EI(node) != EI_FIELD_MODIFICATION)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } /* Create a class ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, clazz, &(filter->clazz)); FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(FieldOnly); filter->field = field; return JVMTI_ERROR_NONE; }
jvmtiError eventFilter_setClassOnlyFilter(HandlerNode *node, jint index, jclass clazz) { JNIEnv *env = getEnv(); ClassFilter *filter = &FILTER(node, index).u.ClassOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if ( (NODE_EI(node) == EI_GC_FINISH) || (NODE_EI(node) == EI_THREAD_START) || (NODE_EI(node) == EI_THREAD_END)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } /* Create a class ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, clazz, &(filter->clazz)); FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ClassOnly); return JVMTI_ERROR_NONE; }
/* Change all references to global in the EventInfo struct */ static void saveEventInfoRefs(JNIEnv *env, EventInfo *evinfo) { jthread *pthread; jclass *pclazz; jobject *pobject; jthread thread; jclass clazz; jobject object; char sig; JNI_FUNC_PTR(env,ExceptionClear)(env); if ( evinfo->thread != NULL ) { pthread = &(evinfo->thread); thread = *pthread; *pthread = NULL; saveGlobalRef(env, thread, pthread); } if ( evinfo->clazz != NULL ) { pclazz = &(evinfo->clazz); clazz = *pclazz; *pclazz = NULL; saveGlobalRef(env, clazz, pclazz); } if ( evinfo->object != NULL ) { pobject = &(evinfo->object); object = *pobject; *pobject = NULL; saveGlobalRef(env, object, pobject); } switch (evinfo->ei) { case EI_FIELD_MODIFICATION: if ( evinfo->u.field_modification.field_clazz != NULL ) { pclazz = &(evinfo->u.field_modification.field_clazz); clazz = *pclazz; *pclazz = NULL; saveGlobalRef(env, clazz, pclazz); } sig = evinfo->u.field_modification.signature_type; if ((sig == JDWP_TAG(ARRAY)) || (sig == JDWP_TAG(OBJECT))) { if ( evinfo->u.field_modification.new_value.l != NULL ) { pobject = &(evinfo->u.field_modification.new_value.l); object = *pobject; *pobject = NULL; saveGlobalRef(env, object, pobject); } } break; case EI_FIELD_ACCESS: if ( evinfo->u.field_access.field_clazz != NULL ) { pclazz = &(evinfo->u.field_access.field_clazz); clazz = *pclazz; *pclazz = NULL; saveGlobalRef(env, clazz, pclazz); } break; case EI_EXCEPTION: if ( evinfo->u.exception.catch_clazz != NULL ) { pclazz = &(evinfo->u.exception.catch_clazz); clazz = *pclazz; *pclazz = NULL; saveGlobalRef(env, clazz, pclazz); } break; default: break; } if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) { EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,"ExceptionOccurred"); } }