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