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