• 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  * Send events to the debugger.
18  */
19 #include "jdwp/JdwpPriv.h"
20 #include "jdwp/JdwpConstants.h"
21 #include "jdwp/JdwpHandler.h"
22 #include "jdwp/JdwpEvent.h"
23 #include "jdwp/ExpandBuf.h"
24 
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stddef.h>     /* for offsetof() */
28 #include <unistd.h>
29 
30 /*
31 General notes:
32 
33 The event add/remove stuff usually happens from the debugger thread,
34 in response to requests from the debugger, but can also happen as the
35 result of an event in an arbitrary thread (e.g. an event with a "count"
36 mod expires).  It's important to keep the event list locked when processing
37 events.
38 
39 Event posting can happen from any thread.  The JDWP thread will not usually
40 post anything but VM start/death, but if a JDWP request causes a class
41 to be loaded, the ClassPrepare event will come from the JDWP thread.
42 
43 
44 We can have serialization issues when we post an event to the debugger.
45 For example, a thread could send an "I hit a breakpoint and am suspending
46 myself" message to the debugger.  Before it manages to suspend itself, the
47 debugger's response ("not interested, resume thread") arrives and is
48 processed.  We try to resume a thread that hasn't yet suspended.
49 
50 This means that, after posting an event to the debugger, we need to wait
51 for the event thread to suspend itself (and, potentially, all other threads)
52 before processing any additional requests from the debugger.  While doing
53 so we need to be aware that multiple threads may be hitting breakpoints
54 or other events simultaneously, so we either need to wait for all of them
55 or serialize the events with each other.
56 
57 The current mechanism works like this:
58   Event thread:
59    - If I'm going to suspend, grab the "I am posting an event" token.  Wait
60      for it if it's not currently available.
61    - Post the event to the debugger.
62    - If appropriate, suspend others and then myself.  As part of suspending
63      myself, release the "I am posting" token.
64   JDWP thread:
65    - When an event arrives, see if somebody is posting an event.  If so,
66      sleep until we can acquire the "I am posting an event" token.  Release
67      it immediately and continue processing -- the event we have already
68      received should not interfere with other events that haven't yet
69      been posted.
70 
71 Some care must be taken to avoid deadlock:
72 
73  - thread A and thread B exit near-simultaneously, and post thread-death
74    events with a "suspend all" clause
75  - thread A gets the event token, thread B sits and waits for it
76  - thread A wants to suspend all other threads, but thread B is waiting
77    for the token and can't be suspended
78 
79 So we need to mark thread B in such a way that thread A doesn't wait for it.
80 
81 If we just bracket the "grab event token" call with a change to VMWAIT
82 before sleeping, the switch back to RUNNING state when we get the token
83 will cause thread B to suspend (remember, thread A's global suspend is
84 still in force, even after it releases the token).  Suspending while
85 holding the event token is very bad, because it prevents the JDWP thread
86 from processing incoming messages.
87 
88 We need to change to VMWAIT state at the *start* of posting an event,
89 and stay there until we either finish posting the event or decide to
90 put ourselves to sleep.  That way we don't interfere with anyone else and
91 don't allow anyone else to interfere with us.
92 */
93 
94 
95 #define kJdwpEventCommandSet    64
96 #define kJdwpCompositeCommand   100
97 
98 /*
99  * Stuff to compare against when deciding if a mod matches.  Only the
100  * values for mods valid for the event being evaluated will be filled in.
101  * The rest will be zeroed.
102  */
103 typedef struct ModBasket {
104     const JdwpLocation* pLoc;           /* LocationOnly */
105     const char*         className;      /* ClassMatch/ClassExclude */
106     ObjectId            threadId;       /* ThreadOnly */
107     RefTypeId           classId;        /* ClassOnly */
108     RefTypeId           excepClassId;   /* ExceptionOnly */
109     bool                caught;         /* ExceptionOnly */
110     FieldId             field;          /* FieldOnly */
111     ObjectId            thisPtr;        /* InstanceOnly */
112     /* nothing for StepOnly -- handled differently */
113 } ModBasket;
114 
115 /*
116  * Get the next "request" serial number.  We use this when sending
117  * packets to the debugger.
118  */
dvmJdwpNextRequestSerial(JdwpState * state)119 u4 dvmJdwpNextRequestSerial(JdwpState* state)
120 {
121     u4 result;
122 
123     dvmDbgLockMutex(&state->serialLock);
124     result = state->requestSerial++;
125     dvmDbgUnlockMutex(&state->serialLock);
126 
127     return result;
128 }
129 
130 /*
131  * Get the next "event" serial number.  We use this in the response to
132  * message type EventRequest.Set.
133  */
dvmJdwpNextEventSerial(JdwpState * state)134 u4 dvmJdwpNextEventSerial(JdwpState* state)
135 {
136     u4 result;
137 
138     dvmDbgLockMutex(&state->serialLock);
139     result = state->eventSerial++;
140     dvmDbgUnlockMutex(&state->serialLock);
141 
142     return result;
143 }
144 
145 /*
146  * Lock the "event" mutex, which guards the list of registered events.
147  */
lockEventMutex(JdwpState * state)148 static void lockEventMutex(JdwpState* state)
149 {
150     //dvmDbgThreadWaiting();
151     dvmDbgLockMutex(&state->eventLock);
152     //dvmDbgThreadRunning();
153 }
154 
155 /*
156  * Unlock the "event" mutex.
157  */
unlockEventMutex(JdwpState * state)158 static void unlockEventMutex(JdwpState* state)
159 {
160     dvmDbgUnlockMutex(&state->eventLock);
161 }
162 
163 /*
164  * Add an event to the list.  Ordering is not important.
165  *
166  * If something prevents the event from being registered, e.g. it's a
167  * single-step request on a thread that doesn't exist, the event will
168  * not be added to the list, and an appropriate error will be returned.
169  */
dvmJdwpRegisterEvent(JdwpState * state,JdwpEvent * pEvent)170 JdwpError dvmJdwpRegisterEvent(JdwpState* state, JdwpEvent* pEvent)
171 {
172     JdwpError err = ERR_NONE;
173     int i;
174 
175     lockEventMutex(state);
176 
177     assert(state != NULL);
178     assert(pEvent != NULL);
179     assert(pEvent->prev == NULL);
180     assert(pEvent->next == NULL);
181 
182     /*
183      * If one or more LocationOnly mods are used, register them with
184      * the interpreter.
185      */
186     for (i = 0; i < pEvent->modCount; i++) {
187         JdwpEventMod* pMod = &pEvent->mods[i];
188         if (pMod->modKind == MK_LOCATION_ONLY) {
189             /* should only be for Breakpoint, Step, and Exception */
190             dvmDbgWatchLocation(&pMod->locationOnly.loc);
191         }
192         if (pMod->modKind == MK_STEP) {
193             /* should only be for EK_SINGLE_STEP; should only be one */
194             dvmDbgConfigureStep(pMod->step.threadId, pMod->step.size,
195                 pMod->step.depth);
196         }
197     }
198 
199     /*
200      * Add to list.
201      */
202     if (state->eventList != NULL) {
203         pEvent->next = state->eventList;
204         state->eventList->prev = pEvent;
205     }
206     state->eventList = pEvent;
207     state->numEvents++;
208 
209     unlockEventMutex(state);
210 
211     return err;
212 }
213 
214 /*
215  * Remove an event from the list.  This will also remove the event from
216  * any optimization tables, e.g. breakpoints.
217  *
218  * Does not free the JdwpEvent.
219  *
220  * Grab the eventLock before calling here.
221  */
unregisterEvent(JdwpState * state,JdwpEvent * pEvent)222 static void unregisterEvent(JdwpState* state, JdwpEvent* pEvent)
223 {
224     int i;
225 
226     if (pEvent->prev == NULL) {
227         /* head of the list */
228         assert(state->eventList == pEvent);
229 
230         state->eventList = pEvent->next;
231     } else {
232         pEvent->prev->next = pEvent->next;
233     }
234 
235     if (pEvent->next != NULL) {
236         pEvent->next->prev = pEvent->prev;
237         pEvent->next = NULL;
238     }
239     pEvent->prev = NULL;
240 
241     /*
242      * Unhook us from the interpreter, if necessary.
243      */
244     for (i = 0; i < pEvent->modCount; i++) {
245         JdwpEventMod* pMod = &pEvent->mods[i];
246         if (pMod->modKind == MK_LOCATION_ONLY) {
247             /* should only be for Breakpoint, Step, and Exception */
248             dvmDbgUnwatchLocation(&pMod->locationOnly.loc);
249         }
250         if (pMod->modKind == MK_STEP) {
251             /* should only be for EK_SINGLE_STEP; should only be one */
252             dvmDbgUnconfigureStep(pMod->step.threadId);
253         }
254     }
255 
256     state->numEvents--;
257     assert(state->numEvents != 0 || state->eventList == NULL);
258 }
259 
260 /*
261  * Remove the event with the given ID from the list.
262  *
263  * Failure to find the event isn't really an error, but it is a little
264  * weird.  (It looks like Eclipse will try to be extra careful and will
265  * explicitly remove one-off single-step events.)
266  */
dvmJdwpUnregisterEventById(JdwpState * state,u4 requestId)267 void dvmJdwpUnregisterEventById(JdwpState* state, u4 requestId)
268 {
269     JdwpEvent* pEvent;
270 
271     lockEventMutex(state);
272 
273     pEvent = state->eventList;
274     while (pEvent != NULL) {
275         if (pEvent->requestId == requestId) {
276             unregisterEvent(state, pEvent);
277             dvmJdwpEventFree(pEvent);
278             goto done;      /* there can be only one with a given ID */
279         }
280 
281         pEvent = pEvent->next;
282     }
283 
284     //LOGD("Odd: no match when removing event reqId=0x%04x\n", requestId);
285 
286 done:
287     unlockEventMutex(state);
288 }
289 
290 /*
291  * Remove all entries from the event list.
292  */
dvmJdwpUnregisterAll(JdwpState * state)293 void dvmJdwpUnregisterAll(JdwpState* state)
294 {
295     JdwpEvent* pEvent;
296     JdwpEvent* pNextEvent;
297 
298     lockEventMutex(state);
299 
300     pEvent = state->eventList;
301     while (pEvent != NULL) {
302         pNextEvent = pEvent->next;
303 
304         unregisterEvent(state, pEvent);
305         dvmJdwpEventFree(pEvent);
306         pEvent = pNextEvent;
307     }
308 
309     state->eventList = NULL;
310 
311     unlockEventMutex(state);
312 }
313 
314 
315 
316 /*
317  * Allocate a JdwpEvent struct with enough space to hold the specified
318  * number of mod records.
319  */
dvmJdwpEventAlloc(int numMods)320 JdwpEvent* dvmJdwpEventAlloc(int numMods)
321 {
322     JdwpEvent* newEvent;
323     int allocSize = offsetof(JdwpEvent, mods) +
324                     numMods * sizeof(newEvent->mods[0]);
325 
326     newEvent = (JdwpEvent*)malloc(allocSize);
327     memset(newEvent, 0, allocSize);
328     return newEvent;
329 }
330 
331 /*
332  * Free a JdwpEvent.
333  *
334  * Do not call this until the event has been removed from the list.
335  */
dvmJdwpEventFree(JdwpEvent * pEvent)336 void dvmJdwpEventFree(JdwpEvent* pEvent)
337 {
338     int i;
339 
340     if (pEvent == NULL)
341         return;
342 
343     /* make sure it was removed from the list */
344     assert(pEvent->prev == NULL);
345     assert(pEvent->next == NULL);
346     /* want to assert state->eventList != pEvent */
347 
348     /*
349      * Free any hairy bits in the mods.
350      */
351     for (i = 0; i < pEvent->modCount; i++) {
352         if (pEvent->mods[i].modKind == MK_CLASS_MATCH) {
353             free(pEvent->mods[i].classMatch.classPattern);
354             pEvent->mods[i].classMatch.classPattern = NULL;
355         }
356         if (pEvent->mods[i].modKind == MK_CLASS_EXCLUDE) {
357             free(pEvent->mods[i].classExclude.classPattern);
358             pEvent->mods[i].classExclude.classPattern = NULL;
359         }
360     }
361 
362     free(pEvent);
363 }
364 
365 /*
366  * Allocate storage for matching events.  To keep things simple we
367  * use an array with enough storage for the entire list.
368  *
369  * The state->eventLock should be held before calling.
370  */
allocMatchList(JdwpState * state)371 static JdwpEvent** allocMatchList(JdwpState* state)
372 {
373     return (JdwpEvent**) malloc(sizeof(JdwpEvent*) * state->numEvents);
374 }
375 
376 /*
377  * Run through the list and remove any entries with an expired "count" mod
378  * from the event list, then free the match list.
379  */
cleanupMatchList(JdwpState * state,JdwpEvent ** matchList,int matchCount)380 static void cleanupMatchList(JdwpState* state, JdwpEvent** matchList,
381     int matchCount)
382 {
383     JdwpEvent** ppEvent = matchList;
384 
385     while (matchCount--) {
386         JdwpEvent* pEvent = *ppEvent;
387         int i;
388 
389         for (i = 0; i < pEvent->modCount; i++) {
390             if (pEvent->mods[i].modKind == MK_COUNT &&
391                 pEvent->mods[i].count.count == 0)
392             {
393                 LOGV("##### Removing expired event\n");
394                 unregisterEvent(state, pEvent);
395                 dvmJdwpEventFree(pEvent);
396                 break;
397             }
398         }
399 
400         ppEvent++;
401     }
402 
403     free(matchList);
404 }
405 
406 /*
407  * Match a string against a "restricted regular expression", which is just
408  * a string that may start or end with '*' (e.g. "*.Foo" or "java.*").
409  *
410  * ("Restricted name globbing" might have been a better term.)
411  */
patternMatch(const char * pattern,const char * target)412 static bool patternMatch(const char* pattern, const char* target)
413 {
414     int patLen = strlen(pattern);
415 
416     if (pattern[0] == '*') {
417         int targetLen = strlen(target);
418         patLen--;
419         // TODO: remove printf when we find a test case to verify this
420         LOGE(">>> comparing '%s' to '%s'\n",
421             pattern+1, target + (targetLen-patLen));
422 
423         if (targetLen < patLen)
424             return false;
425         return strcmp(pattern+1, target + (targetLen-patLen)) == 0;
426     } else if (pattern[patLen-1] == '*') {
427         return strncmp(pattern, target, patLen-1) == 0;
428     } else {
429         return strcmp(pattern, target) == 0;
430     }
431 }
432 
433 /*
434  * See if two locations are equal.
435  *
436  * It's tempting to do a bitwise compare ("struct ==" or memcmp), but if
437  * the storage wasn't zeroed out there could be undefined values in the
438  * padding.  Besides, the odds of "idx" being equal while the others aren't
439  * is very small, so this is usually just a simple integer comparison.
440  */
locationMatch(const JdwpLocation * pLoc1,const JdwpLocation * pLoc2)441 static inline bool locationMatch(const JdwpLocation* pLoc1,
442     const JdwpLocation* pLoc2)
443 {
444     return pLoc1->idx == pLoc2->idx &&
445            pLoc1->methodId == pLoc2->methodId &&
446            pLoc1->classId == pLoc2->classId &&
447            pLoc1->typeTag == pLoc2->typeTag;
448 }
449 
450 /*
451  * See if the event's mods match up with the contents of "basket".
452  *
453  * If we find a Count mod before rejecting an event, we decrement it.  We
454  * need to do this even if later mods cause us to ignore the event.
455  */
modsMatch(JdwpState * state,JdwpEvent * pEvent,ModBasket * basket)456 static bool modsMatch(JdwpState* state, JdwpEvent* pEvent, ModBasket* basket)
457 {
458     JdwpEventMod* pMod = pEvent->mods;
459     int i;
460 
461     for (i = pEvent->modCount; i > 0; i--, pMod++) {
462         switch (pMod->modKind) {
463         case MK_COUNT:
464             assert(pMod->count.count > 0);
465             pMod->count.count--;
466             break;
467         case MK_CONDITIONAL:
468             assert(false);  // should not be getting these
469             break;
470         case MK_THREAD_ONLY:
471             if (pMod->threadOnly.threadId != basket->threadId)
472                 return false;
473             break;
474         case MK_CLASS_ONLY:
475             if (!dvmDbgMatchType(basket->classId,
476                     pMod->classOnly.referenceTypeId))
477                 return false;
478             break;
479         case MK_CLASS_MATCH:
480             if (!patternMatch(pMod->classMatch.classPattern,
481                     basket->className))
482                 return false;
483             break;
484         case MK_CLASS_EXCLUDE:
485             if (patternMatch(pMod->classMatch.classPattern,
486                     basket->className))
487                 return false;
488             break;
489         case MK_LOCATION_ONLY:
490             if (!locationMatch(&pMod->locationOnly.loc, basket->pLoc))
491                 return false;
492             break;
493         case MK_EXCEPTION_ONLY:
494             if (pMod->exceptionOnly.refTypeId != 0 &&
495                 !dvmDbgMatchType(basket->excepClassId,
496                                  pMod->exceptionOnly.refTypeId))
497                 return false;
498             if ((basket->caught && !pMod->exceptionOnly.caught) ||
499                 (!basket->caught && !pMod->exceptionOnly.uncaught))
500                 return false;
501             break;
502         case MK_FIELD_ONLY:
503             // TODO
504             break;
505         case MK_STEP:
506             if (pMod->step.threadId != basket->threadId)
507                 return false;
508             break;
509         case MK_INSTANCE_ONLY:
510             if (pMod->instanceOnly.objectId != basket->thisPtr)
511                 return false;
512             break;
513         default:
514             LOGE("unhandled mod kind %d\n", pMod->modKind);
515             assert(false);
516             break;
517         }
518     }
519 
520     return true;
521 }
522 
523 /*
524  * Find all events of type "eventKind" with mods that match up with the
525  * rest of the arguments.
526  *
527  * Found events are appended to "matchList", and "*pMatchCount" is advanced,
528  * so this may be called multiple times for grouped events.
529  *
530  * DO NOT call this multiple times for the same eventKind, as Count mods are
531  * decremented during the scan.
532  */
findMatchingEvents(JdwpState * state,enum JdwpEventKind eventKind,ModBasket * basket,JdwpEvent ** matchList,int * pMatchCount)533 static void findMatchingEvents(JdwpState* state, enum JdwpEventKind eventKind,
534     ModBasket* basket, JdwpEvent** matchList, int* pMatchCount)
535 {
536     JdwpEvent* pEvent;
537 
538     /* start after the existing entries */
539     matchList += *pMatchCount;
540 
541     pEvent = state->eventList;
542     while (pEvent != NULL) {
543         if (pEvent->eventKind == eventKind && modsMatch(state, pEvent, basket))
544         {
545             *matchList++ = pEvent;
546             (*pMatchCount)++;
547         }
548 
549         pEvent = pEvent->next;
550     }
551 }
552 
553 /*
554  * Scan through the list of matches and determine the most severe
555  * suspension policy.
556  */
scanSuspendPolicy(JdwpEvent ** matchList,int matchCount)557 static enum JdwpSuspendPolicy scanSuspendPolicy(JdwpEvent** matchList,
558     int matchCount)
559 {
560     enum JdwpSuspendPolicy policy = SP_NONE;
561 
562     while (matchCount--) {
563         if ((*matchList)->suspendPolicy > policy)
564             policy = (*matchList)->suspendPolicy;
565         matchList++;
566     }
567 
568     return policy;
569 }
570 
571 /*
572  * Three possibilities:
573  *  SP_NONE - do nothing
574  *  SP_EVENT_THREAD - suspend ourselves
575  *  SP_ALL - suspend everybody except JDWP support thread
576  */
suspendByPolicy(JdwpState * state,enum JdwpSuspendPolicy suspendPolicy)577 static void suspendByPolicy(JdwpState* state,
578     enum JdwpSuspendPolicy suspendPolicy)
579 {
580     if (suspendPolicy == SP_NONE)
581         return;
582 
583     if (suspendPolicy == SP_ALL) {
584         dvmDbgSuspendVM(true);
585     } else {
586         assert(suspendPolicy == SP_EVENT_THREAD);
587     }
588 
589     /* this is rare but possible -- see CLASS_PREPARE handling */
590     if (dvmDbgGetThreadSelfId() == state->debugThreadId) {
591         LOGI("NOTE: suspendByPolicy not suspending JDWP thread\n");
592         return;
593     }
594 
595     DebugInvokeReq* pReq = dvmDbgGetInvokeReq();
596     while (true) {
597         pReq->ready = true;
598         dvmDbgSuspendSelf();
599         pReq->ready = false;
600 
601         /*
602          * The JDWP thread has told us (and possibly all other threads) to
603          * resume.  See if it has left anything in our DebugInvokeReq mailbox.
604          */
605         if (!pReq->invokeNeeded) {
606             /*LOGD("suspendByPolicy: no invoke needed\n");*/
607             break;
608         }
609 
610         /* grab this before posting/suspending again */
611         dvmJdwpSetWaitForEventThread(state, dvmDbgGetThreadSelfId());
612 
613         /* leave pReq->invokeNeeded raised so we can check reentrancy */
614         LOGV("invoking method...\n");
615         dvmDbgExecuteMethod(pReq);
616 
617         pReq->err = ERR_NONE;
618 
619         /* clear this before signaling */
620         pReq->invokeNeeded = false;
621 
622         LOGV("invoke complete, signaling and self-suspending\n");
623         dvmDbgLockMutex(&pReq->lock);
624         dvmDbgCondSignal(&pReq->cv);
625         dvmDbgUnlockMutex(&pReq->lock);
626     }
627 }
628 
629 /*
630  * Determine if there is a method invocation in progress in the current
631  * thread.
632  *
633  * We look at the "invokeNeeded" flag in the per-thread DebugInvokeReq
634  * state.  If set, we're in the process of invoking a method.
635  */
invokeInProgress(JdwpState * state)636 static bool invokeInProgress(JdwpState* state)
637 {
638     DebugInvokeReq* pReq = dvmDbgGetInvokeReq();
639     return pReq->invokeNeeded;
640 }
641 
642 /*
643  * We need the JDWP thread to hold off on doing stuff while we post an
644  * event and then suspend ourselves.
645  *
646  * Call this with a threadId of zero if you just want to wait for the
647  * current thread operation to complete.
648  *
649  * This could go to sleep waiting for another thread, so it's important
650  * that the thread be marked as VMWAIT before calling here.
651  */
dvmJdwpSetWaitForEventThread(JdwpState * state,ObjectId threadId)652 void dvmJdwpSetWaitForEventThread(JdwpState* state, ObjectId threadId)
653 {
654     bool waited = false;
655 
656     /* this is held for very brief periods; contention is unlikely */
657     dvmDbgLockMutex(&state->eventThreadLock);
658 
659     /*
660      * If another thread is already doing stuff, wait for it.  This can
661      * go to sleep indefinitely.
662      */
663     while (state->eventThreadId != 0) {
664         LOGV("event in progress (0x%llx), 0x%llx sleeping\n",
665             state->eventThreadId, threadId);
666         waited = true;
667         dvmDbgCondWait(&state->eventThreadCond, &state->eventThreadLock);
668     }
669 
670     if (waited || threadId != 0)
671         LOGV("event token grabbed (0x%llx)\n", threadId);
672     if (threadId != 0)
673         state->eventThreadId = threadId;
674 
675     dvmDbgUnlockMutex(&state->eventThreadLock);
676 }
677 
678 /*
679  * Clear the threadId and signal anybody waiting.
680  */
dvmJdwpClearWaitForEventThread(JdwpState * state)681 void dvmJdwpClearWaitForEventThread(JdwpState* state)
682 {
683     /*
684      * Grab the mutex.  Don't try to go in/out of VMWAIT mode, as this
685      * function is called by dvmSuspendSelf(), and the transition back
686      * to RUNNING would confuse it.
687      */
688     dvmDbgLockMutex(&state->eventThreadLock);
689 
690     assert(state->eventThreadId != 0);
691     LOGV("cleared event token (0x%llx)\n", state->eventThreadId);
692 
693     state->eventThreadId = 0;
694 
695     dvmDbgCondSignal(&state->eventThreadCond);
696 
697     dvmDbgUnlockMutex(&state->eventThreadLock);
698 }
699 
700 
701 /*
702  * Prep an event.  Allocates storage for the message and leaves space for
703  * the header.
704  */
eventPrep(void)705 static ExpandBuf* eventPrep(void)
706 {
707     ExpandBuf* pReq;
708 
709     pReq = expandBufAlloc();
710     expandBufAddSpace(pReq, kJDWPHeaderLen);
711 
712     return pReq;
713 }
714 
715 /*
716  * Write the header into the buffer and send the packet off to the debugger.
717  *
718  * Takes ownership of "pReq" (currently discards it).
719  */
eventFinish(JdwpState * state,ExpandBuf * pReq)720 static void eventFinish(JdwpState* state, ExpandBuf* pReq)
721 {
722     u1* buf = expandBufGetBuffer(pReq);
723 
724     set4BE(buf, expandBufGetLength(pReq));
725     set4BE(buf+4, dvmJdwpNextRequestSerial(state));
726     set1(buf+8, 0);     /* flags */
727     set1(buf+9, kJdwpEventCommandSet);
728     set1(buf+10, kJdwpCompositeCommand);
729 
730     dvmJdwpSendRequest(state, pReq);
731 
732     expandBufFree(pReq);
733 }
734 
735 
736 /*
737  * Tell the debugger that we have finished initializing.  This is always
738  * sent, even if the debugger hasn't requested it.
739  *
740  * This should be sent "before the main thread is started and before
741  * any application code has been executed".  The thread ID in the message
742  * must be for the main thread.
743  */
dvmJdwpPostVMStart(JdwpState * state,bool suspend)744 bool dvmJdwpPostVMStart(JdwpState* state, bool suspend)
745 {
746     enum JdwpSuspendPolicy suspendPolicy;
747     ObjectId threadId = dvmDbgGetThreadSelfId();
748 
749     if (suspend)
750         suspendPolicy = SP_ALL;
751     else
752         suspendPolicy = SP_NONE;
753 
754     /* probably don't need this here */
755     lockEventMutex(state);
756 
757     ExpandBuf* pReq = NULL;
758     if (true) {
759         LOGV("EVENT: %s\n", dvmJdwpEventKindStr(EK_VM_START));
760         LOGV("  suspendPolicy=%s\n", dvmJdwpSuspendPolicyStr(suspendPolicy));
761 
762         pReq = eventPrep();
763         expandBufAdd1(pReq, suspendPolicy);
764         expandBufAdd4BE(pReq, 1);
765 
766         expandBufAdd1(pReq, EK_VM_START);
767         expandBufAdd4BE(pReq, 0);       /* requestId */
768         expandBufAdd8BE(pReq, threadId);
769     }
770 
771     unlockEventMutex(state);
772 
773     /* send request and possibly suspend ourselves */
774     if (pReq != NULL) {
775         int oldStatus = dvmDbgThreadWaiting();
776         if (suspendPolicy != SP_NONE)
777             dvmJdwpSetWaitForEventThread(state, threadId);
778 
779         eventFinish(state, pReq);
780 
781         suspendByPolicy(state, suspendPolicy);
782         dvmDbgThreadContinuing(oldStatus);
783     }
784 
785     return true;
786 }
787 
788 /*
789  * A location of interest has been reached.  This handles:
790  *   Breakpoint
791  *   SingleStep
792  *   MethodEntry
793  *   MethodExit
794  * These four types must be grouped together in a single response.  The
795  * "eventFlags" indicates the type of event(s) that have happened.
796  *
797  * Valid mods:
798  *   Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, InstanceOnly
799  *   LocationOnly (for breakpoint/step only)
800  *   Step (for step only)
801  *
802  * Interesting test cases:
803  *  - Put a breakpoint on a native method.  Eclipse creates METHOD_ENTRY
804  *    and METHOD_EXIT events with a ClassOnly mod on the method's class.
805  *  - Use "run to line".  Eclipse creates a BREAKPOINT with Count=1.
806  *  - Single-step to a line with a breakpoint.  Should get a single
807  *    event message with both events in it.
808  */
dvmJdwpPostLocationEvent(JdwpState * state,const JdwpLocation * pLoc,ObjectId thisPtr,int eventFlags)809 bool dvmJdwpPostLocationEvent(JdwpState* state, const JdwpLocation* pLoc,
810     ObjectId thisPtr, int eventFlags)
811 {
812     enum JdwpSuspendPolicy suspendPolicy = SP_NONE;
813     ModBasket basket;
814     JdwpEvent** matchList;
815     int matchCount;
816     char* nameAlloc = NULL;
817 
818     memset(&basket, 0, sizeof(basket));
819     basket.pLoc = pLoc;
820     basket.classId = pLoc->classId;
821     basket.thisPtr = thisPtr;
822     basket.threadId = dvmDbgGetThreadSelfId();
823     basket.className = nameAlloc =
824         dvmDescriptorToName(dvmDbgGetClassDescriptor(pLoc->classId));
825 
826     /*
827      * On rare occasions we may need to execute interpreted code in the VM
828      * while handling a request from the debugger.  Don't fire breakpoints
829      * while doing so.  (I don't think we currently do this at all, so
830      * this is mostly paranoia.)
831      */
832     if (basket.threadId == state->debugThreadId) {
833         LOGV("Ignoring location event in JDWP thread\n");
834         free(nameAlloc);
835         return false;
836     }
837 
838     /*
839      * The debugger variable display tab may invoke the interpreter to format
840      * complex objects.  We want to ignore breakpoints and method entry/exit
841      * traps while working on behalf of the debugger.
842      *
843      * If we don't ignore them, the VM will get hung up, because we'll
844      * suspend on a breakpoint while the debugger is still waiting for its
845      * method invocation to complete.
846      */
847     if (invokeInProgress(state)) {
848         LOGV("Not checking breakpoints during invoke (%s)\n", basket.className);
849         free(nameAlloc);
850         return false;
851     }
852 
853     /* don't allow the list to be updated while we scan it */
854     lockEventMutex(state);
855 
856     matchList = allocMatchList(state);
857     matchCount = 0;
858 
859     if ((eventFlags & DBG_BREAKPOINT) != 0)
860         findMatchingEvents(state, EK_BREAKPOINT, &basket, matchList,
861             &matchCount);
862     if ((eventFlags & DBG_SINGLE_STEP) != 0)
863         findMatchingEvents(state, EK_SINGLE_STEP, &basket, matchList,
864             &matchCount);
865     if ((eventFlags & DBG_METHOD_ENTRY) != 0)
866         findMatchingEvents(state, EK_METHOD_ENTRY, &basket, matchList,
867             &matchCount);
868     if ((eventFlags & DBG_METHOD_EXIT) != 0)
869         findMatchingEvents(state, EK_METHOD_EXIT, &basket, matchList,
870             &matchCount);
871 
872     ExpandBuf* pReq = NULL;
873     if (matchCount != 0) {
874         int i;
875 
876         LOGV("EVENT: %s(%d total) %s.%s thread=%llx code=%llx)\n",
877             dvmJdwpEventKindStr(matchList[0]->eventKind), matchCount,
878             basket.className,
879             dvmDbgGetMethodName(pLoc->classId, pLoc->methodId),
880             basket.threadId, pLoc->idx);
881 
882         suspendPolicy = scanSuspendPolicy(matchList, matchCount);
883         LOGV("  suspendPolicy=%s\n",
884             dvmJdwpSuspendPolicyStr(suspendPolicy));
885 
886         pReq = eventPrep();
887         expandBufAdd1(pReq, suspendPolicy);
888         expandBufAdd4BE(pReq, matchCount);
889 
890         for (i = 0; i < matchCount; i++) {
891             expandBufAdd1(pReq, matchList[i]->eventKind);
892             expandBufAdd4BE(pReq, matchList[i]->requestId);
893             expandBufAdd8BE(pReq, basket.threadId);
894             dvmJdwpAddLocation(pReq, pLoc);
895         }
896     }
897 
898     cleanupMatchList(state, matchList, matchCount);
899     unlockEventMutex(state);
900 
901     /* send request and possibly suspend ourselves */
902     if (pReq != NULL) {
903         int oldStatus = dvmDbgThreadWaiting();
904         if (suspendPolicy != SP_NONE)
905             dvmJdwpSetWaitForEventThread(state, basket.threadId);
906 
907         eventFinish(state, pReq);
908 
909         suspendByPolicy(state, suspendPolicy);
910         dvmDbgThreadContinuing(oldStatus);
911     }
912 
913     free(nameAlloc);
914     return matchCount != 0;
915 }
916 
917 /*
918  * A thread is starting or stopping.
919  *
920  * Valid mods:
921  *  Count, ThreadOnly
922  */
dvmJdwpPostThreadChange(JdwpState * state,ObjectId threadId,bool start)923 bool dvmJdwpPostThreadChange(JdwpState* state, ObjectId threadId, bool start)
924 {
925     enum JdwpSuspendPolicy suspendPolicy = SP_NONE;
926     ModBasket basket;
927     JdwpEvent** matchList;
928     int matchCount;
929 
930     assert(threadId = dvmDbgGetThreadSelfId());
931 
932     /*
933      * I don't think this can happen.
934      */
935     if (invokeInProgress(state)) {
936         LOGW("Not posting thread change during invoke\n");
937         return false;
938     }
939 
940     memset(&basket, 0, sizeof(basket));
941     basket.threadId = threadId;
942 
943     /* don't allow the list to be updated while we scan it */
944     lockEventMutex(state);
945 
946     matchList = allocMatchList(state);
947     matchCount = 0;
948 
949     if (start)
950         findMatchingEvents(state, EK_THREAD_START, &basket, matchList,
951             &matchCount);
952     else
953         findMatchingEvents(state, EK_THREAD_DEATH, &basket, matchList,
954             &matchCount);
955 
956     ExpandBuf* pReq = NULL;
957     if (matchCount != 0) {
958         int i;
959 
960         LOGV("EVENT: %s(%d total) thread=%llx)\n",
961             dvmJdwpEventKindStr(matchList[0]->eventKind), matchCount,
962             basket.threadId);
963 
964         suspendPolicy = scanSuspendPolicy(matchList, matchCount);
965         LOGV("  suspendPolicy=%s\n",
966             dvmJdwpSuspendPolicyStr(suspendPolicy));
967 
968         pReq = eventPrep();
969         expandBufAdd1(pReq, suspendPolicy);
970         expandBufAdd4BE(pReq, matchCount);
971 
972         for (i = 0; i < matchCount; i++) {
973             expandBufAdd1(pReq, matchList[i]->eventKind);
974             expandBufAdd4BE(pReq, matchList[i]->requestId);
975             expandBufAdd8BE(pReq, basket.threadId);
976         }
977 
978     }
979 
980     cleanupMatchList(state, matchList, matchCount);
981     unlockEventMutex(state);
982 
983     /* send request and possibly suspend ourselves */
984     if (pReq != NULL) {
985         int oldStatus = dvmDbgThreadWaiting();
986         if (suspendPolicy != SP_NONE)
987             dvmJdwpSetWaitForEventThread(state, basket.threadId);
988 
989         eventFinish(state, pReq);
990 
991         suspendByPolicy(state, suspendPolicy);
992         dvmDbgThreadContinuing(oldStatus);
993     }
994 
995     return matchCount != 0;
996 }
997 
998 /*
999  * Send a polite "VM is dying" message to the debugger.
1000  *
1001  * Skips the usual "event token" stuff.
1002  */
dvmJdwpPostVMDeath(JdwpState * state)1003 bool dvmJdwpPostVMDeath(JdwpState* state)
1004 {
1005     ExpandBuf* pReq;
1006 
1007     LOGV("EVENT: %s\n", dvmJdwpEventKindStr(EK_VM_DEATH));
1008 
1009     pReq = eventPrep();
1010     expandBufAdd1(pReq, SP_NONE);
1011     expandBufAdd4BE(pReq, 1);
1012 
1013     expandBufAdd1(pReq, EK_VM_DEATH);
1014     expandBufAdd4BE(pReq, 0);
1015     eventFinish(state, pReq);
1016     return true;
1017 }
1018 
1019 
1020 /*
1021  * An exception has been thrown.  It may or may not have been caught.
1022  *
1023  * Valid mods:
1024  *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, LocationOnly,
1025  *    ExceptionOnly, InstanceOnly
1026  *
1027  * The "exceptionId" has not been added to the GC-visible object registry,
1028  * because there's a pretty good chance that we're not going to send it
1029  * up the debugger.
1030  */
dvmJdwpPostException(JdwpState * state,const JdwpLocation * pThrowLoc,ObjectId exceptionId,RefTypeId exceptionClassId,const JdwpLocation * pCatchLoc,ObjectId thisPtr)1031 bool dvmJdwpPostException(JdwpState* state, const JdwpLocation* pThrowLoc,
1032     ObjectId exceptionId, RefTypeId exceptionClassId,
1033     const JdwpLocation* pCatchLoc, ObjectId thisPtr)
1034 {
1035     enum JdwpSuspendPolicy suspendPolicy = SP_NONE;
1036     ModBasket basket;
1037     JdwpEvent** matchList;
1038     int matchCount;
1039     char* nameAlloc = NULL;
1040 
1041     memset(&basket, 0, sizeof(basket));
1042     basket.pLoc = pThrowLoc;
1043     basket.classId = pThrowLoc->classId;
1044     basket.threadId = dvmDbgGetThreadSelfId();
1045     basket.className = nameAlloc =
1046         dvmDescriptorToName(dvmDbgGetClassDescriptor(basket.classId));
1047     basket.excepClassId = exceptionClassId;
1048     basket.caught = (pCatchLoc->classId != 0);
1049     basket.thisPtr = thisPtr;
1050 
1051     /* don't try to post an exception caused by the debugger */
1052     if (invokeInProgress(state)) {
1053         LOGV("Not posting exception hit during invoke (%s)\n",basket.className);
1054         free(nameAlloc);
1055         return false;
1056     }
1057 
1058     /* don't allow the list to be updated while we scan it */
1059     lockEventMutex(state);
1060 
1061     matchList = allocMatchList(state);
1062     matchCount = 0;
1063 
1064     findMatchingEvents(state, EK_EXCEPTION, &basket, matchList, &matchCount);
1065 
1066     ExpandBuf* pReq = NULL;
1067     if (matchCount != 0) {
1068         int i;
1069 
1070         LOGV("EVENT: %s(%d total) thread=%llx exceptId=%llx caught=%d)\n",
1071             dvmJdwpEventKindStr(matchList[0]->eventKind), matchCount,
1072             basket.threadId, exceptionId, basket.caught);
1073         LOGV("  throw: %d %llx %x %lld (%s.%s)\n", pThrowLoc->typeTag,
1074             pThrowLoc->classId, pThrowLoc->methodId, pThrowLoc->idx,
1075             dvmDbgGetClassDescriptor(pThrowLoc->classId),
1076             dvmDbgGetMethodName(pThrowLoc->classId, pThrowLoc->methodId));
1077         if (pCatchLoc->classId == 0) {
1078             LOGV("  catch: (not caught)\n");
1079         } else {
1080             LOGV("  catch: %d %llx %x %lld (%s.%s)\n", pCatchLoc->typeTag,
1081                 pCatchLoc->classId, pCatchLoc->methodId, pCatchLoc->idx,
1082                 dvmDbgGetClassDescriptor(pCatchLoc->classId),
1083                 dvmDbgGetMethodName(pCatchLoc->classId, pCatchLoc->methodId));
1084         }
1085 
1086         suspendPolicy = scanSuspendPolicy(matchList, matchCount);
1087         LOGV("  suspendPolicy=%s\n",
1088             dvmJdwpSuspendPolicyStr(suspendPolicy));
1089 
1090         pReq = eventPrep();
1091         expandBufAdd1(pReq, suspendPolicy);
1092         expandBufAdd4BE(pReq, matchCount);
1093 
1094         for (i = 0; i < matchCount; i++) {
1095             expandBufAdd1(pReq, matchList[i]->eventKind);
1096             expandBufAdd4BE(pReq, matchList[i]->requestId);
1097             expandBufAdd8BE(pReq, basket.threadId);
1098 
1099             dvmJdwpAddLocation(pReq, pThrowLoc);
1100             expandBufAdd1(pReq, JT_OBJECT);
1101             expandBufAdd8BE(pReq, exceptionId);
1102             dvmJdwpAddLocation(pReq, pCatchLoc);
1103         }
1104 
1105         /* don't let the GC discard it */
1106         dvmDbgRegisterObjectId(exceptionId);
1107     }
1108 
1109     cleanupMatchList(state, matchList, matchCount);
1110     unlockEventMutex(state);
1111 
1112     /* send request and possibly suspend ourselves */
1113     if (pReq != NULL) {
1114         int oldStatus = dvmDbgThreadWaiting();
1115         if (suspendPolicy != SP_NONE)
1116             dvmJdwpSetWaitForEventThread(state, basket.threadId);
1117 
1118         eventFinish(state, pReq);
1119 
1120         suspendByPolicy(state, suspendPolicy);
1121         dvmDbgThreadContinuing(oldStatus);
1122     }
1123 
1124     free(nameAlloc);
1125     return matchCount != 0;
1126 }
1127 
1128 /*
1129  * Announce that a class has been loaded.
1130  *
1131  * Valid mods:
1132  *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude
1133  */
dvmJdwpPostClassPrepare(JdwpState * state,int tag,RefTypeId refTypeId,const char * signature,int status)1134 bool dvmJdwpPostClassPrepare(JdwpState* state, int tag, RefTypeId refTypeId,
1135     const char* signature, int status)
1136 {
1137     enum JdwpSuspendPolicy suspendPolicy = SP_NONE;
1138     ModBasket basket;
1139     JdwpEvent** matchList;
1140     int matchCount;
1141     char* nameAlloc = NULL;
1142 
1143     memset(&basket, 0, sizeof(basket));
1144     basket.classId = refTypeId;
1145     basket.threadId = dvmDbgGetThreadSelfId();
1146     basket.className = nameAlloc =
1147         dvmDescriptorToName(dvmDbgGetClassDescriptor(basket.classId));
1148 
1149     /* suppress class prep caused by debugger */
1150     if (invokeInProgress(state)) {
1151         LOGV("Not posting class prep caused by invoke (%s)\n",basket.className);
1152         free(nameAlloc);
1153         return false;
1154     }
1155 
1156     /* don't allow the list to be updated while we scan it */
1157     lockEventMutex(state);
1158 
1159     matchList = allocMatchList(state);
1160     matchCount = 0;
1161 
1162     findMatchingEvents(state, EK_CLASS_PREPARE, &basket, matchList,
1163         &matchCount);
1164 
1165     ExpandBuf* pReq = NULL;
1166     if (matchCount != 0) {
1167         int i;
1168 
1169         LOGV("EVENT: %s(%d total) thread=%llx)\n",
1170             dvmJdwpEventKindStr(matchList[0]->eventKind), matchCount,
1171             basket.threadId);
1172 
1173         suspendPolicy = scanSuspendPolicy(matchList, matchCount);
1174         LOGV("  suspendPolicy=%s\n",
1175             dvmJdwpSuspendPolicyStr(suspendPolicy));
1176 
1177         if (basket.threadId == state->debugThreadId) {
1178             /*
1179              * JDWP says that, for a class prep in the debugger thread, we
1180              * should set threadId to null and if any threads were supposed
1181              * to be suspended then we suspend all other threads.
1182              */
1183             LOGV("  NOTE: class prepare in debugger thread!\n");
1184             basket.threadId = 0;
1185             if (suspendPolicy == SP_EVENT_THREAD)
1186                 suspendPolicy = SP_ALL;
1187         }
1188 
1189         pReq = eventPrep();
1190         expandBufAdd1(pReq, suspendPolicy);
1191         expandBufAdd4BE(pReq, matchCount);
1192 
1193         for (i = 0; i < matchCount; i++) {
1194             expandBufAdd1(pReq, matchList[i]->eventKind);
1195             expandBufAdd4BE(pReq, matchList[i]->requestId);
1196             expandBufAdd8BE(pReq, basket.threadId);
1197 
1198             expandBufAdd1(pReq, tag);
1199             expandBufAdd8BE(pReq, refTypeId);
1200             expandBufAddUtf8String(pReq, (const u1*) signature);
1201             expandBufAdd4BE(pReq, status);
1202         }
1203     }
1204 
1205     cleanupMatchList(state, matchList, matchCount);
1206 
1207     unlockEventMutex(state);
1208 
1209     /* send request and possibly suspend ourselves */
1210     if (pReq != NULL) {
1211         int oldStatus = dvmDbgThreadWaiting();
1212         if (suspendPolicy != SP_NONE)
1213             dvmJdwpSetWaitForEventThread(state, basket.threadId);
1214 
1215         eventFinish(state, pReq);
1216 
1217         suspendByPolicy(state, suspendPolicy);
1218         dvmDbgThreadContinuing(oldStatus);
1219     }
1220 
1221     free(nameAlloc);
1222     return matchCount != 0;
1223 }
1224 
1225 /*
1226  * Unload a class.
1227  *
1228  * Valid mods:
1229  *  Count, ClassMatch, ClassExclude
1230  */
dvmJdwpPostClassUnload(JdwpState * state,RefTypeId refTypeId)1231 bool dvmJdwpPostClassUnload(JdwpState* state, RefTypeId refTypeId)
1232 {
1233     assert(false);      // TODO
1234     return false;
1235 }
1236 
1237 /*
1238  * Get or set a field.
1239  *
1240  * Valid mods:
1241  *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, FieldOnly,
1242  *    InstanceOnly
1243  */
dvmJdwpPostFieldAccess(JdwpState * state,int STUFF,ObjectId thisPtr,bool modified)1244 bool dvmJdwpPostFieldAccess(JdwpState* state, int STUFF, ObjectId thisPtr,
1245     bool modified)
1246 {
1247     assert(false);      // TODO
1248     return false;
1249 }
1250 
1251 /*
1252  * Send up a chunk of DDM data.
1253  *
1254  * While this takes the form of a JDWP "event", it doesn't interact with
1255  * other debugger traffic, and can't suspend the VM, so we skip all of
1256  * the fun event token gymnastics.
1257  */
dvmJdwpDdmSendChunkV(JdwpState * state,int type,const struct iovec * iov,int iovcnt)1258 void dvmJdwpDdmSendChunkV(JdwpState* state, int type, const struct iovec* iov,
1259     int iovcnt)
1260 {
1261     u1 header[kJDWPHeaderLen + 8];
1262     size_t dataLen = 0;
1263     int i;
1264 
1265     assert(iov != NULL);
1266     assert(iovcnt > 0 && iovcnt < 10);
1267 
1268     /*
1269      * "Wrap" the contents of the iovec with a JDWP/DDMS header.  We do
1270      * this by creating a new copy of the vector with space for the header.
1271      */
1272     struct iovec wrapiov[iovcnt+1];
1273     for (i = 0; i < iovcnt; i++) {
1274         wrapiov[i+1].iov_base = iov[i].iov_base;
1275         wrapiov[i+1].iov_len = iov[i].iov_len;
1276         dataLen += iov[i].iov_len;
1277     }
1278 
1279     /* form the header (JDWP plus DDMS) */
1280     set4BE(header, sizeof(header) + dataLen);
1281     set4BE(header+4, dvmJdwpNextRequestSerial(state));
1282     set1(header+8, 0);     /* flags */
1283     set1(header+9, kJDWPDdmCmdSet);
1284     set1(header+10, kJDWPDdmCmd);
1285     set4BE(header+11, type);
1286     set4BE(header+15, dataLen);
1287 
1288     wrapiov[0].iov_base = header;
1289     wrapiov[0].iov_len = sizeof(header);
1290 
1291     dvmJdwpSendBufferedRequest(state, wrapiov, iovcnt+1);
1292 }
1293