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