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 "scoped_thread_state_change.h"
35#include "thread-inl.h"
36#include "utils.h"
37
38namespace art {
39
40namespace JDWP {
41
42std::string DescribeField(const FieldId& field_id) {
43  return StringPrintf("%#" PRIx64 " (%s)", field_id, Dbg::GetFieldName(field_id).c_str());
44}
45
46std::string DescribeMethod(const MethodId& method_id) {
47  return StringPrintf("%#" PRIx64 " (%s)", method_id, Dbg::GetMethodName(method_id).c_str());
48}
49
50std::string DescribeRefTypeId(const RefTypeId& ref_type_id) {
51  std::string signature("unknown");
52  Dbg::GetSignature(ref_type_id, &signature);
53  return StringPrintf("%#" PRIx64 " (%s)", ref_type_id, signature.c_str());
54}
55
56static JdwpError WriteTaggedObject(ExpandBuf* reply, ObjectId object_id)
57    SHARED_REQUIRES(Locks::mutator_lock_) {
58  uint8_t tag;
59  JdwpError rc = Dbg::GetObjectTag(object_id, &tag);
60  if (rc == ERR_NONE) {
61    expandBufAdd1(reply, tag);
62    expandBufAddObjectId(reply, object_id);
63  }
64  return rc;
65}
66
67static JdwpError WriteTaggedObjectList(ExpandBuf* reply, const std::vector<ObjectId>& objects)
68    SHARED_REQUIRES(Locks::mutator_lock_) {
69  expandBufAdd4BE(reply, objects.size());
70  for (size_t i = 0; i < objects.size(); ++i) {
71    JdwpError rc = WriteTaggedObject(reply, objects[i]);
72    if (rc != ERR_NONE) {
73      return rc;
74    }
75  }
76  return ERR_NONE;
77}
78
79/*
80 * Common code for *_InvokeMethod requests.
81 *
82 * If "is_constructor" is set, this returns "object_id" rather than the
83 * expected-to-be-void return value of the called function.
84 */
85static JdwpError RequestInvoke(JdwpState*, Request* request,
86                               ObjectId thread_id, ObjectId object_id,
87                               RefTypeId class_id, MethodId method_id, bool is_constructor)
88    SHARED_REQUIRES(Locks::mutator_lock_) {
89  CHECK(!is_constructor || object_id != 0);
90
91  int32_t arg_count = request->ReadSigned32("argument count");
92
93  VLOG(jdwp) << StringPrintf("    --> thread_id=%#" PRIx64 " object_id=%#" PRIx64,
94                             thread_id, object_id);
95  VLOG(jdwp) << StringPrintf("        class_id=%#" PRIx64 " method_id=%#" PRIx64 " %s.%s",
96                             class_id, method_id, Dbg::GetClassName(class_id).c_str(),
97                             Dbg::GetMethodName(method_id).c_str());
98  VLOG(jdwp) << StringPrintf("        %d args:", arg_count);
99
100  std::unique_ptr<JdwpTag[]> argTypes(arg_count > 0 ? new JdwpTag[arg_count] : nullptr);
101  std::unique_ptr<uint64_t[]> argValues(arg_count > 0 ? new uint64_t[arg_count] : nullptr);
102  for (int32_t i = 0; i < arg_count; ++i) {
103    argTypes[i] = request->ReadTag();
104    size_t width = Dbg::GetTagWidth(argTypes[i]);
105    argValues[i] = request->ReadValue(width);
106    VLOG(jdwp) << "          " << argTypes[i] << StringPrintf("(%zd): %#" PRIx64, width,
107                                                              argValues[i]);
108  }
109
110  uint32_t options = request->ReadUnsigned32("InvokeOptions bit flags");
111  VLOG(jdwp) << StringPrintf("        options=0x%04x%s%s", options,
112                             (options & INVOKE_SINGLE_THREADED) ? " (SINGLE_THREADED)" : "",
113                             (options & INVOKE_NONVIRTUAL) ? " (NONVIRTUAL)" : "");
114
115  JDWP::JdwpError error =  Dbg::PrepareInvokeMethod(request->GetId(), thread_id, object_id,
116                                                    class_id, method_id, arg_count,
117                                                    argValues.get(), argTypes.get(), options);
118  if (error == JDWP::ERR_NONE) {
119    // We successfully requested the invoke. The event thread now owns the arguments array in its
120    // DebugInvokeReq mailbox.
121    argValues.release();
122  }
123  return error;
124}
125
126static JdwpError VM_Version(JdwpState*, Request*, ExpandBuf* pReply)
127    SHARED_REQUIRES(Locks::mutator_lock_) {
128  // Text information on runtime version.
129  std::string version(StringPrintf("Android Runtime %s", Runtime::Current()->GetVersion()));
130  expandBufAddUtf8String(pReply, version);
131
132  // JDWP version numbers, major and minor.
133  expandBufAdd4BE(pReply, 1);
134  expandBufAdd4BE(pReply, 6);
135
136  // "java.version".
137  expandBufAddUtf8String(pReply, "1.6.0");
138
139  // "java.vm.name".
140  expandBufAddUtf8String(pReply, "Dalvik");
141
142  return ERR_NONE;
143}
144
145/*
146 * Given a class JNI signature (e.g. "Ljava/lang/Error;"), return the
147 * referenceTypeID.  We need to send back more than one if the class has
148 * been loaded by multiple class loaders.
149 */
150static JdwpError VM_ClassesBySignature(JdwpState*, Request* request, ExpandBuf* pReply)
151    SHARED_REQUIRES(Locks::mutator_lock_) {
152  std::string classDescriptor(request->ReadUtf8String());
153
154  std::vector<RefTypeId> ids;
155  Dbg::FindLoadedClassBySignature(classDescriptor.c_str(), &ids);
156
157  expandBufAdd4BE(pReply, ids.size());
158
159  for (size_t i = 0; i < ids.size(); ++i) {
160    // Get class vs. interface and status flags.
161    JDWP::JdwpTypeTag type_tag;
162    uint32_t class_status;
163    JDWP::JdwpError status = Dbg::GetClassInfo(ids[i], &type_tag, &class_status, nullptr);
164    if (status != ERR_NONE) {
165      return status;
166    }
167
168    expandBufAdd1(pReply, type_tag);
169    expandBufAddRefTypeId(pReply, ids[i]);
170    expandBufAdd4BE(pReply, class_status);
171  }
172
173  return ERR_NONE;
174}
175
176/*
177 * Handle request for the thread IDs of all running threads.
178 *
179 * We exclude ourselves from the list, because we don't allow ourselves
180 * to be suspended, and that violates some JDWP expectations.
181 */
182static JdwpError VM_AllThreads(JdwpState*, Request*, ExpandBuf* pReply)
183    SHARED_REQUIRES(Locks::mutator_lock_) {
184  std::vector<ObjectId> thread_ids;
185  Dbg::GetThreads(nullptr /* all thread groups */, &thread_ids);
186
187  expandBufAdd4BE(pReply, thread_ids.size());
188  for (uint32_t i = 0; i < thread_ids.size(); ++i) {
189    expandBufAddObjectId(pReply, thread_ids[i]);
190  }
191
192  return ERR_NONE;
193}
194
195/*
196 * List all thread groups that do not have a parent.
197 */
198static JdwpError VM_TopLevelThreadGroups(JdwpState*, Request*, ExpandBuf* pReply)
199    SHARED_REQUIRES(Locks::mutator_lock_) {
200  /*
201   * TODO: maintain a list of parentless thread groups in the VM.
202   *
203   * For now, just return "system".  Application threads are created
204   * in "main", which is a child of "system".
205   */
206  uint32_t groups = 1;
207  expandBufAdd4BE(pReply, groups);
208  ObjectId thread_group_id = Dbg::GetSystemThreadGroupId();
209  expandBufAddObjectId(pReply, thread_group_id);
210
211  return ERR_NONE;
212}
213
214/*
215 * Respond with the sizes of the basic debugger types.
216 */
217static JdwpError VM_IDSizes(JdwpState*, Request*, ExpandBuf* pReply)
218    SHARED_REQUIRES(Locks::mutator_lock_) {
219  expandBufAdd4BE(pReply, sizeof(FieldId));
220  expandBufAdd4BE(pReply, sizeof(MethodId));
221  expandBufAdd4BE(pReply, sizeof(ObjectId));
222  expandBufAdd4BE(pReply, sizeof(RefTypeId));
223  expandBufAdd4BE(pReply, sizeof(FrameId));
224  return ERR_NONE;
225}
226
227static JdwpError VM_Dispose(JdwpState*, Request*, ExpandBuf*)
228    SHARED_REQUIRES(Locks::mutator_lock_) {
229  Dbg::Dispose();
230  return ERR_NONE;
231}
232
233/*
234 * Suspend the execution of the application running in the VM (i.e. suspend
235 * all threads).
236 *
237 * This needs to increment the "suspend count" on all threads.
238 */
239static JdwpError VM_Suspend(JdwpState*, Request*, ExpandBuf*)
240    SHARED_REQUIRES(Locks::mutator_lock_) {
241  Thread* self = Thread::Current();
242  ScopedThreadSuspension sts(self, kWaitingForDebuggerSuspension);
243  Dbg::SuspendVM();
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_REQUIRES(Locks::mutator_lock_) {
252  Dbg::ResumeVM();
253  return ERR_NONE;
254}
255
256static JdwpError VM_Exit(JdwpState* state, Request* request, ExpandBuf*)
257    SHARED_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(Locks::mutator_lock_) {
385  return VM_AllClassesImpl(pReply, true, false);
386}
387
388static JdwpError VM_AllClassesWithGeneric(JdwpState*, Request*, ExpandBuf* pReply)
389    SHARED_REQUIRES(Locks::mutator_lock_) {
390  return VM_AllClassesImpl(pReply, true, true);
391}
392
393static JdwpError VM_InstanceCounts(JdwpState*, Request* request, ExpandBuf* pReply)
394    SHARED_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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_REQUIRES(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 * Invoke a static method on an interface.
694 */
695static JdwpError IT_InvokeMethod(JdwpState* state, Request* request,
696                                 ExpandBuf* pReply ATTRIBUTE_UNUSED)
697    SHARED_REQUIRES(Locks::mutator_lock_) {
698  RefTypeId class_id = request->ReadRefTypeId();
699  ObjectId thread_id = request->ReadThreadId();
700  MethodId method_id = request->ReadMethodId();
701
702  return RequestInvoke(state, request, thread_id, 0, class_id, method_id, false);
703}
704
705/*
706 * Return line number information for the method, if present.
707 */
708static JdwpError M_LineTable(JdwpState*, Request* request, ExpandBuf* pReply)
709    SHARED_REQUIRES(Locks::mutator_lock_) {
710  RefTypeId refTypeId = request->ReadRefTypeId();
711  MethodId method_id = request->ReadMethodId();
712
713  Dbg::OutputLineTable(refTypeId, method_id, pReply);
714
715  return ERR_NONE;
716}
717
718static JdwpError M_VariableTable(JdwpState*, Request* request, ExpandBuf* pReply,
719                                 bool generic)
720    SHARED_REQUIRES(Locks::mutator_lock_) {
721  RefTypeId class_id = request->ReadRefTypeId();
722  MethodId method_id = request->ReadMethodId();
723
724  // We could return ERR_ABSENT_INFORMATION here if the DEX file was built without local variable
725  // information. That will cause Eclipse to make a best-effort attempt at displaying local
726  // variables anonymously. However, the attempt isn't very good, so we're probably better off just
727  // not showing anything.
728  Dbg::OutputVariableTable(class_id, method_id, generic, pReply);
729  return ERR_NONE;
730}
731
732static JdwpError M_VariableTable(JdwpState* state, Request* request, ExpandBuf* pReply)
733    SHARED_REQUIRES(Locks::mutator_lock_) {
734  return M_VariableTable(state, request, pReply, false);
735}
736
737static JdwpError M_VariableTableWithGeneric(JdwpState* state, Request* request, ExpandBuf* pReply)
738    SHARED_REQUIRES(Locks::mutator_lock_) {
739  return M_VariableTable(state, request, pReply, true);
740}
741
742static JdwpError M_Bytecodes(JdwpState*, Request* request, ExpandBuf* reply)
743    SHARED_REQUIRES(Locks::mutator_lock_) {
744  RefTypeId class_id = request->ReadRefTypeId();
745  MethodId method_id = request->ReadMethodId();
746
747  std::vector<uint8_t> bytecodes;
748  JdwpError rc = Dbg::GetBytecodes(class_id, method_id, &bytecodes);
749  if (rc != ERR_NONE) {
750    return rc;
751  }
752
753  expandBufAdd4BE(reply, bytecodes.size());
754  for (size_t i = 0; i < bytecodes.size(); ++i) {
755    expandBufAdd1(reply, bytecodes[i]);
756  }
757
758  return ERR_NONE;
759}
760
761// Default implementation for IDEs relying on this command.
762static JdwpError M_IsObsolete(JdwpState*, Request* request, ExpandBuf* reply)
763    SHARED_REQUIRES(Locks::mutator_lock_) {
764  request->ReadRefTypeId();  // unused reference type ID
765  request->ReadMethodId();   // unused method ID
766  expandBufAdd1(reply, false);  // a method is never obsolete.
767  return ERR_NONE;
768}
769
770/*
771 * Given an object reference, return the runtime type of the object
772 * (class or array).
773 *
774 * This can get called on different things, e.g. thread_id gets
775 * passed in here.
776 */
777static JdwpError OR_ReferenceType(JdwpState*, Request* request, ExpandBuf* pReply)
778    SHARED_REQUIRES(Locks::mutator_lock_) {
779  ObjectId object_id = request->ReadObjectId();
780  return Dbg::GetReferenceType(object_id, pReply);
781}
782
783/*
784 * Get values from the fields of an object.
785 */
786static JdwpError OR_GetValues(JdwpState*, Request* request, ExpandBuf* pReply)
787    SHARED_REQUIRES(Locks::mutator_lock_) {
788  ObjectId object_id = request->ReadObjectId();
789  int32_t field_count = request->ReadSigned32("field count");
790
791  expandBufAdd4BE(pReply, field_count);
792  for (int32_t i = 0; i < field_count; ++i) {
793    FieldId fieldId = request->ReadFieldId();
794    JdwpError status = Dbg::GetFieldValue(object_id, fieldId, pReply);
795    if (status != ERR_NONE) {
796      return status;
797    }
798  }
799
800  return ERR_NONE;
801}
802
803/*
804 * Set values in the fields of an object.
805 */
806static JdwpError OR_SetValues(JdwpState*, Request* request, ExpandBuf*)
807    SHARED_REQUIRES(Locks::mutator_lock_) {
808  ObjectId object_id = request->ReadObjectId();
809  int32_t field_count = request->ReadSigned32("field count");
810
811  for (int32_t i = 0; i < field_count; ++i) {
812    FieldId fieldId = request->ReadFieldId();
813
814    JDWP::JdwpTag fieldTag = Dbg::GetFieldBasicTag(fieldId);
815    size_t width = Dbg::GetTagWidth(fieldTag);
816    uint64_t value = request->ReadValue(width);
817
818    VLOG(jdwp) << "    --> fieldId=" << fieldId << " tag=" << fieldTag << "(" << width << ") value=" << value;
819    JdwpError status = Dbg::SetFieldValue(object_id, fieldId, value, width);
820    if (status != ERR_NONE) {
821      return status;
822    }
823  }
824
825  return ERR_NONE;
826}
827
828static JdwpError OR_MonitorInfo(JdwpState*, Request* request, ExpandBuf* reply)
829    SHARED_REQUIRES(Locks::mutator_lock_) {
830  ObjectId object_id = request->ReadObjectId();
831  return Dbg::GetMonitorInfo(object_id, reply);
832}
833
834/*
835 * Invoke an instance method.  The invocation must occur in the specified
836 * thread, which must have been suspended by an event.
837 *
838 * The call is synchronous.  All threads in the VM are resumed, unless the
839 * SINGLE_THREADED flag is set.
840 *
841 * If you ask Eclipse to "inspect" an object (or ask JDB to "print" an
842 * object), it will try to invoke the object's toString() function.  This
843 * feature becomes crucial when examining ArrayLists with Eclipse.
844 */
845static JdwpError OR_InvokeMethod(JdwpState* state, Request* request,
846                                 ExpandBuf* pReply ATTRIBUTE_UNUSED)
847    SHARED_REQUIRES(Locks::mutator_lock_) {
848  ObjectId object_id = request->ReadObjectId();
849  ObjectId thread_id = request->ReadThreadId();
850  RefTypeId class_id = request->ReadRefTypeId();
851  MethodId method_id = request->ReadMethodId();
852
853  return RequestInvoke(state, request, thread_id, object_id, class_id, method_id, false);
854}
855
856static JdwpError OR_DisableCollection(JdwpState*, Request* request, ExpandBuf*)
857    SHARED_REQUIRES(Locks::mutator_lock_) {
858  ObjectId object_id = request->ReadObjectId();
859  return Dbg::DisableCollection(object_id);
860}
861
862static JdwpError OR_EnableCollection(JdwpState*, Request* request, ExpandBuf*)
863    SHARED_REQUIRES(Locks::mutator_lock_) {
864  ObjectId object_id = request->ReadObjectId();
865  return Dbg::EnableCollection(object_id);
866}
867
868static JdwpError OR_IsCollected(JdwpState*, Request* request, ExpandBuf* pReply)
869    SHARED_REQUIRES(Locks::mutator_lock_) {
870  ObjectId object_id = request->ReadObjectId();
871  bool is_collected;
872  JdwpError rc = Dbg::IsCollected(object_id, &is_collected);
873  expandBufAdd1(pReply, is_collected ? 1 : 0);
874  return rc;
875}
876
877static JdwpError OR_ReferringObjects(JdwpState*, Request* request, ExpandBuf* reply)
878    SHARED_REQUIRES(Locks::mutator_lock_) {
879  ObjectId object_id = request->ReadObjectId();
880  int32_t max_count = request->ReadSigned32("max count");
881  if (max_count < 0) {
882    return ERR_ILLEGAL_ARGUMENT;
883  }
884
885  std::vector<ObjectId> referring_objects;
886  JdwpError rc = Dbg::GetReferringObjects(object_id, max_count, &referring_objects);
887  if (rc != ERR_NONE) {
888    return rc;
889  }
890
891  return WriteTaggedObjectList(reply, referring_objects);
892}
893
894/*
895 * Return the string value in a string object.
896 */
897static JdwpError SR_Value(JdwpState*, Request* request, ExpandBuf* pReply)
898    SHARED_REQUIRES(Locks::mutator_lock_) {
899  ObjectId stringObject = request->ReadObjectId();
900  std::string str;
901  JDWP::JdwpError error = Dbg::StringToUtf8(stringObject, &str);
902  if (error != JDWP::ERR_NONE) {
903    return error;
904  }
905
906  VLOG(jdwp) << StringPrintf("    --> %s", PrintableString(str.c_str()).c_str());
907
908  expandBufAddUtf8String(pReply, str);
909
910  return ERR_NONE;
911}
912
913/*
914 * Return a thread's name.
915 */
916static JdwpError TR_Name(JdwpState*, Request* request, ExpandBuf* pReply)
917    SHARED_REQUIRES(Locks::mutator_lock_) {
918  ObjectId thread_id = request->ReadThreadId();
919
920  std::string name;
921  JdwpError error = Dbg::GetThreadName(thread_id, &name);
922  if (error != ERR_NONE) {
923    return error;
924  }
925  VLOG(jdwp) << StringPrintf("  Name of thread %#" PRIx64 " is \"%s\"", thread_id, name.c_str());
926  expandBufAddUtf8String(pReply, name);
927
928  return ERR_NONE;
929}
930
931/*
932 * Suspend the specified thread.
933 *
934 * It's supposed to remain suspended even if interpreted code wants to
935 * resume it; only the JDI is allowed to resume it.
936 */
937static JdwpError TR_Suspend(JdwpState*, Request* request, ExpandBuf*)
938    SHARED_REQUIRES(Locks::mutator_lock_) {
939  ObjectId thread_id = request->ReadThreadId();
940
941  if (thread_id == Dbg::GetThreadSelfId()) {
942    LOG(INFO) << "  Warning: ignoring request to suspend self";
943    return ERR_THREAD_NOT_SUSPENDED;
944  }
945
946  Thread* self = Thread::Current();
947  ScopedThreadSuspension sts(self, kWaitingForDebuggerSend);
948  JdwpError result = Dbg::SuspendThread(thread_id);
949  return result;
950}
951
952/*
953 * Resume the specified thread.
954 */
955static JdwpError TR_Resume(JdwpState*, Request* request, ExpandBuf*)
956    SHARED_REQUIRES(Locks::mutator_lock_) {
957  ObjectId thread_id = request->ReadThreadId();
958
959  if (thread_id == Dbg::GetThreadSelfId()) {
960    LOG(INFO) << "  Warning: ignoring request to resume self";
961    return ERR_NONE;
962  }
963
964  Dbg::ResumeThread(thread_id);
965  return ERR_NONE;
966}
967
968/*
969 * Return status of specified thread.
970 */
971static JdwpError TR_Status(JdwpState*, Request* request, ExpandBuf* pReply)
972    SHARED_REQUIRES(Locks::mutator_lock_) {
973  ObjectId thread_id = request->ReadThreadId();
974
975  JDWP::JdwpThreadStatus threadStatus;
976  JDWP::JdwpSuspendStatus suspendStatus;
977  JdwpError error = Dbg::GetThreadStatus(thread_id, &threadStatus, &suspendStatus);
978  if (error != ERR_NONE) {
979    return error;
980  }
981
982  VLOG(jdwp) << "    --> " << threadStatus << ", " << suspendStatus;
983
984  expandBufAdd4BE(pReply, threadStatus);
985  expandBufAdd4BE(pReply, suspendStatus);
986
987  return ERR_NONE;
988}
989
990/*
991 * Return the thread group that the specified thread is a member of.
992 */
993static JdwpError TR_ThreadGroup(JdwpState*, Request* request, ExpandBuf* pReply)
994    SHARED_REQUIRES(Locks::mutator_lock_) {
995  ObjectId thread_id = request->ReadThreadId();
996  return Dbg::GetThreadGroup(thread_id, pReply);
997}
998
999/*
1000 * Return the current call stack of a suspended thread.
1001 *
1002 * If the thread isn't suspended, the error code isn't defined, but should
1003 * be THREAD_NOT_SUSPENDED.
1004 */
1005static JdwpError TR_Frames(JdwpState*, Request* request, ExpandBuf* pReply)
1006    SHARED_REQUIRES(Locks::mutator_lock_) {
1007  ObjectId thread_id = request->ReadThreadId();
1008  uint32_t start_frame = request->ReadUnsigned32("start frame");
1009  uint32_t length = request->ReadUnsigned32("length");
1010
1011  size_t actual_frame_count;
1012  JdwpError error = Dbg::GetThreadFrameCount(thread_id, &actual_frame_count);
1013  if (error != ERR_NONE) {
1014    return error;
1015  }
1016
1017  if (actual_frame_count <= 0) {
1018    return ERR_THREAD_NOT_SUSPENDED;  // 0 means no managed frames (which means "in native").
1019  }
1020
1021  if (start_frame > actual_frame_count) {
1022    return ERR_INVALID_INDEX;
1023  }
1024  if (length == static_cast<uint32_t>(-1)) {
1025    length = actual_frame_count - start_frame;
1026  }
1027  if (start_frame + length > actual_frame_count) {
1028    return ERR_INVALID_LENGTH;
1029  }
1030
1031  return Dbg::GetThreadFrames(thread_id, start_frame, length, pReply);
1032}
1033
1034/*
1035 * Returns the #of frames on the specified thread, which must be suspended.
1036 */
1037static JdwpError TR_FrameCount(JdwpState*, Request* request, ExpandBuf* pReply)
1038    SHARED_REQUIRES(Locks::mutator_lock_) {
1039  ObjectId thread_id = request->ReadThreadId();
1040
1041  size_t frame_count;
1042  JdwpError rc = Dbg::GetThreadFrameCount(thread_id, &frame_count);
1043  if (rc != ERR_NONE) {
1044    return rc;
1045  }
1046  expandBufAdd4BE(pReply, static_cast<uint32_t>(frame_count));
1047
1048  return ERR_NONE;
1049}
1050
1051static JdwpError TR_OwnedMonitors(Request* request, ExpandBuf* reply, bool with_stack_depths)
1052    SHARED_REQUIRES(Locks::mutator_lock_) {
1053  ObjectId thread_id = request->ReadThreadId();
1054
1055  std::vector<ObjectId> monitors;
1056  std::vector<uint32_t> stack_depths;
1057  JdwpError rc = Dbg::GetOwnedMonitors(thread_id, &monitors, &stack_depths);
1058  if (rc != ERR_NONE) {
1059    return rc;
1060  }
1061
1062  expandBufAdd4BE(reply, monitors.size());
1063  for (size_t i = 0; i < monitors.size(); ++i) {
1064    rc = WriteTaggedObject(reply, monitors[i]);
1065    if (rc != ERR_NONE) {
1066      return rc;
1067    }
1068    if (with_stack_depths) {
1069      expandBufAdd4BE(reply, stack_depths[i]);
1070    }
1071  }
1072  return ERR_NONE;
1073}
1074
1075static JdwpError TR_OwnedMonitors(JdwpState*, Request* request, ExpandBuf* reply)
1076    SHARED_REQUIRES(Locks::mutator_lock_) {
1077  return TR_OwnedMonitors(request, reply, false);
1078}
1079
1080static JdwpError TR_OwnedMonitorsStackDepthInfo(JdwpState*, Request* request, ExpandBuf* reply)
1081    SHARED_REQUIRES(Locks::mutator_lock_) {
1082  return TR_OwnedMonitors(request, reply, true);
1083}
1084
1085static JdwpError TR_CurrentContendedMonitor(JdwpState*, Request* request, ExpandBuf* reply)
1086    SHARED_REQUIRES(Locks::mutator_lock_) {
1087  ObjectId thread_id = request->ReadThreadId();
1088
1089  ObjectId contended_monitor;
1090  JdwpError rc = Dbg::GetContendedMonitor(thread_id, &contended_monitor);
1091  if (rc != ERR_NONE) {
1092    return rc;
1093  }
1094  return WriteTaggedObject(reply, contended_monitor);
1095}
1096
1097static JdwpError TR_Interrupt(JdwpState*, Request* request, ExpandBuf* reply ATTRIBUTE_UNUSED)
1098    SHARED_REQUIRES(Locks::mutator_lock_) {
1099  ObjectId thread_id = request->ReadThreadId();
1100  return Dbg::Interrupt(thread_id);
1101}
1102
1103/*
1104 * Return the debug suspend count for the specified thread.
1105 *
1106 * (The thread *might* still be running -- it might not have examined
1107 * its suspend count recently.)
1108 */
1109static JdwpError TR_DebugSuspendCount(JdwpState*, Request* request, ExpandBuf* pReply)
1110    SHARED_REQUIRES(Locks::mutator_lock_) {
1111  ObjectId thread_id = request->ReadThreadId();
1112  return Dbg::GetThreadDebugSuspendCount(thread_id, pReply);
1113}
1114
1115/*
1116 * Return the name of a thread group.
1117 *
1118 * The Eclipse debugger recognizes "main" and "system" as special.
1119 */
1120static JdwpError TGR_Name(JdwpState*, Request* request, ExpandBuf* pReply)
1121    SHARED_REQUIRES(Locks::mutator_lock_) {
1122  ObjectId thread_group_id = request->ReadThreadGroupId();
1123  return Dbg::GetThreadGroupName(thread_group_id, pReply);
1124}
1125
1126/*
1127 * Returns the thread group -- if any -- that contains the specified
1128 * thread group.
1129 */
1130static JdwpError TGR_Parent(JdwpState*, Request* request, ExpandBuf* pReply)
1131    SHARED_REQUIRES(Locks::mutator_lock_) {
1132  ObjectId thread_group_id = request->ReadThreadGroupId();
1133  return Dbg::GetThreadGroupParent(thread_group_id, pReply);
1134}
1135
1136/*
1137 * Return the active threads and thread groups that are part of the
1138 * specified thread group.
1139 */
1140static JdwpError TGR_Children(JdwpState*, Request* request, ExpandBuf* pReply)
1141    SHARED_REQUIRES(Locks::mutator_lock_) {
1142  ObjectId thread_group_id = request->ReadThreadGroupId();
1143  return Dbg::GetThreadGroupChildren(thread_group_id, pReply);
1144}
1145
1146/*
1147 * Return the #of components in the array.
1148 */
1149static JdwpError AR_Length(JdwpState*, Request* request, ExpandBuf* pReply)
1150    SHARED_REQUIRES(Locks::mutator_lock_) {
1151  ObjectId array_id = request->ReadArrayId();
1152
1153  int32_t length;
1154  JdwpError status = Dbg::GetArrayLength(array_id, &length);
1155  if (status != ERR_NONE) {
1156    return status;
1157  }
1158  VLOG(jdwp) << "    --> " << length;
1159
1160  expandBufAdd4BE(pReply, length);
1161
1162  return ERR_NONE;
1163}
1164
1165/*
1166 * Return the values from an array.
1167 */
1168static JdwpError AR_GetValues(JdwpState*, Request* request, ExpandBuf* pReply)
1169    SHARED_REQUIRES(Locks::mutator_lock_) {
1170  ObjectId array_id = request->ReadArrayId();
1171  uint32_t offset = request->ReadUnsigned32("offset");
1172  uint32_t length = request->ReadUnsigned32("length");
1173  return Dbg::OutputArray(array_id, offset, length, pReply);
1174}
1175
1176/*
1177 * Set values in an array.
1178 */
1179static JdwpError AR_SetValues(JdwpState*, Request* request, ExpandBuf*)
1180    SHARED_REQUIRES(Locks::mutator_lock_) {
1181  ObjectId array_id = request->ReadArrayId();
1182  uint32_t offset = request->ReadUnsigned32("offset");
1183  uint32_t count = request->ReadUnsigned32("count");
1184  return Dbg::SetArrayElements(array_id, offset, count, request);
1185}
1186
1187static JdwpError CLR_VisibleClasses(JdwpState*, Request* request, ExpandBuf* pReply)
1188    SHARED_REQUIRES(Locks::mutator_lock_) {
1189  request->ReadObjectId();  // classLoaderObject
1190  // TODO: we should only return classes which have the given class loader as a defining or
1191  // initiating loader. The former would be easy; the latter is hard, because we don't have
1192  // any such notion.
1193  return VM_AllClassesImpl(pReply, false, false);
1194}
1195
1196// Delete function class to use std::unique_ptr with JdwpEvent.
1197struct JdwpEventDeleter {
1198  void operator()(JdwpEvent* event) {
1199    EventFree(event);
1200  }
1201};
1202
1203/*
1204 * Set an event trigger.
1205 *
1206 * Reply with a requestID.
1207 */
1208static JdwpError ER_Set(JdwpState* state, Request* request, ExpandBuf* pReply)
1209    SHARED_REQUIRES(Locks::mutator_lock_) {
1210  JdwpEventKind event_kind = request->ReadEnum1<JdwpEventKind>("event kind");
1211  JdwpSuspendPolicy suspend_policy = request->ReadEnum1<JdwpSuspendPolicy>("suspend policy");
1212  int32_t modifier_count = request->ReadSigned32("modifier count");
1213
1214  CHECK_LT(modifier_count, 256);    /* reasonableness check */
1215
1216  std::unique_ptr<JDWP::JdwpEvent, JdwpEventDeleter> pEvent(EventAlloc(modifier_count));
1217  pEvent->eventKind = event_kind;
1218  pEvent->suspend_policy = suspend_policy;
1219  pEvent->modCount = modifier_count;
1220
1221  /*
1222   * Read modifiers.  Ordering may be significant (see explanation of Count
1223   * mods in JDWP doc).
1224   */
1225  for (int32_t i = 0; i < modifier_count; ++i) {
1226    JdwpEventMod& mod = pEvent->mods[i];
1227    mod.modKind = request->ReadModKind();
1228    switch (mod.modKind) {
1229    case MK_COUNT:
1230      {
1231        // Report once, when "--count" reaches 0.
1232        uint32_t count = request->ReadUnsigned32("count");
1233        if (count == 0) {
1234          return ERR_INVALID_COUNT;
1235        }
1236        mod.count.count = count;
1237      }
1238      break;
1239    case MK_CONDITIONAL:
1240      {
1241        // Conditional on expression.
1242        uint32_t exprId = request->ReadUnsigned32("expr id");
1243        mod.conditional.exprId = exprId;
1244      }
1245      break;
1246    case MK_THREAD_ONLY:
1247      {
1248        // Only report events in specified thread.
1249        ObjectId thread_id = request->ReadThreadId();
1250        mod.threadOnly.threadId = thread_id;
1251      }
1252      break;
1253    case MK_CLASS_ONLY:
1254      {
1255        // For ClassPrepare, MethodEntry.
1256        RefTypeId class_id = request->ReadRefTypeId();
1257        mod.classOnly.refTypeId = class_id;
1258      }
1259      break;
1260    case MK_CLASS_MATCH:
1261      {
1262        // Restrict events to matching classes.
1263        // pattern is "java.foo.*", we want "java/foo/*".
1264        std::string pattern(request->ReadUtf8String());
1265        std::replace(pattern.begin(), pattern.end(), '.', '/');
1266        mod.classMatch.classPattern = strdup(pattern.c_str());
1267      }
1268      break;
1269    case MK_CLASS_EXCLUDE:
1270      {
1271        // Restrict events to non-matching classes.
1272        // pattern is "java.foo.*", we want "java/foo/*".
1273        std::string pattern(request->ReadUtf8String());
1274        std::replace(pattern.begin(), pattern.end(), '.', '/');
1275        mod.classExclude.classPattern = strdup(pattern.c_str());
1276      }
1277      break;
1278    case MK_LOCATION_ONLY:
1279      {
1280        // Restrict certain events based on location.
1281        JdwpLocation location = request->ReadLocation();
1282        mod.locationOnly.loc = location;
1283      }
1284      break;
1285    case MK_EXCEPTION_ONLY:
1286      {
1287        // Modifies EK_EXCEPTION events,
1288        mod.exceptionOnly.refTypeId = request->ReadRefTypeId();  // null => all exceptions.
1289        mod.exceptionOnly.caught = request->ReadEnum1<uint8_t>("caught");
1290        mod.exceptionOnly.uncaught = request->ReadEnum1<uint8_t>("uncaught");
1291      }
1292      break;
1293    case MK_FIELD_ONLY:
1294      {
1295        // For field access/modification events.
1296        RefTypeId declaring = request->ReadRefTypeId();
1297        FieldId fieldId = request->ReadFieldId();
1298        mod.fieldOnly.refTypeId = declaring;
1299        mod.fieldOnly.fieldId = fieldId;
1300      }
1301      break;
1302    case MK_STEP:
1303      {
1304        // For use with EK_SINGLE_STEP.
1305        ObjectId thread_id = request->ReadThreadId();
1306        uint32_t size = request->ReadUnsigned32("step size");
1307        uint32_t depth = request->ReadUnsigned32("step depth");
1308        VLOG(jdwp) << StringPrintf("    Step: thread=%#" PRIx64, thread_id)
1309                     << " size=" << JdwpStepSize(size) << " depth=" << JdwpStepDepth(depth);
1310
1311        mod.step.threadId = thread_id;
1312        mod.step.size = size;
1313        mod.step.depth = depth;
1314      }
1315      break;
1316    case MK_INSTANCE_ONLY:
1317      {
1318        // Report events related to a specific object.
1319        ObjectId instance = request->ReadObjectId();
1320        mod.instanceOnly.objectId = instance;
1321      }
1322      break;
1323    default:
1324      LOG(WARNING) << "Unsupported modifier " << mod.modKind << " for event " << pEvent->eventKind;
1325      return JDWP::ERR_NOT_IMPLEMENTED;
1326    }
1327  }
1328
1329  /*
1330   * We reply with an integer "requestID".
1331   */
1332  uint32_t requestId = state->NextEventSerial();
1333  expandBufAdd4BE(pReply, requestId);
1334
1335  pEvent->requestId = requestId;
1336
1337  VLOG(jdwp) << StringPrintf("    --> event requestId=%#x", requestId);
1338
1339  /* add it to the list */
1340  JdwpError err = state->RegisterEvent(pEvent.get());
1341  if (err != ERR_NONE) {
1342    /* registration failed, probably because event is bogus */
1343    LOG(WARNING) << "WARNING: event request rejected";
1344    return err;
1345  }
1346  pEvent.release();
1347  return ERR_NONE;
1348}
1349
1350static JdwpError ER_Clear(JdwpState* state, Request* request, ExpandBuf*)
1351    SHARED_REQUIRES(Locks::mutator_lock_) {
1352  request->ReadEnum1<JdwpEventKind>("event kind");
1353  uint32_t requestId = request->ReadUnsigned32("request id");
1354
1355  // Failure to find an event with a matching ID is a no-op
1356  // and does not return an error.
1357  state->UnregisterEventById(requestId);
1358  return ERR_NONE;
1359}
1360
1361/*
1362 * Return the values of arguments and local variables.
1363 */
1364static JdwpError SF_GetValues(JdwpState*, Request* request, ExpandBuf* pReply)
1365    SHARED_REQUIRES(Locks::mutator_lock_) {
1366  return Dbg::GetLocalValues(request, pReply);
1367}
1368
1369/*
1370 * Set the values of arguments and local variables.
1371 */
1372static JdwpError SF_SetValues(JdwpState*, Request* request, ExpandBuf*)
1373    SHARED_REQUIRES(Locks::mutator_lock_) {
1374  return Dbg::SetLocalValues(request);
1375}
1376
1377static JdwpError SF_ThisObject(JdwpState*, Request* request, ExpandBuf* reply)
1378    SHARED_REQUIRES(Locks::mutator_lock_) {
1379  ObjectId thread_id = request->ReadThreadId();
1380  FrameId frame_id = request->ReadFrameId();
1381
1382  ObjectId object_id;
1383  JdwpError rc = Dbg::GetThisObject(thread_id, frame_id, &object_id);
1384  if (rc != ERR_NONE) {
1385    return rc;
1386  }
1387
1388  return WriteTaggedObject(reply, object_id);
1389}
1390
1391/*
1392 * Return the reference type reflected by this class object.
1393 *
1394 * This appears to be required because ReferenceTypeId values are NEVER
1395 * reused, whereas ClassIds can be recycled like any other object.  (Either
1396 * that, or I have no idea what this is for.)
1397 */
1398static JdwpError COR_ReflectedType(JdwpState*, Request* request, ExpandBuf* pReply)
1399    SHARED_REQUIRES(Locks::mutator_lock_) {
1400  RefTypeId class_object_id = request->ReadRefTypeId();
1401  return Dbg::GetReflectedType(class_object_id, pReply);
1402}
1403
1404/*
1405 * Handle a DDM packet with a single chunk in it.
1406 */
1407static JdwpError DDM_Chunk(JdwpState* state, Request* request, ExpandBuf* pReply)
1408    SHARED_REQUIRES(Locks::mutator_lock_) {
1409  state->NotifyDdmsActive();
1410  uint8_t* replyBuf = nullptr;
1411  int replyLen = -1;
1412  if (Dbg::DdmHandlePacket(request, &replyBuf, &replyLen)) {
1413    // If they want to send something back, we copy it into the buffer.
1414    // TODO: consider altering the JDWP stuff to hold the packet header
1415    // in a separate buffer.  That would allow us to writev() DDM traffic
1416    // instead of copying it into the expanding buffer.  The reduction in
1417    // heap requirements is probably more valuable than the efficiency.
1418    CHECK_GT(replyLen, 0);
1419    memcpy(expandBufAddSpace(pReply, replyLen), replyBuf, replyLen);
1420    delete[] replyBuf;
1421  }
1422  return ERR_NONE;
1423}
1424
1425/*
1426 * Handler map decl.
1427 */
1428typedef JdwpError (*JdwpRequestHandler)(JdwpState* state, Request* request, ExpandBuf* reply);
1429
1430struct JdwpHandlerMap {
1431  uint8_t cmdSet;
1432  uint8_t cmd;
1433  JdwpRequestHandler func;
1434  const char* name;
1435};
1436
1437/*
1438 * Map commands to functions.
1439 *
1440 * Command sets 0-63 are incoming requests, 64-127 are outbound requests,
1441 * and 128-256 are vendor-defined.
1442 */
1443static const JdwpHandlerMap gHandlers[] = {
1444  /* VirtualMachine command set (1) */
1445  { 1,    1,  VM_Version,               "VirtualMachine.Version" },
1446  { 1,    2,  VM_ClassesBySignature,    "VirtualMachine.ClassesBySignature" },
1447  { 1,    3,  VM_AllClasses,            "VirtualMachine.AllClasses" },
1448  { 1,    4,  VM_AllThreads,            "VirtualMachine.AllThreads" },
1449  { 1,    5,  VM_TopLevelThreadGroups,  "VirtualMachine.TopLevelThreadGroups" },
1450  { 1,    6,  VM_Dispose,               "VirtualMachine.Dispose" },
1451  { 1,    7,  VM_IDSizes,               "VirtualMachine.IDSizes" },
1452  { 1,    8,  VM_Suspend,               "VirtualMachine.Suspend" },
1453  { 1,    9,  VM_Resume,                "VirtualMachine.Resume" },
1454  { 1,    10, VM_Exit,                  "VirtualMachine.Exit" },
1455  { 1,    11, VM_CreateString,          "VirtualMachine.CreateString" },
1456  { 1,    12, VM_Capabilities,          "VirtualMachine.Capabilities" },
1457  { 1,    13, VM_ClassPaths,            "VirtualMachine.ClassPaths" },
1458  { 1,    14, VM_DisposeObjects,        "VirtualMachine.DisposeObjects" },
1459  { 1,    15, nullptr,                  "VirtualMachine.HoldEvents" },
1460  { 1,    16, nullptr,                  "VirtualMachine.ReleaseEvents" },
1461  { 1,    17, VM_CapabilitiesNew,       "VirtualMachine.CapabilitiesNew" },
1462  { 1,    18, nullptr,                  "VirtualMachine.RedefineClasses" },
1463  { 1,    19, nullptr,                  "VirtualMachine.SetDefaultStratum" },
1464  { 1,    20, VM_AllClassesWithGeneric, "VirtualMachine.AllClassesWithGeneric" },
1465  { 1,    21, VM_InstanceCounts,        "VirtualMachine.InstanceCounts" },
1466
1467  /* ReferenceType command set (2) */
1468  { 2,    1,  RT_Signature,            "ReferenceType.Signature" },
1469  { 2,    2,  RT_ClassLoader,          "ReferenceType.ClassLoader" },
1470  { 2,    3,  RT_Modifiers,            "ReferenceType.Modifiers" },
1471  { 2,    4,  RT_Fields,               "ReferenceType.Fields" },
1472  { 2,    5,  RT_Methods,              "ReferenceType.Methods" },
1473  { 2,    6,  RT_GetValues,            "ReferenceType.GetValues" },
1474  { 2,    7,  RT_SourceFile,           "ReferenceType.SourceFile" },
1475  { 2,    8,  nullptr,                 "ReferenceType.NestedTypes" },
1476  { 2,    9,  RT_Status,               "ReferenceType.Status" },
1477  { 2,    10, RT_Interfaces,           "ReferenceType.Interfaces" },
1478  { 2,    11, RT_ClassObject,          "ReferenceType.ClassObject" },
1479  { 2,    12, RT_SourceDebugExtension, "ReferenceType.SourceDebugExtension" },
1480  { 2,    13, RT_SignatureWithGeneric, "ReferenceType.SignatureWithGeneric" },
1481  { 2,    14, RT_FieldsWithGeneric,    "ReferenceType.FieldsWithGeneric" },
1482  { 2,    15, RT_MethodsWithGeneric,   "ReferenceType.MethodsWithGeneric" },
1483  { 2,    16, RT_Instances,            "ReferenceType.Instances" },
1484  { 2,    17, nullptr,                 "ReferenceType.ClassFileVersion" },
1485  { 2,    18, nullptr,                 "ReferenceType.ConstantPool" },
1486
1487  /* ClassType command set (3) */
1488  { 3,    1,  CT_Superclass,    "ClassType.Superclass" },
1489  { 3,    2,  CT_SetValues,     "ClassType.SetValues" },
1490  { 3,    3,  CT_InvokeMethod,  "ClassType.InvokeMethod" },
1491  { 3,    4,  CT_NewInstance,   "ClassType.NewInstance" },
1492
1493  /* ArrayType command set (4) */
1494  { 4,    1,  AT_newInstance,   "ArrayType.NewInstance" },
1495
1496  /* InterfaceType command set (5) */
1497  { 5,    1, IT_InvokeMethod,  "InterfaceType.InvokeMethod" },
1498
1499  /* Method command set (6) */
1500  { 6,    1,  M_LineTable,                "Method.LineTable" },
1501  { 6,    2,  M_VariableTable,            "Method.VariableTable" },
1502  { 6,    3,  M_Bytecodes,                "Method.Bytecodes" },
1503  { 6,    4,  M_IsObsolete,               "Method.IsObsolete" },
1504  { 6,    5,  M_VariableTableWithGeneric, "Method.VariableTableWithGeneric" },
1505
1506  /* Field command set (8) */
1507
1508  /* ObjectReference command set (9) */
1509  { 9,    1,  OR_ReferenceType,     "ObjectReference.ReferenceType" },
1510  { 9,    2,  OR_GetValues,         "ObjectReference.GetValues" },
1511  { 9,    3,  OR_SetValues,         "ObjectReference.SetValues" },
1512  { 9,    4,  nullptr,              "ObjectReference.UNUSED" },
1513  { 9,    5,  OR_MonitorInfo,       "ObjectReference.MonitorInfo" },
1514  { 9,    6,  OR_InvokeMethod,      "ObjectReference.InvokeMethod" },
1515  { 9,    7,  OR_DisableCollection, "ObjectReference.DisableCollection" },
1516  { 9,    8,  OR_EnableCollection,  "ObjectReference.EnableCollection" },
1517  { 9,    9,  OR_IsCollected,       "ObjectReference.IsCollected" },
1518  { 9,    10, OR_ReferringObjects,  "ObjectReference.ReferringObjects" },
1519
1520  /* StringReference command set (10) */
1521  { 10,   1,  SR_Value,         "StringReference.Value" },
1522
1523  /* ThreadReference command set (11) */
1524  { 11,   1,  TR_Name,                        "ThreadReference.Name" },
1525  { 11,   2,  TR_Suspend,                     "ThreadReference.Suspend" },
1526  { 11,   3,  TR_Resume,                      "ThreadReference.Resume" },
1527  { 11,   4,  TR_Status,                      "ThreadReference.Status" },
1528  { 11,   5,  TR_ThreadGroup,                 "ThreadReference.ThreadGroup" },
1529  { 11,   6,  TR_Frames,                      "ThreadReference.Frames" },
1530  { 11,   7,  TR_FrameCount,                  "ThreadReference.FrameCount" },
1531  { 11,   8,  TR_OwnedMonitors,               "ThreadReference.OwnedMonitors" },
1532  { 11,   9,  TR_CurrentContendedMonitor,     "ThreadReference.CurrentContendedMonitor" },
1533  { 11,   10, nullptr,                        "ThreadReference.Stop" },
1534  { 11,   11, TR_Interrupt,                   "ThreadReference.Interrupt" },
1535  { 11,   12, TR_DebugSuspendCount,           "ThreadReference.SuspendCount" },
1536  { 11,   13, TR_OwnedMonitorsStackDepthInfo, "ThreadReference.OwnedMonitorsStackDepthInfo" },
1537  { 11,   14, nullptr,                        "ThreadReference.ForceEarlyReturn" },
1538
1539  /* ThreadGroupReference command set (12) */
1540  { 12,   1,  TGR_Name,         "ThreadGroupReference.Name" },
1541  { 12,   2,  TGR_Parent,       "ThreadGroupReference.Parent" },
1542  { 12,   3,  TGR_Children,     "ThreadGroupReference.Children" },
1543
1544  /* ArrayReference command set (13) */
1545  { 13,   1,  AR_Length,        "ArrayReference.Length" },
1546  { 13,   2,  AR_GetValues,     "ArrayReference.GetValues" },
1547  { 13,   3,  AR_SetValues,     "ArrayReference.SetValues" },
1548
1549  /* ClassLoaderReference command set (14) */
1550  { 14,   1,  CLR_VisibleClasses, "ClassLoaderReference.VisibleClasses" },
1551
1552  /* EventRequest command set (15) */
1553  { 15,   1,  ER_Set,           "EventRequest.Set" },
1554  { 15,   2,  ER_Clear,         "EventRequest.Clear" },
1555  { 15,   3,  nullptr,          "EventRequest.ClearAllBreakpoints" },
1556
1557  /* StackFrame command set (16) */
1558  { 16,   1,  SF_GetValues,     "StackFrame.GetValues" },
1559  { 16,   2,  SF_SetValues,     "StackFrame.SetValues" },
1560  { 16,   3,  SF_ThisObject,    "StackFrame.ThisObject" },
1561  { 16,   4,  nullptr,          "StackFrame.PopFrames" },
1562
1563  /* ClassObjectReference command set (17) */
1564  { 17,   1,  COR_ReflectedType, "ClassObjectReference.ReflectedType" },
1565
1566  /* Event command set (64) */
1567  { 64, 100,  nullptr, "Event.Composite" },  // sent from VM to debugger, never received by VM
1568
1569  { 199,  1,  DDM_Chunk,        "DDM.Chunk" },
1570};
1571
1572static const char* GetCommandName(Request* request) {
1573  for (size_t i = 0; i < arraysize(gHandlers); ++i) {
1574    if (gHandlers[i].cmdSet == request->GetCommandSet() &&
1575        gHandlers[i].cmd == request->GetCommand()) {
1576      return gHandlers[i].name;
1577    }
1578  }
1579  return "?UNKNOWN?";
1580}
1581
1582static std::string DescribeCommand(Request* request) {
1583  std::string result;
1584  result += "REQUEST: ";
1585  result += GetCommandName(request);
1586  result += StringPrintf(" (length=%zu id=0x%06x)", request->GetLength(), request->GetId());
1587  return result;
1588}
1589
1590// Returns true if the given command_set and command identify an "invoke" command.
1591static bool IsInvokeCommand(uint8_t command_set, uint8_t command) {
1592  if (command_set == kJDWPClassTypeCmdSet) {
1593    return command == kJDWPClassTypeInvokeMethodCmd || command == kJDWPClassTypeNewInstanceCmd;
1594  } else if (command_set == kJDWPObjectReferenceCmdSet) {
1595    return command == kJDWPObjectReferenceInvokeCmd;
1596  } else if (command_set == kJDWPInterfaceTypeCmdSet) {
1597    return command == kJDWPInterfaceTypeInvokeMethodCmd;
1598  } else {
1599    return false;
1600  }
1601}
1602
1603/*
1604 * Process a request from the debugger. The skip_reply flag is set to true to indicate to the
1605 * caller the reply must not be sent to the debugger. This is used for invoke commands where the
1606 * reply is sent by the event thread after completing the invoke.
1607 *
1608 * On entry, the JDWP thread is in VMWAIT.
1609 */
1610size_t JdwpState::ProcessRequest(Request* request, ExpandBuf* pReply, bool* skip_reply) {
1611  JdwpError result = ERR_NONE;
1612  *skip_reply = false;
1613
1614  if (request->GetCommandSet() != kJDWPDdmCmdSet) {
1615    /*
1616     * Activity from a debugger, not merely ddms.  Mark us as having an
1617     * active debugger session, and zero out the last-activity timestamp
1618     * so waitForDebugger() doesn't return if we stall for a bit here.
1619     */
1620    Dbg::GoActive();
1621    last_activity_time_ms_.StoreSequentiallyConsistent(0);
1622  }
1623
1624  /*
1625   * If a debugger event has fired in another thread, wait until the
1626   * initiating thread has suspended itself before processing commands
1627   * from the debugger.  Otherwise we (the JDWP thread) could be told to
1628   * resume the thread before it has suspended.
1629   *
1630   * Note that we MUST clear the event token before waking the event
1631   * thread up, or risk waiting for the thread to suspend after we've
1632   * told it to resume.
1633   */
1634  AcquireJdwpTokenForCommand();
1635
1636  /*
1637   * Tell the VM that we're running and shouldn't be interrupted by GC.
1638   * Do this after anything that can stall indefinitely.
1639   */
1640  Thread* self = Thread::Current();
1641  ScopedObjectAccess soa(self);
1642
1643  expandBufAddSpace(pReply, kJDWPHeaderLen);
1644
1645  size_t i;
1646  for (i = 0; i < arraysize(gHandlers); ++i) {
1647    if (gHandlers[i].cmdSet == request->GetCommandSet() &&
1648        gHandlers[i].cmd == request->GetCommand() &&
1649        gHandlers[i].func != nullptr) {
1650      VLOG(jdwp) << DescribeCommand(request);
1651      result = (*gHandlers[i].func)(this, request, pReply);
1652      if (result == ERR_NONE) {
1653        request->CheckConsumed();
1654      }
1655      self->AssertNoPendingException();
1656      break;
1657    }
1658  }
1659  if (i == arraysize(gHandlers)) {
1660    LOG(ERROR) << "Command not implemented: " << DescribeCommand(request);
1661    LOG(ERROR) << HexDump(request->data(), request->size(), false, "");
1662    result = ERR_NOT_IMPLEMENTED;
1663  }
1664
1665  size_t replyLength = 0U;
1666  if (result == ERR_NONE && IsInvokeCommand(request->GetCommandSet(), request->GetCommand())) {
1667    // We successfully request an invoke in the event thread. It will send the reply once the
1668    // invoke completes so we must not send it now.
1669    *skip_reply = true;
1670  } else {
1671    /*
1672     * Set up the reply header.
1673     *
1674     * If we encountered an error, only send the header back.
1675     */
1676    uint8_t* replyBuf = expandBufGetBuffer(pReply);
1677    replyLength = (result == ERR_NONE) ? expandBufGetLength(pReply) : kJDWPHeaderLen;
1678    Set4BE(replyBuf + kJDWPHeaderSizeOffset, replyLength);
1679    Set4BE(replyBuf + kJDWPHeaderIdOffset, request->GetId());
1680    Set1(replyBuf + kJDWPHeaderFlagsOffset, kJDWPFlagReply);
1681    Set2BE(replyBuf + kJDWPHeaderErrorCodeOffset, result);
1682
1683    CHECK_GT(expandBufGetLength(pReply), 0U) << GetCommandName(request) << " " << request->GetId();
1684
1685    size_t respLen = expandBufGetLength(pReply) - kJDWPHeaderLen;
1686    VLOG(jdwp) << "REPLY: " << GetCommandName(request) << " " << result << " (length=" << respLen << ")";
1687    if (false) {
1688      VLOG(jdwp) << HexDump(expandBufGetBuffer(pReply) + kJDWPHeaderLen, respLen, false, "");
1689    }
1690  }
1691
1692  VLOG(jdwp) << "----------";
1693
1694  /*
1695   * Update last-activity timestamp.  We really only need this during
1696   * the initial setup.  Only update if this is a non-DDMS packet.
1697   */
1698  if (request->GetCommandSet() != kJDWPDdmCmdSet) {
1699    last_activity_time_ms_.StoreSequentiallyConsistent(MilliTime());
1700  }
1701
1702  return replyLength;
1703}
1704
1705}  // namespace JDWP
1706
1707}  // namespace art
1708