• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * JDWP initialization.
18  */
19 #include "jdwp/JdwpPriv.h"
20 #include "Dalvik.h"
21 #include "Atomic.h"
22 
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/time.h>
26 #include <time.h>
27 #include <errno.h>
28 
29 
30 static void* jdwpThreadStart(void* arg);
31 
32 
33 /*
34  * Initialize JDWP.
35  *
36  * Does not return until JDWP thread is running, but may return before
37  * the thread is accepting network connections.
38  */
dvmJdwpStartup(const JdwpStartupParams * pParams)39 JdwpState* dvmJdwpStartup(const JdwpStartupParams* pParams)
40 {
41     JdwpState* state = NULL;
42     int i, sleepIter;
43     u8 startWhen;
44 
45     /* comment this out when debugging JDWP itself */
46     android_setMinPriority(LOG_TAG, ANDROID_LOG_DEBUG);
47 
48     state = (JdwpState*) calloc(1, sizeof(JdwpState));
49 
50     state->params = *pParams;
51 
52     state->requestSerial = 0x10000000;
53     state->eventSerial = 0x20000000;
54     dvmDbgInitMutex(&state->threadStartLock);
55     dvmDbgInitMutex(&state->attachLock);
56     dvmDbgInitMutex(&state->serialLock);
57     dvmDbgInitMutex(&state->eventLock);
58     state->eventThreadId = 0;
59     dvmDbgInitMutex(&state->eventThreadLock);
60     dvmDbgInitCond(&state->threadStartCond);
61     dvmDbgInitCond(&state->attachCond);
62     dvmDbgInitCond(&state->eventThreadCond);
63 
64     switch (pParams->transport) {
65     case kJdwpTransportSocket:
66         // LOGD("prepping for JDWP over TCP\n");
67         state->transport = dvmJdwpSocketTransport();
68         break;
69     case kJdwpTransportAndroidAdb:
70         // LOGD("prepping for JDWP over ADB\n");
71         state->transport = dvmJdwpAndroidAdbTransport();
72         /* TODO */
73         break;
74     default:
75         LOGE("Unknown transport %d\n", pParams->transport);
76         assert(false);
77         goto fail;
78     }
79 
80     if (!dvmJdwpNetStartup(state, pParams))
81         goto fail;
82 
83     /*
84      * Grab a mutex or two before starting the thread.  This ensures they
85      * won't signal the cond var before we're waiting.
86      */
87     dvmDbgLockMutex(&state->threadStartLock);
88     if (pParams->suspend)
89         dvmDbgLockMutex(&state->attachLock);
90 
91     /*
92      * We have bound to a port, or are trying to connect outbound to a
93      * debugger.  Create the JDWP thread and let it continue the mission.
94      */
95     if (!dvmCreateInternalThread(&state->debugThreadHandle, "JDWP",
96             jdwpThreadStart, state))
97     {
98         /* state is getting tossed, but unlock these anyway for cleanliness */
99         dvmDbgUnlockMutex(&state->threadStartLock);
100         if (pParams->suspend)
101             dvmDbgUnlockMutex(&state->attachLock);
102         goto fail;
103     }
104 
105     /*
106      * Wait until the thread finishes basic initialization.
107      * TODO: cond vars should be waited upon in a loop
108      */
109     dvmDbgCondWait(&state->threadStartCond, &state->threadStartLock);
110     dvmDbgUnlockMutex(&state->threadStartLock);
111 
112 
113     /*
114      * For suspend=y, wait for the debugger to connect to us or for us to
115      * connect to the debugger.
116      *
117      * The JDWP thread will signal us when it connects successfully or
118      * times out (for timeout=xxx), so we have to check to see what happened
119      * when we wake up.
120      */
121     if (pParams->suspend) {
122         dvmChangeStatus(NULL, THREAD_VMWAIT);
123         dvmDbgCondWait(&state->attachCond, &state->attachLock);
124         dvmDbgUnlockMutex(&state->attachLock);
125         dvmChangeStatus(NULL, THREAD_RUNNING);
126 
127         if (!dvmJdwpIsActive(state)) {
128             LOGE("JDWP connection failed\n");
129             goto fail;
130         }
131 
132         LOGI("JDWP connected\n");
133 
134         /*
135          * Ordinarily we would pause briefly to allow the debugger to set
136          * breakpoints and so on, but for "suspend=y" the VM init code will
137          * pause the VM when it sends the VM_START message.
138          */
139     }
140 
141     return state;
142 
143 fail:
144     dvmJdwpShutdown(state);     // frees state
145     return NULL;
146 }
147 
148 /*
149  * Reset all session-related state.  There should not be an active connection
150  * to the client at this point (we may be listening for a new one though).
151  *
152  * This includes freeing up the debugger event list.
153  */
dvmJdwpResetState(JdwpState * state)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  */
dvmJdwpShutdown(JdwpState * state)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         LOGD("JDWP shutting down net...\n");
189         dvmJdwpNetShutdown(state);
190 
191         if (state->debugThreadStarted) {
192             state->run = false;
193             if (pthread_join(state->debugThreadHandle, &threadReturn) != 0) {
194                 LOGW("JDWP thread join failed\n");
195             }
196         }
197 
198         LOGV("JDWP freeing netstate...\n");
199         dvmJdwpNetFree(state);
200         state->netState = NULL;
201     }
202     assert(state->netState == NULL);
203 
204     dvmJdwpResetState(state);
205     free(state);
206 }
207 
208 /*
209  * Are we talking to a debugger?
210  */
dvmJdwpIsActive(JdwpState * state)211 bool dvmJdwpIsActive(JdwpState* state)
212 {
213     return dvmJdwpIsConnected(state);
214 }
215 
216 /*
217  * Entry point for JDWP thread.  The thread was created through the VM
218  * mechanisms, so there is a java/lang/Thread associated with us.
219  */
jdwpThreadStart(void * arg)220 static void* jdwpThreadStart(void* arg)
221 {
222     JdwpState* state = (JdwpState*) arg;
223 
224     LOGV("JDWP: thread running\n");
225 
226     /*
227      * Finish initializing "state", then notify the creating thread that
228      * we're running.
229      */
230     state->debugThreadHandle = dvmThreadSelf()->handle;
231     state->run = true;
232     MEM_BARRIER();
233     state->debugThreadStarted = true;       // touch this last
234 
235     dvmDbgLockMutex(&state->threadStartLock);
236     dvmDbgCondBroadcast(&state->threadStartCond);
237     dvmDbgUnlockMutex(&state->threadStartLock);
238 
239     /* set the thread state to VMWAIT so GCs don't wait for us */
240     dvmDbgThreadWaiting();
241 
242     /*
243      * Loop forever if we're in server mode, processing connections.  In
244      * non-server mode, we bail out of the thread when the debugger drops
245      * us.
246      *
247      * We broadcast a notification when a debugger attaches, after we
248      * successfully process the handshake.
249      */
250     while (state->run) {
251         bool first;
252         int cc;
253 
254         if (state->params.server) {
255             /*
256              * Block forever, waiting for a connection.  To support the
257              * "timeout=xxx" option we'll need to tweak this.
258              */
259             if (!dvmJdwpAcceptConnection(state))
260                 break;
261         } else {
262             /*
263              * If we're not acting as a server, we need to connect out to the
264              * debugger.  To support the "timeout=xxx" option we need to
265              * have a timeout if the handshake reply isn't received in a
266              * reasonable amount of time.
267              */
268             if (!dvmJdwpEstablishConnection(state)) {
269                 /* wake anybody who was waiting for us to succeed */
270                 dvmDbgLockMutex(&state->attachLock);
271                 dvmDbgCondBroadcast(&state->attachCond);
272                 dvmDbgUnlockMutex(&state->attachLock);
273                 break;
274             }
275         }
276 
277         /* prep debug code to handle the new connection */
278         dvmDbgConnected();
279 
280         /* process requests until the debugger drops */
281         first = true;
282         while (true) {
283             // sanity check -- shouldn't happen?
284             if (dvmThreadSelf()->status != THREAD_VMWAIT) {
285                 LOGE("JDWP thread no longer in VMWAIT (now %d); resetting\n",
286                     dvmThreadSelf()->status);
287                 dvmDbgThreadWaiting();
288             }
289 
290             if (!dvmJdwpProcessIncoming(state))     /* blocking read */
291                 break;
292 
293             if (first && !dvmJdwpAwaitingHandshake(state)) {
294                 /* handshake worked, tell the interpreter that we're active */
295                 first = false;
296 
297                 /* set thread ID; requires object registry to be active */
298                 state->debugThreadId = dvmDbgGetThreadSelfId();
299 
300                 /* wake anybody who's waiting for us */
301                 dvmDbgLockMutex(&state->attachLock);
302                 dvmDbgCondBroadcast(&state->attachCond);
303                 dvmDbgUnlockMutex(&state->attachLock);
304             }
305         }
306 
307         dvmJdwpCloseConnection(state);
308 
309         if (state->ddmActive) {
310             state->ddmActive = false;
311 
312             /* broadcast the disconnect; must be in RUNNING state */
313             dvmDbgThreadRunning();
314             dvmDbgDdmDisconnected();
315             dvmDbgThreadWaiting();
316         }
317 
318         /* interpreter can ignore breakpoints */
319         dvmDbgDisconnected();
320 
321         /* if we had stuff suspended, resume it now */
322         dvmUndoDebuggerSuspensions();
323 
324         dvmJdwpResetState(state);
325 
326         /* if we connected out, this was a one-shot deal */
327         if (!state->params.server)
328             state->run = false;
329     }
330 
331     /* back to running, for thread shutdown */
332     dvmDbgThreadRunning();
333 
334     LOGV("JDWP: thread exiting\n");
335     return NULL;
336 }
337 
338 
339 /*
340  * Return the thread handle, or (pthread_t)0 if the debugger isn't running.
341  */
dvmJdwpGetDebugThread(JdwpState * state)342 pthread_t dvmJdwpGetDebugThread(JdwpState* state)
343 {
344     if (state == NULL)
345         return 0;
346 
347     return state->debugThreadHandle;
348 }
349 
350 #if 0
351 /*
352  * Wait until the debugger attaches.  Returns immediately if the debugger
353  * is already attached.
354  *
355  * If we return the instant the debugger connects, we run the risk of
356  * executing code before the debugger has had a chance to configure
357  * breakpoints or issue suspend calls.  It would be nice to just sit in
358  * the suspended state, but most debuggers don't expect any threads to be
359  * suspended when they attach.
360  *
361  * There's no event we can post to tell the debugger "we've stopped, and
362  * we like it that way".  We could send a fake breakpoint, which should
363  * cause the debugger to immediately send a resume, but the debugger might
364  * send the resume immediately or might throw an exception of its own upon
365  * receiving a breakpoint event that it didn't ask for.
366  *
367  * What we really want is a "wait until the debugger is done configuring
368  * stuff" event.  We can get close with a "wait until the debugger has
369  * been idle for a brief period", and we can do a mild approximation with
370  * "just sleep for a second after it connects".
371  *
372  * We should be in THREAD_VMWAIT here, so we're not allowed to do anything
373  * with objects because a GC could be in progress.
374  *
375  * NOTE: this trips as soon as something connects to the socket.  This
376  * is no longer appropriate -- we don't want to return when DDMS connects.
377  * We could fix this by polling for the first debugger packet, but we have
378  * to watch out for disconnects.  If we're going to do polling, it's
379  * probably best to do it at a higher level.
380  */
381 void dvmJdwpWaitForDebugger(JdwpState* state)
382 {
383     // no more
384 }
385 #endif
386 
387 /*
388  * Get a notion of the current time, in milliseconds.  We leave it in
389  * two 32-bit pieces.
390  */
dvmJdwpGetNowMsec(long * pSec,long * pMsec)391 void dvmJdwpGetNowMsec(long* pSec, long* pMsec)
392 {
393 #ifdef HAVE_POSIX_CLOCKS
394     struct timespec now;
395     clock_gettime(CLOCK_MONOTONIC, &now);
396     *pSec = now.tv_sec;
397     *pMsec = now.tv_nsec / 1000000;
398 #else
399     struct timeval now;
400     gettimeofday(&now, NULL);
401     *pSec = now.tv_sec;
402     *pMsec = now.tv_usec / 1000;
403 #endif
404 }
405 
406 /*
407  * Return the time, in milliseconds, since the last debugger activity.
408  *
409  * Returns -1 if no debugger is attached, or 0 if we're in the middle of
410  * processing a debugger request.
411  */
dvmJdwpLastDebuggerActivity(JdwpState * state)412 s8 dvmJdwpLastDebuggerActivity(JdwpState* state)
413 {
414     long lastSec, lastMsec;
415     long nowSec, nowMsec;
416 
417     /* these are volatile; lastSec becomes 0 during update */
418     lastSec = state->lastActivitySec;
419     lastMsec = state->lastActivityMsec;
420 
421     /* initializing or in the middle of something? */
422     if (lastSec == 0 || state->lastActivitySec != lastSec) {
423         //LOGI("+++ last=busy\n");
424         return 0;
425     }
426 
427     /* get the current time *after* latching the "last" time */
428     dvmJdwpGetNowMsec(&nowSec, &nowMsec);
429 
430     s8 last = (s8)lastSec * 1000 + lastMsec;
431     s8 now = (s8)nowSec * 1000 + nowMsec;
432 
433     //LOGI("last is %ld.%ld --> %lld\n", lastSec, lastMsec, last);
434     //LOGI("now is  %ld.%ld --> %lld\n", nowSec, nowMsec, now);
435 
436 
437     //LOGI("+++ interval=%lld\n", now - last);
438     return now - last;
439 }
440 
441