OSDN Git Service

1688e5e7b41abab3dd6916c80a7875d4d1d4334f
[android-x86/dalvik.git] / vm / jdwp / JdwpMain.c
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * JDWP initialization.
19  */
20 #include "jdwp/JdwpPriv.h"
21 #include "Dalvik.h"
22 #include "Atomic.h"
23
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/time.h>
27 #include <time.h>
28 #include <errno.h>
29
30
31 static void* jdwpThreadStart(void* arg);
32
33
34 /*
35  * Initialize JDWP.
36  *
37  * Does not return until JDWP thread is running, but may return before
38  * the thread is accepting network connections.
39  */
40 JdwpState* dvmJdwpStartup(const JdwpStartupParams* pParams)
41 {
42     JdwpState* state = NULL;
43
44     /* comment this out when debugging JDWP itself */
45     android_setMinPriority(LOG_TAG, ANDROID_LOG_DEBUG);
46
47     state = (JdwpState*) calloc(1, sizeof(JdwpState));
48
49     state->params = *pParams;
50
51     state->requestSerial = 0x10000000;
52     state->eventSerial = 0x20000000;
53     dvmDbgInitMutex(&state->threadStartLock);
54     dvmDbgInitMutex(&state->attachLock);
55     dvmDbgInitMutex(&state->serialLock);
56     dvmDbgInitMutex(&state->eventLock);
57     state->eventThreadId = 0;
58     dvmDbgInitMutex(&state->eventThreadLock);
59     dvmDbgInitCond(&state->threadStartCond);
60     dvmDbgInitCond(&state->attachCond);
61     dvmDbgInitCond(&state->eventThreadCond);
62
63     switch (pParams->transport) {
64     case kJdwpTransportSocket:
65         // LOGD("prepping for JDWP over TCP\n");
66         state->transport = dvmJdwpSocketTransport();
67         break;
68     case kJdwpTransportAndroidAdb:
69         // LOGD("prepping for JDWP over ADB\n");
70         state->transport = dvmJdwpAndroidAdbTransport();
71         /* TODO */
72         break;
73     default:
74         LOGE("Unknown transport %d\n", pParams->transport);
75         assert(false);
76         goto fail;
77     }
78
79     if (!dvmJdwpNetStartup(state, pParams))
80         goto fail;
81
82     /*
83      * Grab a mutex or two before starting the thread.  This ensures they
84      * won't signal the cond var before we're waiting.
85      */
86     dvmDbgLockMutex(&state->threadStartLock);
87     if (pParams->suspend)
88         dvmDbgLockMutex(&state->attachLock);
89
90     /*
91      * We have bound to a port, or are trying to connect outbound to a
92      * debugger.  Create the JDWP thread and let it continue the mission.
93      */
94     if (!dvmCreateInternalThread(&state->debugThreadHandle, "JDWP",
95             jdwpThreadStart, state))
96     {
97         /* state is getting tossed, but unlock these anyway for cleanliness */
98         dvmDbgUnlockMutex(&state->threadStartLock);
99         if (pParams->suspend)
100             dvmDbgUnlockMutex(&state->attachLock);
101         goto fail;
102     }
103
104     /*
105      * Wait until the thread finishes basic initialization.
106      * TODO: cond vars should be waited upon in a loop
107      */
108     dvmDbgCondWait(&state->threadStartCond, &state->threadStartLock);
109     dvmDbgUnlockMutex(&state->threadStartLock);
110
111
112     /*
113      * For suspend=y, wait for the debugger to connect to us or for us to
114      * connect to the debugger.
115      *
116      * The JDWP thread will signal us when it connects successfully or
117      * times out (for timeout=xxx), so we have to check to see what happened
118      * when we wake up.
119      */
120     if (pParams->suspend) {
121         dvmChangeStatus(NULL, THREAD_VMWAIT);
122         dvmDbgCondWait(&state->attachCond, &state->attachLock);
123         dvmDbgUnlockMutex(&state->attachLock);
124         dvmChangeStatus(NULL, THREAD_RUNNING);
125
126         if (!dvmJdwpIsActive(state)) {
127             LOGE("JDWP connection failed\n");
128             goto fail;
129         }
130
131         LOGI("JDWP connected\n");
132
133         /*
134          * Ordinarily we would pause briefly to allow the debugger to set
135          * breakpoints and so on, but for "suspend=y" the VM init code will
136          * pause the VM when it sends the VM_START message.
137          */
138     }
139
140     return state;
141
142 fail:
143     dvmJdwpShutdown(state);     // frees state
144     return NULL;
145 }
146
147 /*
148  * Reset all session-related state.  There should not be an active connection
149  * to the client at this point.  The rest of the VM still thinks there is
150  * a debugger attached.
151  *
152  * This includes freeing up the debugger event list.
153  */
154 void dvmJdwpResetState(JdwpState* state)
155 {
156     /* could reset the serial numbers, but no need to */
157
158     dvmJdwpUnregisterAll(state);
159     assert(state->eventList == NULL);
160
161     /*
162      * Should not have one of these in progress.  If the debugger went away
163      * mid-request, though, we could see this.
164      */
165     if (state->eventThreadId != 0) {
166         LOGW("WARNING: resetting state while event in progress\n");
167         assert(false);
168     }
169 }
170
171 /*
172  * Tell the JDWP thread to shut down.  Frees "state".
173  */
174 void dvmJdwpShutdown(JdwpState* state)
175 {
176     void* threadReturn;
177
178     if (state == NULL)
179         return;
180
181     if (dvmJdwpIsTransportDefined(state)) {
182         if (dvmJdwpIsConnected(state))
183             dvmJdwpPostVMDeath(state);
184
185         /*
186          * Close down the network to inspire the thread to halt.
187          */
188         if (gDvm.verboseShutdown)
189             LOGD("JDWP shutting down net...\n");
190         dvmJdwpNetShutdown(state);
191
192         if (state->debugThreadStarted) {
193             state->run = false;
194             if (pthread_join(state->debugThreadHandle, &threadReturn) != 0) {
195                 LOGW("JDWP thread join failed\n");
196             }
197         }
198
199         if (gDvm.verboseShutdown)
200             LOGD("JDWP freeing netstate...\n");
201         dvmJdwpNetFree(state);
202         state->netState = NULL;
203     }
204     assert(state->netState == NULL);
205
206     dvmJdwpResetState(state);
207     free(state);
208 }
209
210 /*
211  * Are we talking to a debugger?
212  */
213 bool dvmJdwpIsActive(JdwpState* state)
214 {
215     return dvmJdwpIsConnected(state);
216 }
217
218 /*
219  * Entry point for JDWP thread.  The thread was created through the VM
220  * mechanisms, so there is a java/lang/Thread associated with us.
221  */
222 static void* jdwpThreadStart(void* arg)
223 {
224     JdwpState* state = (JdwpState*) arg;
225
226     LOGV("JDWP: thread running\n");
227
228     /*
229      * Finish initializing "state", then notify the creating thread that
230      * we're running.
231      */
232     state->debugThreadHandle = dvmThreadSelf()->handle;
233     state->run = true;
234     ANDROID_MEMBAR_FULL();
235     state->debugThreadStarted = true;       // touch this last
236
237     dvmDbgLockMutex(&state->threadStartLock);
238     dvmDbgCondBroadcast(&state->threadStartCond);
239     dvmDbgUnlockMutex(&state->threadStartLock);
240
241     /* set the thread state to VMWAIT so GCs don't wait for us */
242     dvmDbgThreadWaiting();
243
244     /*
245      * Loop forever if we're in server mode, processing connections.  In
246      * non-server mode, we bail out of the thread when the debugger drops
247      * us.
248      *
249      * We broadcast a notification when a debugger attaches, after we
250      * successfully process the handshake.
251      */
252     while (state->run) {
253         bool first;
254
255         if (state->params.server) {
256             /*
257              * Block forever, waiting for a connection.  To support the
258              * "timeout=xxx" option we'll need to tweak this.
259              */
260             if (!dvmJdwpAcceptConnection(state))
261                 break;
262         } else {
263             /*
264              * If we're not acting as a server, we need to connect out to the
265              * debugger.  To support the "timeout=xxx" option we need to
266              * have a timeout if the handshake reply isn't received in a
267              * reasonable amount of time.
268              */
269             if (!dvmJdwpEstablishConnection(state)) {
270                 /* wake anybody who was waiting for us to succeed */
271                 dvmDbgLockMutex(&state->attachLock);
272                 dvmDbgCondBroadcast(&state->attachCond);
273                 dvmDbgUnlockMutex(&state->attachLock);
274                 break;
275             }
276         }
277
278         /* prep debug code to handle the new connection */
279         dvmDbgConnected();
280
281         /* process requests until the debugger drops */
282         first = true;
283         while (true) {
284             // sanity check -- shouldn't happen?
285             if (dvmThreadSelf()->status != THREAD_VMWAIT) {
286                 LOGE("JDWP thread no longer in VMWAIT (now %d); resetting\n",
287                     dvmThreadSelf()->status);
288                 dvmDbgThreadWaiting();
289             }
290
291             if (!dvmJdwpProcessIncoming(state))     /* blocking read */
292                 break;
293
294             if (first && !dvmJdwpAwaitingHandshake(state)) {
295                 /* handshake worked, tell the interpreter that we're active */
296                 first = false;
297
298                 /* set thread ID; requires object registry to be active */
299                 state->debugThreadId = dvmDbgGetThreadSelfId();
300
301                 /* wake anybody who's waiting for us */
302                 dvmDbgLockMutex(&state->attachLock);
303                 dvmDbgCondBroadcast(&state->attachCond);
304                 dvmDbgUnlockMutex(&state->attachLock);
305             }
306         }
307
308         dvmJdwpCloseConnection(state);
309
310         if (state->ddmActive) {
311             state->ddmActive = false;
312
313             /* broadcast the disconnect; must be in RUNNING state */
314             dvmDbgThreadRunning();
315             dvmDbgDdmDisconnected();
316             dvmDbgThreadWaiting();
317         }
318
319         /* release session state, e.g. remove breakpoint instructions */
320         dvmJdwpResetState(state);
321
322         /* tell the interpreter that the debugger is no longer around */
323         dvmDbgDisconnected();
324
325         /* if we had threads suspended, resume them now */
326         dvmUndoDebuggerSuspensions();
327
328         /* if we connected out, this was a one-shot deal */
329         if (!state->params.server)
330             state->run = false;
331     }
332
333     /* back to running, for thread shutdown */
334     dvmDbgThreadRunning();
335
336     LOGV("JDWP: thread exiting\n");
337     return NULL;
338 }
339
340
341 /*
342  * Return the thread handle, or (pthread_t)0 if the debugger isn't running.
343  */
344 pthread_t dvmJdwpGetDebugThread(JdwpState* state)
345 {
346     if (state == NULL)
347         return 0;
348
349     return state->debugThreadHandle;
350 }
351
352
353 /*
354  * Support routines for waitForDebugger().
355  *
356  * We can't have a trivial "waitForDebugger" function that returns the
357  * instant the debugger connects, because we run the risk of executing code
358  * before the debugger has had a chance to configure breakpoints or issue
359  * suspend calls.  It would be nice to just sit in the suspended state, but
360  * most debuggers don't expect any threads to be suspended when they attach.
361  *
362  * There's no JDWP event we can post to tell the debugger, "we've stopped,
363  * and we like it that way".  We could send a fake breakpoint, which should
364  * cause the debugger to immediately send a resume, but the debugger might
365  * send the resume immediately or might throw an exception of its own upon
366  * receiving a breakpoint event that it didn't ask for.
367  *
368  * What we really want is a "wait until the debugger is done configuring
369  * stuff" event.  We can approximate this with a "wait until the debugger
370  * has been idle for a brief period".
371  */
372
373 /*
374  * Get a notion of the current time, in milliseconds.
375  */
376 s8 dvmJdwpGetNowMsec(void)
377 {
378 #ifdef HAVE_POSIX_CLOCKS
379     struct timespec now;
380     clock_gettime(CLOCK_MONOTONIC, &now);
381     return now.tv_sec * 1000LL + now.tv_nsec / 1000000LL;
382 #else
383     struct timeval now;
384     gettimeofday(&now, NULL);
385     return now.tv_sec * 1000LL + now.tv_usec / 1000LL;
386 #endif
387 }
388
389 /*
390  * Return the time, in milliseconds, since the last debugger activity.
391  *
392  * Returns -1 if no debugger is attached, or 0 if we're in the middle of
393  * processing a debugger request.
394  */
395 s8 dvmJdwpLastDebuggerActivity(JdwpState* state)
396 {
397     if (!gDvm.debuggerActive) {
398         LOGD("dvmJdwpLastDebuggerActivity: no active debugger\n");
399         return -1;
400     }
401
402     s8 last = dvmQuasiAtomicRead64(&state->lastActivityWhen);
403
404     /* initializing or in the middle of something? */
405     if (last == 0) {
406         LOGV("+++ last=busy\n");
407         return 0;
408     }
409
410     /* now get the current time */
411     s8 now = dvmJdwpGetNowMsec();
412     assert(now > last);
413
414     LOGV("+++ debugger interval=%lld\n", now - last);
415     return now - last;
416 }