jdwp_event.cc revision 761928d24e4e7ed7776b52243eaf9095ad35f448
1872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
2872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Copyright (C) 2008 The Android Open Source Project
3872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
4872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * you may not use this file except in compliance with the License.
6872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * You may obtain a copy of the License at
7872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
8872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
10872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Unless required by applicable law or agreed to in writing, software
11872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See the License for the specific language governing permissions and
14872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * limitations under the License.
15872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
16872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
17872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Send events to the debugger.
18872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
19872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "debugger.h"
20872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_priv.h"
21872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_constants.h"
22872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_handler.h"
23872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_event.h"
24872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_expand_buf.h"
25872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "logging.h"
26872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "stringprintf.h"
27872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
28872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <stdlib.h>
29872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <string.h>
30872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <stddef.h>     /* for offsetof() */
31872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <unistd.h>
32872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
33872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
34872d4ec7225444d9400d30f9027247deb91012fdElliott HughesGeneral notes:
35872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
36872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThe event add/remove stuff usually happens from the debugger thread,
37872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesin response to requests from the debugger, but can also happen as the
38872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesresult of an event in an arbitrary thread (e.g. an event with a "count"
39872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesmod expires).  It's important to keep the event list locked when processing
40872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesevents.
41872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
42872d4ec7225444d9400d30f9027247deb91012fdElliott HughesEvent posting can happen from any thread.  The JDWP thread will not usually
43872d4ec7225444d9400d30f9027247deb91012fdElliott Hughespost anything but VM start/death, but if a JDWP request causes a class
44872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesto be loaded, the ClassPrepare event will come from the JDWP thread.
45872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
46872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
47872d4ec7225444d9400d30f9027247deb91012fdElliott HughesWe can have serialization issues when we post an event to the debugger.
48872d4ec7225444d9400d30f9027247deb91012fdElliott HughesFor example, a thread could send an "I hit a breakpoint and am suspending
49872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesmyself" message to the debugger.  Before it manages to suspend itself, the
50872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesdebugger's response ("not interested, resume thread") arrives and is
51872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesprocessed.  We try to resume a thread that hasn't yet suspended.
52872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
53872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThis means that, after posting an event to the debugger, we need to wait
54872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesfor the event thread to suspend itself (and, potentially, all other threads)
55872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesbefore processing any additional requests from the debugger.  While doing
56872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesso we need to be aware that multiple threads may be hitting breakpoints
57872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesor other events simultaneously, so we either need to wait for all of them
58872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesor serialize the events with each other.
59872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
60872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThe current mechanism works like this:
61872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  Event thread:
62872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - If I'm going to suspend, grab the "I am posting an event" token.  Wait
63872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     for it if it's not currently available.
64872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - Post the event to the debugger.
65872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - If appropriate, suspend others and then myself.  As part of suspending
66872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     myself, release the "I am posting" token.
67872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JDWP thread:
68872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - When an event arrives, see if somebody is posting an event.  If so,
69872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     sleep until we can acquire the "I am posting an event" token.  Release
70872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     it immediately and continue processing -- the event we have already
71872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     received should not interfere with other events that haven't yet
72872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     been posted.
73872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
74872d4ec7225444d9400d30f9027247deb91012fdElliott HughesSome care must be taken to avoid deadlock:
75872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
76872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A and thread B exit near-simultaneously, and post thread-death
77872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   events with a "suspend all" clause
78872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A gets the event token, thread B sits and waits for it
79872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A wants to suspend all other threads, but thread B is waiting
80872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   for the token and can't be suspended
81872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
82872d4ec7225444d9400d30f9027247deb91012fdElliott HughesSo we need to mark thread B in such a way that thread A doesn't wait for it.
83872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
84872d4ec7225444d9400d30f9027247deb91012fdElliott HughesIf we just bracket the "grab event token" call with a change to VMWAIT
85872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesbefore sleeping, the switch back to RUNNING state when we get the token
86872d4ec7225444d9400d30f9027247deb91012fdElliott Hugheswill cause thread B to suspend (remember, thread A's global suspend is
87872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstill in force, even after it releases the token).  Suspending while
88872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesholding the event token is very bad, because it prevents the JDWP thread
89872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesfrom processing incoming messages.
90872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
91872d4ec7225444d9400d30f9027247deb91012fdElliott HughesWe need to change to VMWAIT state at the *start* of posting an event,
92872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesand stay there until we either finish posting the event or decide to
93872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesput ourselves to sleep.  That way we don't interfere with anyone else and
94872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesdon't allow anyone else to interfere with us.
95872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes*/
96872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
97872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
98872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#define kJdwpEventCommandSet    64
99872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#define kJdwpCompositeCommand   100
100872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
101872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art {
102872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
103872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace JDWP {
104872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
105872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
106872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Stuff to compare against when deciding if a mod matches.  Only the
107872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * values for mods valid for the event being evaluated will be filled in.
108872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The rest will be zeroed.
109872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
110872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstruct ModBasket {
111872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  const JdwpLocation* pLoc;           /* LocationOnly */
112a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  std::string         className;      /* ClassMatch/ClassExclude */
113872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId            threadId;       /* ThreadOnly */
114872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  RefTypeId           classId;        /* ClassOnly */
115872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  RefTypeId           excepClassId;   /* ExceptionOnly */
116872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  bool                caught;         /* ExceptionOnly */
117872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  FieldId             field;          /* FieldOnly */
118872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId            thisPtr;        /* InstanceOnly */
119872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* nothing for StepOnly -- handled differently */
120872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes};
121872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
122872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
123872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Dump an event to the log file.
124872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstatic void dumpEvent(const JdwpEvent* pEvent) {
126872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  LOG(INFO) << StringPrintf("Event id=0x%4x %p (prev=%p next=%p):", pEvent->requestId, pEvent, pEvent->prev, pEvent->next);
127872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  LOG(INFO) << "  kind=" << pEvent->eventKind << " susp=" << pEvent->suspendPolicy << " modCount=" << pEvent->modCount;
128872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
129872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
130872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    const JdwpEventMod* pMod = &pEvent->mods[i];
131872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(INFO) << "  " << static_cast<JdwpModKind>(pMod->modKind);
132872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* TODO - show details */
133872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
134872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
135872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Add an event to the list.  Ordering is not important.
138872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
139872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If something prevents the event from being registered, e.g. it's a
140872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * single-step request on a thread that doesn't exist, the event will
141872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * not be added to the list, and an appropriate error will be returned.
142872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
143761928d24e4e7ed7776b52243eaf9095ad35f448Elliott HughesJdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) {
144761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  MutexLock mu(event_lock_);
145872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
146872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent != NULL);
147872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->prev == NULL);
148872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->next == NULL);
149872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
150872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
151872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If one or more "break"-type mods are used, register them with
152872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * the interpreter.
153872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
154872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
155872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    const JdwpEventMod* pMod = &pEvent->mods[i];
156872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pMod->modKind == MK_LOCATION_ONLY) {
157872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for Breakpoint, Step, and Exception */
158872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      Dbg::WatchLocation(&pMod->locationOnly.loc);
159872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    } else if (pMod->modKind == MK_STEP) {
160872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for EK_SINGLE_STEP; should only be one */
161872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      JdwpStepSize size = static_cast<JdwpStepSize>(pMod->step.size);
162872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      JdwpStepDepth depth = static_cast<JdwpStepDepth>(pMod->step.depth);
163872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      Dbg::ConfigureStep(pMod->step.threadId, size, depth);
164872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    } else if (pMod->modKind == MK_FIELD_ONLY) {
165872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should be for EK_FIELD_ACCESS or EK_FIELD_MODIFICATION */
166872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      dumpEvent(pEvent);  /* TODO - need for field watches */
167872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
168872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
169872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
170872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
171872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Add to list.
172872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
173761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (eventList != NULL) {
174761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    pEvent->next = eventList;
175761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    eventList->prev = pEvent;
176872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
177761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  eventList = pEvent;
178761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  numEvents++;
179872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
180872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
181872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
182872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
183872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
184872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove an event from the list.  This will also remove the event from
185872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * any optimization tables, e.g. breakpoints.
186872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
187872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Does not free the JdwpEvent.
188872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
189872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Grab the eventLock before calling here.
190872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
191761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterEvent(JdwpEvent* pEvent) {
192872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent->prev == NULL) {
193872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* head of the list */
194761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    CHECK(eventList == pEvent);
195872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
196761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    eventList = pEvent->next;
197872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
198872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->prev->next = pEvent->next;
199872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
200872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
201872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent->next != NULL) {
202872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->next->prev = pEvent->prev;
203872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->next = NULL;
204872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
205872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  pEvent->prev = NULL;
206872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
207872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
208872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Unhook us from the interpreter, if necessary.
209872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
210872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
211872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEventMod* pMod = &pEvent->mods[i];
212872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pMod->modKind == MK_LOCATION_ONLY) {
213872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for Breakpoint, Step, and Exception */
214872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      Dbg::UnwatchLocation(&pMod->locationOnly.loc);
215872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
216872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pMod->modKind == MK_STEP) {
217872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for EK_SINGLE_STEP; should only be one */
218872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      Dbg::UnconfigureStep(pMod->step.threadId);
219872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
220872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
221872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
222761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  numEvents--;
223761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  CHECK(numEvents != 0 || eventList == NULL);
224872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
225872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
226872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
227872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove the event with the given ID from the list.
228872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
229872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Failure to find the event isn't really an error, but it is a little
230872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * weird.  (It looks like Eclipse will try to be extra careful and will
231872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * explicitly remove one-off single-step events.)
232872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
233761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterEventById(uint32_t requestId) {
234761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  MutexLock mu(event_lock_);
235872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
236761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  JdwpEvent* pEvent = eventList;
237872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (pEvent != NULL) {
238872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pEvent->requestId == requestId) {
239761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      UnregisterEvent(pEvent);
240872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      EventFree(pEvent);
241761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      return;      /* there can be only one with a given ID */
242872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
243872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
244872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent = pEvent->next;
245872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
246872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
247872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  //LOGD("Odd: no match when removing event reqId=0x%04x", requestId);
248872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
249872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
250872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
251872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove all entries from the event list.
252872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
253761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterAll() {
254761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  MutexLock mu(event_lock_);
255872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
256761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  JdwpEvent* pEvent = eventList;
257872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (pEvent != NULL) {
258872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEvent* pNextEvent = pEvent->next;
259872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
260761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    UnregisterEvent(pEvent);
261872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    EventFree(pEvent);
262872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent = pNextEvent;
263872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
264872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
265761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  eventList = NULL;
266872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
267872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
268872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
269872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate a JdwpEvent struct with enough space to hold the specified
270872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * number of mod records.
271872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
272872d4ec7225444d9400d30f9027247deb91012fdElliott HughesJdwpEvent* EventAlloc(int numMods) {
273872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpEvent* newEvent;
274872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  int allocSize = offsetof(JdwpEvent, mods) + numMods * sizeof(newEvent->mods[0]);
275872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  newEvent = reinterpret_cast<JdwpEvent*>(malloc(allocSize));
276872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  memset(newEvent, 0, allocSize);
277872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return newEvent;
278872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
279872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
280872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
281872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Free a JdwpEvent.
282872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
283872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Do not call this until the event has been removed from the list.
284872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
285872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid EventFree(JdwpEvent* pEvent) {
286872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent == NULL) {
287872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
288872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
289872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
290872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* make sure it was removed from the list */
291872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->prev == NULL);
292872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->next == NULL);
293872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* want to check state->eventList != pEvent */
294872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
295872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
296872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Free any hairy bits in the mods.
297872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
298872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
299872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pEvent->mods[i].modKind == MK_CLASS_MATCH) {
300872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      free(pEvent->mods[i].classMatch.classPattern);
301872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pEvent->mods[i].classMatch.classPattern = NULL;
302872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
303872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pEvent->mods[i].modKind == MK_CLASS_EXCLUDE) {
304872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      free(pEvent->mods[i].classExclude.classPattern);
305872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pEvent->mods[i].classExclude.classPattern = NULL;
306872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
307872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
308872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
309872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  free(pEvent);
310872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
311872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
312872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
313872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate storage for matching events.  To keep things simple we
314872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * use an array with enough storage for the entire list.
315872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
316872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The state->eventLock should be held before calling.
317872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
318761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesstatic JdwpEvent** AllocMatchList(size_t event_count) {
319761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  return new JdwpEvent*[event_count];
320872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
321872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
322872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
323872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Run through the list and remove any entries with an expired "count" mod
324872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * from the event list, then free the match list.
325872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
326761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::CleanupMatchList(JdwpEvent** matchList, int matchCount) {
327872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpEvent** ppEvent = matchList;
328872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
329872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (matchCount--) {
330872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEvent* pEvent = *ppEvent;
331872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
332872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    for (int i = 0; i < pEvent->modCount; i++) {
333872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pEvent->mods[i].modKind == MK_COUNT && pEvent->mods[i].count.count == 0) {
334872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        LOG(VERBOSE) << "##### Removing expired event";
335761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        UnregisterEvent(pEvent);
336872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        EventFree(pEvent);
337872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        break;
338872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
339872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
340872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
341872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    ppEvent++;
342872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
343872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
344761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  delete[] matchList;
345872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
346872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
347872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
348872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Match a string against a "restricted regular expression", which is just
349872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * a string that may start or end with '*' (e.g. "*.Foo" or "java.*").
350872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
351872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * ("Restricted name globbing" might have been a better term.)
352872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
353761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesstatic bool PatternMatch(const char* pattern, const std::string& target) {
354a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  size_t patLen = strlen(pattern);
355872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
356872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pattern[0] == '*') {
357872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    patLen--;
358872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    // TODO: remove printf when we find a test case to verify this
359a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    LOG(ERROR) << ">>> comparing '" << (pattern + 1) << "' to '" << (target.c_str() + (target.size()-patLen)) << "'";
360872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
361a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    if (target.size() < patLen) {
362872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      return false;
363872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
364a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    return strcmp(pattern+1, target.c_str() + (target.size()-patLen)) == 0;
365872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else if (pattern[patLen-1] == '*') {
366a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    return strncmp(pattern, target.c_str(), patLen-1) == 0;
367872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
368a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    return strcmp(pattern, target.c_str()) == 0;
369872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
370872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
371872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
372872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
373872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See if two locations are equal.
374872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
375872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * It's tempting to do a bitwise compare ("struct ==" or memcmp), but if
376872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * the storage wasn't zeroed out there could be undefined values in the
377872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * padding.  Besides, the odds of "idx" being equal while the others aren't
378872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * is very small, so this is usually just a simple integer comparison.
379872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
380761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesstatic inline bool LocationMatch(const JdwpLocation* pLoc1, const JdwpLocation* pLoc2) {
381872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return pLoc1->idx == pLoc2->idx &&
382872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pLoc1->methodId == pLoc2->methodId &&
383872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pLoc1->classId == pLoc2->classId &&
384872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pLoc1->typeTag == pLoc2->typeTag;
385872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
386872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
387872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
388872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See if the event's mods match up with the contents of "basket".
389872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
390872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If we find a Count mod before rejecting an event, we decrement it.  We
391872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * need to do this even if later mods cause us to ignore the event.
392872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
393761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesstatic bool ModsMatch(JdwpEvent* pEvent, ModBasket* basket) {
394872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpEventMod* pMod = pEvent->mods;
395872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
396872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = pEvent->modCount; i > 0; i--, pMod++) {
397872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    switch (pMod->modKind) {
398872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_COUNT:
399872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      CHECK_GT(pMod->count.count, 0);
400872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pMod->count.count--;
401872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
402872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CONDITIONAL:
403872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      CHECK(false);  // should not be getting these
404872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
405872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_THREAD_ONLY:
406872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->threadOnly.threadId != basket->threadId) {
407872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
408872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
409872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
410872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_ONLY:
411872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (!Dbg::MatchType(basket->classId, pMod->classOnly.refTypeId)) {
412872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
413872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
414872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
415872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_MATCH:
416761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      if (!PatternMatch(pMod->classMatch.classPattern, basket->className)) {
417872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
418872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
419872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
420872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_EXCLUDE:
421761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      if (PatternMatch(pMod->classMatch.classPattern, basket->className)) {
422872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
423872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
424872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
425872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_LOCATION_ONLY:
426761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      if (!LocationMatch(&pMod->locationOnly.loc, basket->pLoc)) {
427872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
428872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
429872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
430872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_EXCEPTION_ONLY:
431872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->exceptionOnly.refTypeId != 0 && !Dbg::MatchType(basket->excepClassId, pMod->exceptionOnly.refTypeId)) {
432872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
433872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
434872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if ((basket->caught && !pMod->exceptionOnly.caught) || (!basket->caught && !pMod->exceptionOnly.uncaught)) {
435872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
436872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
437872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
438872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_FIELD_ONLY:
439872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (!Dbg::MatchType(basket->classId, pMod->fieldOnly.refTypeId) || pMod->fieldOnly.fieldId != basket->field) {
440872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
441872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
442872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
443872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_STEP:
444872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->step.threadId != basket->threadId) {
445872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
446872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
447872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
448872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_INSTANCE_ONLY:
449872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->instanceOnly.objectId != basket->thisPtr) {
450872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
451872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
452872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
453872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    default:
454872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      LOG(ERROR) << "unhandled mod kind " << pMod->modKind;
455872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      CHECK(false);
456872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
457872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
458872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
459872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return true;
460872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
461872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
462872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
463872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Find all events of type "eventKind" with mods that match up with the
464872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * rest of the arguments.
465872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
466872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Found events are appended to "matchList", and "*pMatchCount" is advanced,
467872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * so this may be called multiple times for grouped events.
468872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
469872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * DO NOT call this multiple times for the same eventKind, as Count mods are
470872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * decremented during the scan.
471872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
472761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::FindMatchingEvents(JdwpEventKind eventKind, ModBasket* basket, JdwpEvent** matchList, int* pMatchCount) {
473872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* start after the existing entries */
474872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  matchList += *pMatchCount;
475872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
476761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  JdwpEvent* pEvent = eventList;
477872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (pEvent != NULL) {
478761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if (pEvent->eventKind == eventKind && ModsMatch(pEvent, basket)) {
479872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      *matchList++ = pEvent;
480872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      (*pMatchCount)++;
481872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
482872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
483872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent = pEvent->next;
484872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
485872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
486872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
487872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
488872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Scan through the list of matches and determine the most severe
489872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * suspension policy.
490872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
491872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstatic JdwpSuspendPolicy scanSuspendPolicy(JdwpEvent** matchList, int matchCount) {
492872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpSuspendPolicy policy = SP_NONE;
493872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
494872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (matchCount--) {
495872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if ((*matchList)->suspendPolicy > policy) {
496872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      policy = (*matchList)->suspendPolicy;
497872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
498872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    matchList++;
499872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
500872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
501872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return policy;
502872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
503872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
504872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
505872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Three possibilities:
506872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_NONE - do nothing
507872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_EVENT_THREAD - suspend ourselves
508872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_ALL - suspend everybody except JDWP support thread
509872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
510761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::SuspendByPolicy(JdwpSuspendPolicy suspendPolicy) {
511761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  LOG(INFO) << "SuspendByPolicy(" << suspendPolicy << ")";
512872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (suspendPolicy == SP_NONE) {
513872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
514872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
515872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
516872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (suspendPolicy == SP_ALL) {
517475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes    Dbg::SuspendVM();
518872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
519872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    CHECK_EQ(suspendPolicy, SP_EVENT_THREAD);
520872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
521872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
522872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* this is rare but possible -- see CLASS_PREPARE handling */
523761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (Dbg::GetThreadSelfId() == debugThreadId) {
524761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    LOG(INFO) << "NOTE: SuspendByPolicy not suspending JDWP thread";
525872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
526872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
527872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
528872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  DebugInvokeReq* pReq = Dbg::GetInvokeReq();
529872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (true) {
530872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pReq->ready = true;
531872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    Dbg::SuspendSelf();
532872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pReq->ready = false;
533872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
534872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /*
535872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     * The JDWP thread has told us (and possibly all other threads) to
536872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     * resume.  See if it has left anything in our DebugInvokeReq mailbox.
537872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     */
538475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes    if (!pReq->invoke_needed) {
539761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      /*LOGD("SuspendByPolicy: no invoke needed");*/
540872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
541872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
542872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
543872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* grab this before posting/suspending again */
544761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    SetWaitForEventThread(Dbg::GetThreadSelfId());
545872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
546475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes    /* leave pReq->invoke_needed raised so we can check reentrancy */
547872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(VERBOSE) << "invoking method...";
548872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    Dbg::ExecuteMethod(pReq);
549872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
550475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes    pReq->error = ERR_NONE;
551872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
552872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* clear this before signaling */
553475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes    pReq->invoke_needed = false;
554872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
555872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(VERBOSE) << "invoke complete, signaling and self-suspending";
556872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    MutexLock mu(pReq->lock_);
557872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pReq->cond_.Signal();
558872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
559872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
560872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
561872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
562872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Determine if there is a method invocation in progress in the current
563872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * thread.
564872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
565475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes * We look at the "invoke_needed" flag in the per-thread DebugInvokeReq
566872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * state.  If set, we're in the process of invoking a method.
567872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
568761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool JdwpState::InvokeInProgress() {
569872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  DebugInvokeReq* pReq = Dbg::GetInvokeReq();
570475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes  return pReq->invoke_needed;
571872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
572872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
573872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
574872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * We need the JDWP thread to hold off on doing stuff while we post an
575872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * event and then suspend ourselves.
576872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
577872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Call this with a threadId of zero if you just want to wait for the
578872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * current thread operation to complete.
579872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
580872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This could go to sleep waiting for another thread, so it's important
581872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * that the thread be marked as VMWAIT before calling here.
582872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
583376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesvoid JdwpState::SetWaitForEventThread(ObjectId threadId) {
584872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  bool waited = false;
585872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
586872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* this is held for very brief periods; contention is unlikely */
587376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  MutexLock mu(event_thread_lock_);
588872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
589872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
590872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If another thread is already doing stuff, wait for it.  This can
591872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * go to sleep indefinitely.
592872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
593376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  while (eventThreadId != 0) {
594376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    LOG(VERBOSE) << StringPrintf("event in progress (0x%llx), 0x%llx sleeping", eventThreadId, threadId);
595872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    waited = true;
596376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    event_thread_cond_.Wait(event_thread_lock_);
597872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
598872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
599872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (waited || threadId != 0) {
600872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(VERBOSE) << StringPrintf("event token grabbed (0x%llx)", threadId);
601872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
602872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (threadId != 0) {
603376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    eventThreadId = threadId;
604872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
605872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
606872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
607872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
608872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Clear the threadId and signal anybody waiting.
609872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
610376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesvoid JdwpState::ClearWaitForEventThread() {
611872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
612872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Grab the mutex.  Don't try to go in/out of VMWAIT mode, as this
613872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * function is called by dvmSuspendSelf(), and the transition back
614872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * to RUNNING would confuse it.
615872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
616376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  MutexLock mu(event_thread_lock_);
617872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
618376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  CHECK_NE(eventThreadId, 0U);
619376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  LOG(VERBOSE) << StringPrintf("cleared event token (0x%llx)", eventThreadId);
620872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
621376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  eventThreadId = 0;
622872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
623376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  event_thread_cond_.Signal();
624872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
625872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
626872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
627872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
628872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Prep an event.  Allocates storage for the message and leaves space for
629872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * the header.
630872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
631872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstatic ExpandBuf* eventPrep() {
632872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = expandBufAlloc();
633872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAddSpace(pReq, kJDWPHeaderLen);
634872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return pReq;
635872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
636872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
637872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
638872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Write the header into the buffer and send the packet off to the debugger.
639872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
640872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Takes ownership of "pReq" (currently discards it).
641872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
642761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::EventFinish(ExpandBuf* pReq) {
643872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  uint8_t* buf = expandBufGetBuffer(pReq);
644872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
645f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(buf, expandBufGetLength(pReq));
646761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  Set4BE(buf+4, NextRequestSerial());
647f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+8, 0);     /* flags */
648f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+9, kJdwpEventCommandSet);
649f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+10, kJdwpCompositeCommand);
650872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
651761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  SendRequest(pReq);
652872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
653872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufFree(pReq);
654872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
655872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
656872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
657872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
658872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Tell the debugger that we have finished initializing.  This is always
659872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * sent, even if the debugger hasn't requested it.
660872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
661872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This should be sent "before the main thread is started and before
662872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * any application code has been executed".  The thread ID in the message
663872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * must be for the main thread.
664872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
665376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesbool JdwpState::PostVMStart() {
666872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpSuspendPolicy suspendPolicy;
667872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId threadId = Dbg::GetThreadSelfId();
668872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
669376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  if (options_->suspend) {
670872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    suspendPolicy = SP_ALL;
671872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
672872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    suspendPolicy = SP_NONE;
673872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
674872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
675761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  ExpandBuf* pReq = eventPrep();
676761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
677761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    MutexLock mu(event_lock_); // probably don't need this here
678872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
679872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(VERBOSE) << "EVENT: " << EK_VM_START;
680872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;
681872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
682872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd1(pReq, suspendPolicy);
683872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd4BE(pReq, 1);
684872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
685872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd1(pReq, EK_VM_START);
686872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd4BE(pReq, 0);       /* requestId */
687872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd8BE(pReq, threadId);
688872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
689872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
690872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* send request and possibly suspend ourselves */
691872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pReq != NULL) {
692376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    int old_state = Dbg::ThreadWaiting();
693872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (suspendPolicy != SP_NONE) {
694376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes      SetWaitForEventThread(threadId);
695872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
696872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
697761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    EventFinish(pReq);
698872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
699761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    SuspendByPolicy(suspendPolicy);
700376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    Dbg::ThreadContinuing(old_state);
701872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
702872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
703872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return true;
704872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
705872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
706872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes// TODO: This doesn't behave like the real dvmDescriptorToName.
707872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes// I'm hoping this isn't used to communicate with the debugger, and we can just use descriptors.
708a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesstd::string dvmDescriptorToName(const std::string& descriptor) {
709a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  return descriptor;
710872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
711872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
712872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
713872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * A location of interest has been reached.  This handles:
714872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Breakpoint
715872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   SingleStep
716872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   MethodEntry
717872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   MethodExit
718872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * These four types must be grouped together in a single response.  The
719872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * "eventFlags" indicates the type of event(s) that have happened.
720872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
721872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
722872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, InstanceOnly
723872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   LocationOnly (for breakpoint/step only)
724872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Step (for step only)
725872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
726872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Interesting test cases:
727872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Put a breakpoint on a native method.  Eclipse creates METHOD_ENTRY
728872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *    and METHOD_EXIT events with a ClassOnly mod on the method's class.
729872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Use "run to line".  Eclipse creates a BREAKPOINT with Count=1.
730872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Single-step to a line with a breakpoint.  Should get a single
731872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *    event message with both events in it.
732872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
733761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool JdwpState::PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags) {
734872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
735872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
736872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  memset(&basket, 0, sizeof(basket));
737872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.pLoc = pLoc;
738872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.classId = pLoc->classId;
739872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.thisPtr = thisPtr;
740872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
741a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  basket.className = dvmDescriptorToName(Dbg::GetClassDescriptor(pLoc->classId));
742872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
743872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
744872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * On rare occasions we may need to execute interpreted code in the VM
745872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * while handling a request from the debugger.  Don't fire breakpoints
746872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * while doing so.  (I don't think we currently do this at all, so
747872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * this is mostly paranoia.)
748872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
749761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (basket.threadId == debugThreadId) {
750872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(VERBOSE) << "Ignoring location event in JDWP thread";
751872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
752872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
753872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
754872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
755872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * The debugger variable display tab may invoke the interpreter to format
756872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * complex objects.  We want to ignore breakpoints and method entry/exit
757872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * traps while working on behalf of the debugger.
758872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   *
759872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If we don't ignore them, the VM will get hung up, because we'll
760872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * suspend on a breakpoint while the debugger is still waiting for its
761872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * method invocation to complete.
762872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
763761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
764872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(VERBOSE) << "Not checking breakpoints during invoke (" << basket.className << ")";
765872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
766872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
767872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
768761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  JdwpEvent** matchList = AllocMatchList(numEvents);
769872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  int matchCount = 0;
770872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
771872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpSuspendPolicy suspendPolicy = SP_NONE;
772872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
773761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
774761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    MutexLock mu(event_lock_);
775761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kBreakPoint) != 0) {
776761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      FindMatchingEvents(EK_BREAKPOINT, &basket, matchList, &matchCount);
777761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
778761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kSingleStep) != 0) {
779761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      FindMatchingEvents(EK_SINGLE_STEP, &basket, matchList, &matchCount);
780761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
781761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kMethodEntry) != 0) {
782761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      FindMatchingEvents(EK_METHOD_ENTRY, &basket, matchList, &matchCount);
783761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
784761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kMethodExit) != 0) {
785761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      FindMatchingEvents(EK_METHOD_EXIT, &basket, matchList, &matchCount);
786761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
787761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if (matchCount != 0) {
788761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
789761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes                   << basket.className << "." << Dbg::GetMethodName(pLoc->classId, pLoc->methodId)
790761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes                   << " thread=" << (void*) basket.threadId << " code=" << (void*) pLoc->idx << ")";
791872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
792761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      suspendPolicy = scanSuspendPolicy(matchList, matchCount);
793761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;
794872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
795761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
796761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      expandBufAdd1(pReq, suspendPolicy);
797761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      expandBufAdd4BE(pReq, matchCount);
798761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes
799761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      for (int i = 0; i < matchCount; i++) {
800761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd1(pReq, matchList[i]->eventKind);
801761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd4BE(pReq, matchList[i]->requestId);
802761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
803761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        AddLocation(pReq, pLoc);
804761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
805872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
806872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
807761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    CleanupMatchList(matchList, matchCount);
808761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  }
809872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
810872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* send request and possibly suspend ourselves */
811872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pReq != NULL) {
812376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    int old_state = Dbg::ThreadWaiting();
813872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (suspendPolicy != SP_NONE) {
814761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      SetWaitForEventThread(basket.threadId);
815872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
816872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
817761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    EventFinish(pReq);
818872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
819761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    SuspendByPolicy(suspendPolicy);
820376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    Dbg::ThreadContinuing(old_state);
821872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
822872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
823872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return matchCount != 0;
824872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
825872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
826872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
827872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * A thread is starting or stopping.
828872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
829872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
830872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  Count, ThreadOnly
831872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
832234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughesbool JdwpState::PostThreadChange(ObjectId threadId, bool start) {
833872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK_EQ(threadId, Dbg::GetThreadSelfId());
834872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
835872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
836872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * I don't think this can happen.
837872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
838761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
839872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(WARNING) << "Not posting thread change during invoke";
840872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
841872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
842872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
843872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
844872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  memset(&basket, 0, sizeof(basket));
845872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = threadId;
846872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
847872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
848872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpSuspendPolicy suspendPolicy = SP_NONE;
849234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes  int matchCount = 0;
850234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes  {
851234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    // Don't allow the list to be updated while we scan it.
852234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    MutexLock mu(event_lock_);
853761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    JdwpEvent** matchList = AllocMatchList(numEvents);
854234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes
855234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    if (start) {
856761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      FindMatchingEvents(EK_THREAD_START, &basket, matchList, &matchCount);
857234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    } else {
858761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      FindMatchingEvents(EK_THREAD_DEATH, &basket, matchList, &matchCount);
859234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    }
860872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
861234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    if (matchCount != 0) {
862234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
863234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes                   << "thread=" << (void*) basket.threadId << ")";
864872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
865234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      suspendPolicy = scanSuspendPolicy(matchList, matchCount);
866234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;
867872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
868234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      pReq = eventPrep();
869234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      expandBufAdd1(pReq, suspendPolicy);
870234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      expandBufAdd4BE(pReq, matchCount);
871234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes
872234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      for (int i = 0; i < matchCount; i++) {
873234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes        expandBufAdd1(pReq, matchList[i]->eventKind);
874234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes        expandBufAdd4BE(pReq, matchList[i]->requestId);
875234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
876234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      }
877872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
878872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
879761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    CleanupMatchList(matchList, matchCount);
880234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes  }
881872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
882872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* send request and possibly suspend ourselves */
883872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pReq != NULL) {
884376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    int old_state = Dbg::ThreadWaiting();
885872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (suspendPolicy != SP_NONE) {
886234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      SetWaitForEventThread(basket.threadId);
887872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
888761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    EventFinish(pReq);
889872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
890761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    SuspendByPolicy(suspendPolicy);
891376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    Dbg::ThreadContinuing(old_state);
892872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
893872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
894872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return matchCount != 0;
895872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
896872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
897872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
898872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Send a polite "VM is dying" message to the debugger.
899872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
900872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Skips the usual "event token" stuff.
901872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
902376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesbool JdwpState::PostVMDeath() {
903872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  LOG(VERBOSE) << "EVENT: " << EK_VM_DEATH;
904872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
905872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = eventPrep();
906872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd1(pReq, SP_NONE);
907872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReq, 1);
908872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
909872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd1(pReq, EK_VM_DEATH);
910872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReq, 0);
911761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  EventFinish(pReq);
912872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return true;
913872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
914872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
915872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
916872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * An exception has been thrown.  It may or may not have been caught.
917872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
918872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
919872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, LocationOnly,
920872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *    ExceptionOnly, InstanceOnly
921872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
922872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The "exceptionId" has not been added to the GC-visible object registry,
923872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * because there's a pretty good chance that we're not going to send it
924872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * up the debugger.
925872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
926761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool JdwpState::PostException(const JdwpLocation* pThrowLoc,
927872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    ObjectId exceptionId, RefTypeId exceptionClassId,
928872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    const JdwpLocation* pCatchLoc, ObjectId thisPtr)
929872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes{
930872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
931872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
932872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  memset(&basket, 0, sizeof(basket));
933872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.pLoc = pThrowLoc;
934872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.classId = pThrowLoc->classId;
935872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
936a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  basket.className = dvmDescriptorToName(Dbg::GetClassDescriptor(basket.classId));
937872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.excepClassId = exceptionClassId;
938872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.caught = (pCatchLoc->classId != 0);
939872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.thisPtr = thisPtr;
940872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
941872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* don't try to post an exception caused by the debugger */
942761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
943872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(VERBOSE) << "Not posting exception hit during invoke (" << basket.className << ")";
944872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
945872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
946872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
947761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  JdwpEvent** matchList = AllocMatchList(numEvents);
948872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  int matchCount = 0;
949872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
950872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpSuspendPolicy suspendPolicy = SP_NONE;
951761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
952761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    MutexLock mu(event_lock_);
953761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    FindMatchingEvents(EK_EXCEPTION, &basket, matchList, &matchCount);
954761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if (matchCount != 0) {
955761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total)"
956761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes                   << " thread=" << (void*) basket.threadId
957761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes                   << " exceptId=" << (void*) exceptionId
958761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes                   << " caught=" << basket.caught << ")";
959761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      LOG(VERBOSE) << StringPrintf("  throw: %d %llx %x %lld (%s.%s)", pThrowLoc->typeTag,
960761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pThrowLoc->classId, pThrowLoc->methodId, pThrowLoc->idx,
961761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      Dbg::GetClassDescriptor(pThrowLoc->classId).c_str(),
962761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      Dbg::GetMethodName(pThrowLoc->classId, pThrowLoc->methodId));
963761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      if (pCatchLoc->classId == 0) {
964761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        LOG(VERBOSE) << "  catch: (not caught)";
965761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      } else {
966761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        LOG(VERBOSE) << StringPrintf("  catch: %d %llx %x %lld (%s.%s)", pCatchLoc->typeTag,
967761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        pCatchLoc->classId, pCatchLoc->methodId, pCatchLoc->idx,
968761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        Dbg::GetClassDescriptor(pCatchLoc->classId).c_str(),
969761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        Dbg::GetMethodName(pCatchLoc->classId, pCatchLoc->methodId));
970761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
971872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
972761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      suspendPolicy = scanSuspendPolicy(matchList, matchCount);
973761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;
974872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
975761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
976761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      expandBufAdd1(pReq, suspendPolicy);
977761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      expandBufAdd4BE(pReq, matchCount);
978761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes
979761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      for (int i = 0; i < matchCount; i++) {
980761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd1(pReq, matchList[i]->eventKind);
981761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd4BE(pReq, matchList[i]->requestId);
982761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
983872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
984761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        AddLocation(pReq, pThrowLoc);
985761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd1(pReq, JT_OBJECT);
986761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, exceptionId);
987761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        AddLocation(pReq, pCatchLoc);
988761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
989872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
990761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      /* don't let the GC discard it */
991761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      Dbg::RegisterObjectId(exceptionId);
992872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
993872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
994761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    CleanupMatchList(matchList, matchCount);
995872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
996872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
997872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* send request and possibly suspend ourselves */
998872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pReq != NULL) {
999376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    int old_state = Dbg::ThreadWaiting();
1000872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (suspendPolicy != SP_NONE) {
1001761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      SetWaitForEventThread(basket.threadId);
1002872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
1003872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1004761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    EventFinish(pReq);
1005872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1006761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    SuspendByPolicy(suspendPolicy);
1007376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    Dbg::ThreadContinuing(old_state);
1008872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1009872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1010872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return matchCount != 0;
1011872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1012872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1013872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1014872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Announce that a class has been loaded.
1015872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1016872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
1017872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude
1018872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1019761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool JdwpState::PostClassPrepare(int tag, RefTypeId refTypeId, const char* signature, int status) {
1020872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
1021872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1022872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  memset(&basket, 0, sizeof(basket));
1023872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.classId = refTypeId;
1024872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
1025a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  basket.className = dvmDescriptorToName(Dbg::GetClassDescriptor(basket.classId));
1026872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1027872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* suppress class prep caused by debugger */
1028761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
1029872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(VERBOSE) << "Not posting class prep caused by invoke (" << basket.className << ")";
1030872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
1031872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1032872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1033761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  JdwpEvent** matchList = AllocMatchList(numEvents);
1034872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  int matchCount = 0;
1035872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
1036872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpSuspendPolicy suspendPolicy = SP_NONE;
1037761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
1038761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    MutexLock mu(event_lock_);
1039761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    FindMatchingEvents(EK_CLASS_PREPARE, &basket, matchList, &matchCount);
1040761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if (matchCount != 0) {
1041761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
1042761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes                   << "thread=" << (void*) basket.threadId << ")";
1043872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1044761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      suspendPolicy = scanSuspendPolicy(matchList, matchCount);
1045761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;
1046872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1047761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      if (basket.threadId == debugThreadId) {
1048761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        /*
1049761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * JDWP says that, for a class prep in the debugger thread, we
1050761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * should set threadId to null and if any threads were supposed
1051761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * to be suspended then we suspend all other threads.
1052761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         */
1053761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        LOG(VERBOSE) << "  NOTE: class prepare in debugger thread!";
1054761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        basket.threadId = 0;
1055761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        if (suspendPolicy == SP_EVENT_THREAD) {
1056761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes          suspendPolicy = SP_ALL;
1057761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        }
1058872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1059872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1060761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
1061761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      expandBufAdd1(pReq, suspendPolicy);
1062761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      expandBufAdd4BE(pReq, matchCount);
1063872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1064761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      for (int i = 0; i < matchCount; i++) {
1065761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd1(pReq, matchList[i]->eventKind);
1066761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd4BE(pReq, matchList[i]->requestId);
1067761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
1068872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1069761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd1(pReq, tag);
1070761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, refTypeId);
1071761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAddUtf8String(pReq, signature);
1072761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd4BE(pReq, status);
1073761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
1074872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
1075761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    CleanupMatchList(matchList, matchCount);
1076872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1077872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1078872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* send request and possibly suspend ourselves */
1079872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pReq != NULL) {
1080376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    int old_state = Dbg::ThreadWaiting();
1081872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (suspendPolicy != SP_NONE) {
1082761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      SetWaitForEventThread(basket.threadId);
1083872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
1084761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    EventFinish(pReq);
1085872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1086761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    SuspendByPolicy(suspendPolicy);
1087376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    Dbg::ThreadContinuing(old_state);
1088872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1089872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1090872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return matchCount != 0;
1091872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1092872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1093872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1094872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Send up a chunk of DDM data.
1095872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1096872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * While this takes the form of a JDWP "event", it doesn't interact with
1097872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * other debugger traffic, and can't suspend the VM, so we skip all of
1098872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * the fun event token gymnastics.
1099872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
11008218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughesvoid JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iovcnt) {
1101872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  uint8_t header[kJDWPHeaderLen + 8];
1102872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  size_t dataLen = 0;
1103872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1104872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(iov != NULL);
1105872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(iovcnt > 0 && iovcnt < 10);
1106872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1107872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
1108872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * "Wrap" the contents of the iovec with a JDWP/DDMS header.  We do
1109872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * this by creating a new copy of the vector with space for the header.
1110872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
1111872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  iovec wrapiov[iovcnt+1];
1112872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < iovcnt; i++) {
1113872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    wrapiov[i+1].iov_base = iov[i].iov_base;
1114872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    wrapiov[i+1].iov_len = iov[i].iov_len;
1115872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    dataLen += iov[i].iov_len;
1116872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1117872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1118872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* form the header (JDWP plus DDMS) */
1119f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header, sizeof(header) + dataLen);
1120f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+4, NextRequestSerial());
1121f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+8, 0);     /* flags */
1122f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+9, kJDWPDdmCmdSet);
1123f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+10, kJDWPDdmCmd);
1124f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+11, type);
1125f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+15, dataLen);
1126872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1127872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  wrapiov[0].iov_base = header;
1128872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  wrapiov[0].iov_len = sizeof(header);
1129872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1130872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
1131872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Make sure we're in VMWAIT in case the write blocks.
1132872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
1133376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  int old_state = Dbg::ThreadWaiting();
1134376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  (*transport->sendBufferedRequest)(this, wrapiov, iovcnt + 1);
1135376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  Dbg::ThreadContinuing(old_state);
1136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1138872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}  // namespace JDWP
1139872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1140872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}  // namespace art
1141