/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Send events to the debugger.
 */
#include "debugger.h"
#include "jdwp/jdwp_priv.h"
#include "jdwp/jdwp_constants.h"
#include "jdwp/jdwp_handler.h"
#include "jdwp/jdwp_event.h"
#include "jdwp/jdwp_expand_buf.h"
#include "logging.h"
#include "stringprintf.h"

#include <stdlib.h>
#include <string.h>
#include <stddef.h>     /* for offsetof() */
#include <unistd.h>

/*
General notes:

The event add/remove stuff usually happens from the debugger thread,
in response to requests from the debugger, but can also happen as the
result of an event in an arbitrary thread (e.g. an event with a "count"
mod expires).  It's important to keep the event list locked when processing
events.

Event posting can happen from any thread.  The JDWP thread will not usually
post anything but VM start/death, but if a JDWP request causes a class
to be loaded, the ClassPrepare event will come from the JDWP thread.


We can have serialization issues when we post an event to the debugger.
For example, a thread could send an "I hit a breakpoint and am suspending
myself" message to the debugger.  Before it manages to suspend itself, the
debugger's response ("not interested, resume thread") arrives and is
processed.  We try to resume a thread that hasn't yet suspended.

This means that, after posting an event to the debugger, we need to wait
for the event thread to suspend itself (and, potentially, all other threads)
before processing any additional requests from the debugger.  While doing
so we need to be aware that multiple threads may be hitting breakpoints
or other events simultaneously, so we either need to wait for all of them
or serialize the events with each other.

The current mechanism works like this:
  Event thread:
   - If I'm going to suspend, grab the "I am posting an event" token.  Wait
     for it if it's not currently available.
   - Post the event to the debugger.
   - If appropriate, suspend others and then myself.  As part of suspending
     myself, release the "I am posting" token.
  JDWP thread:
   - When an event arrives, see if somebody is posting an event.  If so,
     sleep until we can acquire the "I am posting an event" token.  Release
     it immediately and continue processing -- the event we have already
     received should not interfere with other events that haven't yet
     been posted.

Some care must be taken to avoid deadlock:

 - thread A and thread B exit near-simultaneously, and post thread-death
   events with a "suspend all" clause
 - thread A gets the event token, thread B sits and waits for it
 - thread A wants to suspend all other threads, but thread B is waiting
   for the token and can't be suspended

So we need to mark thread B in such a way that thread A doesn't wait for it.

If we just bracket the "grab event token" call with a change to VMWAIT
before sleeping, the switch back to RUNNING state when we get the token
will cause thread B to suspend (remember, thread A's global suspend is
still in force, even after it releases the token).  Suspending while
holding the event token is very bad, because it prevents the JDWP thread
from processing incoming messages.

We need to change to VMWAIT state at the *start* of posting an event,
and stay there until we either finish posting the event or decide to
put ourselves to sleep.  That way we don't interfere with anyone else and
don't allow anyone else to interfere with us.
*/


#define kJdwpEventCommandSet    64
#define kJdwpCompositeCommand   100

namespace art {

namespace JDWP {

/*
 * Stuff to compare against when deciding if a mod matches.  Only the
 * values for mods valid for the event being evaluated will be filled in.
 * The rest will be zeroed.
 */
struct ModBasket {
  const JdwpLocation* pLoc;           /* LocationOnly */
  const char*         className;      /* ClassMatch/ClassExclude */
  ObjectId            threadId;       /* ThreadOnly */
  RefTypeId           classId;        /* ClassOnly */
  RefTypeId           excepClassId;   /* ExceptionOnly */
  bool                caught;         /* ExceptionOnly */
  FieldId             field;          /* FieldOnly */
  ObjectId            thisPtr;        /* InstanceOnly */
  /* nothing for StepOnly -- handled differently */
};

/*
 * Get the next "request" serial number.  We use this when sending
 * packets to the debugger.
 */
uint32_t NextRequestSerial(JdwpState* state) {
  MutexLock mu(state->serial_lock_);
  return state->requestSerial++;
}

/*
 * Get the next "event" serial number.  We use this in the response to
 * message type EventRequest.Set.
 */
uint32_t NextEventSerial(JdwpState* state) {
  MutexLock mu(state->serial_lock_);
  return state->eventSerial++;
}

/*
 * Lock the "event" mutex, which guards the list of registered events.
 */
static void lockEventMutex(JdwpState* state) {
  //Dbg::ThreadWaiting();
  state->event_lock_.Lock();
  //Dbg::ThreadRunning();
}

/*
 * Unlock the "event" mutex.
 */
static void unlockEventMutex(JdwpState* state) {
  state->event_lock_.Unlock();
}

/*
 * Dump an event to the log file.
 */
static void dumpEvent(const JdwpEvent* pEvent) {
  LOG(INFO) << StringPrintf("Event id=0x%4x %p (prev=%p next=%p):", pEvent->requestId, pEvent, pEvent->prev, pEvent->next);
  LOG(INFO) << "  kind=" << pEvent->eventKind << " susp=" << pEvent->suspendPolicy << " modCount=" << pEvent->modCount;

  for (int i = 0; i < pEvent->modCount; i++) {
    const JdwpEventMod* pMod = &pEvent->mods[i];
    LOG(INFO) << "  " << static_cast<JdwpModKind>(pMod->modKind);
    /* TODO - show details */
  }
}

/*
 * Add an event to the list.  Ordering is not important.
 *
 * If something prevents the event from being registered, e.g. it's a
 * single-step request on a thread that doesn't exist, the event will
 * not be added to the list, and an appropriate error will be returned.
 */
JdwpError RegisterEvent(JdwpState* state, JdwpEvent* pEvent) {
  lockEventMutex(state);

  CHECK(state != NULL);
  CHECK(pEvent != NULL);
  CHECK(pEvent->prev == NULL);
  CHECK(pEvent->next == NULL);

  /*
   * If one or more "break"-type mods are used, register them with
   * the interpreter.
   */
  for (int i = 0; i < pEvent->modCount; i++) {
    const JdwpEventMod* pMod = &pEvent->mods[i];
    if (pMod->modKind == MK_LOCATION_ONLY) {
      /* should only be for Breakpoint, Step, and Exception */
      Dbg::WatchLocation(&pMod->locationOnly.loc);
    } else if (pMod->modKind == MK_STEP) {
      /* should only be for EK_SINGLE_STEP; should only be one */
      JdwpStepSize size = static_cast<JdwpStepSize>(pMod->step.size);
      JdwpStepDepth depth = static_cast<JdwpStepDepth>(pMod->step.depth);
      Dbg::ConfigureStep(pMod->step.threadId, size, depth);
    } else if (pMod->modKind == MK_FIELD_ONLY) {
      /* should be for EK_FIELD_ACCESS or EK_FIELD_MODIFICATION */
      dumpEvent(pEvent);  /* TODO - need for field watches */
    }
  }

  /*
   * Add to list.
   */
  if (state->eventList != NULL) {
    pEvent->next = state->eventList;
    state->eventList->prev = pEvent;
  }
  state->eventList = pEvent;
  state->numEvents++;

  unlockEventMutex(state);

  return ERR_NONE;
}

/*
 * Remove an event from the list.  This will also remove the event from
 * any optimization tables, e.g. breakpoints.
 *
 * Does not free the JdwpEvent.
 *
 * Grab the eventLock before calling here.
 */
static void unregisterEvent(JdwpState* state, JdwpEvent* pEvent) {
  if (pEvent->prev == NULL) {
    /* head of the list */
    CHECK(state->eventList == pEvent);

    state->eventList = pEvent->next;
  } else {
    pEvent->prev->next = pEvent->next;
  }

  if (pEvent->next != NULL) {
    pEvent->next->prev = pEvent->prev;
    pEvent->next = NULL;
  }
  pEvent->prev = NULL;

  /*
   * Unhook us from the interpreter, if necessary.
   */
  for (int i = 0; i < pEvent->modCount; i++) {
    JdwpEventMod* pMod = &pEvent->mods[i];
    if (pMod->modKind == MK_LOCATION_ONLY) {
      /* should only be for Breakpoint, Step, and Exception */
      Dbg::UnwatchLocation(&pMod->locationOnly.loc);
    }
    if (pMod->modKind == MK_STEP) {
      /* should only be for EK_SINGLE_STEP; should only be one */
      Dbg::UnconfigureStep(pMod->step.threadId);
    }
  }

  state->numEvents--;
  CHECK(state->numEvents != 0 || state->eventList == NULL);
}

/*
 * Remove the event with the given ID from the list.
 *
 * Failure to find the event isn't really an error, but it is a little
 * weird.  (It looks like Eclipse will try to be extra careful and will
 * explicitly remove one-off single-step events.)
 */
void UnregisterEventById(JdwpState* state, uint32_t requestId) {
  lockEventMutex(state);

  JdwpEvent* pEvent = state->eventList;
  while (pEvent != NULL) {
    if (pEvent->requestId == requestId) {
      unregisterEvent(state, pEvent);
      EventFree(pEvent);
      goto done;      /* there can be only one with a given ID */
    }

    pEvent = pEvent->next;
  }

  //LOGD("Odd: no match when removing event reqId=0x%04x", requestId);

done:
  unlockEventMutex(state);
}

/*
 * Remove all entries from the event list.
 */
void UnregisterAll(JdwpState* state) {
  lockEventMutex(state);

  JdwpEvent* pEvent = state->eventList;
  while (pEvent != NULL) {
    JdwpEvent* pNextEvent = pEvent->next;

    unregisterEvent(state, pEvent);
    EventFree(pEvent);
    pEvent = pNextEvent;
  }

  state->eventList = NULL;

  unlockEventMutex(state);
}

/*
 * Allocate a JdwpEvent struct with enough space to hold the specified
 * number of mod records.
 */
JdwpEvent* EventAlloc(int numMods) {
  JdwpEvent* newEvent;
  int allocSize = offsetof(JdwpEvent, mods) + numMods * sizeof(newEvent->mods[0]);
  newEvent = reinterpret_cast<JdwpEvent*>(malloc(allocSize));
  memset(newEvent, 0, allocSize);
  return newEvent;
}

/*
 * Free a JdwpEvent.
 *
 * Do not call this until the event has been removed from the list.
 */
void EventFree(JdwpEvent* pEvent) {
  if (pEvent == NULL) {
    return;
  }

  /* make sure it was removed from the list */
  CHECK(pEvent->prev == NULL);
  CHECK(pEvent->next == NULL);
  /* want to check state->eventList != pEvent */

  /*
   * Free any hairy bits in the mods.
   */
  for (int i = 0; i < pEvent->modCount; i++) {
    if (pEvent->mods[i].modKind == MK_CLASS_MATCH) {
      free(pEvent->mods[i].classMatch.classPattern);
      pEvent->mods[i].classMatch.classPattern = NULL;
    }
    if (pEvent->mods[i].modKind == MK_CLASS_EXCLUDE) {
      free(pEvent->mods[i].classExclude.classPattern);
      pEvent->mods[i].classExclude.classPattern = NULL;
    }
  }

  free(pEvent);
}

/*
 * Allocate storage for matching events.  To keep things simple we
 * use an array with enough storage for the entire list.
 *
 * The state->eventLock should be held before calling.
 */
static JdwpEvent** allocMatchList(JdwpState* state) {
  return (JdwpEvent**) malloc(sizeof(JdwpEvent*) * state->numEvents);
}

/*
 * Run through the list and remove any entries with an expired "count" mod
 * from the event list, then free the match list.
 */
static void cleanupMatchList(JdwpState* state, JdwpEvent** matchList, int matchCount) {
  JdwpEvent** ppEvent = matchList;

  while (matchCount--) {
    JdwpEvent* pEvent = *ppEvent;

    for (int i = 0; i < pEvent->modCount; i++) {
      if (pEvent->mods[i].modKind == MK_COUNT && pEvent->mods[i].count.count == 0) {
        LOG(VERBOSE) << "##### Removing expired event";
        unregisterEvent(state, pEvent);
        EventFree(pEvent);
        break;
      }
    }

    ppEvent++;
  }

  free(matchList);
}

/*
 * Match a string against a "restricted regular expression", which is just
 * a string that may start or end with '*' (e.g. "*.Foo" or "java.*").
 *
 * ("Restricted name globbing" might have been a better term.)
 */
static bool patternMatch(const char* pattern, const char* target) {
  int patLen = strlen(pattern);

  if (pattern[0] == '*') {
    int targetLen = strlen(target);
    patLen--;
    // TODO: remove printf when we find a test case to verify this
    LOG(ERROR) << ">>> comparing '" << (pattern + 1) << "' to '" << (target + (targetLen-patLen)) << "'";

    if (targetLen < patLen) {
      return false;
    }
    return strcmp(pattern+1, target + (targetLen-patLen)) == 0;
  } else if (pattern[patLen-1] == '*') {
    return strncmp(pattern, target, patLen-1) == 0;
  } else {
    return strcmp(pattern, target) == 0;
  }
}

/*
 * See if two locations are equal.
 *
 * It's tempting to do a bitwise compare ("struct ==" or memcmp), but if
 * the storage wasn't zeroed out there could be undefined values in the
 * padding.  Besides, the odds of "idx" being equal while the others aren't
 * is very small, so this is usually just a simple integer comparison.
 */
static inline bool locationMatch(const JdwpLocation* pLoc1, const JdwpLocation* pLoc2) {
  return pLoc1->idx == pLoc2->idx &&
      pLoc1->methodId == pLoc2->methodId &&
      pLoc1->classId == pLoc2->classId &&
      pLoc1->typeTag == pLoc2->typeTag;
}

/*
 * See if the event's mods match up with the contents of "basket".
 *
 * If we find a Count mod before rejecting an event, we decrement it.  We
 * need to do this even if later mods cause us to ignore the event.
 */
static bool modsMatch(JdwpState* state, JdwpEvent* pEvent, ModBasket* basket) {
  JdwpEventMod* pMod = pEvent->mods;

  for (int i = pEvent->modCount; i > 0; i--, pMod++) {
    switch (pMod->modKind) {
    case MK_COUNT:
      CHECK_GT(pMod->count.count, 0);
      pMod->count.count--;
      break;
    case MK_CONDITIONAL:
      CHECK(false);  // should not be getting these
      break;
    case MK_THREAD_ONLY:
      if (pMod->threadOnly.threadId != basket->threadId) {
        return false;
      }
      break;
    case MK_CLASS_ONLY:
      if (!Dbg::MatchType(basket->classId, pMod->classOnly.refTypeId)) {
        return false;
      }
      break;
    case MK_CLASS_MATCH:
      if (!patternMatch(pMod->classMatch.classPattern, basket->className)) {
        return false;
      }
      break;
    case MK_CLASS_EXCLUDE:
      if (patternMatch(pMod->classMatch.classPattern, basket->className)) {
        return false;
      }
      break;
    case MK_LOCATION_ONLY:
      if (!locationMatch(&pMod->locationOnly.loc, basket->pLoc)) {
        return false;
      }
      break;
    case MK_EXCEPTION_ONLY:
      if (pMod->exceptionOnly.refTypeId != 0 && !Dbg::MatchType(basket->excepClassId, pMod->exceptionOnly.refTypeId)) {
        return false;
      }
      if ((basket->caught && !pMod->exceptionOnly.caught) || (!basket->caught && !pMod->exceptionOnly.uncaught)) {
        return false;
      }
      break;
    case MK_FIELD_ONLY:
      if (!Dbg::MatchType(basket->classId, pMod->fieldOnly.refTypeId) || pMod->fieldOnly.fieldId != basket->field) {
        return false;
      }
      break;
    case MK_STEP:
      if (pMod->step.threadId != basket->threadId) {
        return false;
      }
      break;
    case MK_INSTANCE_ONLY:
      if (pMod->instanceOnly.objectId != basket->thisPtr) {
        return false;
      }
      break;
    default:
      LOG(ERROR) << "unhandled mod kind " << pMod->modKind;
      CHECK(false);
      break;
    }
  }
  return true;
}

/*
 * Find all events of type "eventKind" with mods that match up with the
 * rest of the arguments.
 *
 * Found events are appended to "matchList", and "*pMatchCount" is advanced,
 * so this may be called multiple times for grouped events.
 *
 * DO NOT call this multiple times for the same eventKind, as Count mods are
 * decremented during the scan.
 */
static void findMatchingEvents(JdwpState* state, JdwpEventKind eventKind,
    ModBasket* basket, JdwpEvent** matchList, int* pMatchCount) {
  /* start after the existing entries */
  matchList += *pMatchCount;

  JdwpEvent* pEvent = state->eventList;
  while (pEvent != NULL) {
    if (pEvent->eventKind == eventKind && modsMatch(state, pEvent, basket)) {
      *matchList++ = pEvent;
      (*pMatchCount)++;
    }

    pEvent = pEvent->next;
  }
}

/*
 * Scan through the list of matches and determine the most severe
 * suspension policy.
 */
static JdwpSuspendPolicy scanSuspendPolicy(JdwpEvent** matchList, int matchCount) {
  JdwpSuspendPolicy policy = SP_NONE;

  while (matchCount--) {
    if ((*matchList)->suspendPolicy > policy) {
      policy = (*matchList)->suspendPolicy;
    }
    matchList++;
  }

  return policy;
}

/*
 * Three possibilities:
 *  SP_NONE - do nothing
 *  SP_EVENT_THREAD - suspend ourselves
 *  SP_ALL - suspend everybody except JDWP support thread
 */
static void suspendByPolicy(JdwpState* state, JdwpSuspendPolicy suspendPolicy) {
  if (suspendPolicy == SP_NONE) {
    return;
  }

  if (suspendPolicy == SP_ALL) {
    Dbg::SuspendVM(true);
  } else {
    CHECK_EQ(suspendPolicy, SP_EVENT_THREAD);
  }

  /* this is rare but possible -- see CLASS_PREPARE handling */
  if (Dbg::GetThreadSelfId() == state->debugThreadId) {
    LOG(INFO) << "NOTE: suspendByPolicy not suspending JDWP thread";
    return;
  }

  DebugInvokeReq* pReq = Dbg::GetInvokeReq();
  while (true) {
    pReq->ready = true;
    Dbg::SuspendSelf();
    pReq->ready = false;

    /*
     * The JDWP thread has told us (and possibly all other threads) to
     * resume.  See if it has left anything in our DebugInvokeReq mailbox.
     */
    if (!pReq->invokeNeeded) {
      /*LOGD("suspendByPolicy: no invoke needed");*/
      break;
    }

    /* grab this before posting/suspending again */
    SetWaitForEventThread(state, Dbg::GetThreadSelfId());

    /* leave pReq->invokeNeeded raised so we can check reentrancy */
    LOG(VERBOSE) << "invoking method...";
    Dbg::ExecuteMethod(pReq);

    pReq->err = ERR_NONE;

    /* clear this before signaling */
    pReq->invokeNeeded = false;

    LOG(VERBOSE) << "invoke complete, signaling and self-suspending";
    MutexLock mu(pReq->lock_);
    pReq->cond_.Signal();
  }
}

/*
 * Determine if there is a method invocation in progress in the current
 * thread.
 *
 * We look at the "invokeNeeded" flag in the per-thread DebugInvokeReq
 * state.  If set, we're in the process of invoking a method.
 */
static bool invokeInProgress(JdwpState* state) {
  DebugInvokeReq* pReq = Dbg::GetInvokeReq();
  return pReq->invokeNeeded;
}

/*
 * We need the JDWP thread to hold off on doing stuff while we post an
 * event and then suspend ourselves.
 *
 * Call this with a threadId of zero if you just want to wait for the
 * current thread operation to complete.
 *
 * This could go to sleep waiting for another thread, so it's important
 * that the thread be marked as VMWAIT before calling here.
 */
void SetWaitForEventThread(JdwpState* state, ObjectId threadId) {
  bool waited = false;

  /* this is held for very brief periods; contention is unlikely */
  MutexLock mu(state->event_thread_lock_);

  /*
   * If another thread is already doing stuff, wait for it.  This can
   * go to sleep indefinitely.
   */
  while (state->eventThreadId != 0) {
    LOG(VERBOSE) << StringPrintf("event in progress (0x%llx), 0x%llx sleeping", state->eventThreadId, threadId);
    waited = true;
    state->event_thread_cond_.Wait(state->event_thread_lock_);
  }

  if (waited || threadId != 0) {
    LOG(VERBOSE) << StringPrintf("event token grabbed (0x%llx)", threadId);
  }
  if (threadId != 0) {
    state->eventThreadId = threadId;
  }
}

/*
 * Clear the threadId and signal anybody waiting.
 */
void ClearWaitForEventThread(JdwpState* state) {
  /*
   * Grab the mutex.  Don't try to go in/out of VMWAIT mode, as this
   * function is called by dvmSuspendSelf(), and the transition back
   * to RUNNING would confuse it.
   */
  MutexLock mu(state->event_thread_lock_);

  CHECK_NE(state->eventThreadId, 0U);
  LOG(VERBOSE) << StringPrintf("cleared event token (0x%llx)", state->eventThreadId);

  state->eventThreadId = 0;

  state->event_thread_cond_.Signal();
}


/*
 * Prep an event.  Allocates storage for the message and leaves space for
 * the header.
 */
static ExpandBuf* eventPrep() {
  ExpandBuf* pReq = expandBufAlloc();
  expandBufAddSpace(pReq, kJDWPHeaderLen);
  return pReq;
}

/*
 * Write the header into the buffer and send the packet off to the debugger.
 *
 * Takes ownership of "pReq" (currently discards it).
 */
static void eventFinish(JdwpState* state, ExpandBuf* pReq) {
  uint8_t* buf = expandBufGetBuffer(pReq);

  set4BE(buf, expandBufGetLength(pReq));
  set4BE(buf+4, NextRequestSerial(state));
  set1(buf+8, 0);     /* flags */
  set1(buf+9, kJdwpEventCommandSet);
  set1(buf+10, kJdwpCompositeCommand);

  SendRequest(state, pReq);

  expandBufFree(pReq);
}


/*
 * Tell the debugger that we have finished initializing.  This is always
 * sent, even if the debugger hasn't requested it.
 *
 * This should be sent "before the main thread is started and before
 * any application code has been executed".  The thread ID in the message
 * must be for the main thread.
 */
bool PostVMStart(JdwpState* state, bool suspend) {
  JdwpSuspendPolicy suspendPolicy;
  ObjectId threadId = Dbg::GetThreadSelfId();

  if (suspend) {
    suspendPolicy = SP_ALL;
  } else {
    suspendPolicy = SP_NONE;
  }

  /* probably don't need this here */
  lockEventMutex(state);

  ExpandBuf* pReq = NULL;
  if (true) {
    LOG(VERBOSE) << "EVENT: " << EK_VM_START;
    LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;

    pReq = eventPrep();
    expandBufAdd1(pReq, suspendPolicy);
    expandBufAdd4BE(pReq, 1);

    expandBufAdd1(pReq, EK_VM_START);
    expandBufAdd4BE(pReq, 0);       /* requestId */
    expandBufAdd8BE(pReq, threadId);
  }

  unlockEventMutex(state);

  /* send request and possibly suspend ourselves */
  if (pReq != NULL) {
    int oldStatus = Dbg::ThreadWaiting();
    if (suspendPolicy != SP_NONE) {
      SetWaitForEventThread(state, threadId);
    }

    eventFinish(state, pReq);

    suspendByPolicy(state, suspendPolicy);
    Dbg::ThreadContinuing(oldStatus);
  }

  return true;
}

// TODO: This doesn't behave like the real dvmDescriptorToName.
// I'm hoping this isn't used to communicate with the debugger, and we can just use descriptors.
char* dvmDescriptorToName(const char* descriptor) {
  return strdup(descriptor);
}

/*
 * A location of interest has been reached.  This handles:
 *   Breakpoint
 *   SingleStep
 *   MethodEntry
 *   MethodExit
 * These four types must be grouped together in a single response.  The
 * "eventFlags" indicates the type of event(s) that have happened.
 *
 * Valid mods:
 *   Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, InstanceOnly
 *   LocationOnly (for breakpoint/step only)
 *   Step (for step only)
 *
 * Interesting test cases:
 *  - Put a breakpoint on a native method.  Eclipse creates METHOD_ENTRY
 *    and METHOD_EXIT events with a ClassOnly mod on the method's class.
 *  - Use "run to line".  Eclipse creates a BREAKPOINT with Count=1.
 *  - Single-step to a line with a breakpoint.  Should get a single
 *    event message with both events in it.
 */
bool PostLocationEvent(JdwpState* state, const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags) {
  ModBasket basket;
  char* nameAlloc = NULL;

  memset(&basket, 0, sizeof(basket));
  basket.pLoc = pLoc;
  basket.classId = pLoc->classId;
  basket.thisPtr = thisPtr;
  basket.threadId = Dbg::GetThreadSelfId();
  basket.className = nameAlloc = dvmDescriptorToName(Dbg::GetClassDescriptor(pLoc->classId));

  /*
   * On rare occasions we may need to execute interpreted code in the VM
   * while handling a request from the debugger.  Don't fire breakpoints
   * while doing so.  (I don't think we currently do this at all, so
   * this is mostly paranoia.)
   */
  if (basket.threadId == state->debugThreadId) {
    LOG(VERBOSE) << "Ignoring location event in JDWP thread";
    free(nameAlloc);
    return false;
  }

  /*
   * The debugger variable display tab may invoke the interpreter to format
   * complex objects.  We want to ignore breakpoints and method entry/exit
   * traps while working on behalf of the debugger.
   *
   * If we don't ignore them, the VM will get hung up, because we'll
   * suspend on a breakpoint while the debugger is still waiting for its
   * method invocation to complete.
   */
  if (invokeInProgress(state)) {
    LOG(VERBOSE) << "Not checking breakpoints during invoke (" << basket.className << ")";
    free(nameAlloc);
    return false;
  }

  /* don't allow the list to be updated while we scan it */
  lockEventMutex(state);

  JdwpEvent** matchList = allocMatchList(state);
  int matchCount = 0;

  if ((eventFlags & Dbg::kBreakPoint) != 0) {
    findMatchingEvents(state, EK_BREAKPOINT, &basket, matchList, &matchCount);
  }
  if ((eventFlags & Dbg::kSingleStep) != 0) {
    findMatchingEvents(state, EK_SINGLE_STEP, &basket, matchList, &matchCount);
  }
  if ((eventFlags & Dbg::kMethodEntry) != 0) {
    findMatchingEvents(state, EK_METHOD_ENTRY, &basket, matchList, &matchCount);
  }
  if ((eventFlags & Dbg::kMethodExit) != 0) {
    findMatchingEvents(state, EK_METHOD_EXIT, &basket, matchList, &matchCount);
  }

  ExpandBuf* pReq = NULL;
  JdwpSuspendPolicy suspendPolicy = SP_NONE;
  if (matchCount != 0) {
    LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
                 << basket.className << "." << Dbg::GetMethodName(pLoc->classId, pLoc->methodId)
                 << " thread=" << (void*) basket.threadId << " code=" << (void*) pLoc->idx << ")";

    suspendPolicy = scanSuspendPolicy(matchList, matchCount);
    LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;

    pReq = eventPrep();
    expandBufAdd1(pReq, suspendPolicy);
    expandBufAdd4BE(pReq, matchCount);

    for (int i = 0; i < matchCount; i++) {
      expandBufAdd1(pReq, matchList[i]->eventKind);
      expandBufAdd4BE(pReq, matchList[i]->requestId);
      expandBufAdd8BE(pReq, basket.threadId);
      AddLocation(pReq, pLoc);
    }
  }

  cleanupMatchList(state, matchList, matchCount);
  unlockEventMutex(state);

  /* send request and possibly suspend ourselves */
  if (pReq != NULL) {
    int oldStatus = Dbg::ThreadWaiting();
    if (suspendPolicy != SP_NONE) {
      SetWaitForEventThread(state, basket.threadId);
    }

    eventFinish(state, pReq);

    suspendByPolicy(state, suspendPolicy);
    Dbg::ThreadContinuing(oldStatus);
  }

  free(nameAlloc);
  return matchCount != 0;
}

/*
 * A thread is starting or stopping.
 *
 * Valid mods:
 *  Count, ThreadOnly
 */
bool PostThreadChange(JdwpState* state, ObjectId threadId, bool start) {
  CHECK_EQ(threadId, Dbg::GetThreadSelfId());

  /*
   * I don't think this can happen.
   */
  if (invokeInProgress(state)) {
    LOG(WARNING) << "Not posting thread change during invoke";
    return false;
  }

  ModBasket basket;
  memset(&basket, 0, sizeof(basket));
  basket.threadId = threadId;

  /* don't allow the list to be updated while we scan it */
  lockEventMutex(state);

  JdwpEvent** matchList = allocMatchList(state);
  int matchCount = 0;

  if (start) {
    findMatchingEvents(state, EK_THREAD_START, &basket, matchList, &matchCount);
  } else {
    findMatchingEvents(state, EK_THREAD_DEATH, &basket, matchList, &matchCount);
  }

  ExpandBuf* pReq = NULL;
  JdwpSuspendPolicy suspendPolicy = SP_NONE;
  if (matchCount != 0) {
    LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
                 << "thread=" << (void*) basket.threadId << ")";

    suspendPolicy = scanSuspendPolicy(matchList, matchCount);
    LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;

    pReq = eventPrep();
    expandBufAdd1(pReq, suspendPolicy);
    expandBufAdd4BE(pReq, matchCount);

    for (int i = 0; i < matchCount; i++) {
      expandBufAdd1(pReq, matchList[i]->eventKind);
      expandBufAdd4BE(pReq, matchList[i]->requestId);
      expandBufAdd8BE(pReq, basket.threadId);
    }
  }

  cleanupMatchList(state, matchList, matchCount);
  unlockEventMutex(state);

  /* send request and possibly suspend ourselves */
  if (pReq != NULL) {
    int oldStatus = Dbg::ThreadWaiting();
    if (suspendPolicy != SP_NONE) {
      SetWaitForEventThread(state, basket.threadId);
    }
    eventFinish(state, pReq);

    suspendByPolicy(state, suspendPolicy);
    Dbg::ThreadContinuing(oldStatus);
  }

  return matchCount != 0;
}

/*
 * Send a polite "VM is dying" message to the debugger.
 *
 * Skips the usual "event token" stuff.
 */
bool PostVMDeath(JdwpState* state) {
  LOG(VERBOSE) << "EVENT: " << EK_VM_DEATH;

  ExpandBuf* pReq = eventPrep();
  expandBufAdd1(pReq, SP_NONE);
  expandBufAdd4BE(pReq, 1);

  expandBufAdd1(pReq, EK_VM_DEATH);
  expandBufAdd4BE(pReq, 0);
  eventFinish(state, pReq);
  return true;
}

/*
 * An exception has been thrown.  It may or may not have been caught.
 *
 * Valid mods:
 *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, LocationOnly,
 *    ExceptionOnly, InstanceOnly
 *
 * The "exceptionId" has not been added to the GC-visible object registry,
 * because there's a pretty good chance that we're not going to send it
 * up the debugger.
 */
bool PostException(JdwpState* state, const JdwpLocation* pThrowLoc,
    ObjectId exceptionId, RefTypeId exceptionClassId,
    const JdwpLocation* pCatchLoc, ObjectId thisPtr)
{
  ModBasket basket;
  char* nameAlloc = NULL;

  memset(&basket, 0, sizeof(basket));
  basket.pLoc = pThrowLoc;
  basket.classId = pThrowLoc->classId;
  basket.threadId = Dbg::GetThreadSelfId();
  basket.className = nameAlloc = dvmDescriptorToName(Dbg::GetClassDescriptor(basket.classId));
  basket.excepClassId = exceptionClassId;
  basket.caught = (pCatchLoc->classId != 0);
  basket.thisPtr = thisPtr;

  /* don't try to post an exception caused by the debugger */
  if (invokeInProgress(state)) {
    LOG(VERBOSE) << "Not posting exception hit during invoke (" << basket.className << ")";
    free(nameAlloc);
    return false;
  }

  /* don't allow the list to be updated while we scan it */
  lockEventMutex(state);

  JdwpEvent** matchList = allocMatchList(state);
  int matchCount = 0;

  findMatchingEvents(state, EK_EXCEPTION, &basket, matchList, &matchCount);

  ExpandBuf* pReq = NULL;
  JdwpSuspendPolicy suspendPolicy = SP_NONE;
  if (matchCount != 0) {
    LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total)"
                 << " thread=" << (void*) basket.threadId
                 << " exceptId=" << (void*) exceptionId
                 << " caught=" << basket.caught << ")";
    LOG(VERBOSE) << StringPrintf("  throw: %d %llx %x %lld (%s.%s)", pThrowLoc->typeTag,
        pThrowLoc->classId, pThrowLoc->methodId, pThrowLoc->idx,
        Dbg::GetClassDescriptor(pThrowLoc->classId),
        Dbg::GetMethodName(pThrowLoc->classId, pThrowLoc->methodId));
    if (pCatchLoc->classId == 0) {
      LOG(VERBOSE) << "  catch: (not caught)";
    } else {
      LOG(VERBOSE) << StringPrintf("  catch: %d %llx %x %lld (%s.%s)", pCatchLoc->typeTag,
          pCatchLoc->classId, pCatchLoc->methodId, pCatchLoc->idx,
          Dbg::GetClassDescriptor(pCatchLoc->classId),
          Dbg::GetMethodName(pCatchLoc->classId, pCatchLoc->methodId));
    }

    suspendPolicy = scanSuspendPolicy(matchList, matchCount);
    LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;

    pReq = eventPrep();
    expandBufAdd1(pReq, suspendPolicy);
    expandBufAdd4BE(pReq, matchCount);

    for (int i = 0; i < matchCount; i++) {
      expandBufAdd1(pReq, matchList[i]->eventKind);
      expandBufAdd4BE(pReq, matchList[i]->requestId);
      expandBufAdd8BE(pReq, basket.threadId);

      AddLocation(pReq, pThrowLoc);
      expandBufAdd1(pReq, JT_OBJECT);
      expandBufAdd8BE(pReq, exceptionId);
      AddLocation(pReq, pCatchLoc);
    }

    /* don't let the GC discard it */
    Dbg::RegisterObjectId(exceptionId);
  }

  cleanupMatchList(state, matchList, matchCount);
  unlockEventMutex(state);

  /* send request and possibly suspend ourselves */
  if (pReq != NULL) {
    int oldStatus = Dbg::ThreadWaiting();
    if (suspendPolicy != SP_NONE) {
      SetWaitForEventThread(state, basket.threadId);
    }

    eventFinish(state, pReq);

    suspendByPolicy(state, suspendPolicy);
    Dbg::ThreadContinuing(oldStatus);
  }

  free(nameAlloc);
  return matchCount != 0;
}

/*
 * Announce that a class has been loaded.
 *
 * Valid mods:
 *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude
 */
bool PostClassPrepare(JdwpState* state, int tag, RefTypeId refTypeId, const char* signature, int status) {
  ModBasket basket;
  char* nameAlloc = NULL;

  memset(&basket, 0, sizeof(basket));
  basket.classId = refTypeId;
  basket.threadId = Dbg::GetThreadSelfId();
  basket.className = nameAlloc = dvmDescriptorToName(Dbg::GetClassDescriptor(basket.classId));

  /* suppress class prep caused by debugger */
  if (invokeInProgress(state)) {
    LOG(VERBOSE) << "Not posting class prep caused by invoke (" << basket.className << ")";
    free(nameAlloc);
    return false;
  }

  /* don't allow the list to be updated while we scan it */
  lockEventMutex(state);

  JdwpEvent** matchList = allocMatchList(state);
  int matchCount = 0;

  findMatchingEvents(state, EK_CLASS_PREPARE, &basket, matchList, &matchCount);

  ExpandBuf* pReq = NULL;
  JdwpSuspendPolicy suspendPolicy = SP_NONE;
  if (matchCount != 0) {
    LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
                 << "thread=" << (void*) basket.threadId << ")";

    suspendPolicy = scanSuspendPolicy(matchList, matchCount);
    LOG(VERBOSE) << "  suspendPolicy=" << suspendPolicy;

    if (basket.threadId == state->debugThreadId) {
      /*
       * JDWP says that, for a class prep in the debugger thread, we
       * should set threadId to null and if any threads were supposed
       * to be suspended then we suspend all other threads.
       */
      LOG(VERBOSE) << "  NOTE: class prepare in debugger thread!";
      basket.threadId = 0;
      if (suspendPolicy == SP_EVENT_THREAD) {
        suspendPolicy = SP_ALL;
      }
    }

    pReq = eventPrep();
    expandBufAdd1(pReq, suspendPolicy);
    expandBufAdd4BE(pReq, matchCount);

    for (int i = 0; i < matchCount; i++) {
      expandBufAdd1(pReq, matchList[i]->eventKind);
      expandBufAdd4BE(pReq, matchList[i]->requestId);
      expandBufAdd8BE(pReq, basket.threadId);

      expandBufAdd1(pReq, tag);
      expandBufAdd8BE(pReq, refTypeId);
      expandBufAddUtf8String(pReq, (const uint8_t*) signature);
      expandBufAdd4BE(pReq, status);
    }
  }

  cleanupMatchList(state, matchList, matchCount);

  unlockEventMutex(state);

  /* send request and possibly suspend ourselves */
  if (pReq != NULL) {
    int oldStatus = Dbg::ThreadWaiting();
    if (suspendPolicy != SP_NONE) {
      SetWaitForEventThread(state, basket.threadId);
    }
    eventFinish(state, pReq);

    suspendByPolicy(state, suspendPolicy);
    Dbg::ThreadContinuing(oldStatus);
  }

  free(nameAlloc);
  return matchCount != 0;
}

bool SendBufferedRequest(JdwpState* state, const iovec* iov, int iovcnt) {
  return (*state->transport->sendBufferedRequest)(state, iov, iovcnt);
}

/*
 * Send up a chunk of DDM data.
 *
 * While this takes the form of a JDWP "event", it doesn't interact with
 * other debugger traffic, and can't suspend the VM, so we skip all of
 * the fun event token gymnastics.
 */
void DdmSendChunkV(JdwpState* state, int type, const iovec* iov, int iovcnt) {
  uint8_t header[kJDWPHeaderLen + 8];
  size_t dataLen = 0;

  CHECK(iov != NULL);
  CHECK(iovcnt > 0 && iovcnt < 10);

  /*
   * "Wrap" the contents of the iovec with a JDWP/DDMS header.  We do
   * this by creating a new copy of the vector with space for the header.
   */
  iovec wrapiov[iovcnt+1];
  for (int i = 0; i < iovcnt; i++) {
    wrapiov[i+1].iov_base = iov[i].iov_base;
    wrapiov[i+1].iov_len = iov[i].iov_len;
    dataLen += iov[i].iov_len;
  }

  /* form the header (JDWP plus DDMS) */
  set4BE(header, sizeof(header) + dataLen);
  set4BE(header+4, NextRequestSerial(state));
  set1(header+8, 0);     /* flags */
  set1(header+9, kJDWPDdmCmdSet);
  set1(header+10, kJDWPDdmCmd);
  set4BE(header+11, type);
  set4BE(header+15, dataLen);

  wrapiov[0].iov_base = header;
  wrapiov[0].iov_len = sizeof(header);

  /*
   * Make sure we're in VMWAIT in case the write blocks.
   */
  int oldStatus = Dbg::ThreadWaiting();
  SendBufferedRequest(state, wrapiov, iovcnt+1);
  Dbg::ThreadContinuing(oldStatus);
}

}  // namespace JDWP

}  // namespace art
