jdwp_event.cc revision f52935278fca8c7aa220543eef4544e3d1105d91
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 */
1607ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes
17872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_event.h"
18872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <stddef.h>     /* for offsetof() */
20872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <stdlib.h>
21872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <string.h>
22872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <unistd.h>
23872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2407ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
25e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h"
2607ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "debugger.h"
2707ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "jdwp/jdwp_constants.h"
2807ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "jdwp/jdwp_expand_buf.h"
2907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "jdwp/jdwp_priv.h"
30693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers#include "thread-inl.h"
3107ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes
32872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
33872d4ec7225444d9400d30f9027247deb91012fdElliott HughesGeneral notes:
34872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
35872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThe event add/remove stuff usually happens from the debugger thread,
36872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesin response to requests from the debugger, but can also happen as the
37872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesresult of an event in an arbitrary thread (e.g. an event with a "count"
38872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesmod expires).  It's important to keep the event list locked when processing
39872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesevents.
40872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
41872d4ec7225444d9400d30f9027247deb91012fdElliott HughesEvent posting can happen from any thread.  The JDWP thread will not usually
42872d4ec7225444d9400d30f9027247deb91012fdElliott Hughespost anything but VM start/death, but if a JDWP request causes a class
43872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesto be loaded, the ClassPrepare event will come from the JDWP thread.
44872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
45872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
46872d4ec7225444d9400d30f9027247deb91012fdElliott HughesWe can have serialization issues when we post an event to the debugger.
47872d4ec7225444d9400d30f9027247deb91012fdElliott HughesFor example, a thread could send an "I hit a breakpoint and am suspending
48872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesmyself" message to the debugger.  Before it manages to suspend itself, the
49872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesdebugger's response ("not interested, resume thread") arrives and is
50872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesprocessed.  We try to resume a thread that hasn't yet suspended.
51872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
52872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThis means that, after posting an event to the debugger, we need to wait
53872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesfor the event thread to suspend itself (and, potentially, all other threads)
54872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesbefore processing any additional requests from the debugger.  While doing
55872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesso we need to be aware that multiple threads may be hitting breakpoints
56872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesor other events simultaneously, so we either need to wait for all of them
57872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesor serialize the events with each other.
58872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
59872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThe current mechanism works like this:
60872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  Event thread:
61872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - If I'm going to suspend, grab the "I am posting an event" token.  Wait
62872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     for it if it's not currently available.
63872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - Post the event to the debugger.
64872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - If appropriate, suspend others and then myself.  As part of suspending
65872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     myself, release the "I am posting" token.
66872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JDWP thread:
67872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - When an event arrives, see if somebody is posting an event.  If so,
68872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     sleep until we can acquire the "I am posting an event" token.  Release
69872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     it immediately and continue processing -- the event we have already
70872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     received should not interfere with other events that haven't yet
71872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     been posted.
72872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
73872d4ec7225444d9400d30f9027247deb91012fdElliott HughesSome care must be taken to avoid deadlock:
74872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
75872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A and thread B exit near-simultaneously, and post thread-death
76872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   events with a "suspend all" clause
77872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A gets the event token, thread B sits and waits for it
78872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A wants to suspend all other threads, but thread B is waiting
79872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   for the token and can't be suspended
80872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
81872d4ec7225444d9400d30f9027247deb91012fdElliott HughesSo we need to mark thread B in such a way that thread A doesn't wait for it.
82872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
83872d4ec7225444d9400d30f9027247deb91012fdElliott HughesIf we just bracket the "grab event token" call with a change to VMWAIT
84872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesbefore sleeping, the switch back to RUNNING state when we get the token
85872d4ec7225444d9400d30f9027247deb91012fdElliott Hugheswill cause thread B to suspend (remember, thread A's global suspend is
86872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstill in force, even after it releases the token).  Suspending while
87872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesholding the event token is very bad, because it prevents the JDWP thread
88872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesfrom processing incoming messages.
89872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
90872d4ec7225444d9400d30f9027247deb91012fdElliott HughesWe need to change to VMWAIT state at the *start* of posting an event,
91872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesand stay there until we either finish posting the event or decide to
92872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesput ourselves to sleep.  That way we don't interfere with anyone else and
93872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesdon't allow anyone else to interfere with us.
94872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes*/
95872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
96872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
97872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#define kJdwpEventCommandSet    64
98872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#define kJdwpCompositeCommand   100
99872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
100872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art {
101872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
102872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace JDWP {
103872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
104872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
105872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Stuff to compare against when deciding if a mod matches.  Only the
106872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * values for mods valid for the event being evaluated will be filled in.
107872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The rest will be zeroed.
108872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
109872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstruct ModBasket {
110162fd33474038f0de0388338ca007ecf400bb3dfjeffhao  ModBasket() : pLoc(NULL), threadId(0), classId(0), excepClassId(0),
111162fd33474038f0de0388338ca007ecf400bb3dfjeffhao                caught(false), field(0), thisPtr(0) { }
112162fd33474038f0de0388338ca007ecf400bb3dfjeffhao
113872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  const JdwpLocation* pLoc;           /* LocationOnly */
114a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  std::string         className;      /* ClassMatch/ClassExclude */
115872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId            threadId;       /* ThreadOnly */
116872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  RefTypeId           classId;        /* ClassOnly */
117872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  RefTypeId           excepClassId;   /* ExceptionOnly */
118872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  bool                caught;         /* ExceptionOnly */
119872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  FieldId             field;          /* FieldOnly */
120872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId            thisPtr;        /* InstanceOnly */
121872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* nothing for StepOnly -- handled differently */
122872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes};
123872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
124872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Dump an event to the log file.
126872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
127872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstatic void dumpEvent(const JdwpEvent* pEvent) {
128872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  LOG(INFO) << StringPrintf("Event id=0x%4x %p (prev=%p next=%p):", pEvent->requestId, pEvent, pEvent->prev, pEvent->next);
129f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  LOG(INFO) << "  kind=" << pEvent->eventKind << " susp=" << pEvent->suspend_policy << " modCount=" << pEvent->modCount;
130872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
131872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
132872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    const JdwpEventMod* pMod = &pEvent->mods[i];
1337b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes    LOG(INFO) << "  " << pMod->modKind;
134872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* TODO - show details */
135872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
138872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
139872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Add an event to the list.  Ordering is not important.
140872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
141872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If something prevents the event from being registered, e.g. it's a
142872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * single-step request on a thread that doesn't exist, the event will
143872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * not be added to the list, and an appropriate error will be returned.
144872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
145761928d24e4e7ed7776b52243eaf9095ad35f448Elliott HughesJdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) {
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);
1632435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes      JdwpError status = Dbg::ConfigureStep(pMod->step.threadId, size, depth);
1642435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes      if (status != ERR_NONE) {
1652435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes        return status;
1662435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes      }
167872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    } else if (pMod->modKind == MK_FIELD_ONLY) {
168872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should be for EK_FIELD_ACCESS or EK_FIELD_MODIFICATION */
169872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      dumpEvent(pEvent);  /* TODO - need for field watches */
170872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
171872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
172872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
173872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
174872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Add to list.
175872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
176449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  MutexLock mu(Thread::Current(), event_list_lock_);
177f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  if (event_list_ != NULL) {
178f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    pEvent->next = event_list_;
179f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    event_list_->prev = pEvent;
180872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
181f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  event_list_ = pEvent;
182f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  ++event_list_size_;
183872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
184872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
185872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
186872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
187872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
188872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove an event from the list.  This will also remove the event from
189872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * any optimization tables, e.g. breakpoints.
190872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
191872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Does not free the JdwpEvent.
192872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
193872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Grab the eventLock before calling here.
194872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
195761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterEvent(JdwpEvent* pEvent) {
196872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent->prev == NULL) {
197872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* head of the list */
198f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CHECK(event_list_ == pEvent);
199872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
200f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    event_list_ = pEvent->next;
201872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
202872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->prev->next = pEvent->next;
203872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
204872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
205872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent->next != NULL) {
206872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->next->prev = pEvent->prev;
207872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->next = NULL;
208872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
209872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  pEvent->prev = NULL;
210872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
211872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
212872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Unhook us from the interpreter, if necessary.
213872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
214872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
215872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEventMod* pMod = &pEvent->mods[i];
216872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pMod->modKind == MK_LOCATION_ONLY) {
217872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for Breakpoint, Step, and Exception */
218872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      Dbg::UnwatchLocation(&pMod->locationOnly.loc);
219872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
220872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pMod->modKind == MK_STEP) {
221872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for EK_SINGLE_STEP; should only be one */
222872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      Dbg::UnconfigureStep(pMod->step.threadId);
223872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
224872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
225872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
226f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  --event_list_size_;
227f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  CHECK(event_list_size_ != 0 || event_list_ == NULL);
228872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
229872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
230872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
231872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove the event with the given ID from the list.
232872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
233872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Failure to find the event isn't really an error, but it is a little
234872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * weird.  (It looks like Eclipse will try to be extra careful and will
235872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * explicitly remove one-off single-step events.)
236872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
237761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterEventById(uint32_t requestId) {
23850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  MutexLock mu(Thread::Current(), event_list_lock_);
239872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
240f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent* pEvent = event_list_;
241872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (pEvent != NULL) {
242872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pEvent->requestId == requestId) {
243761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      UnregisterEvent(pEvent);
244872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      EventFree(pEvent);
245761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      return;      /* there can be only one with a given ID */
246872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
247872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
248872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent = pEvent->next;
249872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
250872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
251872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  //LOGD("Odd: no match when removing event reqId=0x%04x", requestId);
252872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
253872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
254872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
255872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove all entries from the event list.
256872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
257761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterAll() {
25850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  MutexLock mu(Thread::Current(), event_list_lock_);
259872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
260f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent* pEvent = event_list_;
261872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (pEvent != NULL) {
262872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEvent* pNextEvent = pEvent->next;
263872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
264761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    UnregisterEvent(pEvent);
265872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    EventFree(pEvent);
266872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent = pNextEvent;
267872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
268872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
269f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  event_list_ = NULL;
270872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
271872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
272872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
273872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate a JdwpEvent struct with enough space to hold the specified
274872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * number of mod records.
275872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
276872d4ec7225444d9400d30f9027247deb91012fdElliott HughesJdwpEvent* EventAlloc(int numMods) {
277872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpEvent* newEvent;
278872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  int allocSize = offsetof(JdwpEvent, mods) + numMods * sizeof(newEvent->mods[0]);
279872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  newEvent = reinterpret_cast<JdwpEvent*>(malloc(allocSize));
280872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  memset(newEvent, 0, allocSize);
281872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return newEvent;
282872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
283872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
284872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
285872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Free a JdwpEvent.
286872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
287872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Do not call this until the event has been removed from the list.
288872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
289872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid EventFree(JdwpEvent* pEvent) {
290872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent == NULL) {
291872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
292872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
293872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
294872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* make sure it was removed from the list */
295872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->prev == NULL);
296872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->next == NULL);
297f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  /* want to check state->event_list_ != pEvent */
298872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
299872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
300872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Free any hairy bits in the mods.
301872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
302872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
303872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pEvent->mods[i].modKind == MK_CLASS_MATCH) {
304872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      free(pEvent->mods[i].classMatch.classPattern);
305872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pEvent->mods[i].classMatch.classPattern = NULL;
306872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
307872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pEvent->mods[i].modKind == MK_CLASS_EXCLUDE) {
308872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      free(pEvent->mods[i].classExclude.classPattern);
309872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pEvent->mods[i].classExclude.classPattern = NULL;
310872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
311872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
312872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
313872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  free(pEvent);
314872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
315872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
316872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
317872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate storage for matching events.  To keep things simple we
318872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * use an array with enough storage for the entire list.
319872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
320872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The state->eventLock should be held before calling.
321872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
322761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesstatic JdwpEvent** AllocMatchList(size_t event_count) {
323761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  return new JdwpEvent*[event_count];
324872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
325872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
326872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
327872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Run through the list and remove any entries with an expired "count" mod
328872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * from the event list, then free the match list.
329872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
330f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughesvoid JdwpState::CleanupMatchList(JdwpEvent** match_list, int match_count) {
331f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent** ppEvent = match_list;
332872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
3332aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  while (match_count--) {
334872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEvent* pEvent = *ppEvent;
335872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
336872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    for (int i = 0; i < pEvent->modCount; i++) {
337872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pEvent->mods[i].modKind == MK_COUNT && pEvent->mods[i].count.count == 0) {
3384dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "##### Removing expired event";
339761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        UnregisterEvent(pEvent);
340872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        EventFree(pEvent);
341872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        break;
342872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
343872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
344872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
345872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    ppEvent++;
346872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
347872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
348f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  delete[] match_list;
349872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
350872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
351872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
352872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Match a string against a "restricted regular expression", which is just
353872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * a string that may start or end with '*' (e.g. "*.Foo" or "java.*").
354872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
355872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * ("Restricted name globbing" might have been a better term.)
356872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
357761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesstatic bool PatternMatch(const char* pattern, const std::string& target) {
358a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  size_t patLen = strlen(pattern);
359872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pattern[0] == '*') {
360872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    patLen--;
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 the event's mods match up with the contents of "basket".
374872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
375872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If we find a Count mod before rejecting an event, we decrement it.  We
376872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * need to do this even if later mods cause us to ignore the event.
377872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
37800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic bool ModsMatch(JdwpEvent* pEvent, ModBasket* basket)
379b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
380872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpEventMod* pMod = pEvent->mods;
381872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
382872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = pEvent->modCount; i > 0; i--, pMod++) {
383872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    switch (pMod->modKind) {
384872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_COUNT:
385872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      CHECK_GT(pMod->count.count, 0);
386872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pMod->count.count--;
387872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
388872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CONDITIONAL:
389872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      CHECK(false);  // should not be getting these
390872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
391872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_THREAD_ONLY:
392872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->threadOnly.threadId != basket->threadId) {
393872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
394872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
395872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
396872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_ONLY:
397872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (!Dbg::MatchType(basket->classId, pMod->classOnly.refTypeId)) {
398872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
399872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
400872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
401872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_MATCH:
402761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      if (!PatternMatch(pMod->classMatch.classPattern, basket->className)) {
403872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
404872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
405872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
406872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_EXCLUDE:
407761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      if (PatternMatch(pMod->classMatch.classPattern, basket->className)) {
408872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
409872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
410872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
411872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_LOCATION_ONLY:
4122aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      if (pMod->locationOnly.loc != *basket->pLoc) {
413872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
414872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
415872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
416872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_EXCEPTION_ONLY:
417872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->exceptionOnly.refTypeId != 0 && !Dbg::MatchType(basket->excepClassId, pMod->exceptionOnly.refTypeId)) {
418872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
419872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
420872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if ((basket->caught && !pMod->exceptionOnly.caught) || (!basket->caught && !pMod->exceptionOnly.uncaught)) {
421872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
422872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
423872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
424872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_FIELD_ONLY:
425872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (!Dbg::MatchType(basket->classId, pMod->fieldOnly.refTypeId) || pMod->fieldOnly.fieldId != basket->field) {
426872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
427872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
428872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
429872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_STEP:
430872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->step.threadId != basket->threadId) {
431872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
432872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
433872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
434872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_INSTANCE_ONLY:
435872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->instanceOnly.objectId != basket->thisPtr) {
436872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
437872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
438872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
439872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    default:
4407b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes      LOG(FATAL) << "unknown mod kind " << pMod->modKind;
441872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
442872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
443872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
444872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return true;
445872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
446872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
447872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
448872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Find all events of type "eventKind" with mods that match up with the
449872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * rest of the arguments.
450872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
451f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes * Found events are appended to "match_list", and "*pMatchCount" is advanced,
452872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * so this may be called multiple times for grouped events.
453872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
454872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * DO NOT call this multiple times for the same eventKind, as Count mods are
455872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * decremented during the scan.
456872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
45700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersvoid JdwpState::FindMatchingEvents(JdwpEventKind eventKind, ModBasket* basket,
45800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                   JdwpEvent** match_list, int* pMatchCount) {
459872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* start after the existing entries */
460f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  match_list += *pMatchCount;
461872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
462f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent* pEvent = event_list_;
463872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (pEvent != NULL) {
464761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if (pEvent->eventKind == eventKind && ModsMatch(pEvent, basket)) {
465f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      *match_list++ = pEvent;
466872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      (*pMatchCount)++;
467872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
468872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
469872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent = pEvent->next;
470872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
471872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
472872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
473872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
474872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Scan through the list of matches and determine the most severe
475872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * suspension policy.
476872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
477f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughesstatic JdwpSuspendPolicy scanSuspendPolicy(JdwpEvent** match_list, int match_count) {
478872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpSuspendPolicy policy = SP_NONE;
479872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
4802aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  while (match_count--) {
481f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    if ((*match_list)->suspend_policy > policy) {
482f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      policy = (*match_list)->suspend_policy;
483872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
484f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    match_list++;
485872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
486872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
487872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return policy;
488872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
489872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
490872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
491872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Three possibilities:
492872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_NONE - do nothing
493872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_EVENT_THREAD - suspend ourselves
494872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_ALL - suspend everybody except JDWP support thread
495872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
49600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersvoid JdwpState::SuspendByPolicy(JdwpSuspendPolicy suspend_policy, JDWP::ObjectId thread_self_id) {
497f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  VLOG(jdwp) << "SuspendByPolicy(" << suspend_policy << ")";
498f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  if (suspend_policy == SP_NONE) {
499872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
500872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
501872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
502f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  if (suspend_policy == SP_ALL) {
503475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes    Dbg::SuspendVM();
504872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
505f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CHECK_EQ(suspend_policy, SP_EVENT_THREAD);
506872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
507872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
508872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* this is rare but possible -- see CLASS_PREPARE handling */
50900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (thread_self_id == debug_thread_id_) {
510761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    LOG(INFO) << "NOTE: SuspendByPolicy not suspending JDWP thread";
511872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
512872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
513872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
514872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  DebugInvokeReq* pReq = Dbg::GetInvokeReq();
515872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (true) {
516872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pReq->ready = true;
517872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    Dbg::SuspendSelf();
518872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pReq->ready = false;
519872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
520872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /*
521872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     * The JDWP thread has told us (and possibly all other threads) to
522872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     * resume.  See if it has left anything in our DebugInvokeReq mailbox.
523872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     */
524d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    if (!pReq->invoke_needed_) {
525761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      /*LOGD("SuspendByPolicy: no invoke needed");*/
526872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
527872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
528872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
529872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* grab this before posting/suspending again */
53000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    SetWaitForEventThread(thread_self_id);
531872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
532d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    /* leave pReq->invoke_needed_ raised so we can check reentrancy */
533872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    Dbg::ExecuteMethod(pReq);
534872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
535475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes    pReq->error = ERR_NONE;
536872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
537872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* clear this before signaling */
538d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    pReq->invoke_needed_ = false;
539872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
5404dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "invoke complete, signaling and self-suspending";
541c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    Thread* self = Thread::Current();
542c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    MutexLock mu(self, pReq->lock_);
543c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    pReq->cond_.Signal(self);
544872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
545872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
546872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
54700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersvoid JdwpState::SendRequestAndPossiblySuspend(ExpandBuf* pReq, JdwpSuspendPolicy suspend_policy,
54800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                              ObjectId threadId) {
54900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Thread* self = Thread::Current();
55000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  self->AssertThreadSuspensionIsAllowable();
55100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  /* send request and possibly suspend ourselves */
55200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (pReq != NULL) {
55300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    JDWP::ObjectId thread_self_id = Dbg::GetThreadSelfId();
55400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
55500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (suspend_policy != SP_NONE) {
55600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      SetWaitForEventThread(threadId);
55700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
55800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    EventFinish(pReq);
55900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    SuspendByPolicy(suspend_policy, thread_self_id);
56000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    self->TransitionFromSuspendedToRunnable();
56100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
56200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}
56300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
564872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
565872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Determine if there is a method invocation in progress in the current
566872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * thread.
567872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
568475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes * We look at the "invoke_needed" flag in the per-thread DebugInvokeReq
569872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * state.  If set, we're in the process of invoking a method.
570872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
571761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool JdwpState::InvokeInProgress() {
572872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  DebugInvokeReq* pReq = Dbg::GetInvokeReq();
573d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes  return pReq->invoke_needed_;
574872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
575872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
576872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
577872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * We need the JDWP thread to hold off on doing stuff while we post an
578872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * event and then suspend ourselves.
579872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
580872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Call this with a threadId of zero if you just want to wait for the
581872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * current thread operation to complete.
582872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
583872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This could go to sleep waiting for another thread, so it's important
584872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * that the thread be marked as VMWAIT before calling here.
585872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
586376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesvoid JdwpState::SetWaitForEventThread(ObjectId threadId) {
587872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  bool waited = false;
588872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
589872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* this is held for very brief periods; contention is unlikely */
59081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* self = Thread::Current();
59181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  MutexLock mu(self, event_thread_lock_);
592872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
593872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
594872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If another thread is already doing stuff, wait for it.  This can
595872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * go to sleep indefinitely.
596872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
597a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  while (event_thread_id_ != 0) {
598a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes    VLOG(jdwp) << StringPrintf("event in progress (%#llx), %#llx sleeping", event_thread_id_, threadId);
599872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    waited = true;
600c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    event_thread_cond_.Wait(self);
601872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
602872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
603872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (waited || threadId != 0) {
604229feb7a09317919ee51c06d1c3e715cea25da75Elliott Hughes    VLOG(jdwp) << StringPrintf("event token grabbed (%#llx)", threadId);
605872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
606872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (threadId != 0) {
607a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes    event_thread_id_ = threadId;
608872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
609872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
610872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
611872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
612872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Clear the threadId and signal anybody waiting.
613872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
614376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesvoid JdwpState::ClearWaitForEventThread() {
615872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
616872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Grab the mutex.  Don't try to go in/out of VMWAIT mode, as this
617872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * function is called by dvmSuspendSelf(), and the transition back
618872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * to RUNNING would confuse it.
619872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
620c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  Thread* self = Thread::Current();
621c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  MutexLock mu(self, event_thread_lock_);
622872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
623a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  CHECK_NE(event_thread_id_, 0U);
624a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  VLOG(jdwp) << StringPrintf("cleared event token (%#llx)", event_thread_id_);
625872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
626a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  event_thread_id_ = 0;
627872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
628c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  event_thread_cond_.Signal(self);
629872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
630872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
631872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
632872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
633872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Prep an event.  Allocates storage for the message and leaves space for
634872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * the header.
635872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
636872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstatic ExpandBuf* eventPrep() {
637872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = expandBufAlloc();
638872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAddSpace(pReq, kJDWPHeaderLen);
639872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return pReq;
640872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
641872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
642872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
643872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Write the header into the buffer and send the packet off to the debugger.
644872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
645872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Takes ownership of "pReq" (currently discards it).
646872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
647761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::EventFinish(ExpandBuf* pReq) {
648872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  uint8_t* buf = expandBufGetBuffer(pReq);
649872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
650f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(buf, expandBufGetLength(pReq));
651761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  Set4BE(buf+4, NextRequestSerial());
652f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+8, 0);     /* flags */
653f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+9, kJdwpEventCommandSet);
654f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+10, kJdwpCompositeCommand);
655872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
656761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  SendRequest(pReq);
657872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
658872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufFree(pReq);
659872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
660872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
661872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
662872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
663872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Tell the debugger that we have finished initializing.  This is always
664872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * sent, even if the debugger hasn't requested it.
665872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
666872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This should be sent "before the main thread is started and before
667872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * any application code has been executed".  The thread ID in the message
668872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * must be for the main thread.
669872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
670376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesbool JdwpState::PostVMStart() {
671f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy;
672872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId threadId = Dbg::GetThreadSelfId();
673872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
674376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  if (options_->suspend) {
675f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    suspend_policy = SP_ALL;
676872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
677f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    suspend_policy = SP_NONE;
678872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
679872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
680761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  ExpandBuf* pReq = eventPrep();
681761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
68250b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), event_list_lock_); // probably don't need this here
683872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
6844dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "EVENT: " << EK_VM_START;
685f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
686872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
687f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    expandBufAdd1(pReq, suspend_policy);
688872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd4BE(pReq, 1);
689872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
690872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd1(pReq, EK_VM_START);
691872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd4BE(pReq, 0);       /* requestId */
692872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd8BE(pReq, threadId);
693872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
694872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
695872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* send request and possibly suspend ourselves */
69600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, threadId);
697872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
698872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return true;
699872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
700872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
701872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
702872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * A location of interest has been reached.  This handles:
703872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Breakpoint
704872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   SingleStep
705872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   MethodEntry
706872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   MethodExit
707872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * These four types must be grouped together in a single response.  The
708872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * "eventFlags" indicates the type of event(s) that have happened.
709872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
710872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
711872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, InstanceOnly
712872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   LocationOnly (for breakpoint/step only)
713872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Step (for step only)
714872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
715872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Interesting test cases:
716872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Put a breakpoint on a native method.  Eclipse creates METHOD_ENTRY
717872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *    and METHOD_EXIT events with a ClassOnly mod on the method's class.
718872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Use "run to line".  Eclipse creates a BREAKPOINT with Count=1.
719872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Single-step to a line with a breakpoint.  Should get a single
720872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *    event message with both events in it.
721872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
722761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool JdwpState::PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags) {
723872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
724872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.pLoc = pLoc;
725748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.classId = pLoc->class_id;
726872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.thisPtr = thisPtr;
727872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
728748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.className = Dbg::GetClassName(pLoc->class_id);
729872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
730872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
731872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * On rare occasions we may need to execute interpreted code in the VM
732872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * while handling a request from the debugger.  Don't fire breakpoints
733872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * while doing so.  (I don't think we currently do this at all, so
734872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * this is mostly paranoia.)
735872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
736a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  if (basket.threadId == debug_thread_id_) {
7374dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Ignoring location event in JDWP thread";
738872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
739872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
740872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
741872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
742872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * The debugger variable display tab may invoke the interpreter to format
743872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * complex objects.  We want to ignore breakpoints and method entry/exit
744872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * traps while working on behalf of the debugger.
745872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   *
746872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If we don't ignore them, the VM will get hung up, because we'll
747872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * suspend on a breakpoint while the debugger is still waiting for its
748872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * method invocation to complete.
749872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
750761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
7514dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Not checking breakpoints during invoke (" << basket.className << ")";
752872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
753872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
754872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
755f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent** match_list = NULL;
7562aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  int match_count = 0;
757872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
758f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy = SP_NONE;
759872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
760761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
76150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), event_list_lock_);
762f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    match_list = AllocMatchList(event_list_size_);
7638696433d1b3d8ba15288483b777edd888de69135Elliott Hughes    if ((eventFlags & Dbg::kBreakpoint) != 0) {
764f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_BREAKPOINT, &basket, match_list, &match_count);
765761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
766761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kSingleStep) != 0) {
767f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_SINGLE_STEP, &basket, match_list, &match_count);
768761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
769761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kMethodEntry) != 0) {
770f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_METHOD_ENTRY, &basket, match_list, &match_count);
771761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
772761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kMethodExit) != 0) {
773f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_METHOD_EXIT, &basket, match_list, &match_count);
7748696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
7758696433d1b3d8ba15288483b777edd888de69135Elliott Hughes      // TODO: match EK_METHOD_EXIT_WITH_RETURN_VALUE too; we need to include the 'value', though.
776f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      //FindMatchingEvents(EK_METHOD_EXIT_WITH_RETURN_VALUE, &basket, match_list, &match_count);
777761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
7782aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    if (match_count != 0) {
779f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
780a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes                 << basket.className << "." << Dbg::GetMethodName(pLoc->method_id)
781229feb7a09317919ee51c06d1c3e715cea25da75Elliott Hughes                 << StringPrintf(" thread=%#llx dex_pc=%#llx)", basket.threadId, pLoc->dex_pc);
782872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
783f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      suspend_policy = scanSuspendPolicy(match_list, match_count);
784f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
785872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
786761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
787f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      expandBufAdd1(pReq, suspend_policy);
7882aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      expandBufAdd4BE(pReq, match_count);
789761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes
7902aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      for (int i = 0; i < match_count; i++) {
791f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd1(pReq, match_list[i]->eventKind);
792f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd4BE(pReq, match_list[i]->requestId);
793761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
7946e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        expandBufAddLocation(pReq, *pLoc);
795761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
796872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
797872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
798f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CleanupMatchList(match_list, match_count);
799761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  }
800872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
80100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
8022aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  return match_count != 0;
803872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
804872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
805872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
806872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * A thread is starting or stopping.
807872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
808872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
809872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  Count, ThreadOnly
810872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
811234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughesbool JdwpState::PostThreadChange(ObjectId threadId, bool start) {
812872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK_EQ(threadId, Dbg::GetThreadSelfId());
813872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
814872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
815872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * I don't think this can happen.
816872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
817761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
818872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(WARNING) << "Not posting thread change during invoke";
819872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
820872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
821872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
822872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
823872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = threadId;
824872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
825872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
826f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy = SP_NONE;
8272aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  int match_count = 0;
828234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes  {
829234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    // Don't allow the list to be updated while we scan it.
83050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), event_list_lock_);
831f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    JdwpEvent** match_list = AllocMatchList(event_list_size_);
832234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes
833234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    if (start) {
834f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_THREAD_START, &basket, match_list, &match_count);
835234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    } else {
836f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_THREAD_DEATH, &basket, match_list, &match_count);
837234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    }
838872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
8392aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    if (match_count != 0) {
840f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
8410cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes                 << StringPrintf("thread=%#llx", basket.threadId) << ")";
842872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
843f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      suspend_policy = scanSuspendPolicy(match_list, match_count);
844f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
845872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
846234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      pReq = eventPrep();
847f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      expandBufAdd1(pReq, suspend_policy);
8482aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      expandBufAdd4BE(pReq, match_count);
849234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes
8502aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      for (int i = 0; i < match_count; i++) {
851f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd1(pReq, match_list[i]->eventKind);
852f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd4BE(pReq, match_list[i]->requestId);
853234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
854234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      }
855872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
856872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
857f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CleanupMatchList(match_list, match_count);
858234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes  }
859872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
86000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
861872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
8622aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  return match_count != 0;
863872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
864872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
865872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
866872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Send a polite "VM is dying" message to the debugger.
867872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
868872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Skips the usual "event token" stuff.
869872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
870376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesbool JdwpState::PostVMDeath() {
8714dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(jdwp) << "EVENT: " << EK_VM_DEATH;
872872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
873872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = eventPrep();
874872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd1(pReq, SP_NONE);
875872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReq, 1);
876872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
877872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd1(pReq, EK_VM_DEATH);
878872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReq, 0);
879761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  EventFinish(pReq);
880872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return true;
881872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
882872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
883872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
884872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * An exception has been thrown.  It may or may not have been caught.
885872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
886872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
887872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, LocationOnly,
888872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *    ExceptionOnly, InstanceOnly
889872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
890872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The "exceptionId" has not been added to the GC-visible object registry,
891872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * because there's a pretty good chance that we're not going to send it
892872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * up the debugger.
893872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
894761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool JdwpState::PostException(const JdwpLocation* pThrowLoc,
895748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes                              ObjectId exceptionId, RefTypeId exceptionClassId,
896748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes                              const JdwpLocation* pCatchLoc, ObjectId thisPtr) {
897872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
898872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
899872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.pLoc = pThrowLoc;
900748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.classId = pThrowLoc->class_id;
901872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
902c308a5d8c1993ff51be355531548e91409bdbd82Elliott Hughes  basket.className = Dbg::GetClassName(basket.classId);
903872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.excepClassId = exceptionClassId;
904748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.caught = (pCatchLoc->class_id != 0);
905872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.thisPtr = thisPtr;
906872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
907872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* don't try to post an exception caused by the debugger */
908761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
9094dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Not posting exception hit during invoke (" << basket.className << ")";
910872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
911872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
912872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
913f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent** match_list = NULL;
9142aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  int match_count = 0;
915872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
916f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy = SP_NONE;
917761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
91850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), event_list_lock_);
919f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    match_list = AllocMatchList(event_list_size_);
920f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    FindMatchingEvents(EK_EXCEPTION, &basket, match_list, &match_count);
9212aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    if (match_count != 0) {
922f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total)"
9230cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes                 << StringPrintf(" thread=%#llx", basket.threadId)
9240cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes                 << StringPrintf(" exceptId=%#llx", exceptionId)
925436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes                 << " caught=" << basket.caught << ")"
926436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes                 << "  throw: " << *pThrowLoc;
927748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes      if (pCatchLoc->class_id == 0) {
9284dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "  catch: (not caught)";
929761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      } else {
9304dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "  catch: " << *pCatchLoc;
931761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
932872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
933f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      suspend_policy = scanSuspendPolicy(match_list, match_count);
934f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
935872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
936761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
937f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      expandBufAdd1(pReq, suspend_policy);
9382aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      expandBufAdd4BE(pReq, match_count);
939761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes
9402aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      for (int i = 0; i < match_count; i++) {
941f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd1(pReq, match_list[i]->eventKind);
942f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd4BE(pReq, match_list[i]->requestId);
943761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
944872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
9456e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        expandBufAddLocation(pReq, *pThrowLoc);
946761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd1(pReq, JT_OBJECT);
947761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, exceptionId);
9486e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        expandBufAddLocation(pReq, *pCatchLoc);
949761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
950872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
951872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
952f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CleanupMatchList(match_list, match_count);
953872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
954872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
95500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
956872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
9572aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  return match_count != 0;
958872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
959872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
960872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
961872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Announce that a class has been loaded.
962872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
963872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
964872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude
965872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
96600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersbool JdwpState::PostClassPrepare(JdwpTypeTag tag, RefTypeId refTypeId, const std::string& signature,
96700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                 int status) {
968872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
969872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
970872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.classId = refTypeId;
971872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
972c308a5d8c1993ff51be355531548e91409bdbd82Elliott Hughes  basket.className = Dbg::GetClassName(basket.classId);
973872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
974872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* suppress class prep caused by debugger */
975761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
9764dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Not posting class prep caused by invoke (" << basket.className << ")";
977872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
978872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
979872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
980872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
981f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy = SP_NONE;
982f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  int match_count = 0;
983761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
98450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), event_list_lock_);
985f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    JdwpEvent** match_list = AllocMatchList(event_list_size_);
986f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    FindMatchingEvents(EK_CLASS_PREPARE, &basket, match_list, &match_count);
9872aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    if (match_count != 0) {
988f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
9890cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes                 << StringPrintf("thread=%#llx", basket.threadId) << ") " << signature;
990872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
991f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      suspend_policy = scanSuspendPolicy(match_list, match_count);
992f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
993872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
994a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes      if (basket.threadId == debug_thread_id_) {
995761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        /*
996761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * JDWP says that, for a class prep in the debugger thread, we
997761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * should set threadId to null and if any threads were supposed
998761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * to be suspended then we suspend all other threads.
999761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         */
10004dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "  NOTE: class prepare in debugger thread!";
1001761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        basket.threadId = 0;
1002f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        if (suspend_policy == SP_EVENT_THREAD) {
1003f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes          suspend_policy = SP_ALL;
1004761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        }
1005872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1006872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1007761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
1008f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      expandBufAdd1(pReq, suspend_policy);
10092aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      expandBufAdd4BE(pReq, match_count);
1010872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
10112aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      for (int i = 0; i < match_count; i++) {
1012f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd1(pReq, match_list[i]->eventKind);
1013f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd4BE(pReq, match_list[i]->requestId);
1014761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
1015872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1016761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd1(pReq, tag);
1017761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, refTypeId);
1018761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAddUtf8String(pReq, signature);
1019761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd4BE(pReq, status);
1020761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
1021872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
1022f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CleanupMatchList(match_list, match_count);
1023872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1024872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
102500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
1026872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
10272aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  return match_count != 0;
1028872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1029872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1030872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1031872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Send up a chunk of DDM data.
1032872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1033872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * While this takes the form of a JDWP "event", it doesn't interact with
1034872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * other debugger traffic, and can't suspend the VM, so we skip all of
1035872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * the fun event token gymnastics.
1036872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1037cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughesvoid JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) {
1038872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  uint8_t header[kJDWPHeaderLen + 8];
1039872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  size_t dataLen = 0;
1040872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1041872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(iov != NULL);
1042cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  CHECK_GT(iov_count, 0);
1043cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  CHECK_LT(iov_count, 10);
1044872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1045872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
1046872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * "Wrap" the contents of the iovec with a JDWP/DDMS header.  We do
1047872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * this by creating a new copy of the vector with space for the header.
1048872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
1049f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom  std::vector<iovec> wrapiov;
1050f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom  wrapiov.push_back(iovec());
1051cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  for (int i = 0; i < iov_count; i++) {
1052f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom    wrapiov.push_back(iov[i]);
1053872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    dataLen += iov[i].iov_len;
1054872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1055872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1056872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* form the header (JDWP plus DDMS) */
1057f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header, sizeof(header) + dataLen);
1058f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+4, NextRequestSerial());
1059f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+8, 0);     /* flags */
1060f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+9, kJDWPDdmCmdSet);
1061f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+10, kJDWPDdmCmd);
1062f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+11, type);
1063f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+15, dataLen);
1064872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1065872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  wrapiov[0].iov_base = header;
1066872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  wrapiov[0].iov_len = sizeof(header);
1067872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
106815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  // Try to avoid blocking GC during a send, but only safe when not using mutexes at a lower-level
106915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  // than mutator for lock ordering reasons.
107000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Thread* self = Thread::Current();
107162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool safe_to_release_mutator_lock_over_send = !Locks::mutator_lock_->IsExclusiveHeld(self);
107262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (safe_to_release_mutator_lock_over_send) {
107338f85e4892f6504971bde994fec81fd61780ac30Brian Carlstrom    for (size_t i = 0; i < kMutatorLock; ++i) {
107462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      if (self->GetHeldMutex(static_cast<LockLevel>(i)) != NULL) {
107562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers        safe_to_release_mutator_lock_over_send = false;
107662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers        break;
107762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      }
107815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    }
107915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  }
108015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  if (safe_to_release_mutator_lock_over_send) {
108115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    // Change state to waiting to allow GC, ... while we're sending.
108215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
1083f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom    SendBufferedRequest(type, wrapiov);
108415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    self->TransitionFromSuspendedToRunnable();
108515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  } else {
108615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    // Send and possibly block GC...
1087f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom    SendBufferedRequest(type, wrapiov);
108815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  }
1089872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1090872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1091872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}  // namespace JDWP
1092872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1093872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}  // namespace art
1094