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