jdwp_handler.cc revision fc0e94bed3f88ed7e50854fd8dfaf5dcb345250f
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <string.h>
19#include <unistd.h>
20
21#include <string>
22
23#include "atomic.h"
24#include "base/logging.h"
25#include "base/macros.h"
26#include "base/stringprintf.h"
27#include "debugger.h"
28#include "jdwp/jdwp_constants.h"
29#include "jdwp/jdwp_event.h"
30#include "jdwp/jdwp_expand_buf.h"
31#include "jdwp/jdwp_priv.h"
32#include "runtime.h"
33#include "thread-inl.h"
34#include "UniquePtr.h"
35
36namespace art {
37
38namespace JDWP {
39
40std::string DescribeField(const FieldId& field_id) {
41  return StringPrintf("%#x (%s)", field_id, Dbg::GetFieldName(field_id).c_str());
42}
43
44std::string DescribeMethod(const MethodId& method_id) {
45  return StringPrintf("%#x (%s)", method_id, Dbg::GetMethodName(method_id).c_str());
46}
47
48std::string DescribeRefTypeId(const RefTypeId& ref_type_id) {
49  std::string signature("unknown");
50  Dbg::GetSignature(ref_type_id, &signature);
51  return StringPrintf("%#llx (%s)", ref_type_id, signature.c_str());
52}
53
54// Helper function: write a variable-width value into the output input buffer.
55static void WriteValue(ExpandBuf* pReply, int width, uint64_t value) {
56  switch (width) {
57  case 1:     expandBufAdd1(pReply, value); break;
58  case 2:     expandBufAdd2BE(pReply, value); break;
59  case 4:     expandBufAdd4BE(pReply, value); break;
60  case 8:     expandBufAdd8BE(pReply, value); break;
61  default:    LOG(FATAL) << width; break;
62  }
63}
64
65static JdwpError WriteTaggedObject(ExpandBuf* reply, ObjectId object_id)
66    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
67  uint8_t tag;
68  JdwpError rc = Dbg::GetObjectTag(object_id, tag);
69  if (rc == ERR_NONE) {
70    expandBufAdd1(reply, tag);
71    expandBufAddObjectId(reply, object_id);
72  }
73  return rc;
74}
75
76static JdwpError WriteTaggedObjectList(ExpandBuf* reply, const std::vector<ObjectId>& objects)
77    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
78  expandBufAdd4BE(reply, objects.size());
79  for (size_t i = 0; i < objects.size(); ++i) {
80    JdwpError rc = WriteTaggedObject(reply, objects[i]);
81    if (rc != ERR_NONE) {
82      return rc;
83    }
84  }
85  return ERR_NONE;
86}
87
88/*
89 * Common code for *_InvokeMethod requests.
90 *
91 * If "is_constructor" is set, this returns "object_id" rather than the
92 * expected-to-be-void return value of the called function.
93 */
94static JdwpError FinishInvoke(JdwpState*, Request& request, ExpandBuf* pReply,
95                              ObjectId thread_id, ObjectId object_id,
96                              RefTypeId class_id, MethodId method_id, bool is_constructor)
97    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
98  CHECK(!is_constructor || object_id != 0);
99
100  int32_t arg_count = request.ReadSigned32("argument count");
101
102  VLOG(jdwp) << StringPrintf("    --> thread_id=%#llx object_id=%#llx", thread_id, object_id);
103  VLOG(jdwp) << StringPrintf("        class_id=%#llx method_id=%x %s.%s", class_id,
104                             method_id, Dbg::GetClassName(class_id).c_str(),
105                             Dbg::GetMethodName(method_id).c_str());
106  VLOG(jdwp) << StringPrintf("        %d args:", arg_count);
107
108  UniquePtr<JdwpTag[]> argTypes(arg_count > 0 ? new JdwpTag[arg_count] : NULL);
109  UniquePtr<uint64_t[]> argValues(arg_count > 0 ? new uint64_t[arg_count] : NULL);
110  for (int32_t i = 0; i < arg_count; ++i) {
111    argTypes[i] = request.ReadTag();
112    size_t width = Dbg::GetTagWidth(argTypes[i]);
113    argValues[i] = request.ReadValue(width);
114    VLOG(jdwp) << "          " << argTypes[i] << StringPrintf("(%zd): %#llx", width, argValues[i]);
115  }
116
117  uint32_t options = request.ReadUnsigned32("InvokeOptions bit flags");
118  VLOG(jdwp) << StringPrintf("        options=0x%04x%s%s", options,
119                             (options & INVOKE_SINGLE_THREADED) ? " (SINGLE_THREADED)" : "",
120                             (options & INVOKE_NONVIRTUAL) ? " (NONVIRTUAL)" : "");
121
122  JdwpTag resultTag;
123  uint64_t resultValue;
124  ObjectId exceptObjId;
125  JdwpError err = Dbg::InvokeMethod(thread_id, object_id, class_id, method_id, arg_count, argValues.get(), argTypes.get(), options, &resultTag, &resultValue, &exceptObjId);
126  if (err != ERR_NONE) {
127    return err;
128  }
129
130  if (err == ERR_NONE) {
131    if (is_constructor) {
132      // If we invoked a constructor (which actually returns void), return the receiver,
133      // unless we threw, in which case we return NULL.
134      resultTag = JT_OBJECT;
135      resultValue = (exceptObjId == 0) ? object_id : 0;
136    }
137
138    size_t width = Dbg::GetTagWidth(resultTag);
139    expandBufAdd1(pReply, resultTag);
140    if (width != 0) {
141      WriteValue(pReply, width, resultValue);
142    }
143    expandBufAdd1(pReply, JT_OBJECT);
144    expandBufAddObjectId(pReply, exceptObjId);
145
146    VLOG(jdwp) << "  --> returned " << resultTag << StringPrintf(" %#llx (except=%#llx)", resultValue, exceptObjId);
147
148    /* show detailed debug output */
149    if (resultTag == JT_STRING && exceptObjId == 0) {
150      if (resultValue != 0) {
151        VLOG(jdwp) << "      string '" << Dbg::StringToUtf8(resultValue) << "'";
152      } else {
153        VLOG(jdwp) << "      string (null)";
154      }
155    }
156  }
157
158  return err;
159}
160
161static JdwpError VM_Version(JdwpState*, Request&, ExpandBuf* pReply)
162    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
163  // Text information on runtime version.
164  std::string version(StringPrintf("Android Runtime %s", Runtime::Current()->GetVersion()));
165  expandBufAddUtf8String(pReply, version);
166
167  // JDWP version numbers, major and minor.
168  expandBufAdd4BE(pReply, 1);
169  expandBufAdd4BE(pReply, 6);
170
171  // "java.version".
172  expandBufAddUtf8String(pReply, "1.6.0");
173
174  // "java.vm.name".
175  expandBufAddUtf8String(pReply, "Dalvik");
176
177  return ERR_NONE;
178}
179
180/*
181 * Given a class JNI signature (e.g. "Ljava/lang/Error;"), return the
182 * referenceTypeID.  We need to send back more than one if the class has
183 * been loaded by multiple class loaders.
184 */
185static JdwpError VM_ClassesBySignature(JdwpState*, Request& request, ExpandBuf* pReply)
186    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
187  std::string classDescriptor(request.ReadUtf8String());
188
189  std::vector<RefTypeId> ids;
190  Dbg::FindLoadedClassBySignature(classDescriptor.c_str(), ids);
191
192  expandBufAdd4BE(pReply, ids.size());
193
194  for (size_t i = 0; i < ids.size(); ++i) {
195    // Get class vs. interface and status flags.
196    JDWP::JdwpTypeTag type_tag;
197    uint32_t class_status;
198    JDWP::JdwpError status = Dbg::GetClassInfo(ids[i], &type_tag, &class_status, NULL);
199    if (status != ERR_NONE) {
200      return status;
201    }
202
203    expandBufAdd1(pReply, type_tag);
204    expandBufAddRefTypeId(pReply, ids[i]);
205    expandBufAdd4BE(pReply, class_status);
206  }
207
208  return ERR_NONE;
209}
210
211/*
212 * Handle request for the thread IDs of all running threads.
213 *
214 * We exclude ourselves from the list, because we don't allow ourselves
215 * to be suspended, and that violates some JDWP expectations.
216 */
217static JdwpError VM_AllThreads(JdwpState*, Request&, ExpandBuf* pReply)
218    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
219  std::vector<ObjectId> thread_ids;
220  Dbg::GetThreads(0, thread_ids);
221
222  expandBufAdd4BE(pReply, thread_ids.size());
223  for (uint32_t i = 0; i < thread_ids.size(); ++i) {
224    expandBufAddObjectId(pReply, thread_ids[i]);
225  }
226
227  return ERR_NONE;
228}
229
230/*
231 * List all thread groups that do not have a parent.
232 */
233static JdwpError VM_TopLevelThreadGroups(JdwpState*, Request&, ExpandBuf* pReply)
234    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
235  /*
236   * TODO: maintain a list of parentless thread groups in the VM.
237   *
238   * For now, just return "system".  Application threads are created
239   * in "main", which is a child of "system".
240   */
241  uint32_t groups = 1;
242  expandBufAdd4BE(pReply, groups);
243  ObjectId thread_group_id = Dbg::GetSystemThreadGroupId();
244  expandBufAddObjectId(pReply, thread_group_id);
245
246  return ERR_NONE;
247}
248
249/*
250 * Respond with the sizes of the basic debugger types.
251 *
252 * All IDs are 8 bytes.
253 */
254static JdwpError VM_IDSizes(JdwpState*, Request&, ExpandBuf* pReply)
255    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
256  expandBufAdd4BE(pReply, sizeof(FieldId));
257  expandBufAdd4BE(pReply, sizeof(MethodId));
258  expandBufAdd4BE(pReply, sizeof(ObjectId));
259  expandBufAdd4BE(pReply, sizeof(RefTypeId));
260  expandBufAdd4BE(pReply, sizeof(FrameId));
261  return ERR_NONE;
262}
263
264static JdwpError VM_Dispose(JdwpState*, Request&, ExpandBuf*)
265    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
266  Dbg::Disposed();
267  return ERR_NONE;
268}
269
270/*
271 * Suspend the execution of the application running in the VM (i.e. suspend
272 * all threads).
273 *
274 * This needs to increment the "suspend count" on all threads.
275 */
276static JdwpError VM_Suspend(JdwpState*, Request&, ExpandBuf*)
277    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
278  Thread* self = Thread::Current();
279  self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSuspension);
280  Dbg::SuspendVM();
281  self->TransitionFromSuspendedToRunnable();
282  return ERR_NONE;
283}
284
285/*
286 * Resume execution.  Decrements the "suspend count" of all threads.
287 */
288static JdwpError VM_Resume(JdwpState*, Request&, ExpandBuf*)
289    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
290  Dbg::ResumeVM();
291  return ERR_NONE;
292}
293
294static JdwpError VM_Exit(JdwpState* state, Request& request, ExpandBuf*)
295    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
296  uint32_t exit_status = request.ReadUnsigned32("exit_status");
297  state->ExitAfterReplying(exit_status);
298  return ERR_NONE;
299}
300
301/*
302 * Create a new string in the VM and return its ID.
303 *
304 * (Ctrl-Shift-I in Eclipse on an array of objects causes it to create the
305 * string "java.util.Arrays".)
306 */
307static JdwpError VM_CreateString(JdwpState*, Request& request, ExpandBuf* pReply)
308    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
309  std::string str(request.ReadUtf8String());
310  ObjectId stringId = Dbg::CreateString(str);
311  if (stringId == 0) {
312    return ERR_OUT_OF_MEMORY;
313  }
314  expandBufAddObjectId(pReply, stringId);
315  return ERR_NONE;
316}
317
318static JdwpError VM_ClassPaths(JdwpState*, Request&, ExpandBuf* pReply)
319    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
320  expandBufAddUtf8String(pReply, "/");
321
322  std::vector<std::string> class_path;
323  Split(Runtime::Current()->GetClassPathString(), ':', class_path);
324  expandBufAdd4BE(pReply, class_path.size());
325  for (size_t i = 0; i < class_path.size(); ++i) {
326    expandBufAddUtf8String(pReply, class_path[i]);
327  }
328
329  std::vector<std::string> boot_class_path;
330  Split(Runtime::Current()->GetBootClassPathString(), ':', boot_class_path);
331  expandBufAdd4BE(pReply, boot_class_path.size());
332  for (size_t i = 0; i < boot_class_path.size(); ++i) {
333    expandBufAddUtf8String(pReply, boot_class_path[i]);
334  }
335
336  return ERR_NONE;
337}
338
339static JdwpError VM_DisposeObjects(JdwpState*, Request& request, ExpandBuf*)
340    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
341  size_t object_count = request.ReadUnsigned32("object_count");
342  for (size_t i = 0; i < object_count; ++i) {
343    ObjectId object_id = request.ReadObjectId();
344    uint32_t reference_count = request.ReadUnsigned32("reference_count");
345    Dbg::DisposeObject(object_id, reference_count);
346  }
347  return ERR_NONE;
348}
349
350static JdwpError VM_Capabilities(JdwpState*, Request&, ExpandBuf* reply)
351    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
352  expandBufAdd1(reply, false);   // canWatchFieldModification
353  expandBufAdd1(reply, false);   // canWatchFieldAccess
354  expandBufAdd1(reply, true);    // canGetBytecodes
355  expandBufAdd1(reply, true);    // canGetSyntheticAttribute
356  expandBufAdd1(reply, true);    // canGetOwnedMonitorInfo
357  expandBufAdd1(reply, true);    // canGetCurrentContendedMonitor
358  expandBufAdd1(reply, true);    // canGetMonitorInfo
359  return ERR_NONE;
360}
361
362static JdwpError VM_CapabilitiesNew(JdwpState*, Request& request, ExpandBuf* reply)
363    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
364  // The first few capabilities are the same as those reported by the older call.
365  VM_Capabilities(NULL, request, reply);
366
367  expandBufAdd1(reply, false);   // canRedefineClasses
368  expandBufAdd1(reply, false);   // canAddMethod
369  expandBufAdd1(reply, false);   // canUnrestrictedlyRedefineClasses
370  expandBufAdd1(reply, false);   // canPopFrames
371  expandBufAdd1(reply, false);   // canUseInstanceFilters
372  expandBufAdd1(reply, false);   // canGetSourceDebugExtension
373  expandBufAdd1(reply, false);   // canRequestVMDeathEvent
374  expandBufAdd1(reply, false);   // canSetDefaultStratum
375  expandBufAdd1(reply, true);    // 1.6: canGetInstanceInfo
376  expandBufAdd1(reply, false);   // 1.6: canRequestMonitorEvents
377  expandBufAdd1(reply, true);    // 1.6: canGetMonitorFrameInfo
378  expandBufAdd1(reply, false);   // 1.6: canUseSourceNameFilters
379  expandBufAdd1(reply, false);   // 1.6: canGetConstantPool
380  expandBufAdd1(reply, false);   // 1.6: canForceEarlyReturn
381
382  // Fill in reserved22 through reserved32; note count started at 1.
383  for (size_t i = 22; i <= 32; ++i) {
384    expandBufAdd1(reply, false);
385  }
386  return ERR_NONE;
387}
388
389static JdwpError VM_AllClassesImpl(ExpandBuf* pReply, bool descriptor_and_status, bool generic)
390    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
391  std::vector<JDWP::RefTypeId> classes;
392  Dbg::GetClassList(classes);
393
394  expandBufAdd4BE(pReply, classes.size());
395
396  for (size_t i = 0; i < classes.size(); ++i) {
397    static const char genericSignature[1] = "";
398    JDWP::JdwpTypeTag type_tag;
399    std::string descriptor;
400    uint32_t class_status;
401    JDWP::JdwpError status = Dbg::GetClassInfo(classes[i], &type_tag, &class_status, &descriptor);
402    if (status != ERR_NONE) {
403      return status;
404    }
405
406    expandBufAdd1(pReply, type_tag);
407    expandBufAddRefTypeId(pReply, classes[i]);
408    if (descriptor_and_status) {
409      expandBufAddUtf8String(pReply, descriptor);
410      if (generic) {
411        expandBufAddUtf8String(pReply, genericSignature);
412      }
413      expandBufAdd4BE(pReply, class_status);
414    }
415  }
416
417  return ERR_NONE;
418}
419
420static JdwpError VM_AllClasses(JdwpState*, Request&, ExpandBuf* pReply)
421    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
422  return VM_AllClassesImpl(pReply, true, false);
423}
424
425static JdwpError VM_AllClassesWithGeneric(JdwpState*, Request&, ExpandBuf* pReply)
426    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
427  return VM_AllClassesImpl(pReply, true, true);
428}
429
430static JdwpError VM_InstanceCounts(JdwpState*, Request& request, ExpandBuf* pReply)
431    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
432  int32_t class_count = request.ReadSigned32("class count");
433  if (class_count < 0) {
434    return ERR_ILLEGAL_ARGUMENT;
435  }
436  std::vector<RefTypeId> class_ids;
437  for (int32_t i = 0; i < class_count; ++i) {
438    class_ids.push_back(request.ReadRefTypeId());
439  }
440
441  std::vector<uint64_t> counts;
442  JdwpError rc = Dbg::GetInstanceCounts(class_ids, counts);
443  if (rc != ERR_NONE) {
444    return rc;
445  }
446
447  expandBufAdd4BE(pReply, counts.size());
448  for (size_t i = 0; i < counts.size(); ++i) {
449    expandBufAdd8BE(pReply, counts[i]);
450  }
451  return ERR_NONE;
452}
453
454static JdwpError RT_Modifiers(JdwpState*, Request& request, ExpandBuf* pReply)
455    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
456  RefTypeId refTypeId = request.ReadRefTypeId();
457  return Dbg::GetModifiers(refTypeId, pReply);
458}
459
460/*
461 * Get values from static fields in a reference type.
462 */
463static JdwpError RT_GetValues(JdwpState*, Request& request, ExpandBuf* pReply)
464    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
465  RefTypeId refTypeId = request.ReadRefTypeId();
466  int32_t field_count = request.ReadSigned32("field count");
467  expandBufAdd4BE(pReply, field_count);
468  for (int32_t i = 0; i < field_count; ++i) {
469    FieldId fieldId = request.ReadFieldId();
470    JdwpError status = Dbg::GetStaticFieldValue(refTypeId, fieldId, pReply);
471    if (status != ERR_NONE) {
472      return status;
473    }
474  }
475  return ERR_NONE;
476}
477
478/*
479 * Get the name of the source file in which a reference type was declared.
480 */
481static JdwpError RT_SourceFile(JdwpState*, Request& request, ExpandBuf* pReply)
482    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
483  RefTypeId refTypeId = request.ReadRefTypeId();
484  std::string source_file;
485  JdwpError status = Dbg::GetSourceFile(refTypeId, source_file);
486  if (status != ERR_NONE) {
487    return status;
488  }
489  expandBufAddUtf8String(pReply, source_file);
490  return ERR_NONE;
491}
492
493/*
494 * Return the current status of the reference type.
495 */
496static JdwpError RT_Status(JdwpState*, Request& request, ExpandBuf* pReply)
497    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
498  RefTypeId refTypeId = request.ReadRefTypeId();
499  JDWP::JdwpTypeTag type_tag;
500  uint32_t class_status;
501  JDWP::JdwpError status = Dbg::GetClassInfo(refTypeId, &type_tag, &class_status, NULL);
502  if (status != ERR_NONE) {
503    return status;
504  }
505  expandBufAdd4BE(pReply, class_status);
506  return ERR_NONE;
507}
508
509/*
510 * Return interfaces implemented directly by this class.
511 */
512static JdwpError RT_Interfaces(JdwpState*, Request& request, ExpandBuf* pReply)
513    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
514  RefTypeId refTypeId = request.ReadRefTypeId();
515  return Dbg::OutputDeclaredInterfaces(refTypeId, pReply);
516}
517
518/*
519 * Return the class object corresponding to this type.
520 */
521static JdwpError RT_ClassObject(JdwpState*, Request& request, ExpandBuf* pReply)
522    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
523  RefTypeId refTypeId = request.ReadRefTypeId();
524  ObjectId class_object_id;
525  JdwpError status = Dbg::GetClassObject(refTypeId, class_object_id);
526  if (status != ERR_NONE) {
527    return status;
528  }
529  VLOG(jdwp) << StringPrintf("    --> ObjectId %#llx", class_object_id);
530  expandBufAddObjectId(pReply, class_object_id);
531  return ERR_NONE;
532}
533
534/*
535 * Returns the value of the SourceDebugExtension attribute.
536 *
537 * JDB seems interested, but DEX files don't currently support this.
538 */
539static JdwpError RT_SourceDebugExtension(JdwpState*, Request&, ExpandBuf*)
540    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
541  /* referenceTypeId in, string out */
542  return ERR_ABSENT_INFORMATION;
543}
544
545static JdwpError RT_Signature(JdwpState*, Request& request, ExpandBuf* pReply, bool with_generic)
546    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
547  RefTypeId refTypeId = request.ReadRefTypeId();
548
549  std::string signature;
550  JdwpError status = Dbg::GetSignature(refTypeId, &signature);
551  if (status != ERR_NONE) {
552    return status;
553  }
554  expandBufAddUtf8String(pReply, signature);
555  if (with_generic) {
556    expandBufAddUtf8String(pReply, "");
557  }
558  return ERR_NONE;
559}
560
561static JdwpError RT_Signature(JdwpState* state, Request& request, ExpandBuf* pReply)
562    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
563  return RT_Signature(state, request, pReply, false);
564}
565
566static JdwpError RT_SignatureWithGeneric(JdwpState* state, Request& request, ExpandBuf* pReply)
567    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
568  return RT_Signature(state, request, pReply, true);
569}
570
571/*
572 * Return the instance of java.lang.ClassLoader that loaded the specified
573 * reference type, or null if it was loaded by the system loader.
574 */
575static JdwpError RT_ClassLoader(JdwpState*, Request& request, ExpandBuf* pReply)
576    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
577  RefTypeId refTypeId = request.ReadRefTypeId();
578  return Dbg::GetClassLoader(refTypeId, pReply);
579}
580
581/*
582 * Given a referenceTypeId, return a block of stuff that describes the
583 * fields declared by a class.
584 */
585static JdwpError RT_FieldsWithGeneric(JdwpState*, Request& request, ExpandBuf* pReply)
586    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
587  RefTypeId refTypeId = request.ReadRefTypeId();
588  return Dbg::OutputDeclaredFields(refTypeId, true, pReply);
589}
590
591// Obsolete equivalent of FieldsWithGeneric, without the generic type information.
592static JdwpError RT_Fields(JdwpState*, Request& request, ExpandBuf* pReply)
593    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
594  RefTypeId refTypeId = request.ReadRefTypeId();
595  return Dbg::OutputDeclaredFields(refTypeId, false, pReply);
596}
597
598/*
599 * Given a referenceTypeID, return a block of goodies describing the
600 * methods declared by a class.
601 */
602static JdwpError RT_MethodsWithGeneric(JdwpState*, Request& request, ExpandBuf* pReply)
603    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
604  RefTypeId refTypeId = request.ReadRefTypeId();
605  return Dbg::OutputDeclaredMethods(refTypeId, true, pReply);
606}
607
608// Obsolete equivalent of MethodsWithGeneric, without the generic type information.
609static JdwpError RT_Methods(JdwpState*, Request& request, ExpandBuf* pReply)
610    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
611  RefTypeId refTypeId = request.ReadRefTypeId();
612  return Dbg::OutputDeclaredMethods(refTypeId, false, pReply);
613}
614
615static JdwpError RT_Instances(JdwpState*, Request& request, ExpandBuf* reply)
616    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
617  RefTypeId class_id = request.ReadRefTypeId();
618  int32_t max_count = request.ReadSigned32("max count");
619  if (max_count < 0) {
620    return ERR_ILLEGAL_ARGUMENT;
621  }
622
623  std::vector<ObjectId> instances;
624  JdwpError rc = Dbg::GetInstances(class_id, max_count, instances);
625  if (rc != ERR_NONE) {
626    return rc;
627  }
628
629  return WriteTaggedObjectList(reply, instances);
630}
631
632/*
633 * Return the immediate superclass of a class.
634 */
635static JdwpError CT_Superclass(JdwpState*, Request& request, ExpandBuf* pReply)
636    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
637  RefTypeId class_id = request.ReadRefTypeId();
638  RefTypeId superClassId;
639  JdwpError status = Dbg::GetSuperclass(class_id, superClassId);
640  if (status != ERR_NONE) {
641    return status;
642  }
643  expandBufAddRefTypeId(pReply, superClassId);
644  return ERR_NONE;
645}
646
647/*
648 * Set static class values.
649 */
650static JdwpError CT_SetValues(JdwpState* , Request& request, ExpandBuf*)
651    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
652  RefTypeId class_id = request.ReadRefTypeId();
653  int32_t values_count = request.ReadSigned32("values count");
654
655  UNUSED(class_id);
656
657  for (int32_t i = 0; i < values_count; ++i) {
658    FieldId fieldId = request.ReadFieldId();
659    JDWP::JdwpTag fieldTag = Dbg::GetStaticFieldBasicTag(fieldId);
660    size_t width = Dbg::GetTagWidth(fieldTag);
661    uint64_t value = request.ReadValue(width);
662
663    VLOG(jdwp) << "    --> field=" << fieldId << " tag=" << fieldTag << " --> " << value;
664    JdwpError status = Dbg::SetStaticFieldValue(fieldId, value, width);
665    if (status != ERR_NONE) {
666      return status;
667    }
668  }
669
670  return ERR_NONE;
671}
672
673/*
674 * Invoke a static method.
675 *
676 * Example: Eclipse sometimes uses java/lang/Class.forName(String s) on
677 * values in the "variables" display.
678 */
679static JdwpError CT_InvokeMethod(JdwpState* state, Request& request, ExpandBuf* pReply)
680    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
681  RefTypeId class_id = request.ReadRefTypeId();
682  ObjectId thread_id = request.ReadThreadId();
683  MethodId method_id = request.ReadMethodId();
684
685  return FinishInvoke(state, request, pReply, thread_id, 0, class_id, method_id, false);
686}
687
688/*
689 * Create a new object of the requested type, and invoke the specified
690 * constructor.
691 *
692 * Example: in IntelliJ, create a watch on "new String(myByteArray)" to
693 * see the contents of a byte[] as a string.
694 */
695static JdwpError CT_NewInstance(JdwpState* state, Request& request, ExpandBuf* pReply)
696    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
697  RefTypeId class_id = request.ReadRefTypeId();
698  ObjectId thread_id = request.ReadThreadId();
699  MethodId method_id = request.ReadMethodId();
700
701  ObjectId object_id;
702  JdwpError status = Dbg::CreateObject(class_id, object_id);
703  if (status != ERR_NONE) {
704    return status;
705  }
706  if (object_id == 0) {
707    return ERR_OUT_OF_MEMORY;
708  }
709  return FinishInvoke(state, request, pReply, thread_id, object_id, class_id, method_id, true);
710}
711
712/*
713 * Create a new array object of the requested type and length.
714 */
715static JdwpError AT_newInstance(JdwpState*, Request& request, ExpandBuf* pReply)
716    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
717  RefTypeId arrayTypeId = request.ReadRefTypeId();
718  int32_t length = request.ReadSigned32("length");
719
720  ObjectId object_id;
721  JdwpError status = Dbg::CreateArrayObject(arrayTypeId, length, object_id);
722  if (status != ERR_NONE) {
723    return status;
724  }
725  if (object_id == 0) {
726    return ERR_OUT_OF_MEMORY;
727  }
728  expandBufAdd1(pReply, JT_ARRAY);
729  expandBufAddObjectId(pReply, object_id);
730  return ERR_NONE;
731}
732
733/*
734 * Return line number information for the method, if present.
735 */
736static JdwpError M_LineTable(JdwpState*, Request& request, ExpandBuf* pReply)
737    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
738  RefTypeId refTypeId = request.ReadRefTypeId();
739  MethodId method_id = request.ReadMethodId();
740
741  Dbg::OutputLineTable(refTypeId, method_id, pReply);
742
743  return ERR_NONE;
744}
745
746static JdwpError M_VariableTable(JdwpState*, Request& request, ExpandBuf* pReply,
747                                 bool generic)
748    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
749  RefTypeId class_id = request.ReadRefTypeId();
750  MethodId method_id = request.ReadMethodId();
751
752  // We could return ERR_ABSENT_INFORMATION here if the DEX file was built without local variable
753  // information. That will cause Eclipse to make a best-effort attempt at displaying local
754  // variables anonymously. However, the attempt isn't very good, so we're probably better off just
755  // not showing anything.
756  Dbg::OutputVariableTable(class_id, method_id, generic, pReply);
757  return ERR_NONE;
758}
759
760static JdwpError M_VariableTable(JdwpState* state, Request& request, ExpandBuf* pReply)
761    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
762  return M_VariableTable(state, request, pReply, false);
763}
764
765static JdwpError M_VariableTableWithGeneric(JdwpState* state, Request& request, ExpandBuf* pReply)
766    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
767  return M_VariableTable(state, request, pReply, true);
768}
769
770static JdwpError M_Bytecodes(JdwpState*, Request& request, ExpandBuf* reply)
771    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
772  RefTypeId class_id = request.ReadRefTypeId();
773  MethodId method_id = request.ReadMethodId();
774
775  std::vector<uint8_t> bytecodes;
776  JdwpError rc = Dbg::GetBytecodes(class_id, method_id, bytecodes);
777  if (rc != ERR_NONE) {
778    return rc;
779  }
780
781  expandBufAdd4BE(reply, bytecodes.size());
782  for (size_t i = 0; i < bytecodes.size(); ++i) {
783    expandBufAdd1(reply, bytecodes[i]);
784  }
785
786  return ERR_NONE;
787}
788
789/*
790 * Given an object reference, return the runtime type of the object
791 * (class or array).
792 *
793 * This can get called on different things, e.g. thread_id gets
794 * passed in here.
795 */
796static JdwpError OR_ReferenceType(JdwpState*, Request& request, ExpandBuf* pReply)
797    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
798  ObjectId object_id = request.ReadObjectId();
799  return Dbg::GetReferenceType(object_id, pReply);
800}
801
802/*
803 * Get values from the fields of an object.
804 */
805static JdwpError OR_GetValues(JdwpState*, Request& request, ExpandBuf* pReply)
806    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
807  ObjectId object_id = request.ReadObjectId();
808  int32_t field_count = request.ReadSigned32("field count");
809
810  expandBufAdd4BE(pReply, field_count);
811  for (int32_t i = 0; i < field_count; ++i) {
812    FieldId fieldId = request.ReadFieldId();
813    JdwpError status = Dbg::GetFieldValue(object_id, fieldId, pReply);
814    if (status != ERR_NONE) {
815      return status;
816    }
817  }
818
819  return ERR_NONE;
820}
821
822/*
823 * Set values in the fields of an object.
824 */
825static JdwpError OR_SetValues(JdwpState*, Request& request, ExpandBuf*)
826    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
827  ObjectId object_id = request.ReadObjectId();
828  int32_t field_count = request.ReadSigned32("field count");
829
830  for (int32_t i = 0; i < field_count; ++i) {
831    FieldId fieldId = request.ReadFieldId();
832
833    JDWP::JdwpTag fieldTag = Dbg::GetFieldBasicTag(fieldId);
834    size_t width = Dbg::GetTagWidth(fieldTag);
835    uint64_t value = request.ReadValue(width);
836
837    VLOG(jdwp) << "    --> fieldId=" << fieldId << " tag=" << fieldTag << "(" << width << ") value=" << value;
838    JdwpError status = Dbg::SetFieldValue(object_id, fieldId, value, width);
839    if (status != ERR_NONE) {
840      return status;
841    }
842  }
843
844  return ERR_NONE;
845}
846
847static JdwpError OR_MonitorInfo(JdwpState*, Request& request, ExpandBuf* reply)
848    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
849  ObjectId object_id = request.ReadObjectId();
850  return Dbg::GetMonitorInfo(object_id, reply);
851}
852
853/*
854 * Invoke an instance method.  The invocation must occur in the specified
855 * thread, which must have been suspended by an event.
856 *
857 * The call is synchronous.  All threads in the VM are resumed, unless the
858 * SINGLE_THREADED flag is set.
859 *
860 * If you ask Eclipse to "inspect" an object (or ask JDB to "print" an
861 * object), it will try to invoke the object's toString() function.  This
862 * feature becomes crucial when examining ArrayLists with Eclipse.
863 */
864static JdwpError OR_InvokeMethod(JdwpState* state, Request& request, ExpandBuf* pReply)
865    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
866  ObjectId object_id = request.ReadObjectId();
867  ObjectId thread_id = request.ReadThreadId();
868  RefTypeId class_id = request.ReadRefTypeId();
869  MethodId method_id = request.ReadMethodId();
870
871  return FinishInvoke(state, request, pReply, thread_id, object_id, class_id, method_id, false);
872}
873
874static JdwpError OR_DisableCollection(JdwpState*, Request& request, ExpandBuf*)
875    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
876  ObjectId object_id = request.ReadObjectId();
877  return Dbg::DisableCollection(object_id);
878}
879
880static JdwpError OR_EnableCollection(JdwpState*, Request& request, ExpandBuf*)
881    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
882  ObjectId object_id = request.ReadObjectId();
883  return Dbg::EnableCollection(object_id);
884}
885
886static JdwpError OR_IsCollected(JdwpState*, Request& request, ExpandBuf* pReply)
887    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
888  ObjectId object_id = request.ReadObjectId();
889  bool is_collected;
890  JdwpError rc = Dbg::IsCollected(object_id, is_collected);
891  expandBufAdd1(pReply, is_collected ? 1 : 0);
892  return rc;
893}
894
895static JdwpError OR_ReferringObjects(JdwpState*, Request& request, ExpandBuf* reply)
896    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
897  ObjectId object_id = request.ReadObjectId();
898  int32_t max_count = request.ReadSigned32("max count");
899  if (max_count < 0) {
900    return ERR_ILLEGAL_ARGUMENT;
901  }
902
903  std::vector<ObjectId> referring_objects;
904  JdwpError rc = Dbg::GetReferringObjects(object_id, max_count, referring_objects);
905  if (rc != ERR_NONE) {
906    return rc;
907  }
908
909  return WriteTaggedObjectList(reply, referring_objects);
910}
911
912/*
913 * Return the string value in a string object.
914 */
915static JdwpError SR_Value(JdwpState*, Request& request, ExpandBuf* pReply)
916    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
917  ObjectId stringObject = request.ReadObjectId();
918  std::string str(Dbg::StringToUtf8(stringObject));
919
920  VLOG(jdwp) << StringPrintf("    --> %s", PrintableString(str).c_str());
921
922  expandBufAddUtf8String(pReply, str);
923
924  return ERR_NONE;
925}
926
927/*
928 * Return a thread's name.
929 */
930static JdwpError TR_Name(JdwpState*, Request& request, ExpandBuf* pReply)
931    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
932  ObjectId thread_id = request.ReadThreadId();
933
934  std::string name;
935  JdwpError error = Dbg::GetThreadName(thread_id, name);
936  if (error != ERR_NONE) {
937    return error;
938  }
939  VLOG(jdwp) << StringPrintf("  Name of thread %#llx is \"%s\"", thread_id, name.c_str());
940  expandBufAddUtf8String(pReply, name);
941
942  return ERR_NONE;
943}
944
945/*
946 * Suspend the specified thread.
947 *
948 * It's supposed to remain suspended even if interpreted code wants to
949 * resume it; only the JDI is allowed to resume it.
950 */
951static JdwpError TR_Suspend(JdwpState*, Request& request, ExpandBuf*)
952    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
953  ObjectId thread_id = request.ReadThreadId();
954
955  if (thread_id == Dbg::GetThreadSelfId()) {
956    LOG(INFO) << "  Warning: ignoring request to suspend self";
957    return ERR_THREAD_NOT_SUSPENDED;
958  }
959
960  Thread* self = Thread::Current();
961  self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
962  JdwpError result = Dbg::SuspendThread(thread_id);
963  self->TransitionFromSuspendedToRunnable();
964  return result;
965}
966
967/*
968 * Resume the specified thread.
969 */
970static JdwpError TR_Resume(JdwpState*, Request& request, ExpandBuf*)
971    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
972  ObjectId thread_id = request.ReadThreadId();
973
974  if (thread_id == Dbg::GetThreadSelfId()) {
975    LOG(INFO) << "  Warning: ignoring request to resume self";
976    return ERR_NONE;
977  }
978
979  Dbg::ResumeThread(thread_id);
980  return ERR_NONE;
981}
982
983/*
984 * Return status of specified thread.
985 */
986static JdwpError TR_Status(JdwpState*, Request& request, ExpandBuf* pReply)
987    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
988  ObjectId thread_id = request.ReadThreadId();
989
990  JDWP::JdwpThreadStatus threadStatus;
991  JDWP::JdwpSuspendStatus suspendStatus;
992  JdwpError error = Dbg::GetThreadStatus(thread_id, &threadStatus, &suspendStatus);
993  if (error != ERR_NONE) {
994    return error;
995  }
996
997  VLOG(jdwp) << "    --> " << threadStatus << ", " << suspendStatus;
998
999  expandBufAdd4BE(pReply, threadStatus);
1000  expandBufAdd4BE(pReply, suspendStatus);
1001
1002  return ERR_NONE;
1003}
1004
1005/*
1006 * Return the thread group that the specified thread is a member of.
1007 */
1008static JdwpError TR_ThreadGroup(JdwpState*, Request& request, ExpandBuf* pReply)
1009    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1010  ObjectId thread_id = request.ReadThreadId();
1011  return Dbg::GetThreadGroup(thread_id, pReply);
1012}
1013
1014/*
1015 * Return the current call stack of a suspended thread.
1016 *
1017 * If the thread isn't suspended, the error code isn't defined, but should
1018 * be THREAD_NOT_SUSPENDED.
1019 */
1020static JdwpError TR_Frames(JdwpState*, Request& request, ExpandBuf* pReply)
1021    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1022  ObjectId thread_id = request.ReadThreadId();
1023  uint32_t start_frame = request.ReadUnsigned32("start frame");
1024  uint32_t length = request.ReadUnsigned32("length");
1025
1026  size_t actual_frame_count;
1027  JdwpError error = Dbg::GetThreadFrameCount(thread_id, actual_frame_count);
1028  if (error != ERR_NONE) {
1029    return error;
1030  }
1031
1032  if (actual_frame_count <= 0) {
1033    return ERR_THREAD_NOT_SUSPENDED;  // 0 means no managed frames (which means "in native").
1034  }
1035
1036  if (start_frame > actual_frame_count) {
1037    return ERR_INVALID_INDEX;
1038  }
1039  if (length == static_cast<uint32_t>(-1)) {
1040    length = actual_frame_count - start_frame;
1041  }
1042  if (start_frame + length > actual_frame_count) {
1043    return ERR_INVALID_LENGTH;
1044  }
1045
1046  return Dbg::GetThreadFrames(thread_id, start_frame, length, pReply);
1047}
1048
1049/*
1050 * Returns the #of frames on the specified thread, which must be suspended.
1051 */
1052static JdwpError TR_FrameCount(JdwpState*, Request& request, ExpandBuf* pReply)
1053    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1054  ObjectId thread_id = request.ReadThreadId();
1055
1056  size_t frame_count;
1057  JdwpError rc = Dbg::GetThreadFrameCount(thread_id, frame_count);
1058  if (rc != ERR_NONE) {
1059    return rc;
1060  }
1061  expandBufAdd4BE(pReply, static_cast<uint32_t>(frame_count));
1062
1063  return ERR_NONE;
1064}
1065
1066static JdwpError TR_OwnedMonitors(Request& request, ExpandBuf* reply, bool with_stack_depths)
1067    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1068  ObjectId thread_id = request.ReadThreadId();
1069
1070  std::vector<ObjectId> monitors;
1071  std::vector<uint32_t> stack_depths;
1072  JdwpError rc = Dbg::GetOwnedMonitors(thread_id, monitors, stack_depths);
1073  if (rc != ERR_NONE) {
1074    return rc;
1075  }
1076
1077  expandBufAdd4BE(reply, monitors.size());
1078  for (size_t i = 0; i < monitors.size(); ++i) {
1079    rc = WriteTaggedObject(reply, monitors[i]);
1080    if (rc != ERR_NONE) {
1081      return rc;
1082    }
1083    if (with_stack_depths) {
1084      expandBufAdd4BE(reply, stack_depths[i]);
1085    }
1086  }
1087  return ERR_NONE;
1088}
1089
1090static JdwpError TR_OwnedMonitors(JdwpState*, Request& request, ExpandBuf* reply)
1091    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1092  return TR_OwnedMonitors(request, reply, false);
1093}
1094
1095static JdwpError TR_OwnedMonitorsStackDepthInfo(JdwpState*, Request& request, ExpandBuf* reply)
1096    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1097  return TR_OwnedMonitors(request, reply, true);
1098}
1099
1100static JdwpError TR_CurrentContendedMonitor(JdwpState*, Request& request, ExpandBuf* reply)
1101    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1102  ObjectId thread_id = request.ReadThreadId();
1103
1104  ObjectId contended_monitor;
1105  JdwpError rc = Dbg::GetContendedMonitor(thread_id, contended_monitor);
1106  if (rc != ERR_NONE) {
1107    return rc;
1108  }
1109  return WriteTaggedObject(reply, contended_monitor);
1110}
1111
1112static JdwpError TR_Interrupt(JdwpState*, Request& request, ExpandBuf* reply)
1113    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1114  ObjectId thread_id = request.ReadThreadId();
1115  return Dbg::Interrupt(thread_id);
1116}
1117
1118/*
1119 * Return the debug suspend count for the specified thread.
1120 *
1121 * (The thread *might* still be running -- it might not have examined
1122 * its suspend count recently.)
1123 */
1124static JdwpError TR_DebugSuspendCount(JdwpState*, Request& request, ExpandBuf* pReply)
1125    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1126  ObjectId thread_id = request.ReadThreadId();
1127  return Dbg::GetThreadDebugSuspendCount(thread_id, pReply);
1128}
1129
1130/*
1131 * Return the name of a thread group.
1132 *
1133 * The Eclipse debugger recognizes "main" and "system" as special.
1134 */
1135static JdwpError TGR_Name(JdwpState*, Request& request, ExpandBuf* pReply)
1136    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1137  ObjectId thread_group_id = request.ReadThreadGroupId();
1138
1139  expandBufAddUtf8String(pReply, Dbg::GetThreadGroupName(thread_group_id));
1140
1141  return ERR_NONE;
1142}
1143
1144/*
1145 * Returns the thread group -- if any -- that contains the specified
1146 * thread group.
1147 */
1148static JdwpError TGR_Parent(JdwpState*, Request& request, ExpandBuf* pReply)
1149    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1150  ObjectId thread_group_id = request.ReadThreadGroupId();
1151
1152  ObjectId parentGroup = Dbg::GetThreadGroupParent(thread_group_id);
1153  expandBufAddObjectId(pReply, parentGroup);
1154
1155  return ERR_NONE;
1156}
1157
1158/*
1159 * Return the active threads and thread groups that are part of the
1160 * specified thread group.
1161 */
1162static JdwpError TGR_Children(JdwpState*, Request& request, ExpandBuf* pReply)
1163    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1164  ObjectId thread_group_id = request.ReadThreadGroupId();
1165
1166  std::vector<ObjectId> thread_ids;
1167  Dbg::GetThreads(thread_group_id, thread_ids);
1168  expandBufAdd4BE(pReply, thread_ids.size());
1169  for (uint32_t i = 0; i < thread_ids.size(); ++i) {
1170    expandBufAddObjectId(pReply, thread_ids[i]);
1171  }
1172
1173  std::vector<ObjectId> child_thread_groups_ids;
1174  Dbg::GetChildThreadGroups(thread_group_id, child_thread_groups_ids);
1175  expandBufAdd4BE(pReply, child_thread_groups_ids.size());
1176  for (uint32_t i = 0; i < child_thread_groups_ids.size(); ++i) {
1177    expandBufAddObjectId(pReply, child_thread_groups_ids[i]);
1178  }
1179
1180  return ERR_NONE;
1181}
1182
1183/*
1184 * Return the #of components in the array.
1185 */
1186static JdwpError AR_Length(JdwpState*, Request& request, ExpandBuf* pReply)
1187    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1188  ObjectId array_id = request.ReadArrayId();
1189
1190  int length;
1191  JdwpError status = Dbg::GetArrayLength(array_id, length);
1192  if (status != ERR_NONE) {
1193    return status;
1194  }
1195  VLOG(jdwp) << "    --> " << length;
1196
1197  expandBufAdd4BE(pReply, length);
1198
1199  return ERR_NONE;
1200}
1201
1202/*
1203 * Return the values from an array.
1204 */
1205static JdwpError AR_GetValues(JdwpState*, Request& request, ExpandBuf* pReply)
1206    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1207  ObjectId array_id = request.ReadArrayId();
1208  uint32_t offset = request.ReadUnsigned32("offset");
1209  uint32_t length = request.ReadUnsigned32("length");
1210  return Dbg::OutputArray(array_id, offset, length, pReply);
1211}
1212
1213/*
1214 * Set values in an array.
1215 */
1216static JdwpError AR_SetValues(JdwpState*, Request& request, ExpandBuf*)
1217    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1218  ObjectId array_id = request.ReadArrayId();
1219  uint32_t offset = request.ReadUnsigned32("offset");
1220  uint32_t count = request.ReadUnsigned32("count");
1221  return Dbg::SetArrayElements(array_id, offset, count, request);
1222}
1223
1224static JdwpError CLR_VisibleClasses(JdwpState*, Request& request, ExpandBuf* pReply)
1225    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1226  request.ReadObjectId();  // classLoaderObject
1227  // TODO: we should only return classes which have the given class loader as a defining or
1228  // initiating loader. The former would be easy; the latter is hard, because we don't have
1229  // any such notion.
1230  return VM_AllClassesImpl(pReply, false, false);
1231}
1232
1233/*
1234 * Set an event trigger.
1235 *
1236 * Reply with a requestID.
1237 */
1238static JdwpError ER_Set(JdwpState* state, Request& request, ExpandBuf* pReply)
1239    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1240  JdwpEventKind event_kind = request.ReadEnum1<JdwpEventKind>("event kind");
1241  JdwpSuspendPolicy suspend_policy = request.ReadEnum1<JdwpSuspendPolicy>("suspend policy");
1242  int32_t modifier_count = request.ReadSigned32("modifier count");
1243
1244  CHECK_LT(modifier_count, 256);    /* reasonableness check */
1245
1246  JdwpEvent* pEvent = EventAlloc(modifier_count);
1247  pEvent->eventKind = event_kind;
1248  pEvent->suspend_policy = suspend_policy;
1249  pEvent->modCount = modifier_count;
1250
1251  /*
1252   * Read modifiers.  Ordering may be significant (see explanation of Count
1253   * mods in JDWP doc).
1254   */
1255  for (int32_t i = 0; i < modifier_count; ++i) {
1256    JdwpEventMod& mod = pEvent->mods[i];
1257    mod.modKind = request.ReadModKind();
1258    switch (mod.modKind) {
1259    case MK_COUNT:
1260      {
1261        // Report once, when "--count" reaches 0.
1262        uint32_t count = request.ReadUnsigned32("count");
1263        if (count == 0) {
1264          return ERR_INVALID_COUNT;
1265        }
1266        mod.count.count = count;
1267      }
1268      break;
1269    case MK_CONDITIONAL:
1270      {
1271        // Conditional on expression.
1272        uint32_t exprId = request.ReadUnsigned32("expr id");
1273        mod.conditional.exprId = exprId;
1274      }
1275      break;
1276    case MK_THREAD_ONLY:
1277      {
1278        // Only report events in specified thread.
1279        ObjectId thread_id = request.ReadThreadId();
1280        mod.threadOnly.threadId = thread_id;
1281      }
1282      break;
1283    case MK_CLASS_ONLY:
1284      {
1285        // For ClassPrepare, MethodEntry.
1286        RefTypeId class_id = request.ReadRefTypeId();
1287        mod.classOnly.refTypeId = class_id;
1288      }
1289      break;
1290    case MK_CLASS_MATCH:
1291      {
1292        // Restrict events to matching classes.
1293        // pattern is "java.foo.*", we want "java/foo/*".
1294        std::string pattern(request.ReadUtf8String());
1295        std::replace(pattern.begin(), pattern.end(), '.', '/');
1296        mod.classMatch.classPattern = strdup(pattern.c_str());
1297      }
1298      break;
1299    case MK_CLASS_EXCLUDE:
1300      {
1301        // Restrict events to non-matching classes.
1302        // pattern is "java.foo.*", we want "java/foo/*".
1303        std::string pattern(request.ReadUtf8String());
1304        std::replace(pattern.begin(), pattern.end(), '.', '/');
1305        mod.classExclude.classPattern = strdup(pattern.c_str());
1306      }
1307      break;
1308    case MK_LOCATION_ONLY:
1309      {
1310        // Restrict certain events based on location.
1311        JdwpLocation location = request.ReadLocation();
1312        mod.locationOnly.loc = location;
1313      }
1314      break;
1315    case MK_EXCEPTION_ONLY:
1316      {
1317        // Modifies EK_EXCEPTION events,
1318        mod.exceptionOnly.refTypeId = request.ReadRefTypeId();  // null => all exceptions.
1319        mod.exceptionOnly.caught = request.ReadEnum1<uint8_t>("caught");
1320        mod.exceptionOnly.uncaught = request.ReadEnum1<uint8_t>("uncaught");
1321      }
1322      break;
1323    case MK_FIELD_ONLY:
1324      {
1325        // For field access/modification events.
1326        RefTypeId declaring = request.ReadRefTypeId();
1327        FieldId fieldId = request.ReadFieldId();
1328        mod.fieldOnly.refTypeId = declaring;
1329        mod.fieldOnly.fieldId = fieldId;
1330      }
1331      break;
1332    case MK_STEP:
1333      {
1334        // For use with EK_SINGLE_STEP.
1335        ObjectId thread_id = request.ReadThreadId();
1336        uint32_t size = request.ReadUnsigned32("step size");
1337        uint32_t depth = request.ReadUnsigned32("step depth");
1338        VLOG(jdwp) << StringPrintf("    Step: thread=%#llx", thread_id)
1339                     << " size=" << JdwpStepSize(size) << " depth=" << JdwpStepDepth(depth);
1340
1341        mod.step.threadId = thread_id;
1342        mod.step.size = size;
1343        mod.step.depth = depth;
1344      }
1345      break;
1346    case MK_INSTANCE_ONLY:
1347      {
1348        // Report events related to a specific object.
1349        ObjectId instance = request.ReadObjectId();
1350        mod.instanceOnly.objectId = instance;
1351      }
1352      break;
1353    default:
1354      LOG(WARNING) << "GLITCH: unsupported modKind=" << mod.modKind;
1355      break;
1356    }
1357  }
1358
1359  /*
1360   * We reply with an integer "requestID".
1361   */
1362  uint32_t requestId = state->NextEventSerial();
1363  expandBufAdd4BE(pReply, requestId);
1364
1365  pEvent->requestId = requestId;
1366
1367  VLOG(jdwp) << StringPrintf("    --> event requestId=%#x", requestId);
1368
1369  /* add it to the list */
1370  JdwpError err = state->RegisterEvent(pEvent);
1371  if (err != ERR_NONE) {
1372    /* registration failed, probably because event is bogus */
1373    EventFree(pEvent);
1374    LOG(WARNING) << "WARNING: event request rejected";
1375  }
1376  return err;
1377}
1378
1379static JdwpError ER_Clear(JdwpState* state, Request& request, ExpandBuf*)
1380    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1381  request.ReadEnum1<JdwpEventKind>("event kind");
1382  uint32_t requestId = request.ReadUnsigned32("request id");
1383
1384  // Failure to find an event with a matching ID is a no-op
1385  // and does not return an error.
1386  state->UnregisterEventById(requestId);
1387  return ERR_NONE;
1388}
1389
1390/*
1391 * Return the values of arguments and local variables.
1392 */
1393static JdwpError SF_GetValues(JdwpState*, Request& request, ExpandBuf* pReply)
1394    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1395  ObjectId thread_id = request.ReadThreadId();
1396  FrameId frame_id = request.ReadFrameId();
1397  int32_t slot_count = request.ReadSigned32("slot count");
1398
1399  expandBufAdd4BE(pReply, slot_count);     /* "int values" */
1400  for (int32_t i = 0; i < slot_count; ++i) {
1401    uint32_t slot = request.ReadUnsigned32("slot");
1402    JDWP::JdwpTag reqSigByte = request.ReadTag();
1403
1404    VLOG(jdwp) << "    --> slot " << slot << " " << reqSigByte;
1405
1406    size_t width = Dbg::GetTagWidth(reqSigByte);
1407    uint8_t* ptr = expandBufAddSpace(pReply, width+1);
1408    Dbg::GetLocalValue(thread_id, frame_id, slot, reqSigByte, ptr, width);
1409  }
1410
1411  return ERR_NONE;
1412}
1413
1414/*
1415 * Set the values of arguments and local variables.
1416 */
1417static JdwpError SF_SetValues(JdwpState*, Request& request, ExpandBuf*)
1418    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1419  ObjectId thread_id = request.ReadThreadId();
1420  FrameId frame_id = request.ReadFrameId();
1421  int32_t slot_count = request.ReadSigned32("slot count");
1422
1423  for (int32_t i = 0; i < slot_count; ++i) {
1424    uint32_t slot = request.ReadUnsigned32("slot");
1425    JDWP::JdwpTag sigByte = request.ReadTag();
1426    size_t width = Dbg::GetTagWidth(sigByte);
1427    uint64_t value = request.ReadValue(width);
1428
1429    VLOG(jdwp) << "    --> slot " << slot << " " << sigByte << " " << value;
1430    Dbg::SetLocalValue(thread_id, frame_id, slot, sigByte, value, width);
1431  }
1432
1433  return ERR_NONE;
1434}
1435
1436static JdwpError SF_ThisObject(JdwpState*, Request& request, ExpandBuf* reply)
1437    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1438  ObjectId thread_id = request.ReadThreadId();
1439  FrameId frame_id = request.ReadFrameId();
1440
1441  ObjectId object_id;
1442  JdwpError rc = Dbg::GetThisObject(thread_id, frame_id, &object_id);
1443  if (rc != ERR_NONE) {
1444    return rc;
1445  }
1446
1447  return WriteTaggedObject(reply, object_id);
1448}
1449
1450/*
1451 * Return the reference type reflected by this class object.
1452 *
1453 * This appears to be required because ReferenceTypeId values are NEVER
1454 * reused, whereas ClassIds can be recycled like any other object.  (Either
1455 * that, or I have no idea what this is for.)
1456 */
1457static JdwpError COR_ReflectedType(JdwpState*, Request& request, ExpandBuf* pReply)
1458    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1459  RefTypeId class_object_id = request.ReadRefTypeId();
1460  return Dbg::GetReflectedType(class_object_id, pReply);
1461}
1462
1463/*
1464 * Handle a DDM packet with a single chunk in it.
1465 */
1466static JdwpError DDM_Chunk(JdwpState* state, Request& request, ExpandBuf* pReply)
1467    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1468  state->NotifyDdmsActive();
1469  uint8_t* replyBuf = NULL;
1470  int replyLen = -1;
1471  if (Dbg::DdmHandlePacket(request, &replyBuf, &replyLen)) {
1472    // If they want to send something back, we copy it into the buffer.
1473    // TODO: consider altering the JDWP stuff to hold the packet header
1474    // in a separate buffer.  That would allow us to writev() DDM traffic
1475    // instead of copying it into the expanding buffer.  The reduction in
1476    // heap requirements is probably more valuable than the efficiency.
1477    CHECK_GT(replyLen, 0);
1478    memcpy(expandBufAddSpace(pReply, replyLen), replyBuf, replyLen);
1479    free(replyBuf);
1480  }
1481  return ERR_NONE;
1482}
1483
1484/*
1485 * Handler map decl.
1486 */
1487typedef JdwpError (*JdwpRequestHandler)(JdwpState* state, Request& request, ExpandBuf* reply);
1488
1489struct JdwpHandlerMap {
1490  uint8_t cmdSet;
1491  uint8_t cmd;
1492  JdwpRequestHandler func;
1493  const char* name;
1494};
1495
1496/*
1497 * Map commands to functions.
1498 *
1499 * Command sets 0-63 are incoming requests, 64-127 are outbound requests,
1500 * and 128-256 are vendor-defined.
1501 */
1502static const JdwpHandlerMap gHandlers[] = {
1503  /* VirtualMachine command set (1) */
1504  { 1,    1,  VM_Version,               "VirtualMachine.Version" },
1505  { 1,    2,  VM_ClassesBySignature,    "VirtualMachine.ClassesBySignature" },
1506  { 1,    3,  VM_AllClasses,            "VirtualMachine.AllClasses" },
1507  { 1,    4,  VM_AllThreads,            "VirtualMachine.AllThreads" },
1508  { 1,    5,  VM_TopLevelThreadGroups,  "VirtualMachine.TopLevelThreadGroups" },
1509  { 1,    6,  VM_Dispose,               "VirtualMachine.Dispose" },
1510  { 1,    7,  VM_IDSizes,               "VirtualMachine.IDSizes" },
1511  { 1,    8,  VM_Suspend,               "VirtualMachine.Suspend" },
1512  { 1,    9,  VM_Resume,                "VirtualMachine.Resume" },
1513  { 1,    10, VM_Exit,                  "VirtualMachine.Exit" },
1514  { 1,    11, VM_CreateString,          "VirtualMachine.CreateString" },
1515  { 1,    12, VM_Capabilities,          "VirtualMachine.Capabilities" },
1516  { 1,    13, VM_ClassPaths,            "VirtualMachine.ClassPaths" },
1517  { 1,    14, VM_DisposeObjects,        "VirtualMachine.DisposeObjects" },
1518  { 1,    15, NULL,                     "VirtualMachine.HoldEvents" },
1519  { 1,    16, NULL,                     "VirtualMachine.ReleaseEvents" },
1520  { 1,    17, VM_CapabilitiesNew,       "VirtualMachine.CapabilitiesNew" },
1521  { 1,    18, NULL,                     "VirtualMachine.RedefineClasses" },
1522  { 1,    19, NULL,                     "VirtualMachine.SetDefaultStratum" },
1523  { 1,    20, VM_AllClassesWithGeneric, "VirtualMachine.AllClassesWithGeneric" },
1524  { 1,    21, VM_InstanceCounts,        "VirtualMachine.InstanceCounts" },
1525
1526  /* ReferenceType command set (2) */
1527  { 2,    1,  RT_Signature,            "ReferenceType.Signature" },
1528  { 2,    2,  RT_ClassLoader,          "ReferenceType.ClassLoader" },
1529  { 2,    3,  RT_Modifiers,            "ReferenceType.Modifiers" },
1530  { 2,    4,  RT_Fields,               "ReferenceType.Fields" },
1531  { 2,    5,  RT_Methods,              "ReferenceType.Methods" },
1532  { 2,    6,  RT_GetValues,            "ReferenceType.GetValues" },
1533  { 2,    7,  RT_SourceFile,           "ReferenceType.SourceFile" },
1534  { 2,    8,  NULL,                    "ReferenceType.NestedTypes" },
1535  { 2,    9,  RT_Status,               "ReferenceType.Status" },
1536  { 2,    10, RT_Interfaces,           "ReferenceType.Interfaces" },
1537  { 2,    11, RT_ClassObject,          "ReferenceType.ClassObject" },
1538  { 2,    12, RT_SourceDebugExtension, "ReferenceType.SourceDebugExtension" },
1539  { 2,    13, RT_SignatureWithGeneric, "ReferenceType.SignatureWithGeneric" },
1540  { 2,    14, RT_FieldsWithGeneric,    "ReferenceType.FieldsWithGeneric" },
1541  { 2,    15, RT_MethodsWithGeneric,   "ReferenceType.MethodsWithGeneric" },
1542  { 2,    16, RT_Instances,            "ReferenceType.Instances" },
1543  { 2,    17, NULL,                    "ReferenceType.ClassFileVersion" },
1544  { 2,    18, NULL,                    "ReferenceType.ConstantPool" },
1545
1546  /* ClassType command set (3) */
1547  { 3,    1,  CT_Superclass,    "ClassType.Superclass" },
1548  { 3,    2,  CT_SetValues,     "ClassType.SetValues" },
1549  { 3,    3,  CT_InvokeMethod,  "ClassType.InvokeMethod" },
1550  { 3,    4,  CT_NewInstance,   "ClassType.NewInstance" },
1551
1552  /* ArrayType command set (4) */
1553  { 4,    1,  AT_newInstance,   "ArrayType.NewInstance" },
1554
1555  /* InterfaceType command set (5) */
1556
1557  /* Method command set (6) */
1558  { 6,    1,  M_LineTable,                "Method.LineTable" },
1559  { 6,    2,  M_VariableTable,            "Method.VariableTable" },
1560  { 6,    3,  M_Bytecodes,                "Method.Bytecodes" },
1561  { 6,    4,  NULL,                       "Method.IsObsolete" },
1562  { 6,    5,  M_VariableTableWithGeneric, "Method.VariableTableWithGeneric" },
1563
1564  /* Field command set (8) */
1565
1566  /* ObjectReference command set (9) */
1567  { 9,    1,  OR_ReferenceType,     "ObjectReference.ReferenceType" },
1568  { 9,    2,  OR_GetValues,         "ObjectReference.GetValues" },
1569  { 9,    3,  OR_SetValues,         "ObjectReference.SetValues" },
1570  { 9,    4,  NULL,                 "ObjectReference.UNUSED" },
1571  { 9,    5,  OR_MonitorInfo,       "ObjectReference.MonitorInfo" },
1572  { 9,    6,  OR_InvokeMethod,      "ObjectReference.InvokeMethod" },
1573  { 9,    7,  OR_DisableCollection, "ObjectReference.DisableCollection" },
1574  { 9,    8,  OR_EnableCollection,  "ObjectReference.EnableCollection" },
1575  { 9,    9,  OR_IsCollected,       "ObjectReference.IsCollected" },
1576  { 9,    10, OR_ReferringObjects,  "ObjectReference.ReferringObjects" },
1577
1578  /* StringReference command set (10) */
1579  { 10,   1,  SR_Value,         "StringReference.Value" },
1580
1581  /* ThreadReference command set (11) */
1582  { 11,   1,  TR_Name,                        "ThreadReference.Name" },
1583  { 11,   2,  TR_Suspend,                     "ThreadReference.Suspend" },
1584  { 11,   3,  TR_Resume,                      "ThreadReference.Resume" },
1585  { 11,   4,  TR_Status,                      "ThreadReference.Status" },
1586  { 11,   5,  TR_ThreadGroup,                 "ThreadReference.ThreadGroup" },
1587  { 11,   6,  TR_Frames,                      "ThreadReference.Frames" },
1588  { 11,   7,  TR_FrameCount,                  "ThreadReference.FrameCount" },
1589  { 11,   8,  TR_OwnedMonitors,               "ThreadReference.OwnedMonitors" },
1590  { 11,   9,  TR_CurrentContendedMonitor,     "ThreadReference.CurrentContendedMonitor" },
1591  { 11,   10, NULL,                           "ThreadReference.Stop" },
1592  { 11,   11, TR_Interrupt,                   "ThreadReference.Interrupt" },
1593  { 11,   12, TR_DebugSuspendCount,           "ThreadReference.SuspendCount" },
1594  { 11,   13, TR_OwnedMonitorsStackDepthInfo, "ThreadReference.OwnedMonitorsStackDepthInfo" },
1595  { 11,   14, NULL,                           "ThreadReference.ForceEarlyReturn" },
1596
1597  /* ThreadGroupReference command set (12) */
1598  { 12,   1,  TGR_Name,         "ThreadGroupReference.Name" },
1599  { 12,   2,  TGR_Parent,       "ThreadGroupReference.Parent" },
1600  { 12,   3,  TGR_Children,     "ThreadGroupReference.Children" },
1601
1602  /* ArrayReference command set (13) */
1603  { 13,   1,  AR_Length,        "ArrayReference.Length" },
1604  { 13,   2,  AR_GetValues,     "ArrayReference.GetValues" },
1605  { 13,   3,  AR_SetValues,     "ArrayReference.SetValues" },
1606
1607  /* ClassLoaderReference command set (14) */
1608  { 14,   1,  CLR_VisibleClasses, "ClassLoaderReference.VisibleClasses" },
1609
1610  /* EventRequest command set (15) */
1611  { 15,   1,  ER_Set,           "EventRequest.Set" },
1612  { 15,   2,  ER_Clear,         "EventRequest.Clear" },
1613  { 15,   3,  NULL,             "EventRequest.ClearAllBreakpoints" },
1614
1615  /* StackFrame command set (16) */
1616  { 16,   1,  SF_GetValues,     "StackFrame.GetValues" },
1617  { 16,   2,  SF_SetValues,     "StackFrame.SetValues" },
1618  { 16,   3,  SF_ThisObject,    "StackFrame.ThisObject" },
1619  { 16,   4,  NULL,             "StackFrame.PopFrames" },
1620
1621  /* ClassObjectReference command set (17) */
1622  { 17,   1,  COR_ReflectedType, "ClassObjectReference.ReflectedType" },
1623
1624  /* Event command set (64) */
1625  { 64, 100,  NULL, "Event.Composite" },  // sent from VM to debugger, never received by VM
1626
1627  { 199,  1,  DDM_Chunk,        "DDM.Chunk" },
1628};
1629
1630static const char* GetCommandName(Request& request) {
1631  for (size_t i = 0; i < arraysize(gHandlers); ++i) {
1632    if (gHandlers[i].cmdSet == request.GetCommandSet() && gHandlers[i].cmd == request.GetCommand()) {
1633      return gHandlers[i].name;
1634    }
1635  }
1636  return "?UNKNOWN?";
1637}
1638
1639static std::string DescribeCommand(Request& request) {
1640  std::string result;
1641  result += "REQUEST: ";
1642  result += GetCommandName(request);
1643  result += StringPrintf(" (length=%d id=0x%06x)", request.GetLength(), request.GetId());
1644  return result;
1645}
1646
1647/*
1648 * Process a request from the debugger.
1649 *
1650 * On entry, the JDWP thread is in VMWAIT.
1651 */
1652void JdwpState::ProcessRequest(Request& request, ExpandBuf* pReply) {
1653  JdwpError result = ERR_NONE;
1654
1655  if (request.GetCommandSet() != kJDWPDdmCmdSet) {
1656    /*
1657     * Activity from a debugger, not merely ddms.  Mark us as having an
1658     * active debugger session, and zero out the last-activity timestamp
1659     * so waitForDebugger() doesn't return if we stall for a bit here.
1660     */
1661    Dbg::GoActive();
1662    QuasiAtomic::Write64(&last_activity_time_ms_, 0);
1663  }
1664
1665  /*
1666   * If a debugger event has fired in another thread, wait until the
1667   * initiating thread has suspended itself before processing messages
1668   * from the debugger.  Otherwise we (the JDWP thread) could be told to
1669   * resume the thread before it has suspended.
1670   *
1671   * We call with an argument of zero to wait for the current event
1672   * thread to finish, and then clear the block.  Depending on the thread
1673   * suspend policy, this may allow events in other threads to fire,
1674   * but those events have no bearing on what the debugger has sent us
1675   * in the current request.
1676   *
1677   * Note that we MUST clear the event token before waking the event
1678   * thread up, or risk waiting for the thread to suspend after we've
1679   * told it to resume.
1680   */
1681  SetWaitForEventThread(0);
1682
1683  /*
1684   * Tell the VM that we're running and shouldn't be interrupted by GC.
1685   * Do this after anything that can stall indefinitely.
1686   */
1687  Thread* self = Thread::Current();
1688  ThreadState old_state = self->TransitionFromSuspendedToRunnable();
1689
1690  expandBufAddSpace(pReply, kJDWPHeaderLen);
1691
1692  size_t i;
1693  for (i = 0; i < arraysize(gHandlers); ++i) {
1694    if (gHandlers[i].cmdSet == request.GetCommandSet() && gHandlers[i].cmd == request.GetCommand() && gHandlers[i].func != NULL) {
1695      VLOG(jdwp) << DescribeCommand(request);
1696      result = (*gHandlers[i].func)(this, request, pReply);
1697      if (result == ERR_NONE) {
1698        request.CheckConsumed();
1699      }
1700      break;
1701    }
1702  }
1703  if (i == arraysize(gHandlers)) {
1704    LOG(ERROR) << "Command not implemented: " << DescribeCommand(request);
1705    LOG(ERROR) << HexDump(request.data(), request.size());
1706    result = ERR_NOT_IMPLEMENTED;
1707  }
1708
1709  /*
1710   * Set up the reply header.
1711   *
1712   * If we encountered an error, only send the header back.
1713   */
1714  uint8_t* replyBuf = expandBufGetBuffer(pReply);
1715  Set4BE(replyBuf + 4, request.GetId());
1716  Set1(replyBuf + 8, kJDWPFlagReply);
1717  Set2BE(replyBuf + 9, result);
1718  if (result == ERR_NONE) {
1719    Set4BE(replyBuf + 0, expandBufGetLength(pReply));
1720  } else {
1721    Set4BE(replyBuf + 0, kJDWPHeaderLen);
1722  }
1723
1724  CHECK_GT(expandBufGetLength(pReply), 0U) << GetCommandName(request) << " " << request.GetId();
1725
1726  size_t respLen = expandBufGetLength(pReply) - kJDWPHeaderLen;
1727  VLOG(jdwp) << "REPLY: " << GetCommandName(request) << " " << result << " (length=" << respLen << ")";
1728  if (false) {
1729    VLOG(jdwp) << HexDump(expandBufGetBuffer(pReply) + kJDWPHeaderLen, respLen);
1730  }
1731
1732  VLOG(jdwp) << "----------";
1733
1734  /*
1735   * Update last-activity timestamp.  We really only need this during
1736   * the initial setup.  Only update if this is a non-DDMS packet.
1737   */
1738  if (request.GetCommandSet() != kJDWPDdmCmdSet) {
1739    QuasiAtomic::Write64(&last_activity_time_ms_, MilliTime());
1740  }
1741
1742  /* tell the VM that GC is okay again */
1743  self->TransitionFromRunnableToSuspended(old_state);
1744}
1745
1746}  // namespace JDWP
1747
1748}  // namespace art
1749