• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &currentThread);
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