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 *
get_gdata(void)131 get_gdata(void)
132 {
133 static BackendGlobalData s;
134 (void)memset(&s, 0, sizeof(BackendGlobalData));
135 return &s;
136 }
137
138 static jvmtiError
set_event_notification(jvmtiEventMode mode,EventIndex ei)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
compatible_versions(jint major_runtime,jint minor_runtime,jint major_compiletime,jint minor_compiletime)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.
find_extension_functions()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
Agent_OnLoad(JavaVM * vm,char * options,void * reserved)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
Agent_OnUnload(JavaVM * vm)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
cbEarlyVMInit(jvmtiEnv * jvmti_env,JNIEnv * env,jthread thread)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
disposeEnvironment(jvmtiEnv * jvmti_env)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
cbEarlyVMDeath(jvmtiEnv * jvmti_env,JNIEnv * env)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
cbEarlyException(jvmtiEnv * jvmti_env,JNIEnv * env,jthread thread,jmethodID method,jlocation location,jobject exception,jmethodID catch_method,jlocation catch_location)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
startTransport(void * item,void * arg)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
signalInitComplete(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
debugInit_isInitComplete(void)693 debugInit_isInitComplete(void)
694 {
695 return initComplete;
696 }
697
698 /*
699 * Wait for all initialization to complete.
700 */
701 void
debugInit_waitInitComplete(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
forceExit(int exit_code)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
jniFatalError(JNIEnv * env,const char * msg,jvmtiError error,int exit_code)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
initialize(JNIEnv * env,jthread thread,EventIndex triggering_ei)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
debugInit_reset(JNIEnv * env)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 *
debugInit_launchOnInit(void)918 debugInit_launchOnInit(void)
919 {
920 return launchOnInit;
921 }
922
923 jboolean
debugInit_suspendOnInit(void)924 debugInit_suspendOnInit(void)
925 {
926 return suspendOnInit;
927 }
928
929 /*
930 * code below is shamelessly swiped from hprof.
931 */
932
933 static int
get_tok(char ** src,char * buf,int buflen,char sep)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
printUsage(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
checkAddress(void * bagItem,void * arg)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 *
add_to_options(char * options,char * new_options)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
get_boolean(char ** pstr,jboolean * answer)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
atexit_finish_logging(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
parseOptions(char * options)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
debugInit_exit(jvmtiError error,const char * msg)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.
doInitializeOnAttach(JavaVM * vm)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
Agent_OnAttach(JavaVM * vm,char * options,void * reserved)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