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