static void handleReportVMInitCommand(JNIEnv* env, ReportVMInitCommand *command) { PacketOutputStream out; if (command->suspendPolicy == JDWP_SUSPEND_POLICY(ALL)) { (void)threadControl_suspendAll(); } else if (command->suspendPolicy == JDWP_SUSPEND_POLICY(EVENT_THREAD)) { (void)threadControl_suspendThread(command->thread, JNI_FALSE); } outStream_initCommand(&out, uniqueID(), 0x0, JDWP_COMMAND_SET(Event), JDWP_COMMAND(Event, Composite)); (void)outStream_writeByte(&out, command->suspendPolicy); (void)outStream_writeInt(&out, 1); /* Always one component */ (void)outStream_writeByte(&out, JDWP_EVENT(VM_INIT)); (void)outStream_writeInt(&out, 0); /* Not in response to an event req. */ (void)outStream_writeObjectRef(env, &out, command->thread); outStream_sendCommand(&out); outStream_destroy(&out); /* Why aren't we tossing this: tossGlobalRef(env, &(command->thread)); */ }
jdwpError outStream_writeString(PacketOutputStream *stream, char *string) { jdwpError error; jint length; /* Options utf8=y/n controls if we want Standard UTF-8 or Modified */ if ( gdata->modifiedUtf8 ) { length = (int)strlen(string); (void)outStream_writeInt(stream, length); error = writeBytes(stream, (jbyte *)string, length); } else { jint new_length; length = (int)strlen(string); new_length = (gdata->npt->utf8mToUtf8sLength) (gdata->npt->utf, (jbyte*)string, length); if ( new_length == length ) { (void)outStream_writeInt(stream, length); error = writeBytes(stream, (jbyte *)string, length); } else { char *new_string; new_string = jvmtiAllocate(new_length+1); (gdata->npt->utf8mToUtf8s) (gdata->npt->utf, (jbyte*)string, length, (jbyte*)new_string, new_length); (void)outStream_writeInt(stream, new_length); error = writeBytes(stream, (jbyte *)new_string, new_length); jvmtiDeallocate(new_string); } } return error; }
jint outStream_writeString(PacketOutputStream *stream, char *string) { jint length = strlen(string); outStream_writeInt(stream, length); return writeBytes(stream, (jbyte *)string, length); }
jdwpError outStream_writeByteArray(PacketOutputStream*stream, jint length, jbyte *bytes) { (void)outStream_writeInt(stream, length); return writeBytes(stream, bytes, length); }
static void handleUnloadCommandSingle(JNIEnv* env, PacketOutputStream *out, UnloadCommandSingle *command) { (void)outStream_writeByte(out, JDWP_EVENT(CLASS_UNLOAD)); (void)outStream_writeInt(out, command->id); (void)outStream_writeString(out, command->classSignature); jvmtiDeallocate(command->classSignature); command->classSignature = NULL; }
void outStream_writeValue(JNIEnv *env, PacketOutputStream *out, jbyte typeKey, jvalue value) { if (typeKey == JDWP_Tag_OBJECT) { outStream_writeByte(out, specificTypeKey(value.l)); } else { outStream_writeByte(out, typeKey); } if (isObjectTag(typeKey)) { WRITE_GLOBAL_REF(env, out, value.l); } else { switch (typeKey) { case JDWP_Tag_BYTE: outStream_writeByte(out, value.b); break; case JDWP_Tag_CHAR: outStream_writeChar(out, value.c); break; case JDWP_Tag_FLOAT: outStream_writeFloat(out, value.f); break; case JDWP_Tag_DOUBLE: outStream_writeDouble(out, value.d); break; case JDWP_Tag_INT: outStream_writeInt(out, value.i); break; case JDWP_Tag_LONG: outStream_writeLong(out, value.j); break; case JDWP_Tag_SHORT: outStream_writeShort(out, value.s); break; case JDWP_Tag_BOOLEAN: outStream_writeBoolean(out, value.z); break; case JDWP_Tag_VOID: /* happens with function return values */ /* write nothing */ break; default: ERROR_MESSAGE_EXIT("Invalid type key"); } } }
static jboolean children(PacketInputStream *in, PacketOutputStream *out) { jint error; jint i; jint threadCount; jint groupCount; jthread *theThreads; jthread *theGroups; JNIEnv *env = getEnv(); jthreadGroup group = inStream_readThreadGroupRef(in); if (inStream_error(in)) { return JNI_TRUE; } error = jvmdi->GetThreadGroupChildren(group, &threadCount,&theThreads, &groupCount, &theGroups); if (error != JVMDI_ERROR_NONE) { outStream_setError(out, error); return JNI_TRUE; } /* Squish out all of the debugger-spawned threads */ threadCount = filterDebugThreads(theThreads, threadCount); outStream_writeInt(out, threadCount); for (i = 0; i < threadCount; i++) { WRITE_GLOBAL_REF(env, out, theThreads[i]); } outStream_writeInt(out, groupCount); for (i = 0; i < groupCount; i++) { WRITE_GLOBAL_REF(env, out, theGroups[i]); } jdwpFree(theGroups); jdwpFree(theThreads); return JNI_TRUE; }
jint outStream_writeFieldID(PacketOutputStream *stream, jfieldID val) { /* * Not good - we're writing a pointer as a jint. Need * to write as a jlong if sizeof(jfieldID) == 8. */ if (sizeof(jfieldID) == 8) { return outStream_writeLong(stream, (jlong)val); } else { return outStream_writeInt(stream, (jint)val); } }
jdwpError outStream_writeMethodID(PacketOutputStream *stream, jmethodID val) { /* * Not good - we're writing a pointer as a jint. Need * to write as a jlong if sizeof(jmethodID) == 8. */ if (sizeof(jmethodID) == 8) { /*LINTED*/ return outStream_writeLong(stream, (jlong)(intptr_t)val); } else { /*LINTED*/ return outStream_writeInt(stream, (jint)(intptr_t)val); } }
static jboolean length(PacketInputStream *in, PacketOutputStream *out) { JNIEnv *env = getEnv(); jsize arrayLength; jarray array = inStream_readArrayRef(env, in); if (inStream_error(in)) { return JNI_TRUE; } arrayLength = JNI_FUNC_PTR(env,GetArrayLength)(env, array); (void)outStream_writeInt(out, arrayLength); return JNI_TRUE; }
jdwpError outStream_writeValue(JNIEnv *env, PacketOutputStream *out, jbyte typeKey, jvalue value) { if (typeKey == JDWP_TAG(OBJECT)) { (void)outStream_writeByte(out, specificTypeKey(env, value.l)); } else { (void)outStream_writeByte(out, typeKey); } if (isObjectTag(typeKey)) { (void)outStream_writeObjectRef(env, out, value.l); } else { switch (typeKey) { case JDWP_TAG(BYTE): return outStream_writeByte(out, value.b); case JDWP_TAG(CHAR): return outStream_writeChar(out, value.c); case JDWP_TAG(FLOAT): return outStream_writeFloat(out, value.f); case JDWP_TAG(DOUBLE): return outStream_writeDouble(out, value.d); case JDWP_TAG(INT): return outStream_writeInt(out, value.i); case JDWP_TAG(LONG): return outStream_writeLong(out, value.j); case JDWP_TAG(SHORT): return outStream_writeShort(out, value.s); case JDWP_TAG(BOOLEAN): return outStream_writeBoolean(out, value.z); case JDWP_TAG(VOID): /* happens with function return values */ /* write nothing */ return JDWP_ERROR(NONE); default: EXIT_ERROR(AGENT_ERROR_INVALID_OBJECT,"Invalid type key"); break; } } return JDWP_ERROR(NONE); }
static void handleEventCommandSingle(JNIEnv *env, PacketOutputStream *out, EventCommandSingle *command) { EventInfo *evinfo = &command->info; (void)outStream_writeByte(out, eventIndex2jdwp(evinfo->ei)); (void)outStream_writeInt(out, command->id); switch (evinfo->ei) { case EI_SINGLE_STEP: writeSingleStepEvent(env, out, evinfo); break; case EI_BREAKPOINT: writeBreakpointEvent(env, out, evinfo); break; case EI_FIELD_ACCESS: writeFieldAccessEvent(env, out, evinfo); break; case EI_FIELD_MODIFICATION: writeFieldModificationEvent(env, out, evinfo); break; case EI_EXCEPTION: writeExceptionEvent(env, out, evinfo); break; case EI_THREAD_START: case EI_THREAD_END: writeThreadEvent(env, out, evinfo); break; case EI_CLASS_LOAD: case EI_CLASS_PREPARE: writeClassEvent(env, out, evinfo); break; case EI_MONITOR_CONTENDED_ENTER: case EI_MONITOR_CONTENDED_ENTERED: case EI_MONITOR_WAIT: case EI_MONITOR_WAITED: writeMonitorEvent(env, out, evinfo); break; case EI_VM_DEATH: writeVMDeathEvent(env, out, evinfo); break; default: EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,"unknown event index"); break; } tossEventInfoRefs(env, evinfo); }
static void writeIntComponents(JNIEnv *env, PacketOutputStream *out, jarray array, jint index, jint length) { jint *components; components = newComponents(out, length, sizeof(jint)); if (components != NULL) { jint i; JNI_FUNC_PTR(env,GetIntArrayRegion)(env, array, index, length, components); for (i = 0; i < length; i++) { (void)outStream_writeInt(out, components[i]); } deleteComponents(components); } }
static void writeClassEvent(JNIEnv *env, PacketOutputStream *out, EventInfo *evinfo) { jbyte classTag; jint status; char *signature = NULL; jvmtiError error; classTag = referenceTypeTag(evinfo->clazz); error = classSignature(evinfo->clazz, &signature, NULL); if (error != JVMTI_ERROR_NONE) { EXIT_ERROR(error,"signature"); } status = classStatus(evinfo->clazz); (void)outStream_writeObjectRef(env, out, evinfo->thread); (void)outStream_writeByte(out, classTag); (void)outStream_writeObjectRef(env, out, evinfo->clazz); (void)outStream_writeString(out, signature); (void)outStream_writeInt(out, map2jdwpClassStatus(status)); jvmtiDeallocate(signature); }
static void handleFrameEventCommandSingle(JNIEnv* env, PacketOutputStream *out, FrameEventCommandSingle *command) { if (command->typeKey) { (void)outStream_writeByte(out, JDWP_EVENT(METHOD_EXIT_WITH_RETURN_VALUE)); } else { (void)outStream_writeByte(out, eventIndex2jdwp(command->ei)); } (void)outStream_writeInt(out, command->id); (void)outStream_writeObjectRef(env, out, command->thread); writeCodeLocation(out, command->clazz, command->method, command->location); if (command->typeKey) { (void)outStream_writeValue(env, out, command->typeKey, command->returnValue); if (isObjectTag(command->typeKey) && command->returnValue.l != NULL) { tossGlobalRef(env, &(command->returnValue.l)); } } tossGlobalRef(env, &(command->thread)); tossGlobalRef(env, &(command->clazz)); }
/** * This is the back-end implementation for enabling * (what are at the JDI level) EventRequests. * * Allocate the event request handler (eventHandler). * Add any filters (explicit or implicit). * Install the handler. * Return the handlerID which is used to map subsequent * events to the EventRequest that created it. */ static jboolean setCommand(PacketInputStream *in, PacketOutputStream *out) { jdwpError serror; HandlerNode *node; HandlerID requestID = -1; jdwpEvent eventType; jbyte suspendPolicy; jint filterCount; EventIndex ei; node = NULL; eventType = inStream_readByte(in); if (inStream_error(in)) { return JNI_TRUE; } suspendPolicy = inStream_readByte(in); if (inStream_error(in)) { return JNI_TRUE; } filterCount = inStream_readInt(in); if (inStream_error(in)) { return JNI_TRUE; } ei = jdwp2EventIndex(eventType); if (ei == 0) { outStream_setError(out, JDWP_ERROR(INVALID_EVENT_TYPE)); return JNI_TRUE; } if (ei == EI_VM_INIT) { /* * VM is already initialized so there's no need to install a handler * for this event. However we need to allocate a requestID to send in * the reply to the debugger. */ serror = JDWP_ERROR(NONE); requestID = eventHandler_allocHandlerID(); } else { node = eventHandler_alloc(filterCount, ei, suspendPolicy); if (node == NULL) { outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY)); return JNI_TRUE; } if (eventType == JDWP_EVENT(METHOD_EXIT_WITH_RETURN_VALUE)) { node->needReturnValue = 1; } else { node->needReturnValue = 0; } serror = readAndSetFilters(getEnv(), in, node, filterCount); if (serror == JDWP_ERROR(NONE)) { jvmtiError error; error = eventHandler_installExternal(node); serror = map2jdwpError(error); if (serror == JDWP_ERROR(NONE)) { requestID = node->handlerID; } } } if (serror == JDWP_ERROR(NONE)) { (void)outStream_writeInt(out, requestID); } else { (void)eventHandler_free(node); outStream_setError(out, serror); } return JNI_TRUE; }
static void handleReportEventCompositeCommand(JNIEnv *env, ReportEventCompositeCommand *recc) { PacketOutputStream out; jint count = recc->eventCount; jint i; if (recc->suspendPolicy != JDWP_SUSPEND_POLICY(NONE)) { /* must determine thread to interrupt before writing */ /* since writing destroys it */ jthread thread = NULL; for (i = 0; i < count; i++) { CommandSingle *single = &(recc->singleCommand[i]); switch (single->singleKind) { case COMMAND_SINGLE_EVENT: thread = single->u.eventCommand.info.thread; break; case COMMAND_SINGLE_FRAME_EVENT: thread = single->u.frameEventCommand.thread; break; } if (thread != NULL) { break; } } if (thread == NULL) { (void)threadControl_suspendAll(); } else { suspendWithInvokeEnabled(recc->suspendPolicy, thread); } } outStream_initCommand(&out, uniqueID(), 0x0, JDWP_COMMAND_SET(Event), JDWP_COMMAND(Event, Composite)); (void)outStream_writeByte(&out, recc->suspendPolicy); (void)outStream_writeInt(&out, count); for (i = 0; i < count; i++) { CommandSingle *single = &(recc->singleCommand[i]); switch (single->singleKind) { case COMMAND_SINGLE_EVENT: handleEventCommandSingle(env, &out, &single->u.eventCommand); break; case COMMAND_SINGLE_UNLOAD: handleUnloadCommandSingle(env, &out, &single->u.unloadCommand); break; case COMMAND_SINGLE_FRAME_EVENT: handleFrameEventCommandSingle(env, &out, &single->u.frameEventCommand); break; } } outStream_sendCommand(&out); outStream_destroy(&out); }