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