/*
 * 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 */
};

/*
 * 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();
  } 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->invoke_needed) {
      /*LOGD("suspendByPolicy: no invoke needed");*/
      break;
    }

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

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

    pReq->error = ERR_NONE;

    /* clear this before signaling */
    pReq->invoke_needed = 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 "invoke_needed" 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->invoke_needed;
}

/*
 * 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 JdwpState::SetWaitForEventThread(ObjectId threadId) {
  bool waited = false;

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

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

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

/*
 * Clear the threadId and signal anybody waiting.
 */
void JdwpState::ClearWaitForEventThread() {
  /*
   * 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(event_thread_lock_);

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

  eventThreadId = 0;

  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, state->NextRequestSerial());
  Set1(buf+8, 0);     /* flags */
  Set1(buf+9, kJdwpEventCommandSet);
  Set1(buf+10, kJdwpCompositeCommand);

  state->SendRequest(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 JdwpState::PostVMStart() {
  JdwpSuspendPolicy suspendPolicy;
  ObjectId threadId = Dbg::GetThreadSelfId();

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

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

  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(this);

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

    eventFinish(this, pReq);

    suspendByPolicy(this, suspendPolicy);
    Dbg::ThreadContinuing(old_state);
  }

  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 old_state = Dbg::ThreadWaiting();
    if (suspendPolicy != SP_NONE) {
      state->SetWaitForEventThread(basket.threadId);
    }

    eventFinish(state, pReq);

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

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

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

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

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

  ExpandBuf* pReq = NULL;
  JdwpSuspendPolicy suspendPolicy = SP_NONE;
  int matchCount = 0;
  {
    // Don't allow the list to be updated while we scan it.
    MutexLock mu(event_lock_);
    JdwpEvent** matchList = allocMatchList(this);

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

    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(this, matchList, matchCount);
  }

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

    suspendByPolicy(this, suspendPolicy);
    Dbg::ThreadContinuing(old_state);
  }

  return matchCount != 0;
}

/*
 * Send a polite "VM is dying" message to the debugger.
 *
 * Skips the usual "event token" stuff.
 */
bool JdwpState::PostVMDeath() {
  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(this, 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 old_state = Dbg::ThreadWaiting();
    if (suspendPolicy != SP_NONE) {
      state->SetWaitForEventThread(basket.threadId);
    }

    eventFinish(state, pReq);

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

  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 old_state = Dbg::ThreadWaiting();
    if (suspendPolicy != SP_NONE) {
      state->SetWaitForEventThread(basket.threadId);
    }
    eventFinish(state, pReq);

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

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

/*
 * 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 JdwpState::DdmSendChunkV(uint32_t 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());
  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 old_state = Dbg::ThreadWaiting();
  (*transport->sendBufferedRequest)(this, wrapiov, iovcnt + 1);
  Dbg::ThreadContinuing(old_state);
}

}  // namespace JDWP

}  // namespace art
