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