/* * Print the last transport error */ static void printLastError(jdwpTransportEnv *t, jdwpTransportError err) { char *msg; jbyte *utf8msg; jdwpTransportError rv; msg = NULL; utf8msg = NULL; rv = (*t)->GetLastError(t, &msg); /* This is a platform encoded string */ if ( msg != NULL ) { int len; int maxlen; /* Convert this string to UTF8 */ len = (int)strlen(msg); maxlen = len+len/2+2; /* Should allow for plenty of room */ utf8msg = (jbyte*)jvmtiAllocate(maxlen+1); (void)(gdata->npt->utf8FromPlatform)(gdata->npt->utf, msg, len, utf8msg, maxlen); utf8msg[maxlen] = 0; } if (rv == JDWPTRANSPORT_ERROR_NONE) { ERROR_MESSAGE(("transport error %d: %s",err, utf8msg)); } else if ( msg!=NULL ) { ERROR_MESSAGE(("transport error %d: %s",err, utf8msg)); } else { ERROR_MESSAGE(("transport error %d: %s",err, "UNKNOWN")); } jvmtiDeallocate(msg); jvmtiDeallocate(utf8msg); }
void bagDestroyBag(struct bag *theBag) { if (theBag != NULL) { jvmtiDeallocate(theBag->items); jvmtiDeallocate(theBag); } }
/** * Free up global refs held by the filter. * free things up at the JNI level if needed. */ static jvmtiError clearFilters(HandlerNode *node) { JNIEnv *env = getEnv(); jint i; jvmtiError error = JVMTI_ERROR_NONE; Filter *filter = FILTERS_ARRAY(node); for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { switch (filter->modifier) { case JDWP_REQUEST_MODIFIER(ThreadOnly): if ( filter->u.ThreadOnly.thread != NULL ) { tossGlobalRef(env, &(filter->u.ThreadOnly.thread)); } break; case JDWP_REQUEST_MODIFIER(LocationOnly): tossGlobalRef(env, &(filter->u.LocationOnly.clazz)); break; case JDWP_REQUEST_MODIFIER(FieldOnly): tossGlobalRef(env, &(filter->u.FieldOnly.clazz)); break; case JDWP_REQUEST_MODIFIER(ExceptionOnly): if ( filter->u.ExceptionOnly.exception != NULL ) { tossGlobalRef(env, &(filter->u.ExceptionOnly.exception)); } break; case JDWP_REQUEST_MODIFIER(InstanceOnly): if ( filter->u.InstanceOnly.instance != NULL ) { tossGlobalRef(env, &(filter->u.InstanceOnly.instance)); } break; case JDWP_REQUEST_MODIFIER(ClassOnly): tossGlobalRef(env, &(filter->u.ClassOnly.clazz)); break; case JDWP_REQUEST_MODIFIER(ClassMatch): jvmtiDeallocate(filter->u.ClassMatch.classPattern); break; case JDWP_REQUEST_MODIFIER(ClassExclude): jvmtiDeallocate(filter->u.ClassExclude.classPattern); break; case JDWP_REQUEST_MODIFIER(Step): { jthread thread = filter->u.Step.thread; error = stepControl_endStep(thread); if (error == JVMTI_ERROR_NONE) { tossGlobalRef(env, &(filter->u.Step.thread)); } break; } } } if (error == JVMTI_ERROR_NONE) { FILTER_COUNT(node) = 0; /* blast so we don't clear again */ } return error; }
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; }
void * bagAdd(struct bag *theBag) { int allocated = theBag->allocated; int itemSize = theBag->itemSize; void *items = theBag->items; void *ret; /* if there are no unused slots reallocate */ if (theBag->used >= allocated) { void *new_items; allocated *= 2; new_items = jvmtiAllocate(allocated * itemSize); if (new_items == NULL) { return NULL; } (void)memcpy(new_items, items, (theBag->used) * itemSize); jvmtiDeallocate(items); items = new_items; theBag->allocated = allocated; theBag->items = items; } ret = ((char *)items) + (itemSize * (theBag->used)++); (void)memset(ret, 0, itemSize); return ret; }
/* Reset the commonRefs usage */ void commonRef_reset(JNIEnv *env) { debugMonitorEnter(gdata->refLock); { int i; for (i = 0; i < gdata->objectsByIDsize; i++) { RefNode *node; node = gdata->objectsByID[i]; while (node != NULL) { RefNode *next; next = node->next; deleteNode(env, node); node = next; } gdata->objectsByID[i] = NULL; } /* Toss entire hash table and re-create a new one */ jvmtiDeallocate(gdata->objectsByID); gdata->objectsByID = NULL; gdata->nextSeqNum = 1; /* 0 used for error indication */ initializeObjectsByID(HASH_INIT_SIZE); } debugMonitorExit(gdata->refLock); }
static void freeCommand(HelperCommand *command) { if ( command == NULL ) return; jvmtiDeallocate(command); }
char * inStream_readString(PacketInputStream *stream) { int length; char *string; length = inStream_readInt(stream); string = jvmtiAllocate(length + 1); if (string != NULL) { int new_length; (void)readBytes(stream, string, length); string[length] = '\0'; /* This is Standard UTF-8, convert to Modified UTF-8 if necessary */ new_length = (gdata->npt->utf8sToUtf8mLength) (gdata->npt->utf, (jbyte*)string, length); if ( new_length != length ) { char *new_string; new_string = jvmtiAllocate(new_length+1); (gdata->npt->utf8sToUtf8m) (gdata->npt->utf, (jbyte*)string, length, (jbyte*)new_string, new_length); jvmtiDeallocate(string); return new_string; } } return string; }
void outStream_destroy(PacketOutputStream *stream) { struct PacketData *next; if (stream->error || !stream->sent) { (void)bagEnumerateOver(stream->ids, releaseID, NULL); } next = stream->firstSegment.next; while (next != NULL) { struct PacketData *p = next; next = p->next; jvmtiDeallocate(p->data); jvmtiDeallocate(p); } bagDestroyBag(stream->ids); }
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 inStream_destroy(PacketInputStream *stream) { if (stream->packet.type.cmd.data != NULL) { jvmtiDeallocate(stream->packet.type.cmd.data); } (void)bagEnumerateOver(stream->refs, deleteRef, (void *)getEnv()); bagDestroyBag(stream->refs); }
static void deleteNode(JNIEnv *env, RefNode *node) { LOG_MISC(("Freeing %d (%x)\n", (int)node->seqNum, node->ref)); if (node->isStrong) { JNI_FUNC_PTR(env,DeleteGlobalRef)(env, node->ref); } else { JNI_FUNC_PTR(env,DeleteWeakGlobalRef)(env, node->ref); } jvmtiDeallocate(node); }
static jdwpError launch(char *command, char *name, char *address) { jint rc; char *buf; char *commandLine; int len; /* Construct complete command line (all in UTF-8) */ commandLine = jvmtiAllocate((int)strlen(command) + (int)strlen(name) + (int)strlen(address) + 3); if (commandLine == NULL) { return JDWP_ERROR(OUT_OF_MEMORY); } (void)strcpy(commandLine, command); (void)strcat(commandLine, " "); (void)strcat(commandLine, name); (void)strcat(commandLine, " "); (void)strcat(commandLine, address); /* Convert commandLine from UTF-8 to platform encoding */ len = (int)strlen(commandLine); buf = jvmtiAllocate(len*3+3); (void)(gdata->npt->utf8ToPlatform)(gdata->npt->utf, (jbyte*)commandLine, len, buf, len*3+3); /* Exec commandLine */ rc = dbgsysExec(buf); /* Free up buffers */ jvmtiDeallocate(buf); jvmtiDeallocate(commandLine); /* And non-zero exit status means we had an error */ if (rc != SYS_OK) { return JDWP_ERROR(TRANSPORT_INIT); } return JDWP_ERROR(NONE); }
/* Create a fresh RefNode structure, create a weak ref and tag the object */ static RefNode * createNode(JNIEnv *env, jobject ref) { RefNode *node; jobject weakRef; jvmtiError error; /* Could allocate RefNode's in blocks, not sure it would help much */ node = (RefNode*)jvmtiAllocate((int)sizeof(RefNode)); if (node == NULL) { return NULL; } /* Create weak reference to make sure we have a reference */ weakRef = JNI_FUNC_PTR(env,NewWeakGlobalRef)(env, ref); if (weakRef == NULL) { jvmtiDeallocate(node); return NULL; } /* Set tag on weakRef */ error = JVMTI_FUNC_PTR(gdata->jvmti, SetTag) (gdata->jvmti, weakRef, ptr_to_jlong(node)); if ( error != JVMTI_ERROR_NONE ) { JNI_FUNC_PTR(env,DeleteWeakGlobalRef)(env, weakRef); jvmtiDeallocate(node); return NULL; } /* Fill in RefNode */ node->ref = weakRef; node->isStrong = JNI_FALSE; node->count = 1; node->seqNum = newSeqNum(); /* Count RefNode's created */ gdata->objectsByIDcount++; return node; }
static jdwpError 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 = SMALLEST(2 * stream->segment->length, MAX_SEGMENT_SIZE); jbyte *newSeg = jvmtiAllocate(segSize); struct PacketData *newHeader = jvmtiAllocate(sizeof(*newHeader)); if ((newSeg == NULL) || (newHeader == NULL)) { jvmtiDeallocate(newSeg); jvmtiDeallocate(newHeader); stream->error = JDWP_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 = SMALLEST(size, stream->left); (void)memcpy(stream->current, bytes, count); stream->current += count; stream->left -= count; stream->segment->length += count; size -= count; bytes += count; } return JDWP_ERROR(NONE); }
static jint outStream_send(PacketOutputStream *stream) { jint rc; jint len = 0; PacketData *segment; jbyte *data, *posP; /* * If there's only 1 segment then we just send the * packet. */ if (stream->firstSegment.next == NULL) { stream->packet.type.cmd.len = 11 + stream->firstSegment.length; stream->packet.type.cmd.data = stream->firstSegment.data; rc = transport_sendPacket(&stream->packet); return rc; } /* * Multiple segments */ len = 0; segment = (PacketData *)&(stream->firstSegment); do { len += segment->length; segment = segment->next; } while (segment != NULL); data = jvmtiAllocate(len); if (data == NULL) { return JDWP_ERROR(OUT_OF_MEMORY); } posP = data; segment = (PacketData *)&(stream->firstSegment); while (segment != NULL) { (void)memcpy(posP, segment->data, segment->length); posP += segment->length; segment = segment->next; } stream->packet.type.cmd.len = 11 + len; stream->packet.type.cmd.data = data; rc = transport_sendPacket(&stream->packet); stream->packet.type.cmd.data = NULL; jvmtiDeallocate(data); return rc; }
/* Allocate and add RefNode to hash table */ static RefNode * newCommonRef(JNIEnv *env, jobject ref) { RefNode *node; /* Allocate the node and set it up */ node = createNode(env, ref); if ( node == NULL ) { return NULL; } /* See if hash table needs expansion */ if ( gdata->objectsByIDcount > gdata->objectsByIDsize*HASH_EXPAND_SCALE && gdata->objectsByIDsize < HASH_MAX_SIZE ) { RefNode **old; int oldsize; int newsize; int i; /* Save old information */ old = gdata->objectsByID; oldsize = gdata->objectsByIDsize; /* Allocate new hash table */ gdata->objectsByID = NULL; newsize = oldsize*HASH_EXPAND_SCALE; if ( newsize > HASH_MAX_SIZE ) newsize = HASH_MAX_SIZE; initializeObjectsByID(newsize); /* Walk over old one and hash in all the RefNodes */ for ( i = 0 ; i < oldsize ; i++ ) { RefNode *onode; onode = old[i]; while (onode != NULL) { RefNode *next; next = onode->next; hashIn(onode); onode = next; } } jvmtiDeallocate(old); } /* Add to id hashtable */ hashIn(node); return node; }
struct bag * bagCreateBag(int itemSize, int initialAllocation) { struct bag *theBag = (struct bag *)jvmtiAllocate(sizeof(struct bag)); if (theBag == NULL) { return NULL; } itemSize = (itemSize + 7) & ~7; /* fit 8 byte boundary */ theBag->items = jvmtiAllocate(initialAllocation * itemSize); if (theBag->items == NULL) { jvmtiDeallocate(theBag); return NULL; } theBag->used = 0; theBag->allocated = initialAllocation; theBag->itemSize = itemSize; return theBag; }
/* Delete a RefNode allocation, delete weak/global ref and clear tag */ static void deleteNode(JNIEnv *env, RefNode *node) { LOG_MISC(("Freeing %d (%x)\n", (int)node->seqNum, node->ref)); if ( node->ref != NULL ) { /* Clear tag */ (void)JVMTI_FUNC_PTR(gdata->jvmti,SetTag) (gdata->jvmti, node->ref, NULL_OBJECT_ID); if (node->isStrong) { JNI_FUNC_PTR(env,DeleteGlobalRef)(env, node->ref); } else { JNI_FUNC_PTR(env,DeleteWeakGlobalRef)(env, node->ref); } } gdata->objectsByIDcount--; jvmtiDeallocate(node); }
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 jboolean dequeue(jdwpPacket *packet) { struct PacketList *node = NULL; debugMonitorEnter(cmdQueueLock); while (!transportError && (cmdQueue == NULL)) { debugMonitorWait(cmdQueueLock); } if (cmdQueue != NULL) { node = (struct PacketList *)cmdQueue; cmdQueue = node->next; } debugMonitorExit(cmdQueueLock); if (node != NULL) { *packet = node->packet; jvmtiDeallocate(node); } return (node != NULL); }
static void deleteComponents(void *ptr) { jvmtiDeallocate(ptr); }
/* * Determine if this event is interesting to this handler. * Do so by checking each of the handler's filters. * Return false if any of the filters fail, * true if the handler wants this event. * Anyone modifying this function should check * eventFilterRestricted_passesUnloadFilter and * eventFilter_predictFiltering as well. * * If shouldDelete is returned true, a count filter has expired * and the corresponding node should be deleted. */ jboolean eventFilterRestricted_passesFilter(JNIEnv *env, char *classname, EventInfo *evinfo, HandlerNode *node, jboolean *shouldDelete) { jthread thread; jclass clazz; jmethodID method; Filter *filter = FILTERS_ARRAY(node); int i; *shouldDelete = JNI_FALSE; thread = evinfo->thread; clazz = evinfo->clazz; method = evinfo->method; /* * Suppress most events if they happen in debug threads */ if ((evinfo->ei != EI_CLASS_PREPARE) && (evinfo->ei != EI_GC_FINISH) && (evinfo->ei != EI_CLASS_LOAD) && threadControl_isDebugThread(thread)) { return JNI_FALSE; } for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { switch (filter->modifier) { case JDWP_REQUEST_MODIFIER(ThreadOnly): if (!isSameObject(env, thread, filter->u.ThreadOnly.thread)) { return JNI_FALSE; } break; case JDWP_REQUEST_MODIFIER(ClassOnly): /* Class filters catch events in the specified * class and any subclass/subinterface. */ if (!JNI_FUNC_PTR(env,IsAssignableFrom)(env, clazz, filter->u.ClassOnly.clazz)) { return JNI_FALSE; } break; /* This is kinda cheating assumming the event * fields will be in the same locations, but it is * true now. */ case JDWP_REQUEST_MODIFIER(LocationOnly): if (evinfo->method != filter->u.LocationOnly.method || evinfo->location != filter->u.LocationOnly.location || !isSameObject(env, clazz, filter->u.LocationOnly.clazz)) { return JNI_FALSE; } break; case JDWP_REQUEST_MODIFIER(FieldOnly): /* Field watchpoints can be triggered from the * declared class or any subclass/subinterface. */ if ((evinfo->u.field_access.field != filter->u.FieldOnly.field) || !isSameObject(env, evinfo->u.field_access.field_clazz, filter->u.FieldOnly.clazz)) { return JNI_FALSE; } break; case JDWP_REQUEST_MODIFIER(ExceptionOnly): /* do we want caught/uncaught exceptions */ if (!((evinfo->u.exception.catch_clazz == NULL)? filter->u.ExceptionOnly.uncaught : filter->u.ExceptionOnly.caught)) { return JNI_FALSE; } /* do we care about exception class */ if (filter->u.ExceptionOnly.exception != NULL) { jclass exception = evinfo->object; /* do we want this exception class */ if (!JNI_FUNC_PTR(env,IsInstanceOf)(env, exception, filter->u.ExceptionOnly.exception)) { return JNI_FALSE; } } break; case JDWP_REQUEST_MODIFIER(InstanceOnly): { jobject eventInst = eventInstance(evinfo); jobject filterInst = filter->u.InstanceOnly.instance; /* if no error and doesn't match, don't pass * filter */ if (eventInst != NULL && !isSameObject(env, eventInst, filterInst)) { return JNI_FALSE; } break; } case JDWP_REQUEST_MODIFIER(Count): { JDI_ASSERT(filter->u.Count.count > 0); if (--filter->u.Count.count > 0) { return JNI_FALSE; } *shouldDelete = JNI_TRUE; break; } case JDWP_REQUEST_MODIFIER(Conditional): /*** if (... filter->u.Conditional.exprID ...) { return JNI_FALSE; } ***/ break; case JDWP_REQUEST_MODIFIER(ClassMatch): { if (!patternStringMatch(classname, filter->u.ClassMatch.classPattern)) { return JNI_FALSE; } break; } case JDWP_REQUEST_MODIFIER(ClassExclude): { if (patternStringMatch(classname, filter->u.ClassExclude.classPattern)) { return JNI_FALSE; } break; } case JDWP_REQUEST_MODIFIER(Step): if (!isSameObject(env, thread, filter->u.Step.thread)) { return JNI_FALSE; } if (!stepControl_handleStep(env, thread, clazz, method)) { return JNI_FALSE; } break; case JDWP_REQUEST_MODIFIER(SourceNameMatch): { char* desiredNamePattern = filter->u.SourceNameOnly.sourceNamePattern; if (!searchAllSourceNames(env, clazz, desiredNamePattern) == 1) { /* The name isn't in the SDE; try the sourceName in the ref * type */ char *sourceName = 0; jvmtiError error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName) (gdata->jvmti, clazz, &sourceName); if (error == JVMTI_ERROR_NONE && sourceName != 0 && patternStringMatch(sourceName, desiredNamePattern)) { // got a hit - report the event jvmtiDeallocate(sourceName); break; } // We have no match, we have no source file name, // or we got a JVM TI error. Don't report the event. jvmtiDeallocate(sourceName); return JNI_FALSE; } break; } default: EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"Invalid filter modifier"); return JNI_FALSE; } } return JNI_TRUE; }
int dbgsysExec(char *cmdLine) { int i; int argc; pid_t pid_err = (pid_t)(-1); /* this is the error return value */ pid_t pid; char **argv = NULL; char *p; char *args; /* Skip leading whitespace */ cmdLine = skipWhitespace(cmdLine); /*LINTED*/ args = jvmtiAllocate((jint)strlen(cmdLine)+1); if (args == NULL) { return SYS_NOMEM; } (void)strcpy(args, cmdLine); p = args; argc = 0; while (*p != '\0') { p = skipNonWhitespace(p); argc++; if (*p == '\0') { break; } p = skipWhitespace(p); } /*LINTED*/ argv = jvmtiAllocate((argc + 1) * (jint)sizeof(char *)); if (argv == 0) { jvmtiDeallocate(args); return SYS_NOMEM; } for (i = 0, p = args; i < argc; i++) { argv[i] = p; p = skipNonWhitespace(p); *p++ = '\0'; p = skipWhitespace(p); } argv[i] = NULL; /* NULL terminate */ if ((pid = FORK()) == 0) { /* Child process */ int i; long max_fd; /* close everything */ max_fd = sysconf(_SC_OPEN_MAX); /*LINTED*/ for (i = 3; i < (int)max_fd; i++) { (void)close(i); } (void)execvp(argv[0], argv); exit(-1); } jvmtiDeallocate(args); jvmtiDeallocate(argv); if (pid == pid_err) { return SYS_ERR; } else { return SYS_OK; } }
jdwpError transport_startTransport(jboolean isServer, char *name, char *address, long timeout) { jvmtiStartFunction func; jdwpTransportEnv *trans; char threadName[MAXPATHLEN + 100]; jint err; jdwpError serror; /* * If the transport is already loaded then use it * Note: We're assuming here that we don't support multiple * transports - when we do then we need to handle the case * where the transport library only supports a single environment. * That probably means we have a bag a transport environments * to correspond to the transports bag. */ if (transport != NULL) { trans = transport; } else { serror = loadTransport(name, &trans); if (serror != JDWP_ERROR(NONE)) { return serror; } } if (isServer) { char *retAddress; char *launchCommand; TransportInfo *info; jvmtiError error; int len; char* prop_value; info = jvmtiAllocate(sizeof(*info)); if (info == NULL) { return JDWP_ERROR(OUT_OF_MEMORY); } info->name = jvmtiAllocate((int)strlen(name)+1); (void)strcpy(info->name, name); info->address = NULL; info->timeout = timeout; if (info->name == NULL) { serror = JDWP_ERROR(OUT_OF_MEMORY); goto handleError; } if (address != NULL) { info->address = jvmtiAllocate((int)strlen(address)+1); (void)strcpy(info->address, address); if (info->address == NULL) { serror = JDWP_ERROR(OUT_OF_MEMORY); goto handleError; } } info->transport = trans; err = (*trans)->StartListening(trans, address, &retAddress); if (err != JDWPTRANSPORT_ERROR_NONE) { printLastError(trans, err); serror = JDWP_ERROR(TRANSPORT_INIT); goto handleError; } /* * Record listener address in a system property */ len = (int)strlen(name) + (int)strlen(retAddress) + 2; /* ':' and '\0' */ prop_value = (char*)jvmtiAllocate(len); strcpy(prop_value, name); strcat(prop_value, ":"); strcat(prop_value, retAddress); setTransportProperty(getEnv(), prop_value); jvmtiDeallocate(prop_value); (void)strcpy(threadName, "JDWP Transport Listener: "); (void)strcat(threadName, name); func = &acceptThread; error = spawnNewThread(func, (void*)info, threadName); if (error != JVMTI_ERROR_NONE) { serror = map2jdwpError(error); goto handleError; } launchCommand = debugInit_launchOnInit(); if (launchCommand != NULL) { serror = launch(launchCommand, name, retAddress); if (serror != JDWP_ERROR(NONE)) { goto handleError; } } else { if ( ! gdata->quiet ) { TTY_MESSAGE(("Listening for transport %s at address: %s", name, retAddress)); } } return JDWP_ERROR(NONE); handleError: jvmtiDeallocate(info->name); jvmtiDeallocate(info->address); jvmtiDeallocate(info); } else { /* * Note that we don't attempt to do a launch here. Launching * is currently supported only in server mode. */ /* * If we're connecting to another process, there shouldn't be * any concurrent listens, so its ok if we block here in this * thread, waiting for the attach to finish. */ err = (*trans)->Attach(trans, address, timeout, 0); if (err != JDWPTRANSPORT_ERROR_NONE) { printLastError(trans, err); serror = JDWP_ERROR(TRANSPORT_INIT); return serror; } /* * Start the transport loop in a separate thread */ (void)strcpy(threadName, "JDWP Transport Listener: "); (void)strcat(threadName, name); func = &attachThread; err = spawnNewThread(func, (void*)trans, threadName); serror = map2jdwpError(err); } return serror; }
/* * Determine the component class by looking thru all classes for * one that has the signature of the component and the same class loadeer * as the array. See JVM spec 5.3.3: * If the component type is a reference type, C is marked as having * been defined by the defining class loader of the component type. */ static jdwpError getComponentClass(JNIEnv *env, jclass arrayClass, char *componentSignature, jclass *componentClassPtr) { jobject arrayClassLoader; jclass *classes; jint count; jclass componentClass = NULL; jdwpError serror; jvmtiError error; serror = JDWP_ERROR(NONE); error = classLoader(arrayClass, &arrayClassLoader); if (error != JVMTI_ERROR_NONE) { return map2jdwpError(error); } error = allLoadedClasses(&classes, &count); if (error != JVMTI_ERROR_NONE) { serror = map2jdwpError(error); } else { int i; for (i = 0; (i < count) && (componentClass == NULL); i++) { char *signature = NULL; jclass clazz = classes[i]; jboolean match; jvmtiError error; /* signature must match */ error = classSignature(clazz, &signature, NULL); if (error != JVMTI_ERROR_NONE) { serror = map2jdwpError(error); break; } match = strcmp(signature, componentSignature) == 0; jvmtiDeallocate(signature); /* if signature matches, get class loader to check if * it matches */ if (match) { jobject loader; error = classLoader(clazz, &loader); if (error != JVMTI_ERROR_NONE) { return map2jdwpError(error); } match = isSameObject(env, loader, arrayClassLoader); } if (match) { componentClass = clazz; } } jvmtiDeallocate(classes); *componentClassPtr = componentClass; } if (serror == JDWP_ERROR(NONE) && componentClass == NULL) { /* per JVM spec, component class is always loaded * before array class, so this should never occur. */ serror = JDWP_ERROR(NOT_FOUND); } return serror; }
static void JNICALL cbEarlyException(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread, jmethodID method, jlocation location, jobject exception, jmethodID catch_method, jlocation catch_location) { jvmtiError error; jthrowable currentException; LOG_CB(("cbEarlyException: thread=%p", thread)); if ( gdata->vmDead ) { EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at initial Exception event"); } if (!vmInitialized) { LOG_MISC(("VM is not initialized yet")); return; } /* * We want to preserve any current exception that might get wiped * out during event handling (e.g. JNI calls). We have to rely on * space for the local reference on the current frame because * doing a PushLocalFrame here might itself generate an exception. */ currentException = JNI_FUNC_PTR(env,ExceptionOccurred)(env); JNI_FUNC_PTR(env,ExceptionClear)(env); if (initOnUncaught && catch_method == NULL) { LOG_MISC(("Initializing on uncaught exception")); initialize(env, thread, EI_EXCEPTION); } else if (initOnException != NULL) { jclass clazz; /* Get class of exception thrown */ clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, exception); if ( clazz != NULL ) { char *signature = NULL; /* initing on throw, check */ error = classSignature(clazz, &signature, NULL); LOG_MISC(("Checking specific exception: looking for %s, got %s", initOnException, signature)); if ( (error==JVMTI_ERROR_NONE) && (strcmp(signature, initOnException) == 0)) { LOG_MISC(("Initializing on specific exception")); initialize(env, thread, EI_EXCEPTION); } else { error = AGENT_ERROR_INTERNAL; /* Just to cause restore */ } if ( signature != NULL ) { jvmtiDeallocate(signature); } } else { error = AGENT_ERROR_INTERNAL; /* Just to cause restore */ } /* If initialize didn't happen, we need to restore things */ if ( error != JVMTI_ERROR_NONE ) { /* * Restore exception state from before callback call */ LOG_MISC(("No initialization, didn't find right exception")); if (currentException != NULL) { JNI_FUNC_PTR(env,Throw)(env, currentException); } else { JNI_FUNC_PTR(env,ExceptionClear)(env); } } } LOG_MISC(("END cbEarlyException")); }