/* All JVM fatal error exits lead here (e.g. we need to kill the VM). */ static void jniFatalError(JNIEnv *env, const char *msg, jvmtiError error, int exit_code) { JavaVM *vm; char buf[512]; gdata->vmDead = JNI_TRUE; if ( msg==NULL ) msg = "UNKNOWN REASON"; vm = gdata->jvm; if ( env==NULL && vm!=NULL ) { jint rc = (*((*vm)->GetEnv))(vm, (void **)&env, JNI_VERSION_1_2); if (rc != JNI_OK ) { env = NULL; } } if ( error != JVMTI_ERROR_NONE ) { (void)snprintf(buf, sizeof(buf), "JDWP %s, jvmtiError=%s(%d)", msg, jvmtiErrorText(error), error); } else { (void)snprintf(buf, sizeof(buf), "JDWP %s", buf); } if (env != NULL) { (*((*env)->FatalError))(env, buf); } else { /* Should rarely ever reach here, means VM is really dead */ print_message(stderr, "ERROR: JDWP: ", "\n", "Can't call JNI FatalError(NULL, \"%s\")", buf); } forceExit(exit_code); }
static jvmtiError set_event_notification(jvmtiEventMode mode, EventIndex ei) { jvmtiError error; error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode) (gdata->jvmti, mode, eventIndex2jvmti(ei), NULL); if (error != JVMTI_ERROR_NONE) { ERROR_MESSAGE(("JDWP unable to configure initial JVMTI event %s: %s(%d)", eventText(ei), jvmtiErrorText(error), error)); } return error; }
/* All normal exit doors lead here */ void debugInit_exit(jvmtiError error, const char *msg) { enum exit_codes { EXIT_NO_ERRORS = 0, EXIT_JVMTI_ERROR = 1, EXIT_TRANSPORT_ERROR = 2 }; // Prepare to exit. Log error and finish logging LOG_MISC(("Exiting with error %s(%d): %s", jvmtiErrorText(error), error, ((msg == NULL) ? "" : msg))); // coredump requested by command line. Keep JVMTI data dirty if (error != JVMTI_ERROR_NONE && docoredump) { LOG_MISC(("Dumping core as requested by command line")); finish_logging(); abort(); } finish_logging(); // Cleanup the JVMTI if we have one if (gdata != NULL) { gdata->vmDead = JNI_TRUE; if (gdata->jvmti != NULL) { // Dispose of jvmti (gdata->jvmti becomes NULL) disposeEnvironment(gdata->jvmti); } } // We are here with no errors. Kill entire process and exit with zero exit code if (error == JVMTI_ERROR_NONE) { forceExit(EXIT_NO_ERRORS); return; } // No transport initilized. // As we don't have any details here exiting with separate exit code if (error == AGENT_ERROR_TRANSPORT_INIT) { forceExit(EXIT_TRANSPORT_ERROR); return; } // We have JVMTI error. Call hotspot jni_FatalError handler jniFatalError(NULL, msg, error, EXIT_JVMTI_ERROR); // hotspot calls os:abort() so we should never reach code below, // but guard against possible hotspot changes // Last chance to die, this kills the entire process. forceExit(EXIT_JVMTI_ERROR); }
static void disposeEnvironment(jvmtiEnv *jvmti_env) { jvmtiError error; error = JVMTI_FUNC_PTR(jvmti_env,DisposeEnvironment)(jvmti_env); if ( error == JVMTI_ERROR_MUST_POSSESS_CAPABILITY ) error = JVMTI_ERROR_NONE; /* Hack! FIXUP when JVMTI has disposeEnv */ /* What should error return say? */ if (error != JVMTI_ERROR_NONE) { ERROR_MESSAGE(("JDWP unable to dispose of JVMTI environment: %s(%d)", jvmtiErrorText(error), error)); } gdata->jvmti = NULL; }
/* All normal exit doors lead here */ void debugInit_exit(jvmtiError error, const char *msg) { int exit_code = 0; /* Pick an error code */ if ( error != JVMTI_ERROR_NONE ) { exit_code = 1; if ( docoredump ) { finish_logging(exit_code); abort(); } } if ( msg==NULL ) { msg = ""; } LOG_MISC(("Exiting with error %s(%d): %s", jvmtiErrorText(error), error, msg)); gdata->vmDead = JNI_TRUE; /* Let's try and cleanup the JVMTI, if we even have one */ if ( gdata->jvmti != NULL ) { /* Dispose of jvmti (gdata->jvmti becomes NULL) */ disposeEnvironment(gdata->jvmti); } /* Finish up logging. We reach here if JDWP is doing the exiting. */ finish_logging(exit_code); /* Only first call matters */ /* Let's give the JNI a FatalError if non-exit 0, which is historic way */ if ( exit_code != 0 ) { JNIEnv *env = NULL; jniFatalError(env, msg, error, exit_code); } /* Last chance to die, this kills the entire process. */ forceExit(exit_code); }
/* OnLoad startup: * Returning JNI_ERR will cause the java_g VM to core dump, be careful. */ JNIEXPORT jint JNICALL DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { jvmtiError error; jvmtiCapabilities needed_capabilities; jvmtiCapabilities potential_capabilities; jint jvmtiCompileTimeMajorVersion; jint jvmtiCompileTimeMinorVersion; jint jvmtiCompileTimeMicroVersion; /* See if it's already loaded */ if ( gdata!=NULL && gdata->isLoaded==JNI_TRUE ) { ERROR_MESSAGE(("Cannot load this JVM TI agent twice, check your java command line for duplicate jdwp options.")); return JNI_ERR; } /* If gdata is defined and the VM died, why are we here? */ if ( gdata!=NULL && gdata->vmDead ) { ERROR_MESSAGE(("JDWP unable to load, VM died")); return JNI_ERR; } /* Get global data area */ gdata = get_gdata(); if (gdata == NULL) { ERROR_MESSAGE(("JDWP unable to allocate memory")); return JNI_ERR; } gdata->isLoaded = JNI_TRUE; /* Start filling in gdata */ gdata->jvm = vm; vmInitialized = JNI_FALSE; gdata->vmDead = JNI_FALSE; /* Get the JVMTI Env, IMPORTANT: Do this first! For jvmtiAllocate(). */ error = JVM_FUNC_PTR(vm,GetEnv) (vm, (void **)&(gdata->jvmti), JVMTI_VERSION_1); if (error != JNI_OK) { ERROR_MESSAGE(("JDWP unable to access JVMTI Version 1 (0x%x)," " is your J2SE a 1.5 or newer version?" " JNIEnv's GetEnv() returned %d", JVMTI_VERSION_1, error)); forceExit(1); /* Kill entire process, no core dump */ } /* Check to make sure the version of jvmti.h we compiled with * matches the runtime version we are using. */ jvmtiCompileTimeMajorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MAJOR ) >> JVMTI_VERSION_SHIFT_MAJOR; jvmtiCompileTimeMinorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MINOR ) >> JVMTI_VERSION_SHIFT_MINOR; jvmtiCompileTimeMicroVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MICRO ) >> JVMTI_VERSION_SHIFT_MICRO; /* Check for compatibility */ if ( !compatible_versions(jvmtiMajorVersion(), jvmtiMinorVersion(), jvmtiCompileTimeMajorVersion, jvmtiCompileTimeMinorVersion) ) { ERROR_MESSAGE(("This jdwp native library will not work with this VM's " "version of JVMTI (%d.%d.%d), it needs JVMTI %d.%d[.%d].", jvmtiMajorVersion(), jvmtiMinorVersion(), jvmtiMicroVersion(), jvmtiCompileTimeMajorVersion, jvmtiCompileTimeMinorVersion, jvmtiCompileTimeMicroVersion)); /* Do not let VM get a fatal error, we don't want a core dump here. */ forceExit(1); /* Kill entire process, no core dump wanted */ } /* Parse input options */ if (!parseOptions(options)) { /* No message necessary, should have been printed out already */ /* Do not let VM get a fatal error, we don't want a core dump here. */ forceExit(1); /* Kill entire process, no core dump wanted */ } LOG_MISC(("Onload: %s", options)); /* Get potential capabilities */ (void)memset(&potential_capabilities,0,sizeof(potential_capabilities)); error = JVMTI_FUNC_PTR(gdata->jvmti,GetPotentialCapabilities) (gdata->jvmti, &potential_capabilities); if (error != JVMTI_ERROR_NONE) { ERROR_MESSAGE(("JDWP unable to get potential JVMTI capabilities: %s(%d)", jvmtiErrorText(error), error)); return JNI_ERR; } /* Fill in ones that we must have */ (void)memset(&needed_capabilities,0,sizeof(needed_capabilities)); needed_capabilities.can_access_local_variables = 1; needed_capabilities.can_generate_single_step_events = 1; needed_capabilities.can_generate_exception_events = 1; needed_capabilities.can_generate_frame_pop_events = 1; needed_capabilities.can_generate_breakpoint_events = 1; needed_capabilities.can_suspend = 1; needed_capabilities.can_generate_method_entry_events = 1; needed_capabilities.can_generate_method_exit_events = 1; needed_capabilities.can_generate_garbage_collection_events = 1; needed_capabilities.can_maintain_original_method_order = 1; needed_capabilities.can_generate_monitor_events = 1; needed_capabilities.can_tag_objects = 1; /* And what potential ones that would be nice to have */ needed_capabilities.can_force_early_return = potential_capabilities.can_force_early_return; needed_capabilities.can_generate_field_modification_events = potential_capabilities.can_generate_field_modification_events; needed_capabilities.can_generate_field_access_events = potential_capabilities.can_generate_field_access_events; needed_capabilities.can_get_bytecodes = potential_capabilities.can_get_bytecodes; needed_capabilities.can_get_synthetic_attribute = potential_capabilities.can_get_synthetic_attribute; needed_capabilities.can_get_owned_monitor_info = potential_capabilities.can_get_owned_monitor_info; needed_capabilities.can_get_current_contended_monitor = potential_capabilities.can_get_current_contended_monitor; needed_capabilities.can_get_monitor_info = potential_capabilities.can_get_monitor_info; needed_capabilities.can_pop_frame = potential_capabilities.can_pop_frame; needed_capabilities.can_redefine_classes = potential_capabilities.can_redefine_classes; needed_capabilities.can_redefine_any_class = potential_capabilities.can_redefine_any_class; needed_capabilities.can_get_owned_monitor_stack_depth_info = potential_capabilities.can_get_owned_monitor_stack_depth_info; needed_capabilities.can_get_constant_pool = potential_capabilities.can_get_constant_pool; { needed_capabilities.can_get_source_debug_extension = 1; needed_capabilities.can_get_source_file_name = 1; needed_capabilities.can_get_line_numbers = 1; needed_capabilities.can_signal_thread = potential_capabilities.can_signal_thread; } /* Add the capabilities */ error = JVMTI_FUNC_PTR(gdata->jvmti,AddCapabilities) (gdata->jvmti, &needed_capabilities); if (error != JVMTI_ERROR_NONE) { ERROR_MESSAGE(("JDWP unable to get necessary JVMTI capabilities.")); forceExit(1); /* Kill entire process, no core dump wanted */ } /* Initialize event number mapping tables */ eventIndexInit(); /* Set the initial JVMTI event notifications */ error = set_event_notification(JVMTI_ENABLE, EI_VM_DEATH); if (error != JVMTI_ERROR_NONE) { return JNI_ERR; } error = set_event_notification(JVMTI_ENABLE, EI_VM_INIT); if (error != JVMTI_ERROR_NONE) { return JNI_ERR; } if (initOnUncaught || (initOnException != NULL)) { error = set_event_notification(JVMTI_ENABLE, EI_EXCEPTION); if (error != JVMTI_ERROR_NONE) { return JNI_ERR; } } /* Set callbacks just for 3 functions */ (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks)); gdata->callbacks.VMInit = &cbEarlyVMInit; gdata->callbacks.VMDeath = &cbEarlyVMDeath; gdata->callbacks.Exception = &cbEarlyException; error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks) (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks)); if (error != JVMTI_ERROR_NONE) { ERROR_MESSAGE(("JDWP unable to set JVMTI event callbacks: %s(%d)", jvmtiErrorText(error), error)); return JNI_ERR; } LOG_MISC(("OnLoad: DONE")); return JNI_OK; }