1/* 2 * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26#include <ctype.h> 27 28#include "util.h" 29#include "commonRef.h" 30#include "debugDispatch.h" 31#include "eventHandler.h" 32#include "eventHelper.h" 33#include "threadControl.h" 34#include "stepControl.h" 35#include "transport.h" 36#include "classTrack.h" 37#include "debugLoop.h" 38#include "bag.h" 39#include "invoker.h" 40#include "sys.h" 41 42/* How the options get to OnLoad: */ 43#define XDEBUG "-Xdebug" 44#define XRUN "-Xrunjdwp" 45#define AGENTLIB "-agentlib:jdwp" 46 47/* Debug version defaults */ 48#ifdef DEBUG 49 #define DEFAULT_ASSERT_ON JNI_TRUE 50 #define DEFAULT_ASSERT_FATAL JNI_TRUE 51 #define DEFAULT_LOGFILE "jdwp.log" 52#else 53 #define DEFAULT_ASSERT_ON JNI_FALSE 54 #define DEFAULT_ASSERT_FATAL JNI_FALSE 55 #define DEFAULT_LOGFILE NULL 56#endif 57 58static jboolean vmInitialized; 59static jrawMonitorID initMonitor; 60static jboolean initComplete; 61static jbyte currentSessionID; 62 63/* 64 * Options set through the OnLoad options string. All of these values 65 * are set once at VM startup and never reset. 66 */ 67static jboolean isServer = JNI_FALSE; /* Listens for connecting debuggers? */ 68static jboolean isStrict = JNI_FALSE; /* Unused */ 69static jboolean useStandardAlloc = JNI_FALSE; /* Use standard malloc/free? */ 70static struct bag *transports; /* of TransportSpec */ 71 72static jboolean initOnStartup = JNI_TRUE; /* init immediately */ 73static char *initOnException = NULL; /* init when this exception thrown */ 74static jboolean initOnUncaught = JNI_FALSE; /* init when uncaught exc thrown */ 75 76static char *launchOnInit = NULL; /* launch this app during init */ 77static jboolean suspendOnInit = JNI_TRUE; /* suspend all app threads after init */ 78static jboolean dopause = JNI_FALSE; /* pause for debugger attach */ 79static jboolean docoredump = JNI_FALSE; /* core dump on exit */ 80static char *logfile = NULL; /* Name of logfile (if logging) */ 81static unsigned logflags = 0; /* Log flags */ 82 83static char *names; /* strings derived from OnLoad options */ 84 85/* 86 * Elements of the transports bag 87 */ 88typedef struct TransportSpec { 89 char *name; 90 char *address; 91 long timeout; 92 char *allow; 93} TransportSpec; 94 95/* 96 * Forward Refs 97 */ 98static void JNICALL cbEarlyVMInit(jvmtiEnv*, JNIEnv *, jthread); 99static void JNICALL cbEarlyVMDeath(jvmtiEnv*, JNIEnv *); 100static void JNICALL cbEarlyException(jvmtiEnv*, JNIEnv *, 101 jthread, jmethodID, jlocation, jobject, jmethodID, jlocation); 102 103static void initialize(JNIEnv *env, jthread thread, EventIndex triggering_ei); 104static jboolean parseOptions(char *str); 105 106/* 107 * Phase 1: Initial load. 108 * 109 * OnLoad is called by the VM immediately after the back-end 110 * library is loaded. We can do very little in this function since 111 * the VM has not completed initialization. So, we parse the JDWP 112 * options and set up a simple initial event callbacks for JVMTI events. 113 * When a triggering event occurs, that callback will begin debugger initialization. 114 */ 115 116/* Get a static area to hold the Global Data */ 117static BackendGlobalData * 118get_gdata(void) 119{ 120 static BackendGlobalData s; 121 (void)memset(&s, 0, sizeof(BackendGlobalData)); 122 return &s; 123} 124 125static jvmtiError 126set_event_notification(jvmtiEventMode mode, EventIndex ei) 127{ 128 jvmtiError error; 129 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode) 130 (gdata->jvmti, mode, eventIndex2jvmti(ei), NULL); 131 if (error != JVMTI_ERROR_NONE) { 132 ERROR_MESSAGE(("JDWP unable to configure initial JVMTI event %s: %s(%d)", 133 eventText(ei), jvmtiErrorText(error), error)); 134 } 135 return error; 136} 137 138typedef struct { 139 int major; 140 int minor; 141} version_type; 142 143typedef struct { 144 version_type runtime; 145 version_type compiletime; 146} compatible_versions_type; 147 148/* 149 * List of explicitly compatible JVMTI versions, specified as 150 * { runtime version, compile-time version } pairs. -1 is a wildcard. 151 */ 152static int nof_compatible_versions = 3; 153static compatible_versions_type compatible_versions_list[] = { 154 /* 155 * FIXUP: Allow version 0 to be compatible with anything 156 * Special check for FCS of 1.0. 157 */ 158 { { 0, -1 }, { -1, -1 } }, 159 { { -1, -1 }, { 0, -1 } }, 160 /* 161 * 1.2 is runtime compatible with 1.1 -- just make sure to check the 162 * version before using any new 1.2 features 163 */ 164 { { 1, 1 }, { 1, 2 } } 165}; 166 167 168/* Logic to determine JVMTI version compatibility */ 169static jboolean 170compatible_versions(jint major_runtime, jint minor_runtime, 171 jint major_compiletime, jint minor_compiletime) 172{ 173 /* 174 * First check to see if versions are explicitly compatible via the 175 * list specified above. 176 */ 177 int i; 178 for (i = 0; i < nof_compatible_versions; ++i) { 179 version_type runtime = compatible_versions_list[i].runtime; 180 version_type comptime = compatible_versions_list[i].compiletime; 181 182 if ((major_runtime == runtime.major || runtime.major == -1) && 183 (minor_runtime == runtime.minor || runtime.minor == -1) && 184 (major_compiletime == comptime.major || comptime.major == -1) && 185 (minor_compiletime == comptime.minor || comptime.minor == -1)) { 186 return JNI_TRUE; 187 } 188 } 189 190 return major_runtime == major_compiletime && 191 minor_runtime >= minor_compiletime; 192} 193 194/* OnLoad startup: 195 * Returning JNI_ERR will cause the java_g VM to core dump, be careful. 196 */ 197JNIEXPORT jint JNICALL 198DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) 199{ 200 jvmtiError error; 201 jvmtiCapabilities needed_capabilities; 202 jvmtiCapabilities potential_capabilities; 203 jint jvmtiCompileTimeMajorVersion; 204 jint jvmtiCompileTimeMinorVersion; 205 jint jvmtiCompileTimeMicroVersion; 206 207 /* See if it's already loaded */ 208 if ( gdata!=NULL && gdata->isLoaded==JNI_TRUE ) { 209 ERROR_MESSAGE(("Cannot load this JVM TI agent twice, check your java command line for duplicate jdwp options.")); 210 return JNI_ERR; 211 } 212 213 /* If gdata is defined and the VM died, why are we here? */ 214 if ( gdata!=NULL && gdata->vmDead ) { 215 ERROR_MESSAGE(("JDWP unable to load, VM died")); 216 return JNI_ERR; 217 } 218 219 /* Get global data area */ 220 gdata = get_gdata(); 221 if (gdata == NULL) { 222 ERROR_MESSAGE(("JDWP unable to allocate memory")); 223 return JNI_ERR; 224 } 225 gdata->isLoaded = JNI_TRUE; 226 227 /* Start filling in gdata */ 228 gdata->jvm = vm; 229 vmInitialized = JNI_FALSE; 230 gdata->vmDead = JNI_FALSE; 231 232 /* Get the JVMTI Env, IMPORTANT: Do this first! For jvmtiAllocate(). */ 233 error = JVM_FUNC_PTR(vm,GetEnv) 234 (vm, (void **)&(gdata->jvmti), JVMTI_VERSION_1); 235 if (error != JNI_OK) { 236 ERROR_MESSAGE(("JDWP unable to access JVMTI Version 1 (0x%x)," 237 " is your J2SE a 1.5 or newer version?" 238 " JNIEnv's GetEnv() returned %d", 239 JVMTI_VERSION_1, error)); 240 forceExit(1); /* Kill entire process, no core dump */ 241 } 242 243 /* Check to make sure the version of jvmti.h we compiled with 244 * matches the runtime version we are using. 245 */ 246 jvmtiCompileTimeMajorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MAJOR ) 247 >> JVMTI_VERSION_SHIFT_MAJOR; 248 jvmtiCompileTimeMinorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MINOR ) 249 >> JVMTI_VERSION_SHIFT_MINOR; 250 jvmtiCompileTimeMicroVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MICRO ) 251 >> JVMTI_VERSION_SHIFT_MICRO; 252 253 /* Check for compatibility */ 254 if ( !compatible_versions(jvmtiMajorVersion(), jvmtiMinorVersion(), 255 jvmtiCompileTimeMajorVersion, jvmtiCompileTimeMinorVersion) ) { 256 257 ERROR_MESSAGE(("This jdwp native library will not work with this VM's " 258 "version of JVMTI (%d.%d.%d), it needs JVMTI %d.%d[.%d].", 259 jvmtiMajorVersion(), 260 jvmtiMinorVersion(), 261 jvmtiMicroVersion(), 262 jvmtiCompileTimeMajorVersion, 263 jvmtiCompileTimeMinorVersion, 264 jvmtiCompileTimeMicroVersion)); 265 266 /* Do not let VM get a fatal error, we don't want a core dump here. */ 267 forceExit(1); /* Kill entire process, no core dump wanted */ 268 } 269 270 /* Parse input options */ 271 if (!parseOptions(options)) { 272 /* No message necessary, should have been printed out already */ 273 /* Do not let VM get a fatal error, we don't want a core dump here. */ 274 forceExit(1); /* Kill entire process, no core dump wanted */ 275 } 276 277 LOG_MISC(("Onload: %s", options)); 278 279 /* Get potential capabilities */ 280 (void)memset(&potential_capabilities,0,sizeof(potential_capabilities)); 281 error = JVMTI_FUNC_PTR(gdata->jvmti,GetPotentialCapabilities) 282 (gdata->jvmti, &potential_capabilities); 283 if (error != JVMTI_ERROR_NONE) { 284 ERROR_MESSAGE(("JDWP unable to get potential JVMTI capabilities: %s(%d)", 285 jvmtiErrorText(error), error)); 286 return JNI_ERR; 287 } 288 289 /* Fill in ones that we must have */ 290 (void)memset(&needed_capabilities,0,sizeof(needed_capabilities)); 291 needed_capabilities.can_access_local_variables = 1; 292 needed_capabilities.can_generate_single_step_events = 1; 293 needed_capabilities.can_generate_exception_events = 1; 294 needed_capabilities.can_generate_frame_pop_events = 1; 295 needed_capabilities.can_generate_breakpoint_events = 1; 296 needed_capabilities.can_suspend = 1; 297 needed_capabilities.can_generate_method_entry_events = 1; 298 needed_capabilities.can_generate_method_exit_events = 1; 299 needed_capabilities.can_generate_garbage_collection_events = 1; 300 needed_capabilities.can_maintain_original_method_order = 1; 301 needed_capabilities.can_generate_monitor_events = 1; 302 needed_capabilities.can_tag_objects = 1; 303 304 /* And what potential ones that would be nice to have */ 305 needed_capabilities.can_force_early_return 306 = potential_capabilities.can_force_early_return; 307 needed_capabilities.can_generate_field_modification_events 308 = potential_capabilities.can_generate_field_modification_events; 309 needed_capabilities.can_generate_field_access_events 310 = potential_capabilities.can_generate_field_access_events; 311 needed_capabilities.can_get_bytecodes 312 = potential_capabilities.can_get_bytecodes; 313 needed_capabilities.can_get_synthetic_attribute 314 = potential_capabilities.can_get_synthetic_attribute; 315 needed_capabilities.can_get_owned_monitor_info 316 = potential_capabilities.can_get_owned_monitor_info; 317 needed_capabilities.can_get_current_contended_monitor 318 = potential_capabilities.can_get_current_contended_monitor; 319 needed_capabilities.can_get_monitor_info 320 = potential_capabilities.can_get_monitor_info; 321 needed_capabilities.can_pop_frame 322 = potential_capabilities.can_pop_frame; 323 needed_capabilities.can_redefine_classes 324 = potential_capabilities.can_redefine_classes; 325 needed_capabilities.can_redefine_any_class 326 = potential_capabilities.can_redefine_any_class; 327 needed_capabilities.can_get_owned_monitor_stack_depth_info 328 = potential_capabilities.can_get_owned_monitor_stack_depth_info; 329 needed_capabilities.can_get_constant_pool 330 = potential_capabilities.can_get_constant_pool; 331 { 332 needed_capabilities.can_get_source_debug_extension = 1; 333 needed_capabilities.can_get_source_file_name = 1; 334 needed_capabilities.can_get_line_numbers = 1; 335 needed_capabilities.can_signal_thread 336 = potential_capabilities.can_signal_thread; 337 } 338 339 /* Add the capabilities */ 340 error = JVMTI_FUNC_PTR(gdata->jvmti,AddCapabilities) 341 (gdata->jvmti, &needed_capabilities); 342 if (error != JVMTI_ERROR_NONE) { 343 ERROR_MESSAGE(("JDWP unable to get necessary JVMTI capabilities.")); 344 forceExit(1); /* Kill entire process, no core dump wanted */ 345 } 346 347 /* Initialize event number mapping tables */ 348 eventIndexInit(); 349 350 /* Set the initial JVMTI event notifications */ 351 error = set_event_notification(JVMTI_ENABLE, EI_VM_DEATH); 352 if (error != JVMTI_ERROR_NONE) { 353 return JNI_ERR; 354 } 355 error = set_event_notification(JVMTI_ENABLE, EI_VM_INIT); 356 if (error != JVMTI_ERROR_NONE) { 357 return JNI_ERR; 358 } 359 if (initOnUncaught || (initOnException != NULL)) { 360 error = set_event_notification(JVMTI_ENABLE, EI_EXCEPTION); 361 if (error != JVMTI_ERROR_NONE) { 362 return JNI_ERR; 363 } 364 } 365 366 /* Set callbacks just for 3 functions */ 367 (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks)); 368 gdata->callbacks.VMInit = &cbEarlyVMInit; 369 gdata->callbacks.VMDeath = &cbEarlyVMDeath; 370 gdata->callbacks.Exception = &cbEarlyException; 371 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks) 372 (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks)); 373 if (error != JVMTI_ERROR_NONE) { 374 ERROR_MESSAGE(("JDWP unable to set JVMTI event callbacks: %s(%d)", 375 jvmtiErrorText(error), error)); 376 return JNI_ERR; 377 } 378 379 LOG_MISC(("OnLoad: DONE")); 380 return JNI_OK; 381} 382 383JNIEXPORT void JNICALL 384DEF_Agent_OnUnload(JavaVM *vm) 385{ 386 387 gdata->isLoaded = JNI_FALSE; 388 389 /* Cleanup, but make sure VM is alive before using JNI, and 390 * make sure JVMTI environment is ok before deallocating 391 * memory allocated through JVMTI, which all of it is. 392 */ 393 394 /* 395 * Close transport before exit 396 */ 397 if (transport_is_open()) { 398 transport_close(); 399 } 400} 401 402/* 403 * Phase 2: Initial events. Phase 2 consists of waiting for the 404 * event that triggers full initialization. Under normal circumstances 405 * (initOnStartup == TRUE) this is the JVMTI_EVENT_VM_INIT event. 406 * Otherwise, we delay initialization until the app throws a 407 * particular exception. The triggering event invokes 408 * the bulk of the initialization, including creation of threads and 409 * monitors, transport setup, and installation of a new event callback which 410 * handles the complete set of events. 411 * 412 * Since the triggering event comes in on an application thread, some of the 413 * initialization is difficult to do here. Specifically, this thread along 414 * with all other app threads may need to be suspended until a debugger 415 * connects. These kinds of tasks are left to the third phase which is 416 * invoked by one of the spawned debugger threads, the event handler. 417 */ 418 419/* 420 * Wait for a triggering event; then kick off debugger 421 * initialization. A different event callback will be installed by 422 * debugger initialization, and this function will not be called 423 * again. 424 */ 425 426 /* 427 * TO DO: Decide whether we need to protect this code with 428 * a lock. It might be too early to create a monitor safely (?). 429 */ 430 431static void JNICALL 432cbEarlyVMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) 433{ 434 LOG_CB(("cbEarlyVMInit")); 435 if ( gdata->vmDead ) { 436 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at VM_INIT time"); 437 } 438 if (initOnStartup) 439 initialize(env, thread, EI_VM_INIT); 440 vmInitialized = JNI_TRUE; 441 LOG_MISC(("END cbEarlyVMInit")); 442} 443 444static void 445disposeEnvironment(jvmtiEnv *jvmti_env) 446{ 447 jvmtiError error; 448 449 error = JVMTI_FUNC_PTR(jvmti_env,DisposeEnvironment)(jvmti_env); 450 if ( error == JVMTI_ERROR_MUST_POSSESS_CAPABILITY ) 451 error = JVMTI_ERROR_NONE; /* Hack! FIXUP when JVMTI has disposeEnv */ 452 /* What should error return say? */ 453 if (error != JVMTI_ERROR_NONE) { 454 ERROR_MESSAGE(("JDWP unable to dispose of JVMTI environment: %s(%d)", 455 jvmtiErrorText(error), error)); 456 } 457 gdata->jvmti = NULL; 458} 459 460static void JNICALL 461cbEarlyVMDeath(jvmtiEnv *jvmti_env, JNIEnv *env) 462{ 463 LOG_CB(("cbEarlyVMDeath")); 464 if ( gdata->vmDead ) { 465 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM died more than once"); 466 } 467 disposeEnvironment(jvmti_env); 468 gdata->jvmti = NULL; 469 gdata->jvm = NULL; 470 gdata->vmDead = JNI_TRUE; 471 LOG_MISC(("END cbEarlyVMDeath")); 472} 473 474static void JNICALL 475cbEarlyException(jvmtiEnv *jvmti_env, JNIEnv *env, 476 jthread thread, jmethodID method, jlocation location, 477 jobject exception, 478 jmethodID catch_method, jlocation catch_location) 479{ 480 jvmtiError error; 481 jthrowable currentException; 482 483 LOG_CB(("cbEarlyException: thread=%p", thread)); 484 485 if ( gdata->vmDead ) { 486 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at initial Exception event"); 487 } 488 if (!vmInitialized) { 489 LOG_MISC(("VM is not initialized yet")); 490 return; 491 } 492 493 /* 494 * We want to preserve any current exception that might get wiped 495 * out during event handling (e.g. JNI calls). We have to rely on 496 * space for the local reference on the current frame because 497 * doing a PushLocalFrame here might itself generate an exception. 498 */ 499 500 currentException = JNI_FUNC_PTR(env,ExceptionOccurred)(env); 501 JNI_FUNC_PTR(env,ExceptionClear)(env); 502 503 if (initOnUncaught && catch_method == NULL) { 504 505 LOG_MISC(("Initializing on uncaught exception")); 506 initialize(env, thread, EI_EXCEPTION); 507 508 } else if (initOnException != NULL) { 509 510 jclass clazz; 511 512 /* Get class of exception thrown */ 513 clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, exception); 514 if ( clazz != NULL ) { 515 char *signature = NULL; 516 /* initing on throw, check */ 517 error = classSignature(clazz, &signature, NULL); 518 LOG_MISC(("Checking specific exception: looking for %s, got %s", 519 initOnException, signature)); 520 if ( (error==JVMTI_ERROR_NONE) && 521 (strcmp(signature, initOnException) == 0)) { 522 LOG_MISC(("Initializing on specific exception")); 523 initialize(env, thread, EI_EXCEPTION); 524 } else { 525 error = AGENT_ERROR_INTERNAL; /* Just to cause restore */ 526 } 527 if ( signature != NULL ) { 528 jvmtiDeallocate(signature); 529 } 530 } else { 531 error = AGENT_ERROR_INTERNAL; /* Just to cause restore */ 532 } 533 534 /* If initialize didn't happen, we need to restore things */ 535 if ( error != JVMTI_ERROR_NONE ) { 536 /* 537 * Restore exception state from before callback call 538 */ 539 LOG_MISC(("No initialization, didn't find right exception")); 540 if (currentException != NULL) { 541 JNI_FUNC_PTR(env,Throw)(env, currentException); 542 } else { 543 JNI_FUNC_PTR(env,ExceptionClear)(env); 544 } 545 } 546 547 } 548 549 LOG_MISC(("END cbEarlyException")); 550 551} 552 553typedef struct EnumerateArg { 554 jboolean isServer; 555 jdwpError error; 556 jint startCount; 557} EnumerateArg; 558 559static jboolean 560startTransport(void *item, void *arg) 561{ 562 TransportSpec *transport = item; 563 EnumerateArg *enumArg = arg; 564 jdwpError serror; 565 566 LOG_MISC(("Begin startTransport")); 567 serror = transport_startTransport(enumArg->isServer, transport->name, 568 transport->address, transport->timeout, 569 transport->allow); 570 if (serror != JDWP_ERROR(NONE)) { 571 ERROR_MESSAGE(("JDWP Transport %s failed to initialize, %s(%d)", 572 transport->name, jdwpErrorText(serror), serror)); 573 enumArg->error = serror; 574 } else { 575 /* (Don't overwrite any previous error) */ 576 577 enumArg->startCount++; 578 } 579 580 LOG_MISC(("End startTransport")); 581 582 return JNI_TRUE; /* Always continue, even if there was an error */ 583} 584 585static void 586signalInitComplete(void) 587{ 588 /* 589 * Initialization is complete 590 */ 591 LOG_MISC(("signal initialization complete")); 592 debugMonitorEnter(initMonitor); 593 initComplete = JNI_TRUE; 594 debugMonitorNotifyAll(initMonitor); 595 debugMonitorExit(initMonitor); 596} 597 598/* 599 * Determine if initialization is complete. 600 */ 601jboolean 602debugInit_isInitComplete(void) 603{ 604 return initComplete; 605} 606 607/* 608 * Wait for all initialization to complete. 609 */ 610void 611debugInit_waitInitComplete(void) 612{ 613 debugMonitorEnter(initMonitor); 614 while (!initComplete) { 615 debugMonitorWait(initMonitor); 616 } 617 debugMonitorExit(initMonitor); 618} 619 620/* All process exit() calls come from here */ 621void 622forceExit(int exit_code) 623{ 624 /* make sure the transport is closed down before we exit() */ 625 transport_close(); 626 exit(exit_code); 627} 628 629/* All JVM fatal error exits lead here (e.g. we need to kill the VM). */ 630static void 631jniFatalError(JNIEnv *env, const char *msg, jvmtiError error, int exit_code) 632{ 633 JavaVM *vm; 634 char buf[512]; 635 636 gdata->vmDead = JNI_TRUE; 637 if ( msg==NULL ) 638 msg = "UNKNOWN REASON"; 639 vm = gdata->jvm; 640 if ( env==NULL && vm!=NULL ) { 641 jint rc = (*((*vm)->GetEnv))(vm, (void **)&env, JNI_VERSION_1_2); 642 if (rc != JNI_OK ) { 643 env = NULL; 644 } 645 } 646 if ( error != JVMTI_ERROR_NONE ) { 647 (void)snprintf(buf, sizeof(buf), "JDWP %s, jvmtiError=%s(%d)", 648 msg, jvmtiErrorText(error), error); 649 } else { 650 (void)snprintf(buf, sizeof(buf), "JDWP %s", buf); 651 } 652 if (env != NULL) { 653 (*((*env)->FatalError))(env, buf); 654 } else { 655 /* Should rarely ever reach here, means VM is really dead */ 656 print_message(stderr, "ERROR: JDWP: ", "\n", 657 "Can't call JNI FatalError(NULL, \"%s\")", buf); 658 } 659 forceExit(exit_code); 660} 661 662/* 663 * Initialize debugger back end modules 664 */ 665static void 666initialize(JNIEnv *env, jthread thread, EventIndex triggering_ei) 667{ 668 jvmtiError error; 669 EnumerateArg arg; 670 jbyte suspendPolicy; 671 672 LOG_MISC(("Begin initialize()")); 673 currentSessionID = 0; 674 initComplete = JNI_FALSE; 675 676 if ( gdata->vmDead ) { 677 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at initialize() time"); 678 } 679 680 /* Turn off the initial JVMTI event notifications */ 681 error = set_event_notification(JVMTI_DISABLE, EI_EXCEPTION); 682 if (error != JVMTI_ERROR_NONE) { 683 EXIT_ERROR(error, "unable to disable JVMTI event notification"); 684 } 685 error = set_event_notification(JVMTI_DISABLE, EI_VM_INIT); 686 if (error != JVMTI_ERROR_NONE) { 687 EXIT_ERROR(error, "unable to disable JVMTI event notification"); 688 } 689 error = set_event_notification(JVMTI_DISABLE, EI_VM_DEATH); 690 if (error != JVMTI_ERROR_NONE) { 691 EXIT_ERROR(error, "unable to disable JVMTI event notification"); 692 } 693 694 /* Remove initial event callbacks */ 695 (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks)); 696 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks) 697 (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks)); 698 if (error != JVMTI_ERROR_NONE) { 699 EXIT_ERROR(error, "unable to clear JVMTI callbacks"); 700 } 701 702 commonRef_initialize(); 703 util_initialize(env); 704 threadControl_initialize(); 705 stepControl_initialize(); 706 invoker_initialize(); 707 debugDispatch_initialize(); 708 classTrack_initialize(env); 709 debugLoop_initialize(); 710 711 initMonitor = debugMonitorCreate("JDWP Initialization Monitor"); 712 713 714 /* 715 * Initialize transports 716 */ 717 arg.isServer = isServer; 718 arg.error = JDWP_ERROR(NONE); 719 arg.startCount = 0; 720 721 transport_initialize(); 722 (void)bagEnumerateOver(transports, startTransport, &arg); 723 724 /* 725 * Exit with an error only if 726 * 1) none of the transports was successfully started, and 727 * 2) the application has not yet started running 728 */ 729 if ((arg.error != JDWP_ERROR(NONE)) && 730 (arg.startCount == 0) && 731 initOnStartup) { 732 EXIT_ERROR(map2jvmtiError(arg.error), "No transports initialized"); 733 } 734 735 eventHandler_initialize(currentSessionID); 736 737 signalInitComplete(); 738 739 transport_waitForConnection(); 740 741 suspendPolicy = suspendOnInit ? JDWP_SUSPEND_POLICY(ALL) 742 : JDWP_SUSPEND_POLICY(NONE); 743 if (triggering_ei == EI_VM_INIT) { 744 LOG_MISC(("triggering_ei == EI_VM_INIT")); 745 eventHelper_reportVMInit(env, currentSessionID, thread, suspendPolicy); 746 } else { 747 /* 748 * TO DO: Kludgy way of getting the triggering event to the 749 * just-attached debugger. It would be nice to make this a little 750 * cleaner. There is also a race condition where other events 751 * can get in the queue (from other not-yet-suspended threads) 752 * before this one does. (Also need to handle allocation error below?) 753 */ 754 EventInfo info; 755 struct bag *initEventBag; 756 LOG_MISC(("triggering_ei != EI_VM_INIT")); 757 initEventBag = eventHelper_createEventBag(); 758 (void)memset(&info,0,sizeof(info)); 759 info.ei = triggering_ei; 760 eventHelper_recordEvent(&info, 0, suspendPolicy, initEventBag); 761 (void)eventHelper_reportEvents(currentSessionID, initEventBag); 762 bagDestroyBag(initEventBag); 763 } 764 765 if ( gdata->vmDead ) { 766 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead before initialize() completes"); 767 } 768 LOG_MISC(("End initialize()")); 769} 770 771/* 772 * Restore all static data to the initialized state so that another 773 * debugger can connect properly later. 774 */ 775void 776debugInit_reset(JNIEnv *env) 777{ 778 EnumerateArg arg; 779 780 LOG_MISC(("debugInit_reset() beginning")); 781 782 currentSessionID++; 783 initComplete = JNI_FALSE; 784 785 eventHandler_reset(currentSessionID); 786 transport_reset(); 787 debugDispatch_reset(); 788 invoker_reset(); 789 stepControl_reset(); 790 threadControl_reset(); 791 util_reset(); 792 commonRef_reset(env); 793 classTrack_reset(); 794 795 /* 796 * If this is a server, we are now ready to accept another connection. 797 * If it's a client, then we've cleaned up some (more should be added 798 * later) and we're done. 799 */ 800 if (isServer) { 801 arg.isServer = JNI_TRUE; 802 arg.error = JDWP_ERROR(NONE); 803 arg.startCount = 0; 804 (void)bagEnumerateOver(transports, startTransport, &arg); 805 806 signalInitComplete(); 807 808 transport_waitForConnection(); 809 } else { 810 signalInitComplete(); /* Why? */ 811 } 812 813 LOG_MISC(("debugInit_reset() completed.")); 814} 815 816 817char * 818debugInit_launchOnInit(void) 819{ 820 return launchOnInit; 821} 822 823jboolean 824debugInit_suspendOnInit(void) 825{ 826 return suspendOnInit; 827} 828 829/* 830 * code below is shamelessly swiped from hprof. 831 */ 832 833static int 834get_tok(char **src, char *buf, int buflen, char sep) 835{ 836 int i; 837 char *p = *src; 838 for (i = 0; i < buflen; i++) { 839 if (p[i] == 0 || p[i] == sep) { 840 buf[i] = 0; 841 if (p[i] == sep) { 842 i++; 843 } 844 *src += i; 845 return i; 846 } 847 buf[i] = p[i]; 848 } 849 /* overflow */ 850 return 0; 851} 852 853static void 854printUsage(void) 855{ 856 TTY_MESSAGE(( 857 " Java Debugger JDWP Agent Library\n" 858 " --------------------------------\n" 859 "\n" 860 " (see http://java.sun.com/products/jpda for more information)\n" 861 "\n" 862 "jdwp usage: java " AGENTLIB "=[help]|[<option>=<value>, ...]\n" 863 "\n" 864 "Option Name and Value Description Default\n" 865 "--------------------- ----------- -------\n" 866 "suspend=y|n wait on startup? y\n" 867 "transport=<name> transport spec none\n" 868 "address=<listen/attach address> transport spec \"\"\n" 869 "server=y|n listen for debugger? n\n" 870 "launch=<command line> run debugger on event none\n" 871 "onthrow=<exception name> debug on throw none\n" 872 "onuncaught=y|n debug on any uncaught? n\n" 873 "timeout=<timeout value> for listen/attach in milliseconds n\n" 874 "mutf8=y|n output modified utf-8 n\n" 875 "quiet=y|n control over terminal messages n\n")); 876 877 TTY_MESSAGE(( 878 "Obsolete Options\n" 879 "----------------\n" 880 "strict=y|n\n" 881 "stdalloc=y|n\n" 882 "\n" 883 "Examples\n" 884 "--------\n" 885 " - Using sockets connect to a debugger at a specific address:\n" 886 " java " AGENTLIB "=transport=dt_socket,address=localhost:8000 ...\n" 887 " - Using sockets listen for a debugger to attach:\n" 888 " java " AGENTLIB "=transport=dt_socket,server=y,suspend=y ...\n" 889 "\n" 890 "Notes\n" 891 "-----\n" 892 " - A timeout value of 0 (the default) is no timeout.\n" 893 "\n" 894 "Warnings\n" 895 "--------\n" 896 " - The older " XRUN " interface can still be used, but will be removed in\n" 897 " a future release, for example:\n" 898 " java " XDEBUG " " XRUN ":[help]|[<option>=<value>, ...]\n" 899 )); 900 901#ifdef DEBUG 902 903 TTY_MESSAGE(( 904 "\n" 905 "Debugging Options Description Default\n" 906 "----------------- ----------- -------\n" 907 "pause=y|n pause to debug PID n\n" 908 "coredump=y|n coredump at exit n\n" 909 "errorexit=y|n exit on any error n\n" 910 "logfile=filename name of log file none\n" 911 "logflags=flags log flags (bitmask) none\n" 912 " JVM calls = 0x001\n" 913 " JNI calls = 0x002\n" 914 " JVMTI calls = 0x004\n" 915 " misc events = 0x008\n" 916 " step logs = 0x010\n" 917 " locations = 0x020\n" 918 " callbacks = 0x040\n" 919 " errors = 0x080\n" 920 " everything = 0xfff")); 921 922 TTY_MESSAGE(( 923 "debugflags=flags debug flags (bitmask) none\n" 924 " USE_ITERATE_THROUGH_HEAP 0x01\n" 925 "\n" 926 "Environment Variables\n" 927 "---------------------\n" 928 "_JAVA_JDWP_OPTIONS\n" 929 " Options can be added externally via this environment variable.\n" 930 " Anything contained in it will get a comma prepended to it (if needed),\n" 931 " then it will be added to the end of the options supplied via the\n" 932 " " XRUN " or " AGENTLIB " command line option.\n" 933 )); 934 935#endif 936 937 938 939} 940 941static jboolean checkAddress(void *bagItem, void *arg) 942{ 943 TransportSpec *spec = (TransportSpec *)bagItem; 944 if (spec->address == NULL) { 945 ERROR_MESSAGE(("JDWP Non-server transport %s must have a connection " 946 "address specified through the 'address=' option", 947 spec->name)); 948 return JNI_FALSE; 949 } else { 950 return JNI_TRUE; 951 } 952} 953 954static char * 955add_to_options(char *options, char *new_options) 956{ 957 size_t originalLength; 958 char *combinedOptions; 959 960 /* 961 * Allocate enough space for both strings and 962 * comma in between. 963 */ 964 originalLength = strlen(options); 965 combinedOptions = jvmtiAllocate((jint)originalLength + 1 + 966 (jint)strlen(new_options) + 1); 967 if (combinedOptions == NULL) { 968 return NULL; 969 } 970 971 (void)strcpy(combinedOptions, options); 972 (void)strcat(combinedOptions, ","); 973 (void)strcat(combinedOptions, new_options); 974 975 return combinedOptions; 976} 977 978static jboolean 979get_boolean(char **pstr, jboolean *answer) 980{ 981 char buf[80]; 982 *answer = JNI_FALSE; 983 /*LINTED*/ 984 if (get_tok(pstr, buf, (int)sizeof(buf), ',')) { 985 if (strcmp(buf, "y") == 0) { 986 *answer = JNI_TRUE; 987 return JNI_TRUE; 988 } else if (strcmp(buf, "n") == 0) { 989 *answer = JNI_FALSE; 990 return JNI_TRUE; 991 } 992 } 993 return JNI_FALSE; 994} 995 996/* atexit() callback */ 997static void 998atexit_finish_logging(void) 999{ 1000 /* Normal exit(0) (not _exit()) may only reach here */ 1001 finish_logging(); /* Only first call matters */ 1002} 1003 1004static jboolean 1005parseOptions(char *options) 1006{ 1007 TransportSpec *currentTransport = NULL; 1008 char *end; 1009 char *current; 1010 int length; 1011 char *str; 1012 char *errmsg; 1013 1014 /* Set defaults */ 1015 gdata->assertOn = DEFAULT_ASSERT_ON; 1016 gdata->assertFatal = DEFAULT_ASSERT_FATAL; 1017 logfile = DEFAULT_LOGFILE; 1018 1019 /* Options being NULL will end up being an error. */ 1020 if (options == NULL) { 1021 options = ""; 1022 } 1023 1024 /* Check for "help" BEFORE we add any environmental settings */ 1025 if ((strcmp(options, "help")) == 0) { 1026 printUsage(); 1027 forceExit(0); /* Kill entire process, no core dump wanted */ 1028 } 1029 1030 /* These buffers are never freed */ 1031 { 1032 char *envOptions; 1033 1034 /* 1035 * Add environmentally specified options. 1036 */ 1037 envOptions = getenv("_JAVA_JDWP_OPTIONS"); 1038 if (envOptions != NULL) { 1039 options = add_to_options(options, envOptions); 1040 if ( options==NULL ) { 1041 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options"); 1042 } 1043 } 1044 1045 /* 1046 * Allocate a buffer for names derived from option strings. It should 1047 * never be longer than the original options string itself. 1048 * Also keep a copy of the options in gdata->options. 1049 */ 1050 length = (int)strlen(options); 1051 gdata->options = jvmtiAllocate(length + 1); 1052 if (gdata->options == NULL) { 1053 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options"); 1054 } 1055 (void)strcpy(gdata->options, options); 1056 names = jvmtiAllocate(length + 1); 1057 if (names == NULL) { 1058 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options"); 1059 } 1060 1061 transports = bagCreateBag(sizeof(TransportSpec), 3); 1062 if (transports == NULL) { 1063 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"transports"); 1064 } 1065 } 1066 1067 current = names; 1068 end = names + length; 1069 str = options; 1070 1071 while (*str) { 1072 char buf[100]; 1073 /*LINTED*/ 1074 if (!get_tok(&str, buf, (int)sizeof(buf), '=')) { 1075 goto syntax_error; 1076 } 1077 if (strcmp(buf, "transport") == 0) { 1078 currentTransport = bagAdd(transports); 1079 /*LINTED*/ 1080 if (!get_tok(&str, current, (int)(end - current), ',')) { 1081 goto syntax_error; 1082 } 1083 currentTransport->name = current; 1084 currentTransport->address = NULL; 1085 currentTransport->allow = NULL; 1086 currentTransport->timeout = 0L; 1087 current += strlen(current) + 1; 1088 } else if (strcmp(buf, "address") == 0) { 1089 if (currentTransport == NULL) { 1090 errmsg = "address specified without transport"; 1091 goto bad_option_with_errmsg; 1092 } 1093 /*LINTED*/ 1094 if (!get_tok(&str, current, (int)(end - current), ',')) { 1095 goto syntax_error; 1096 } 1097 currentTransport->address = current; 1098 current += strlen(current) + 1; 1099 } else if (strcmp(buf, "allow") == 0) { 1100 if (currentTransport == NULL) { 1101 errmsg = "allow specified without transport"; 1102 goto bad_option_with_errmsg; 1103 } 1104 /*LINTED*/ 1105 if (!get_tok(&str, current, (int)(end - current), ',')) { 1106 goto syntax_error; 1107 } 1108 currentTransport->allow = current; 1109 current += strlen(current) + 1; 1110 } else if (strcmp(buf, "timeout") == 0) { 1111 if (currentTransport == NULL) { 1112 errmsg = "timeout specified without transport"; 1113 goto bad_option_with_errmsg; 1114 } 1115 /*LINTED*/ 1116 if (!get_tok(&str, current, (int)(end - current), ',')) { 1117 goto syntax_error; 1118 } 1119 currentTransport->timeout = atol(current); 1120 current += strlen(current) + 1; 1121 } else if (strcmp(buf, "launch") == 0) { 1122 /*LINTED*/ 1123 if (!get_tok(&str, current, (int)(end - current), ',')) { 1124 goto syntax_error; 1125 } 1126 launchOnInit = current; 1127 current += strlen(current) + 1; 1128 } else if (strcmp(buf, "onthrow") == 0) { 1129 /* Read class name and convert in place to a signature */ 1130 *current = 'L'; 1131 /*LINTED*/ 1132 if (!get_tok(&str, current + 1, (int)(end - current - 1), ',')) { 1133 goto syntax_error; 1134 } 1135 initOnException = current; 1136 while (*current != '\0') { 1137 if (*current == '.') { 1138 *current = '/'; 1139 } 1140 current++; 1141 } 1142 *current++ = ';'; 1143 *current++ = '\0'; 1144 } else if (strcmp(buf, "assert") == 0) { 1145 /*LINTED*/ 1146 if (!get_tok(&str, current, (int)(end - current), ',')) { 1147 goto syntax_error; 1148 } 1149 if (strcmp(current, "y") == 0) { 1150 gdata->assertOn = JNI_TRUE; 1151 gdata->assertFatal = JNI_FALSE; 1152 } else if (strcmp(current, "fatal") == 0) { 1153 gdata->assertOn = JNI_TRUE; 1154 gdata->assertFatal = JNI_TRUE; 1155 } else if (strcmp(current, "n") == 0) { 1156 gdata->assertOn = JNI_FALSE; 1157 gdata->assertFatal = JNI_FALSE; 1158 } else { 1159 goto syntax_error; 1160 } 1161 current += strlen(current) + 1; 1162 } else if (strcmp(buf, "pause") == 0) { 1163 if ( !get_boolean(&str, &dopause) ) { 1164 goto syntax_error; 1165 } 1166 if ( dopause ) { 1167 do_pause(); 1168 } 1169 } else if (strcmp(buf, "coredump") == 0) { 1170 if ( !get_boolean(&str, &docoredump) ) { 1171 goto syntax_error; 1172 } 1173 } else if (strcmp(buf, "errorexit") == 0) { 1174 if ( !get_boolean(&str, &(gdata->doerrorexit)) ) { 1175 goto syntax_error; 1176 } 1177 } else if (strcmp(buf, "exitpause") == 0) { 1178 errmsg = "The exitpause option removed, use -XX:OnError"; 1179 goto bad_option_with_errmsg; 1180 } else if (strcmp(buf, "precrash") == 0) { 1181 errmsg = "The precrash option removed, use -XX:OnError"; 1182 goto bad_option_with_errmsg; 1183 } else if (strcmp(buf, "logfile") == 0) { 1184 /*LINTED*/ 1185 if (!get_tok(&str, current, (int)(end - current), ',')) { 1186 goto syntax_error; 1187 } 1188 logfile = current; 1189 current += strlen(current) + 1; 1190 } else if (strcmp(buf, "logflags") == 0) { 1191 /*LINTED*/ 1192 if (!get_tok(&str, current, (int)(end - current), ',')) { 1193 goto syntax_error; 1194 } 1195 /*LINTED*/ 1196 logflags = (unsigned)strtol(current, NULL, 0); 1197 } else if (strcmp(buf, "debugflags") == 0) { 1198 /*LINTED*/ 1199 if (!get_tok(&str, current, (int)(end - current), ',')) { 1200 goto syntax_error; 1201 } 1202 /*LINTED*/ 1203 gdata->debugflags = (unsigned)strtol(current, NULL, 0); 1204 } else if ( strcmp(buf, "suspend")==0 ) { 1205 if ( !get_boolean(&str, &suspendOnInit) ) { 1206 goto syntax_error; 1207 } 1208 } else if ( strcmp(buf, "server")==0 ) { 1209 if ( !get_boolean(&str, &isServer) ) { 1210 goto syntax_error; 1211 } 1212 } else if ( strcmp(buf, "strict")==0 ) { /* Obsolete, but accept it */ 1213 if ( !get_boolean(&str, &isStrict) ) { 1214 goto syntax_error; 1215 } 1216 } else if ( strcmp(buf, "quiet")==0 ) { 1217 if ( !get_boolean(&str, &(gdata->quiet)) ) { 1218 goto syntax_error; 1219 } 1220 } else if ( strcmp(buf, "onuncaught")==0 ) { 1221 if ( !get_boolean(&str, &initOnUncaught) ) { 1222 goto syntax_error; 1223 } 1224 } else if ( strcmp(buf, "mutf8")==0 ) { 1225 if ( !get_boolean(&str, &(gdata->modifiedUtf8)) ) { 1226 goto syntax_error; 1227 } 1228 } else if ( strcmp(buf, "stdalloc")==0 ) { /* Obsolete, but accept it */ 1229 if ( !get_boolean(&str, &useStandardAlloc) ) { 1230 goto syntax_error; 1231 } 1232 } else { 1233 goto syntax_error; 1234 } 1235 } 1236 1237 /* Setup logging now */ 1238 if ( logfile!=NULL ) { 1239 setup_logging(logfile, logflags); 1240 (void)atexit(&atexit_finish_logging); 1241 } 1242 1243 if (bagSize(transports) == 0) { 1244 errmsg = "no transport specified"; 1245 goto bad_option_with_errmsg; 1246 } 1247 1248 /* 1249 * TO DO: Remove when multiple transports are allowed. (replace with 1250 * check below. 1251 */ 1252 if (bagSize(transports) > 1) { 1253 errmsg = "multiple transports are not supported in this release"; 1254 goto bad_option_with_errmsg; 1255 } 1256 1257 1258 if (!isServer) { 1259 jboolean specified = bagEnumerateOver(transports, checkAddress, NULL); 1260 if (!specified) { 1261 /* message already printed */ 1262 goto bad_option_no_msg; 1263 } 1264 } 1265 1266 /* 1267 * The user has selected to wait for an exception before init happens 1268 */ 1269 if ((initOnException != NULL) || (initOnUncaught)) { 1270 initOnStartup = JNI_FALSE; 1271 1272 if (launchOnInit == NULL) { 1273 /* 1274 * These rely on the launch=/usr/bin/foo 1275 * suboption, so it is an error if user did not 1276 * provide one. 1277 */ 1278 errmsg = "Specify launch=<command line> when using onthrow or onuncaught suboption"; 1279 goto bad_option_with_errmsg; 1280 } 1281 } 1282 1283 return JNI_TRUE; 1284 1285syntax_error: 1286 ERROR_MESSAGE(("JDWP option syntax error: %s=%s", AGENTLIB, options)); 1287 return JNI_FALSE; 1288 1289bad_option_with_errmsg: 1290 ERROR_MESSAGE(("JDWP %s: %s=%s", errmsg, AGENTLIB, options)); 1291 return JNI_FALSE; 1292 1293bad_option_no_msg: 1294 ERROR_MESSAGE(("JDWP %s: %s=%s", "invalid option", AGENTLIB, options)); 1295 return JNI_FALSE; 1296} 1297 1298/* All normal exit doors lead here */ 1299void 1300debugInit_exit(jvmtiError error, const char *msg) 1301{ 1302 enum exit_codes { EXIT_NO_ERRORS = 0, EXIT_JVMTI_ERROR = 1, EXIT_TRANSPORT_ERROR = 2 }; 1303 1304 // Prepare to exit. Log error and finish logging 1305 LOG_MISC(("Exiting with error %s(%d): %s", jvmtiErrorText(error), error, 1306 ((msg == NULL) ? "" : msg))); 1307 1308 // coredump requested by command line. Keep JVMTI data dirty 1309 if (error != JVMTI_ERROR_NONE && docoredump) { 1310 LOG_MISC(("Dumping core as requested by command line")); 1311 finish_logging(); 1312 abort(); 1313 } 1314 1315 finish_logging(); 1316 1317 // Cleanup the JVMTI if we have one 1318 if (gdata != NULL) { 1319 gdata->vmDead = JNI_TRUE; 1320 if (gdata->jvmti != NULL) { 1321 // Dispose of jvmti (gdata->jvmti becomes NULL) 1322 disposeEnvironment(gdata->jvmti); 1323 } 1324 } 1325 1326 // We are here with no errors. Kill entire process and exit with zero exit code 1327 if (error == JVMTI_ERROR_NONE) { 1328 forceExit(EXIT_NO_ERRORS); 1329 return; 1330 } 1331 1332 // No transport initilized. 1333 // As we don't have any details here exiting with separate exit code 1334 if (error == AGENT_ERROR_TRANSPORT_INIT) { 1335 forceExit(EXIT_TRANSPORT_ERROR); 1336 return; 1337 } 1338 1339 // We have JVMTI error. Call hotspot jni_FatalError handler 1340 jniFatalError(NULL, msg, error, EXIT_JVMTI_ERROR); 1341 1342 // hotspot calls os:abort() so we should never reach code below, 1343 // but guard against possible hotspot changes 1344 1345 // Last chance to die, this kills the entire process. 1346 forceExit(EXIT_JVMTI_ERROR); 1347} 1348