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