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