/* * Called once to build the initial prepared class hash table. */ void classTrack_initialize() { JNIEnv *env = getEnv(); jint classCount; jclass *classes = allLoadedClasses(&classCount); jint i; if (classes == NULL) { ALLOC_ERROR_EXIT(); } table = jdwpClearedAlloc(HASH_SLOT_COUNT * sizeof(KlassNode *)); if (table == NULL) { jdwpFree(classes); ALLOC_ERROR_EXIT(); } for (i=0; i<classCount; i++) { jclass klass = classes[i]; /* Filter out unprepared classes (arrays may or * may not be marked as prepared) */ jboolean preped = (classStatus(klass) & JVMDI_CLASS_STATUS_PREPARED) != 0; if (preped || isArrayClass(klass)) { classTrack_addPreparedClass(env, klass); } (*env)->DeleteGlobalRef(env, klass); } jdwpFree(classes); }
/* * Add a class to the prepared class hash table. * Assumes no duplicates. */ void classTrack_addPreparedClass(JNIEnv *env, jclass klass) { jint slot = hashKlass(klass); KlassNode **head = &table[slot]; KlassNode *node; if (assertOn) { /* Check this is not a duplicate */ for (node = *head; node != NULL; node = node->next) { if ((*env)->IsSameObject(env, klass, node->klass)) { JDI_ASSERT_FAILED("Attempting to insert duplicate class"); break; } } } node = jdwpAlloc(sizeof(KlassNode)); if (node == NULL) { ALLOC_ERROR_EXIT(); } if ((node->signature = classSignature(klass)) == NULL) { jdwpFree(node); ALLOC_ERROR_EXIT(); } if ((node->klass = (*env)->NewWeakGlobalRef(env, klass)) == NULL) { jdwpFree(node->signature); jdwpFree(node); ALLOC_ERROR_EXIT(); } /* Insert the new node */ node->next = *head; *head = node; }
/* * Called after class unloads have occurred. Creates a new hash table * of currently loaded prepared classes. * The signatures of classes which were unloaded (not present in the * new table) are returned. */ struct bag * classTrack_processUnloads(JNIEnv *env) { KlassNode **newTable = jdwpClearedAlloc(HASH_SLOT_COUNT * sizeof(KlassNode *)); jint classCount; jclass *classes; jint i; struct bag *unloadedSignatures; if (newTable == NULL) { ALLOC_ERROR_EXIT(); } if ((classes = allLoadedClasses(&classCount)) == NULL) { jdwpFree(newTable); ALLOC_ERROR_EXIT(); } /* Transfer each current class into the new table */ for (i=0; i<classCount; i++) { jclass klass = classes[i]; transferClass(env, klass, newTable); (*env)->DeleteGlobalRef(env, klass); } jdwpFree(classes); /* Delete old table, install new one */ unloadedSignatures = deleteTable(env, table); table = newTable; return unloadedSignatures; }
void outStream_destroy(PacketOutputStream *stream) { struct PacketData *next; if (stream->error || !stream->sent) { bagEnumerateOver(stream->ids, releaseID, NULL); } next = stream->packet.type.cmd.data.next; while (next != NULL) { struct PacketData *p = next; next = p->next; jdwpFree(p->data); jdwpFree(p); } bagDestroyBag(stream->ids); }
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; }
static jint writeBytes(PacketOutputStream *stream, void *source, int size) { jbyte *bytes = (jbyte *)source; if (stream->error) { return stream->error; } while (size > 0) { jint count; if (stream->left == 0) { jint segSize = MIN(2 * stream->segment->length, MAX_SEGMENT_SIZE); jbyte *newSeg = jdwpAlloc(segSize); struct PacketData *newHeader = jdwpAlloc(sizeof(*newHeader)); if ((newSeg == NULL) || (newHeader == NULL)) { jdwpFree(newSeg); jdwpFree(newHeader); stream->error = JVMDI_ERROR_OUT_OF_MEMORY; return stream->error; } newHeader->length = 0; newHeader->data = newSeg; newHeader->next = NULL; stream->segment->next = newHeader; stream->segment = newHeader; stream->current = newHeader->data; stream->left = segSize; } count = MIN(size, stream->left); memcpy(stream->current, bytes, count); stream->current += count; stream->left -= count; stream->segment->length += count; size -= count; bytes += count; } return JVMDI_ERROR_NONE; }
/* * Match the name of a class against a wildcard * string pattern. */ static jboolean patternMatch(jclass clazz, const char *pattern) { jboolean rc; char *signature = classSignature(clazz); if (signature == NULL) { return JNI_FALSE; } convertSignatureToClassname(signature); rc = patternStringMatch(signature, pattern); jdwpFree(signature); return rc; }
/* * Delete a hash table of classes. * The signatures of classes in the table are returned. */ static struct bag * deleteTable(JNIEnv *env, KlassNode *oldTable[]) { struct bag *signatures = bagCreateBag(sizeof(char*), 10); jint slot; if (signatures == NULL) { ALLOC_ERROR_EXIT(); } for (slot = 0; slot < HASH_SLOT_COUNT; slot++) { KlassNode *node = oldTable[slot]; while (node != NULL) { KlassNode *next; char **sigSpot; /* Add signature to the signature bag */ sigSpot = bagAdd(signatures); if (sigSpot == NULL) { ALLOC_ERROR_EXIT(); } *sigSpot = node->signature; /* Free weak ref and the node itself */ (*env)->DeleteWeakGlobalRef(env, node->klass); next = node->next; jdwpFree(node); node = next; } } jdwpFree(oldTable); return signatures; }
static jboolean parent(PacketInputStream *in, PacketOutputStream *out) { JNIEnv *env = getEnv(); JVMDI_thread_group_info info; jthreadGroup group = inStream_readThreadGroupRef(in); if (inStream_error(in)) { return JNI_TRUE; } threadGroupInfo(group, &info); WRITE_GLOBAL_REF(env, out, info.parent); jdwpFree(info.name); return JNI_TRUE; }
static jboolean name(PacketInputStream *in, PacketOutputStream *out) { JNIEnv *env = getEnv(); JVMDI_thread_group_info info; jthreadGroup group = inStream_readThreadGroupRef(in); if (inStream_error(in)) { return JNI_TRUE; } threadGroupInfo(group, &info); outStream_writeString(out, info.name); (*env)->DeleteGlobalRef(env, info.parent); jdwpFree(info.name); return JNI_TRUE; }
/** * Free up global refs held by the filter. * free things up at the JNI level if needed. */ static jint clearFilters(HandlerNode *node) { JNIEnv *env = getEnv(); jint i; jint error = JVMDI_ERROR_NONE; Filter *filter = FILTERS_ARRAY(node); for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { switch (filter->modifier) { case JDWP_REQUEST_MODIFIER(ThreadOnly): { jthread threadOnly = filter->u.ThreadOnly.thread; if (threadOnly != NULL) { (*env)->DeleteGlobalRef(env, threadOnly); } break; } case JDWP_REQUEST_MODIFIER(LocationOnly): { jclass clazz = filter->u.LocationOnly.clazz; (*env)->DeleteGlobalRef(env, clazz); break; } case JDWP_REQUEST_MODIFIER(FieldOnly): { jclass clazz = filter->u.FieldOnly.clazz; (*env)->DeleteGlobalRef(env, clazz); break; } case JDWP_REQUEST_MODIFIER(ExceptionOnly): { (*env)->DeleteGlobalRef(env, filter->u.ExceptionOnly.exception); break; } case JDWP_REQUEST_MODIFIER(InstanceOnly): { (*env)->DeleteGlobalRef(env, filter->u.InstanceOnly.instance); break; } case JDWP_REQUEST_MODIFIER(ClassOnly): { (*env)->DeleteGlobalRef(env, filter->u.ClassOnly.clazz); break; } case JDWP_REQUEST_MODIFIER(ClassMatch): { jdwpFree(filter->u.ClassMatch.classPattern); break; } case JDWP_REQUEST_MODIFIER(ClassExclude): { jdwpFree(filter->u.ClassExclude.classPattern); break; } case JDWP_REQUEST_MODIFIER(Step): { jthread thread = filter->u.Step.thread; error = stepControl_endStep(thread); if (error == JVMDI_ERROR_NONE) { (*env)->DeleteGlobalRef(env, thread); } break; } } } if (error == JVMDI_ERROR_NONE) { FILTER_COUNT(node) = 0; /* blast so we don't clear again */ } return error; }
int dbgsysExec(char *cmdLine) { int i; int argc; int pid = -1; /* this is the error return value */ char **argv = NULL; char *p; char *args; /* Skip leading whitespace */ cmdLine = skipWhitespace(cmdLine); args = jdwpAlloc(strlen(cmdLine)+1); if (args == NULL) { return SYS_NOMEM; } strcpy(args, cmdLine); p = args; argc = 0; while (*p != '\0') { p = skipNonWhitespace(p); argc++; if (*p == '\0') { break; } p = skipWhitespace(p); } argv = jdwpAlloc((argc + 1) * sizeof(char *)); if (argv == 0) { jdwpFree(args); return SYS_NOMEM; } for (i = 0, p = args; i < argc; i++) { argv[i] = p; p = skipNonWhitespace(p); *p++ = '\0'; p = skipWhitespace(p); } if ((pid = fork()) == 0) { /* Child process */ int i, max_fd; /* close everything */ max_fd = sysconf(_SC_OPEN_MAX); for (i = 3; i < max_fd; i++) { close(i); } execvp(argv[0], argv); exit(-1); } jdwpFree(args); jdwpFree(argv); if (pid < 0) { return SYS_ERR; } else { return SYS_OK; } }