jdwp_event.cc revision 15bf2d34efa2218e287b584fb3653d268b9edc8d
1872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
2872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Copyright (C) 2008 The Android Open Source Project
3872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
4872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * you may not use this file except in compliance with the License.
6872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * You may obtain a copy of the License at
7872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
8872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
10872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Unless required by applicable law or agreed to in writing, software
11872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See the License for the specific language governing permissions and
14872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * limitations under the License.
15872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
16872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
17872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Send events to the debugger.
18872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
19872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "debugger.h"
20872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_priv.h"
21872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_constants.h"
22872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_handler.h"
23872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_event.h"
24872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_expand_buf.h"
25872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "logging.h"
26872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "stringprintf.h"
27872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
28872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <stdlib.h>
29872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <string.h>
30872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <stddef.h>     /* for offsetof() */
31872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <unistd.h>
32872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
33872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
34872d4ec7225444d9400d30f9027247deb91012fdElliott HughesGeneral notes:
35872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
36872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThe event add/remove stuff usually happens from the debugger thread,
37872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesin response to requests from the debugger, but can also happen as the
38872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesresult of an event in an arbitrary thread (e.g. an event with a "count"
39872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesmod expires).  It's important to keep the event list locked when processing
40872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesevents.
41872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
42872d4ec7225444d9400d30f9027247deb91012fdElliott HughesEvent posting can happen from any thread.  The JDWP thread will not usually
43872d4ec7225444d9400d30f9027247deb91012fdElliott Hughespost anything but VM start/death, but if a JDWP request causes a class
44872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesto be loaded, the ClassPrepare event will come from the JDWP thread.
45872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
46872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
47872d4ec7225444d9400d30f9027247deb91012fdElliott HughesWe can have serialization issues when we post an event to the debugger.
48872d4ec7225444d9400d30f9027247deb91012fdElliott HughesFor example, a thread could send an "I hit a breakpoint and am suspending
49872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesmyself" message to the debugger.  Before it manages to suspend itself, the
50872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesdebugger's response ("not interested, resume thread") arrives and is
51872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesprocessed.  We try to resume a thread that hasn't yet suspended.
52872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
53872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThis means that, after posting an event to the debugger, we need to wait
54872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesfor the event thread to suspend itself (and, potentially, all other threads)
55872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesbefore processing any additional requests from the debugger.  While doing
56872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesso we need to be aware that multiple threads may be hitting breakpoints
57872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesor other events simultaneously, so we either need to wait for all of them
58872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesor serialize the events with each other.
59872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
60872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThe current mechanism works like this:
61872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  Event thread:
62872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - If I'm going to suspend, grab the "I am posting an event" token.  Wait
63872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     for it if it's not currently available.
64872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - Post the event to the debugger.
65872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - If appropriate, suspend others and then myself.  As part of suspending
66872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     myself, release the "I am posting" token.
67872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JDWP thread:
68872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - When an event arrives, see if somebody is posting an event.  If so,
69872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     sleep until we can acquire the "I am posting an event" token.  Release
70872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     it immediately and continue processing -- the event we have already
71872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     received should not interfere with other events that haven't yet
72872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     been posted.
73872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
74872d4ec7225444d9400d30f9027247deb91012fdElliott HughesSome care must be taken to avoid deadlock:
75872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
76872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A and thread B exit near-simultaneously, and post thread-death
77872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   events with a "suspend all" clause
78872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A gets the event token, thread B sits and waits for it
79872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A wants to suspend all other threads, but thread B is waiting
80872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   for the token and can't be suspended
81872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
82872d4ec7225444d9400d30f9027247deb91012fdElliott HughesSo we need to mark thread B in such a way that thread A doesn't wait for it.
83872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
84872d4ec7225444d9400d30f9027247deb91012fdElliott HughesIf we just bracket the "grab event token" call with a change to VMWAIT
85872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesbefore sleeping, the switch back to RUNNING state when we get the token
86872d4ec7225444d9400d30f9027247deb91012fdElliott Hugheswill cause thread B to suspend (remember, thread A's global suspend is
87872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstill in force, even after it releases the token).  Suspending while
88872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesholding the event token is very bad, because it prevents the JDWP thread
89872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesfrom processing incoming messages.
90872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
91872d4ec7225444d9400d30f9027247deb91012fdElliott HughesWe need to change to VMWAIT state at the *start* of posting an event,
92872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesand stay there until we either finish posting the event or decide to
93872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesput ourselves to sleep.  That way we don't interfere with anyone else and
94872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesdon't allow anyone else to interfere with us.
95872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes*/
96872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
97872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
98872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#define kJdwpEventCommandSet    64
99872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#define kJdwpCompositeCommand   100
100872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
101872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art {
102872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
103872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace JDWP {
104872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
105872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
106872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Stuff to compare against when deciding if a mod matches.  Only the
107872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * values for mods valid for the event being evaluated will be filled in.
108872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The rest will be zeroed.
109872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
110872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstruct ModBasket {
111872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  const JdwpLocation* pLoc;           /* LocationOnly */
112a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  std::string         className;      /* ClassMatch/ClassExclude */
113872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId            threadId;       /* ThreadOnly */
114872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  RefTypeId           classId;        /* ClassOnly */
115872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  RefTypeId           excepClassId;   /* ExceptionOnly */
116872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  bool                caught;         /* ExceptionOnly */
117872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  FieldId             field;          /* FieldOnly */
118872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId            thisPtr;        /* InstanceOnly */
119872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* nothing for StepOnly -- handled differently */
120872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes};
121872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
122872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
123872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Dump an event to the log file.
124872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstatic void dumpEvent(const JdwpEvent* pEvent) {
126872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  LOG(INFO) << StringPrintf("Event id=0x%4x %p (prev=%p next=%p):", pEvent->requestId, pEvent, pEvent->prev, pEvent->next);
127f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  LOG(INFO) << "  kind=" << pEvent->eventKind << " susp=" << pEvent->suspend_policy << " modCount=" << pEvent->modCount;
128872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
129872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
130872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    const JdwpEventMod* pMod = &pEvent->mods[i];
1317b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes    LOG(INFO) << "  " << pMod->modKind;
132872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* TODO - show details */
133872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
134872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
135872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Add an event to the list.  Ordering is not important.
138872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
139872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If something prevents the event from being registered, e.g. it's a
140872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * single-step request on a thread that doesn't exist, the event will
141872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * not be added to the list, and an appropriate error will be returned.
142872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
143761928d24e4e7ed7776b52243eaf9095ad35f448Elliott HughesJdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) {
144f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  MutexLock mu(event_list_lock_);
145872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
146872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent != NULL);
147872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->prev == NULL);
148872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->next == NULL);
149872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
150872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
151872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If one or more "break"-type mods are used, register them with
152872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * the interpreter.
153872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
154872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
155872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    const JdwpEventMod* pMod = &pEvent->mods[i];
156872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pMod->modKind == MK_LOCATION_ONLY) {
157872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for Breakpoint, Step, and Exception */
158872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      Dbg::WatchLocation(&pMod->locationOnly.loc);
159872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    } else if (pMod->modKind == MK_STEP) {
160872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for EK_SINGLE_STEP; should only be one */
161872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      JdwpStepSize size = static_cast<JdwpStepSize>(pMod->step.size);
162872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      JdwpStepDepth depth = static_cast<JdwpStepDepth>(pMod->step.depth);
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   */
176f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  if (event_list_ != NULL) {
177f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    pEvent->next = event_list_;
178f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    event_list_->prev = pEvent;
179872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
180f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  event_list_ = pEvent;
181f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  ++event_list_size_;
182872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
183872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
184872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
185872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
186872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
187872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove an event from the list.  This will also remove the event from
188872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * any optimization tables, e.g. breakpoints.
189872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
190872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Does not free the JdwpEvent.
191872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
192872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Grab the eventLock before calling here.
193872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
194761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterEvent(JdwpEvent* pEvent) {
195872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent->prev == NULL) {
196872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* head of the list */
197f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CHECK(event_list_ == pEvent);
198872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
199f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    event_list_ = pEvent->next;
200872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
201872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->prev->next = pEvent->next;
202872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
203872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
204872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent->next != NULL) {
205872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->next->prev = pEvent->prev;
206872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->next = NULL;
207872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
208872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  pEvent->prev = NULL;
209872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
210872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
211872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Unhook us from the interpreter, if necessary.
212872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
213872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
214872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEventMod* pMod = &pEvent->mods[i];
215872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pMod->modKind == MK_LOCATION_ONLY) {
216872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for Breakpoint, Step, and Exception */
217872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      Dbg::UnwatchLocation(&pMod->locationOnly.loc);
218872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
219872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pMod->modKind == MK_STEP) {
220872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for EK_SINGLE_STEP; should only be one */
221872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      Dbg::UnconfigureStep(pMod->step.threadId);
222872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
223872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
224872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
225f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  --event_list_size_;
226f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  CHECK(event_list_size_ != 0 || event_list_ == NULL);
227872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
228872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
229872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
230872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove the event with the given ID from the list.
231872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
232872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Failure to find the event isn't really an error, but it is a little
233872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * weird.  (It looks like Eclipse will try to be extra careful and will
234872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * explicitly remove one-off single-step events.)
235872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
236761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterEventById(uint32_t requestId) {
237f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  MutexLock mu(event_list_lock_);
238872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
239f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent* pEvent = event_list_;
240872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (pEvent != NULL) {
241872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pEvent->requestId == requestId) {
242761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      UnregisterEvent(pEvent);
243872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      EventFree(pEvent);
244761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      return;      /* there can be only one with a given ID */
245872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
246872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
247872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent = pEvent->next;
248872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
249872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
250872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  //LOGD("Odd: no match when removing event reqId=0x%04x", requestId);
251872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
252872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
253872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
254872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove all entries from the event list.
255872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
256761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterAll() {
257f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  MutexLock mu(event_list_lock_);
258872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
259f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent* pEvent = event_list_;
260872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (pEvent != NULL) {
261872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEvent* pNextEvent = pEvent->next;
262872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
263761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    UnregisterEvent(pEvent);
264872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    EventFree(pEvent);
265872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent = pNextEvent;
266872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
267872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
268f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  event_list_ = NULL;
269872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
270872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
271872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
272872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate a JdwpEvent struct with enough space to hold the specified
273872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * number of mod records.
274872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
275872d4ec7225444d9400d30f9027247deb91012fdElliott HughesJdwpEvent* EventAlloc(int numMods) {
276872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpEvent* newEvent;
277872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  int allocSize = offsetof(JdwpEvent, mods) + numMods * sizeof(newEvent->mods[0]);
278872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  newEvent = reinterpret_cast<JdwpEvent*>(malloc(allocSize));
279872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  memset(newEvent, 0, allocSize);
280872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return newEvent;
281872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
282872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
283872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
284872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Free a JdwpEvent.
285872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
286872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Do not call this until the event has been removed from the list.
287872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
288872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid EventFree(JdwpEvent* pEvent) {
289872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent == NULL) {
290872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
291872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
292872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
293872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* make sure it was removed from the list */
294872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->prev == NULL);
295872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->next == NULL);
296f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  /* want to check state->event_list_ != pEvent */
297872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
298872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
299872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Free any hairy bits in the mods.
300872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
301872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
302872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pEvent->mods[i].modKind == MK_CLASS_MATCH) {
303872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      free(pEvent->mods[i].classMatch.classPattern);
304872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pEvent->mods[i].classMatch.classPattern = NULL;
305872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
306872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pEvent->mods[i].modKind == MK_CLASS_EXCLUDE) {
307872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      free(pEvent->mods[i].classExclude.classPattern);
308872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pEvent->mods[i].classExclude.classPattern = NULL;
309872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
310872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
311872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
312872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  free(pEvent);
313872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
314872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
315872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
316872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate storage for matching events.  To keep things simple we
317872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * use an array with enough storage for the entire list.
318872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
319872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The state->eventLock should be held before calling.
320872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
321761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesstatic JdwpEvent** AllocMatchList(size_t event_count) {
322761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  return new JdwpEvent*[event_count];
323872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
324872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
325872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
326872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Run through the list and remove any entries with an expired "count" mod
327872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * from the event list, then free the match list.
328872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
329f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughesvoid JdwpState::CleanupMatchList(JdwpEvent** match_list, int match_count) {
330f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent** ppEvent = match_list;
331872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
3322aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  while (match_count--) {
333872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEvent* pEvent = *ppEvent;
334872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
335872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    for (int i = 0; i < pEvent->modCount; i++) {
336872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pEvent->mods[i].modKind == MK_COUNT && pEvent->mods[i].count.count == 0) {
3374dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "##### Removing expired event";
338761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        UnregisterEvent(pEvent);
339872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        EventFree(pEvent);
340872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        break;
341872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
342872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
343872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
344872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    ppEvent++;
345872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
346872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
347f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  delete[] match_list;
348872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
349872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
350872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
351872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Match a string against a "restricted regular expression", which is just
352872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * a string that may start or end with '*' (e.g. "*.Foo" or "java.*").
353872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
354872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * ("Restricted name globbing" might have been a better term.)
355872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
356761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesstatic bool PatternMatch(const char* pattern, const std::string& target) {
357a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  size_t patLen = strlen(pattern);
358872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pattern[0] == '*') {
359872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    patLen--;
360a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    if (target.size() < patLen) {
361872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      return false;
362872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
363a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    return strcmp(pattern+1, target.c_str() + (target.size()-patLen)) == 0;
364872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else if (pattern[patLen-1] == '*') {
365a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    return strncmp(pattern, target.c_str(), patLen-1) == 0;
366872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
367a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    return strcmp(pattern, target.c_str()) == 0;
368872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
369872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
370872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
371872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
372872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See if the event's mods match up with the contents of "basket".
373872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
374872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If we find a Count mod before rejecting an event, we decrement it.  We
375872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * need to do this even if later mods cause us to ignore the event.
376872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
37700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic bool ModsMatch(JdwpEvent* pEvent, ModBasket* basket)
37800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
379872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpEventMod* pMod = pEvent->mods;
380872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
381872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = pEvent->modCount; i > 0; i--, pMod++) {
382872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    switch (pMod->modKind) {
383872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_COUNT:
384872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      CHECK_GT(pMod->count.count, 0);
385872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pMod->count.count--;
386872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
387872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CONDITIONAL:
388872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      CHECK(false);  // should not be getting these
389872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
390872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_THREAD_ONLY:
391872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->threadOnly.threadId != basket->threadId) {
392872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
393872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
394872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
395872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_ONLY:
396872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (!Dbg::MatchType(basket->classId, pMod->classOnly.refTypeId)) {
397872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
398872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
399872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
400872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_MATCH:
401761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      if (!PatternMatch(pMod->classMatch.classPattern, basket->className)) {
402872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
403872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
404872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
405872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_EXCLUDE:
406761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      if (PatternMatch(pMod->classMatch.classPattern, basket->className)) {
407872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
408872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
409872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
410872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_LOCATION_ONLY:
4112aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      if (pMod->locationOnly.loc != *basket->pLoc) {
412872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
413872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
414872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
415872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_EXCEPTION_ONLY:
416872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->exceptionOnly.refTypeId != 0 && !Dbg::MatchType(basket->excepClassId, pMod->exceptionOnly.refTypeId)) {
417872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
418872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
419872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if ((basket->caught && !pMod->exceptionOnly.caught) || (!basket->caught && !pMod->exceptionOnly.uncaught)) {
420872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
421872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
422872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
423872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_FIELD_ONLY:
424872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (!Dbg::MatchType(basket->classId, pMod->fieldOnly.refTypeId) || pMod->fieldOnly.fieldId != basket->field) {
425872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
426872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
427872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
428872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_STEP:
429872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->step.threadId != basket->threadId) {
430872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
431872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
432872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
433872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_INSTANCE_ONLY:
434872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->instanceOnly.objectId != basket->thisPtr) {
435872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
436872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
437872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
438872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    default:
4397b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes      LOG(FATAL) << "unknown mod kind " << pMod->modKind;
440872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
441872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
442872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
443872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return true;
444872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
445872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
446872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
447872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Find all events of type "eventKind" with mods that match up with the
448872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * rest of the arguments.
449872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
450f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes * Found events are appended to "match_list", and "*pMatchCount" is advanced,
451872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * so this may be called multiple times for grouped events.
452872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
453872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * DO NOT call this multiple times for the same eventKind, as Count mods are
454872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * decremented during the scan.
455872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
45600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersvoid JdwpState::FindMatchingEvents(JdwpEventKind eventKind, ModBasket* basket,
45700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                   JdwpEvent** match_list, int* pMatchCount) {
458872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* start after the existing entries */
459f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  match_list += *pMatchCount;
460872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
461f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent* pEvent = event_list_;
462872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (pEvent != NULL) {
463761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if (pEvent->eventKind == eventKind && ModsMatch(pEvent, basket)) {
464f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      *match_list++ = pEvent;
465872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      (*pMatchCount)++;
466872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
467872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
468872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent = pEvent->next;
469872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
470872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
471872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
472872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
473872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Scan through the list of matches and determine the most severe
474872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * suspension policy.
475872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
476f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughesstatic JdwpSuspendPolicy scanSuspendPolicy(JdwpEvent** match_list, int match_count) {
477872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpSuspendPolicy policy = SP_NONE;
478872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
4792aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  while (match_count--) {
480f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    if ((*match_list)->suspend_policy > policy) {
481f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      policy = (*match_list)->suspend_policy;
482872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
483f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    match_list++;
484872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
485872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
486872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return policy;
487872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
488872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
489872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
490872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Three possibilities:
491872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_NONE - do nothing
492872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_EVENT_THREAD - suspend ourselves
493872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_ALL - suspend everybody except JDWP support thread
494872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
49500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersvoid JdwpState::SuspendByPolicy(JdwpSuspendPolicy suspend_policy, JDWP::ObjectId thread_self_id) {
496f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  VLOG(jdwp) << "SuspendByPolicy(" << suspend_policy << ")";
497f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  if (suspend_policy == SP_NONE) {
498872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
499872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
500872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
501f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  if (suspend_policy == SP_ALL) {
502475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes    Dbg::SuspendVM();
503872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
504f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CHECK_EQ(suspend_policy, SP_EVENT_THREAD);
505872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
506872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
507872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* this is rare but possible -- see CLASS_PREPARE handling */
50800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (thread_self_id == debug_thread_id_) {
509761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    LOG(INFO) << "NOTE: SuspendByPolicy not suspending JDWP thread";
510872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
511872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
512872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
513872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  DebugInvokeReq* pReq = Dbg::GetInvokeReq();
514872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (true) {
515872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pReq->ready = true;
516872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    Dbg::SuspendSelf();
517872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pReq->ready = false;
518872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
519872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /*
520872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     * The JDWP thread has told us (and possibly all other threads) to
521872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     * resume.  See if it has left anything in our DebugInvokeReq mailbox.
522872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     */
523d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    if (!pReq->invoke_needed_) {
524761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      /*LOGD("SuspendByPolicy: no invoke needed");*/
525872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
526872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
527872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
528872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* grab this before posting/suspending again */
52900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    SetWaitForEventThread(thread_self_id);
530872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
531d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    /* leave pReq->invoke_needed_ raised so we can check reentrancy */
532872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    Dbg::ExecuteMethod(pReq);
533872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
534475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes    pReq->error = ERR_NONE;
535872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
536872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* clear this before signaling */
537d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    pReq->invoke_needed_ = false;
538872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
5394dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "invoke complete, signaling and self-suspending";
540872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    MutexLock mu(pReq->lock_);
541872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pReq->cond_.Signal();
542872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
543872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
544872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
54500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersvoid JdwpState::SendRequestAndPossiblySuspend(ExpandBuf* pReq, JdwpSuspendPolicy suspend_policy,
54600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                              ObjectId threadId) {
54700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Thread* self = Thread::Current();
54800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  self->AssertThreadSuspensionIsAllowable();
54900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  /* send request and possibly suspend ourselves */
55000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (pReq != NULL) {
55100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    JDWP::ObjectId thread_self_id = Dbg::GetThreadSelfId();
55200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
55300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (suspend_policy != SP_NONE) {
55400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      SetWaitForEventThread(threadId);
55500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
55600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    EventFinish(pReq);
55700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    SuspendByPolicy(suspend_policy, thread_self_id);
55800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    self->TransitionFromSuspendedToRunnable();
55900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
56000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}
56100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
562872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
563872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Determine if there is a method invocation in progress in the current
564872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * thread.
565872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
566475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes * We look at the "invoke_needed" flag in the per-thread DebugInvokeReq
567872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * state.  If set, we're in the process of invoking a method.
568872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
569761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool JdwpState::InvokeInProgress() {
570872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  DebugInvokeReq* pReq = Dbg::GetInvokeReq();
571d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes  return pReq->invoke_needed_;
572872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
573872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
574872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
575872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * We need the JDWP thread to hold off on doing stuff while we post an
576872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * event and then suspend ourselves.
577872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
578872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Call this with a threadId of zero if you just want to wait for the
579872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * current thread operation to complete.
580872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
581872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This could go to sleep waiting for another thread, so it's important
582872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * that the thread be marked as VMWAIT before calling here.
583872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
584376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesvoid JdwpState::SetWaitForEventThread(ObjectId threadId) {
585872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  bool waited = false;
586872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
587872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* this is held for very brief periods; contention is unlikely */
588376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  MutexLock mu(event_thread_lock_);
589872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
590872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
591872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If another thread is already doing stuff, wait for it.  This can
592872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * go to sleep indefinitely.
593872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
594a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  while (event_thread_id_ != 0) {
595a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes    VLOG(jdwp) << StringPrintf("event in progress (%#llx), %#llx sleeping", event_thread_id_, threadId);
596872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    waited = true;
597376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes    event_thread_cond_.Wait(event_thread_lock_);
598872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
599872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
600872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (waited || threadId != 0) {
601229feb7a09317919ee51c06d1c3e715cea25da75Elliott Hughes    VLOG(jdwp) << StringPrintf("event token grabbed (%#llx)", threadId);
602872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
603872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (threadId != 0) {
604a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes    event_thread_id_ = threadId;
605872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
606872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
607872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
608872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
609872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Clear the threadId and signal anybody waiting.
610872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
611376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesvoid JdwpState::ClearWaitForEventThread() {
612872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
613872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Grab the mutex.  Don't try to go in/out of VMWAIT mode, as this
614872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * function is called by dvmSuspendSelf(), and the transition back
615872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * to RUNNING would confuse it.
616872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
617376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  MutexLock mu(event_thread_lock_);
618872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
619a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  CHECK_NE(event_thread_id_, 0U);
620a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  VLOG(jdwp) << StringPrintf("cleared event token (%#llx)", event_thread_id_);
621872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
622a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  event_thread_id_ = 0;
623872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
624376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  event_thread_cond_.Signal();
625872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
626872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
627872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
628872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
629872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Prep an event.  Allocates storage for the message and leaves space for
630872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * the header.
631872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
632872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstatic ExpandBuf* eventPrep() {
633872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = expandBufAlloc();
634872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAddSpace(pReq, kJDWPHeaderLen);
635872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return pReq;
636872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
637872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
638872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
639872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Write the header into the buffer and send the packet off to the debugger.
640872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
641872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Takes ownership of "pReq" (currently discards it).
642872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
643761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::EventFinish(ExpandBuf* pReq) {
644872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  uint8_t* buf = expandBufGetBuffer(pReq);
645872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
646f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(buf, expandBufGetLength(pReq));
647761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  Set4BE(buf+4, NextRequestSerial());
648f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+8, 0);     /* flags */
649f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+9, kJdwpEventCommandSet);
650f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+10, kJdwpCompositeCommand);
651872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
652761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  SendRequest(pReq);
653872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
654872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufFree(pReq);
655872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
656872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
657872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
658872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
659872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Tell the debugger that we have finished initializing.  This is always
660872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * sent, even if the debugger hasn't requested it.
661872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
662872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This should be sent "before the main thread is started and before
663872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * any application code has been executed".  The thread ID in the message
664872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * must be for the main thread.
665872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
666376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesbool JdwpState::PostVMStart() {
667f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy;
668872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId threadId = Dbg::GetThreadSelfId();
669872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
670376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  if (options_->suspend) {
671f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    suspend_policy = SP_ALL;
672872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
673f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    suspend_policy = SP_NONE;
674872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
675872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
676761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  ExpandBuf* pReq = eventPrep();
677761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
678f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    MutexLock mu(event_list_lock_); // probably don't need this here
679872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
6804dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "EVENT: " << EK_VM_START;
681f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
682872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
683f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    expandBufAdd1(pReq, suspend_policy);
684872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd4BE(pReq, 1);
685872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
686872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd1(pReq, EK_VM_START);
687872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd4BE(pReq, 0);       /* requestId */
688872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd8BE(pReq, threadId);
689872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
690872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
691872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* send request and possibly suspend ourselves */
69200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, threadId);
693872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
694872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return true;
695872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
696872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
697872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
698872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * A location of interest has been reached.  This handles:
699872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Breakpoint
700872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   SingleStep
701872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   MethodEntry
702872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   MethodExit
703872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * These four types must be grouped together in a single response.  The
704872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * "eventFlags" indicates the type of event(s) that have happened.
705872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
706872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
707872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, InstanceOnly
708872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   LocationOnly (for breakpoint/step only)
709872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Step (for step only)
710872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
711872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Interesting test cases:
712872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Put a breakpoint on a native method.  Eclipse creates METHOD_ENTRY
713872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *    and METHOD_EXIT events with a ClassOnly mod on the method's class.
714872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Use "run to line".  Eclipse creates a BREAKPOINT with Count=1.
715872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Single-step to a line with a breakpoint.  Should get a single
716872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *    event message with both events in it.
717872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
718761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool JdwpState::PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags) {
719872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
720872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
721872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  memset(&basket, 0, sizeof(basket));
722872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.pLoc = pLoc;
723748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.classId = pLoc->class_id;
724872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.thisPtr = thisPtr;
725872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
726748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.className = Dbg::GetClassName(pLoc->class_id);
727872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
728872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
729872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * On rare occasions we may need to execute interpreted code in the VM
730872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * while handling a request from the debugger.  Don't fire breakpoints
731872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * while doing so.  (I don't think we currently do this at all, so
732872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * this is mostly paranoia.)
733872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
734a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  if (basket.threadId == debug_thread_id_) {
7354dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Ignoring location event in JDWP thread";
736872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
737872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
738872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
739872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
740872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * The debugger variable display tab may invoke the interpreter to format
741872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * complex objects.  We want to ignore breakpoints and method entry/exit
742872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * traps while working on behalf of the debugger.
743872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   *
744872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If we don't ignore them, the VM will get hung up, because we'll
745872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * suspend on a breakpoint while the debugger is still waiting for its
746872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * method invocation to complete.
747872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
748761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
7494dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Not checking breakpoints during invoke (" << basket.className << ")";
750872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
751872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
752872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
753f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent** match_list = NULL;
7542aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  int match_count = 0;
755872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
756f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy = SP_NONE;
757872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
758761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
759f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    MutexLock mu(event_list_lock_);
760f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    match_list = AllocMatchList(event_list_size_);
7618696433d1b3d8ba15288483b777edd888de69135Elliott Hughes    if ((eventFlags & Dbg::kBreakpoint) != 0) {
762f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_BREAKPOINT, &basket, match_list, &match_count);
763761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
764761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kSingleStep) != 0) {
765f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_SINGLE_STEP, &basket, match_list, &match_count);
766761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
767761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kMethodEntry) != 0) {
768f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_METHOD_ENTRY, &basket, match_list, &match_count);
769761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
770761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kMethodExit) != 0) {
771f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_METHOD_EXIT, &basket, match_list, &match_count);
7728696433d1b3d8ba15288483b777edd888de69135Elliott Hughes
7738696433d1b3d8ba15288483b777edd888de69135Elliott Hughes      // TODO: match EK_METHOD_EXIT_WITH_RETURN_VALUE too; we need to include the 'value', though.
774f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      //FindMatchingEvents(EK_METHOD_EXIT_WITH_RETURN_VALUE, &basket, match_list, &match_count);
775761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
7762aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    if (match_count != 0) {
777f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
778748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes                 << basket.className << "." << Dbg::GetMethodName(pLoc->class_id, pLoc->method_id)
779229feb7a09317919ee51c06d1c3e715cea25da75Elliott Hughes                 << StringPrintf(" thread=%#llx dex_pc=%#llx)", basket.threadId, pLoc->dex_pc);
780872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
781f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      suspend_policy = scanSuspendPolicy(match_list, match_count);
782f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
783872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
784761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
785f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      expandBufAdd1(pReq, suspend_policy);
7862aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      expandBufAdd4BE(pReq, match_count);
787761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes
7882aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      for (int i = 0; i < match_count; i++) {
789f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd1(pReq, match_list[i]->eventKind);
790f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd4BE(pReq, match_list[i]->requestId);
791761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
7926e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        expandBufAddLocation(pReq, *pLoc);
793761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
794872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
795872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
796f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CleanupMatchList(match_list, match_count);
797761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  }
798872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
79900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
800872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
8012aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  return match_count != 0;
802872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
803872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
804872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
805872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * A thread is starting or stopping.
806872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
807872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
808872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  Count, ThreadOnly
809872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
810234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughesbool JdwpState::PostThreadChange(ObjectId threadId, bool start) {
811872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK_EQ(threadId, Dbg::GetThreadSelfId());
812872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
813872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
814872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * I don't think this can happen.
815872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
816761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
817872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(WARNING) << "Not posting thread change during invoke";
818872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
819872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
820872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
821872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
822872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  memset(&basket, 0, sizeof(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.
830f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    MutexLock mu(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  memset(&basket, 0, sizeof(basket));
900872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.pLoc = pThrowLoc;
901748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.classId = pThrowLoc->class_id;
902872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
903c308a5d8c1993ff51be355531548e91409bdbd82Elliott Hughes  basket.className = Dbg::GetClassName(basket.classId);
904872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.excepClassId = exceptionClassId;
905748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.caught = (pCatchLoc->class_id != 0);
906872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.thisPtr = thisPtr;
907872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
908872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* don't try to post an exception caused by the debugger */
909761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
9104dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Not posting exception hit during invoke (" << basket.className << ")";
911872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
912872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
913872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
914f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent** match_list = NULL;
9152aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  int match_count = 0;
916872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
917f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy = SP_NONE;
918761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
919f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    MutexLock mu(event_list_lock_);
920f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    match_list = AllocMatchList(event_list_size_);
921f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    FindMatchingEvents(EK_EXCEPTION, &basket, match_list, &match_count);
9222aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    if (match_count != 0) {
923f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total)"
9240cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes                 << StringPrintf(" thread=%#llx", basket.threadId)
9250cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes                 << StringPrintf(" exceptId=%#llx", exceptionId)
926436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes                 << " caught=" << basket.caught << ")"
927436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes                 << "  throw: " << *pThrowLoc;
928748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes      if (pCatchLoc->class_id == 0) {
9294dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "  catch: (not caught)";
930761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      } else {
9314dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "  catch: " << *pCatchLoc;
932761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
933872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
934f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      suspend_policy = scanSuspendPolicy(match_list, match_count);
935f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
936872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
937761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
938f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      expandBufAdd1(pReq, suspend_policy);
9392aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      expandBufAdd4BE(pReq, match_count);
940761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes
9412aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      for (int i = 0; i < match_count; i++) {
942f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd1(pReq, match_list[i]->eventKind);
943f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd4BE(pReq, match_list[i]->requestId);
944761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
945872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
9466e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        expandBufAddLocation(pReq, *pThrowLoc);
947761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd1(pReq, JT_OBJECT);
948761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, exceptionId);
9496e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        expandBufAddLocation(pReq, *pCatchLoc);
950761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
951872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
952761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      /* don't let the GC discard it */
953761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      Dbg::RegisterObjectId(exceptionId);
954872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
955872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
956f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CleanupMatchList(match_list, match_count);
957872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
958872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
95900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
960872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
9612aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  return match_count != 0;
962872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
963872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
964872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
965872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Announce that a class has been loaded.
966872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
967872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
968872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude
969872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
97000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersbool JdwpState::PostClassPrepare(JdwpTypeTag tag, RefTypeId refTypeId, const std::string& signature,
97100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                 int status) {
972872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
973872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
974872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  memset(&basket, 0, sizeof(basket));
975872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.classId = refTypeId;
976872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
977c308a5d8c1993ff51be355531548e91409bdbd82Elliott Hughes  basket.className = Dbg::GetClassName(basket.classId);
978872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
979872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* suppress class prep caused by debugger */
980761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
9814dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Not posting class prep caused by invoke (" << basket.className << ")";
982872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
983872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
984872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
985872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
986f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy = SP_NONE;
987f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  int match_count = 0;
988761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
989f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    MutexLock mu(event_list_lock_);
990f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    JdwpEvent** match_list = AllocMatchList(event_list_size_);
991f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    FindMatchingEvents(EK_CLASS_PREPARE, &basket, match_list, &match_count);
9922aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    if (match_count != 0) {
993f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
9940cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes                 << StringPrintf("thread=%#llx", basket.threadId) << ") " << signature;
995872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
996f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      suspend_policy = scanSuspendPolicy(match_list, match_count);
997f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
998872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
999a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes      if (basket.threadId == debug_thread_id_) {
1000761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        /*
1001761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * JDWP says that, for a class prep in the debugger thread, we
1002761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * should set threadId to null and if any threads were supposed
1003761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * to be suspended then we suspend all other threads.
1004761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         */
10054dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "  NOTE: class prepare in debugger thread!";
1006761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        basket.threadId = 0;
1007f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        if (suspend_policy == SP_EVENT_THREAD) {
1008f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes          suspend_policy = SP_ALL;
1009761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        }
1010872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1011872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1012761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
1013f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      expandBufAdd1(pReq, suspend_policy);
10142aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      expandBufAdd4BE(pReq, match_count);
1015872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
10162aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      for (int i = 0; i < match_count; i++) {
1017f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd1(pReq, match_list[i]->eventKind);
1018f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd4BE(pReq, match_list[i]->requestId);
1019761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
1020872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1021761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd1(pReq, tag);
1022761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, refTypeId);
1023761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAddUtf8String(pReq, signature);
1024761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd4BE(pReq, status);
1025761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
1026872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
1027f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CleanupMatchList(match_list, match_count);
1028872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1029872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
103000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
1031872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
10322aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  return match_count != 0;
1033872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1034872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1035872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1036872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Send up a chunk of DDM data.
1037872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1038872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * While this takes the form of a JDWP "event", it doesn't interact with
1039872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * other debugger traffic, and can't suspend the VM, so we skip all of
1040872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * the fun event token gymnastics.
1041872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1042cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughesvoid JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) {
1043872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  uint8_t header[kJDWPHeaderLen + 8];
1044872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  size_t dataLen = 0;
1045872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1046872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(iov != NULL);
1047cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  CHECK_GT(iov_count, 0);
1048cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  CHECK_LT(iov_count, 10);
1049872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1050872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
1051872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * "Wrap" the contents of the iovec with a JDWP/DDMS header.  We do
1052872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * this by creating a new copy of the vector with space for the header.
1053872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
1054cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  iovec wrapiov[iov_count+1];
1055cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  for (int i = 0; i < iov_count; i++) {
1056872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    wrapiov[i+1].iov_base = iov[i].iov_base;
1057872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    wrapiov[i+1].iov_len = iov[i].iov_len;
1058872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    dataLen += iov[i].iov_len;
1059872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1060872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1061872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* form the header (JDWP plus DDMS) */
1062f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header, sizeof(header) + dataLen);
1063f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+4, NextRequestSerial());
1064f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+8, 0);     /* flags */
1065f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+9, kJDWPDdmCmdSet);
1066f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+10, kJDWPDdmCmd);
1067f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+11, type);
1068f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+15, dataLen);
1069872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1070872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  wrapiov[0].iov_base = header;
1071872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  wrapiov[0].iov_len = sizeof(header);
1072872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
107315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  // Try to avoid blocking GC during a send, but only safe when not using mutexes at a lower-level
107415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  // than mutator for lock ordering reasons.
107500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Thread* self = Thread::Current();
107615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  bool safe_to_release_mutator_lock_over_send;
107715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  for (size_t i=0; i < kMutatorLock; ++i) {
107815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    if (self->GetHeldMutex(static_cast<MutexLevel>(i)) != NULL) {
107915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers      safe_to_release_mutator_lock_over_send = false;
108015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers      break;
108115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    }
108215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  }
108315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  if (safe_to_release_mutator_lock_over_send) {
108415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    // Change state to waiting to allow GC, ... while we're sending.
108515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
108615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    (*transport_->sendBufferedRequest)(this, wrapiov, iov_count + 1);
108715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    self->TransitionFromSuspendedToRunnable();
108815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  } else {
108915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    // Send and possibly block GC...
109015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    (*transport_->sendBufferedRequest)(this, wrapiov, iov_count + 1);
109115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  }
1092872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1093872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1094872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}  // namespace JDWP
1095872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1096872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}  // namespace art
1097