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_atomic_release_store(true, &state->debugThreadStarted); 235 236 dvmDbgLockMutex(&state->threadStartLock); 237 dvmDbgCondBroadcast(&state->threadStartCond); 238 dvmDbgUnlockMutex(&state->threadStartLock); 239 240 /* set the thread state to VMWAIT so GCs don't wait for us */ 241 dvmDbgThreadWaiting(); 242 243 /* 244 * Loop forever if we're in server mode, processing connections. In 245 * non-server mode, we bail out of the thread when the debugger drops 246 * us. 247 * 248 * We broadcast a notification when a debugger attaches, after we 249 * successfully process the handshake. 250 */ 251 while (state->run) { 252 bool first; 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 /* release session state, e.g. remove breakpoint instructions */ 319 dvmJdwpResetState(state); 320 321 /* tell the interpreter that the debugger is no longer around */ 322 dvmDbgDisconnected(); 323 324 /* if we had threads suspended, resume them now */ 325 dvmUndoDebuggerSuspensions(); 326 327 /* if we connected out, this was a one-shot deal */ 328 if (!state->params.server) 329 state->run = false; 330 } 331 332 /* back to running, for thread shutdown */ 333 dvmDbgThreadRunning(); 334 335 LOGV("JDWP: thread exiting\n"); 336 return NULL; 337 } 338 339 340 /* 341 * Return the thread handle, or (pthread_t)0 if the debugger isn't running. 342 */ 343 pthread_t dvmJdwpGetDebugThread(JdwpState* state) 344 { 345 if (state == NULL) 346 return 0; 347 348 return state->debugThreadHandle; 349 } 350 351 352 /* 353 * Support routines for waitForDebugger(). 354 * 355 * We can't have a trivial "waitForDebugger" function that returns the 356 * instant the debugger connects, because we run the risk of executing code 357 * before the debugger has had a chance to configure breakpoints or issue 358 * suspend calls. It would be nice to just sit in the suspended state, but 359 * most debuggers don't expect any threads to be suspended when they attach. 360 * 361 * There's no JDWP event we can post to tell the debugger, "we've stopped, 362 * and 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 approximate this with a "wait until the debugger 369 * has been idle for a brief period". 370 */ 371 372 /* 373 * Get a notion of the current time, in milliseconds. 374 */ 375 s8 dvmJdwpGetNowMsec(void) 376 { 377 #ifdef HAVE_POSIX_CLOCKS 378 struct timespec now; 379 clock_gettime(CLOCK_MONOTONIC, &now); 380 return now.tv_sec * 1000LL + now.tv_nsec / 1000000LL; 381 #else 382 struct timeval now; 383 gettimeofday(&now, NULL); 384 return now.tv_sec * 1000LL + now.tv_usec / 1000LL; 385 #endif 386 } 387 388 /* 389 * Return the time, in milliseconds, since the last debugger activity. 390 * 391 * Returns -1 if no debugger is attached, or 0 if we're in the middle of 392 * processing a debugger request. 393 */ 394 s8 dvmJdwpLastDebuggerActivity(JdwpState* state) 395 { 396 if (!gDvm.debuggerActive) { 397 LOGD("dvmJdwpLastDebuggerActivity: no active debugger\n"); 398 return -1; 399 } 400 401 s8 last = dvmQuasiAtomicRead64(&state->lastActivityWhen); 402 403 /* initializing or in the middle of something? */ 404 if (last == 0) { 405 LOGV("+++ last=busy\n"); 406 return 0; 407 } 408 409 /* now get the current time */ 410 s8 now = dvmJdwpGetNowMsec(); 411 assert(now > last); 412 413 LOGV("+++ debugger interval=%lld\n", now - last); 414 return now - last; 415 } 416