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