/* * Read an object from the stream. The ID used in the wire protocol * is converted to a reference which is returned. The reference is * global and strong, but it should *not* be deleted by the caller * since it is freed when this stream is destroyed. */ jobject inStream_readObjectRef(PacketInputStream *stream) { jobject ref; jobject *refPtr; jlong id = inStream_readLong(stream); if (stream->error) { return NULL; } if (id == NULL_OBJECT_ID) { return NULL; } ref = commonRef_idToRef(id); if (ref == NULL) { stream->error = JDWP_ERROR(INVALID_OBJECT); return NULL; } refPtr = bagAdd(stream->refs); if (refPtr == NULL) { commonRef_idToRef_delete(NULL, ref); return NULL; } *refPtr = ref; return ref; }
void eventHelper_recordClassUnload(jint id, char *signature, struct bag *eventBag) { CommandSingle *command = bagAdd(eventBag); if (command == NULL) { EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"bagAdd(eventBag)"); } command->singleKind = COMMAND_SINGLE_UNLOAD; command->u.unloadCommand.id = id; command->u.unloadCommand.classSignature = signature; }
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_recordEvent(EventInfo *evinfo, jint id, jbyte suspendPolicy, struct bag *eventBag) { JNIEnv *env = getEnv(); CommandSingle *command = bagAdd(eventBag); if (command == NULL) { EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"badAdd(eventBag)"); } command->singleKind = COMMAND_SINGLE_EVENT; command->u.eventCommand.suspendPolicy = suspendPolicy; command->u.eventCommand.id = id; /* * Copy the event into the command so that it can be used * asynchronously by the event helper thread. */ (void)memcpy(&command->u.eventCommand.info, evinfo, sizeof(*evinfo)); saveEventInfoRefs(env, &command->u.eventCommand.info); }
/* * 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; }
jdwpError outStream_writeObjectRef(JNIEnv *env, PacketOutputStream *stream, jobject val) { jlong id; jlong *idPtr; if (stream->error) { return stream->error; } if (val == NULL) { id = NULL_OBJECT_ID; } else { /* Convert the object to an object id */ id = commonRef_refToID(env, val); if (id == NULL_OBJECT_ID) { stream->error = JDWP_ERROR(OUT_OF_MEMORY); return stream->error; } /* Track the common ref in case we need to release it on a future error */ idPtr = bagAdd(stream->ids); if (idPtr == NULL) { commonRef_release(env, id); stream->error = JDWP_ERROR(OUT_OF_MEMORY); return stream->error; } else { *idPtr = id; } /* Add the encoded object id to the stream */ id = HOST_TO_JAVA_LONG(id); } return writeBytes(stream, &id, sizeof(id)); }
static jboolean parseOptions(char *options) { TransportSpec *currentTransport = NULL; char *end; char *current; int length; char *str; char *errmsg; /* Set defaults */ gdata->assertOn = DEFAULT_ASSERT_ON; gdata->assertFatal = DEFAULT_ASSERT_FATAL; logfile = DEFAULT_LOGFILE; /* Options being NULL will end up being an error. */ if (options == NULL) { options = ""; } /* Check for "help" BEFORE we add any environmental settings */ if ((strcmp(options, "help")) == 0) { printUsage(); forceExit(0); /* Kill entire process, no core dump wanted */ } /* These buffers are never freed */ { char *envOptions; /* * Add environmentally specified options. */ envOptions = getenv("_JAVA_JDWP_OPTIONS"); if (envOptions != NULL) { options = add_to_options(options, envOptions); if ( options==NULL ) { EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options"); } } /* * Allocate a buffer for names derived from option strings. It should * never be longer than the original options string itself. * Also keep a copy of the options in gdata->options. */ length = (int)strlen(options); gdata->options = jvmtiAllocate(length + 1); if (gdata->options == NULL) { EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options"); } (void)strcpy(gdata->options, options); names = jvmtiAllocate(length + 1); if (names == NULL) { EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options"); } transports = bagCreateBag(sizeof(TransportSpec), 3); if (transports == NULL) { EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"transports"); } } current = names; end = names + length; str = options; while (*str) { char buf[100]; /*LINTED*/ if (!get_tok(&str, buf, (int)sizeof(buf), '=')) { goto syntax_error; } if (strcmp(buf, "transport") == 0) { currentTransport = bagAdd(transports); /*LINTED*/ if (!get_tok(&str, current, (int)(end - current), ',')) { goto syntax_error; } currentTransport->name = current; current += strlen(current) + 1; } else if (strcmp(buf, "address") == 0) { if (currentTransport == NULL) { errmsg = "address specified without transport"; goto bad_option_with_errmsg; } /*LINTED*/ if (!get_tok(&str, current, (int)(end - current), ',')) { goto syntax_error; } currentTransport->address = current; current += strlen(current) + 1; } else if (strcmp(buf, "timeout") == 0) { if (currentTransport == NULL) { errmsg = "timeout specified without transport"; goto bad_option_with_errmsg; } /*LINTED*/ if (!get_tok(&str, current, (int)(end - current), ',')) { goto syntax_error; } currentTransport->timeout = atol(current); current += strlen(current) + 1; } else if (strcmp(buf, "launch") == 0) { /*LINTED*/ if (!get_tok(&str, current, (int)(end - current), ',')) { goto syntax_error; } launchOnInit = current; current += strlen(current) + 1; } else if (strcmp(buf, "onthrow") == 0) { /* Read class name and convert in place to a signature */ *current = 'L'; /*LINTED*/ if (!get_tok(&str, current + 1, (int)(end - current - 1), ',')) { goto syntax_error; } initOnException = current; while (*current != '\0') { if (*current == '.') { *current = '/'; } current++; } *current++ = ';'; *current++ = '\0'; } else if (strcmp(buf, "assert") == 0) { /*LINTED*/ if (!get_tok(&str, current, (int)(end - current), ',')) { goto syntax_error; } if (strcmp(current, "y") == 0) { gdata->assertOn = JNI_TRUE; gdata->assertFatal = JNI_FALSE; } else if (strcmp(current, "fatal") == 0) { gdata->assertOn = JNI_TRUE; gdata->assertFatal = JNI_TRUE; } else if (strcmp(current, "n") == 0) { gdata->assertOn = JNI_FALSE; gdata->assertFatal = JNI_FALSE; } else { goto syntax_error; } current += strlen(current) + 1; } else if (strcmp(buf, "pause") == 0) { if ( !get_boolean(&str, &dopause) ) { goto syntax_error; } if ( dopause ) { do_pause(); } } else if (strcmp(buf, "coredump") == 0) { if ( !get_boolean(&str, &docoredump) ) { goto syntax_error; } } else if (strcmp(buf, "errorexit") == 0) { if ( !get_boolean(&str, &(gdata->doerrorexit)) ) { goto syntax_error; } } else if (strcmp(buf, "exitpause") == 0) { errmsg = "The exitpause option removed, use -XX:OnError"; goto bad_option_with_errmsg; } else if (strcmp(buf, "precrash") == 0) { errmsg = "The precrash option removed, use -XX:OnError"; goto bad_option_with_errmsg; } else if (strcmp(buf, "logfile") == 0) { /*LINTED*/ if (!get_tok(&str, current, (int)(end - current), ',')) { goto syntax_error; } logfile = current; current += strlen(current) + 1; } else if (strcmp(buf, "logflags") == 0) { /*LINTED*/ if (!get_tok(&str, current, (int)(end - current), ',')) { goto syntax_error; } /*LINTED*/ logflags = (unsigned)strtol(current, NULL, 0); } else if (strcmp(buf, "debugflags") == 0) { /*LINTED*/ if (!get_tok(&str, current, (int)(end - current), ',')) { goto syntax_error; } /*LINTED*/ gdata->debugflags = (unsigned)strtol(current, NULL, 0); } else if ( strcmp(buf, "suspend")==0 ) { if ( !get_boolean(&str, &suspendOnInit) ) { goto syntax_error; } } else if ( strcmp(buf, "server")==0 ) { if ( !get_boolean(&str, &isServer) ) { goto syntax_error; } } else if ( strcmp(buf, "strict")==0 ) { /* Obsolete, but accept it */ if ( !get_boolean(&str, &isStrict) ) { goto syntax_error; } } else if ( strcmp(buf, "quiet")==0 ) { if ( !get_boolean(&str, &(gdata->quiet)) ) { goto syntax_error; } } else if ( strcmp(buf, "onuncaught")==0 ) { if ( !get_boolean(&str, &initOnUncaught) ) { goto syntax_error; } } else if ( strcmp(buf, "mutf8")==0 ) { if ( !get_boolean(&str, &(gdata->modifiedUtf8)) ) { goto syntax_error; } } else if ( strcmp(buf, "stdalloc")==0 ) { /* Obsolete, but accept it */ if ( !get_boolean(&str, &useStandardAlloc) ) { goto syntax_error; } } else { goto syntax_error; } } /* Setup logging now */ if ( logfile!=NULL ) { setup_logging(logfile, logflags); (void)atexit(&atexit_finish_logging); } if (bagSize(transports) == 0) { errmsg = "no transport specified"; goto bad_option_with_errmsg; } /* * TO DO: Remove when multiple transports are allowed. (replace with * check below. */ if (bagSize(transports) > 1) { errmsg = "multiple transports are not supported in this release"; goto bad_option_with_errmsg; } if (!isServer) { jboolean specified = bagEnumerateOver(transports, checkAddress, NULL); if (!specified) { /* message already printed */ goto bad_option_no_msg; } } /* * The user has selected to wait for an exception before init happens */ if ((initOnException != NULL) || (initOnUncaught)) { initOnStartup = JNI_FALSE; if (launchOnInit == NULL) { /* * These rely on the launch=/usr/bin/foo * suboption, so it is an error if user did not * provide one. */ errmsg = "Specify launch=<command line> when using onthrow or onuncaught suboption"; goto bad_option_with_errmsg; } } return JNI_TRUE; syntax_error: ERROR_MESSAGE(("JDWP option syntax error: %s=%s", AGENTLIB, options)); return JNI_FALSE; bad_option_with_errmsg: ERROR_MESSAGE(("JDWP %s: %s=%s", errmsg, AGENTLIB, options)); return JNI_FALSE; bad_option_no_msg: ERROR_MESSAGE(("JDWP %s: %s=%s", "invalid option", AGENTLIB, options)); return JNI_FALSE; }