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