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