PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/vm/jdwp/JdwpMain.c

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