jdwp_handler.cc revision 43c8d729556844d1a74449a8a300c795d6a5406a
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <string.h>
19#include <unistd.h>
20
21#include <string>
22
23#include "atomic.h"
24#include "base/hex_dump.h"
25#include "base/logging.h"
26#include "base/macros.h"
27#include "base/stringprintf.h"
28#include "debugger.h"
29#include "jdwp/jdwp_constants.h"
30#include "jdwp/jdwp_event.h"
31#include "jdwp/jdwp_expand_buf.h"
32#include "jdwp/jdwp_priv.h"
33#include "runtime.h"
34#include "thread-inl.h"
35#include "UniquePtr.h"
36
37namespace art {
38
39namespace JDWP {
40
41std::string DescribeField(const FieldId& field_id) {
42  return StringPrintf("%#x (%s)", field_id, Dbg::GetFieldName(field_id).c_str());
43}
44
45std::string DescribeMethod(const MethodId& method_id) {
46  return StringPrintf("%#x (%s)", method_id, Dbg::GetMethodName(method_id).c_str());
47}
48
49std::string DescribeRefTypeId(const RefTypeId& ref_type_id) {
50  std::string signature("unknown");
51  Dbg::GetSignature(ref_type_id, &signature);
52  return StringPrintf("%#" PRIx64 " (%s)", ref_type_id, signature.c_str());
53}
54
55// Helper function: write a variable-width value into the output input buffer.
56static void WriteValue(ExpandBuf* pReply, int width, uint64_t value) {
57  switch (width) {
58  case 1:     expandBufAdd1(pReply, value); break;
59  case 2:     expandBufAdd2BE(pReply, value); break;
60  case 4:     expandBufAdd4BE(pReply, value); break;
61  case 8:     expandBufAdd8BE(pReply, value); break;
62  default:    LOG(FATAL) << width; break;
63  }
64}
65
66static JdwpError WriteTaggedObject(ExpandBuf* reply, ObjectId object_id)
67    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
68  uint8_t tag;
69  JdwpError rc = Dbg::GetObjectTag(object_id, tag);
70  if (rc == ERR_NONE) {
71    expandBufAdd1(reply, tag);
72    expandBufAddObjectId(reply, object_id);
73  }
74  return rc;
75}
76
77static JdwpError WriteTaggedObjectList(ExpandBuf* reply, const std::vector<ObjectId>& objects)
78    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
79  expandBufAdd4BE(reply, objects.size());
80  for (size_t i = 0; i < objects.size(); ++i) {
81    JdwpError rc = WriteTaggedObject(reply, objects[i]);
82    if (rc != ERR_NONE) {
83      return rc;
84    }
85  }
86  return ERR_NONE;
87}
88
89/*
90 * Common code for *_InvokeMethod requests.
91 *
92 * If "is_constructor" is set, this returns "object_id" rather than the
93 * expected-to-be-void return value of the called function.
94 */
95static JdwpError FinishInvoke(JdwpState*, Request& request, ExpandBuf* pReply,
96                              ObjectId thread_id, ObjectId object_id,
97                              RefTypeId class_id, MethodId method_id, bool is_constructor)
98    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
99  CHECK(!is_constructor || object_id != 0);
100
101  int32_t arg_count = request.ReadSigned32("argument count");
102
103  VLOG(jdwp) << StringPrintf("    --> thread_id=%#" PRIx64 " object_id=%#" PRIx64,
104                             thread_id, object_id);
105  VLOG(jdwp) << StringPrintf("        class_id=%#" PRIx64 " method_id=%x %s.%s", class_id,
106                             method_id, Dbg::GetClassName(class_id).c_str(),
107                             Dbg::GetMethodName(method_id).c_str());
108  VLOG(jdwp) << StringPrintf("        %d args:", arg_count);
109
110  UniquePtr<JdwpTag[]> argTypes(arg_count > 0 ? new JdwpTag[arg_count] : NULL);
111  UniquePtr<uint64_t[]> argValues(arg_count > 0 ? new uint64_t[arg_count] : NULL);
112  for (int32_t i = 0; i < arg_count; ++i) {
113    argTypes[i] = request.ReadTag();
114    size_t width = Dbg::GetTagWidth(argTypes[i]);
115    argValues[i] = request.ReadValue(width);
116    VLOG(jdwp) << "          " << argTypes[i] << StringPrintf("(%zd): %#" PRIx64, width,
117                                                              argValues[i]);
118  }
119
120  uint32_t options = request.ReadUnsigned32("InvokeOptions bit flags");
121  VLOG(jdwp) << StringPrintf("        options=0x%04x%s%s", options,
122                             (options & INVOKE_SINGLE_THREADED) ? " (SINGLE_THREADED)" : "",
123                             (options & INVOKE_NONVIRTUAL) ? " (NONVIRTUAL)" : "");
124
125  JdwpTag resultTag;
126  uint64_t resultValue;
127  ObjectId exceptObjId;
128  JdwpError err = Dbg::InvokeMethod(thread_id, object_id, class_id, method_id, arg_count, argValues.get(), argTypes.get(), options, &resultTag, &resultValue, &exceptObjId);
129  if (err != ERR_NONE) {
130    return err;
131  }
132
133  if (err == ERR_NONE) {
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        VLOG(jdwp) << "      string '" << Dbg::StringToUtf8(resultValue) << "'";
156      } else {
157        VLOG(jdwp) << "      string (null)";
158      }
159    }
160  }
161
162  return err;
163}
164
165static JdwpError VM_Version(JdwpState*, Request&, ExpandBuf* pReply)
166    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
167  // Text information on runtime version.
168  std::string version(StringPrintf("Android Runtime %s", Runtime::Current()->GetVersion()));
169  expandBufAddUtf8String(pReply, version);
170
171  // JDWP version numbers, major and minor.
172  expandBufAdd4BE(pReply, 1);
173  expandBufAdd4BE(pReply, 6);
174
175  // "java.version".
176  expandBufAddUtf8String(pReply, "1.6.0");
177
178  // "java.vm.name".
179  expandBufAddUtf8String(pReply, "Dalvik");
180
181  return ERR_NONE;
182}
183
184/*
185 * Given a class JNI signature (e.g. "Ljava/lang/Error;"), return the
186 * referenceTypeID.  We need to send back more than one if the class has
187 * been loaded by multiple class loaders.
188 */
189static JdwpError VM_ClassesBySignature(JdwpState*, Request& request, ExpandBuf* pReply)
190    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
191  std::string classDescriptor(request.ReadUtf8String());
192
193  std::vector<RefTypeId> ids;
194  Dbg::FindLoadedClassBySignature(classDescriptor.c_str(), ids);
195
196  expandBufAdd4BE(pReply, ids.size());
197
198  for (size_t i = 0; i < ids.size(); ++i) {
199    // Get class vs. interface and status flags.
200    JDWP::JdwpTypeTag type_tag;
201    uint32_t class_status;
202    JDWP::JdwpError status = Dbg::GetClassInfo(ids[i], &type_tag, &class_status, NULL);
203    if (status != ERR_NONE) {
204      return status;
205    }
206
207    expandBufAdd1(pReply, type_tag);
208    expandBufAddRefTypeId(pReply, ids[i]);
209    expandBufAdd4BE(pReply, class_status);
210  }
211
212  return ERR_NONE;
213}
214
215/*
216 * Handle request for the thread IDs of all running threads.
217 *
218 * We exclude ourselves from the list, because we don't allow ourselves
219 * to be suspended, and that violates some JDWP expectations.
220 */
221static JdwpError VM_AllThreads(JdwpState*, Request&, ExpandBuf* pReply)
222    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
223  std::vector<ObjectId> thread_ids;
224  Dbg::GetThreads(0, thread_ids);
225
226  expandBufAdd4BE(pReply, thread_ids.size());
227  for (uint32_t i = 0; i < thread_ids.size(); ++i) {
228    expandBufAddObjectId(pReply, thread_ids[i]);
229  }
230
231  return ERR_NONE;
232}
233
234/*
235 * List all thread groups that do not have a parent.
236 */
237static JdwpError VM_TopLevelThreadGroups(JdwpState*, Request&, ExpandBuf* pReply)
238    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
239  /*
240   * TODO: maintain a list of parentless thread groups in the VM.
241   *
242   * For now, just return "system".  Application threads are created
243   * in "main", which is a child of "system".
244   */
245  uint32_t groups = 1;
246  expandBufAdd4BE(pReply, groups);
247  ObjectId thread_group_id = Dbg::GetSystemThreadGroupId();
248  expandBufAddObjectId(pReply, thread_group_id);
249
250  return ERR_NONE;
251}
252
253/*
254 * Respond with the sizes of the basic debugger types.
255 *
256 * All IDs are 8 bytes.
257 */
258static JdwpError VM_IDSizes(JdwpState*, Request&, ExpandBuf* pReply)
259    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
260  expandBufAdd4BE(pReply, sizeof(FieldId));
261  expandBufAdd4BE(pReply, sizeof(MethodId));
262  expandBufAdd4BE(pReply, sizeof(ObjectId));
263  expandBufAdd4BE(pReply, sizeof(RefTypeId));
264  expandBufAdd4BE(pReply, sizeof(FrameId));
265  return ERR_NONE;
266}
267
268static JdwpError VM_Dispose(JdwpState*, Request&, ExpandBuf*)
269    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
270  Dbg::Disposed();
271  return ERR_NONE;
272}
273
274/*
275 * Suspend the execution of the application running in the VM (i.e. suspend
276 * all threads).
277 *
278 * This needs to increment the "suspend count" on all threads.
279 */
280static JdwpError VM_Suspend(JdwpState*, Request&, ExpandBuf*)
281    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
282  Thread* self = Thread::Current();
283  self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSuspension);
284  Dbg::SuspendVM();
285  self->TransitionFromSuspendedToRunnable();
286  return ERR_NONE;
287}
288
289/*
290 * Resume execution.  Decrements the "suspend count" of all threads.
291 */
292static JdwpError VM_Resume(JdwpState*, Request&, ExpandBuf*)
293    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
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, false);   // canWatchFieldModification
357  expandBufAdd1(reply, false);   // 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, false);   // 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::ResumeThread(thread_id);
984  return ERR_NONE;
985}
986
987/*
988 * Return status of specified thread.
989 */
990static JdwpError TR_Status(JdwpState*, Request& request, ExpandBuf* pReply)
991    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
992  ObjectId thread_id = request.ReadThreadId();
993
994  JDWP::JdwpThreadStatus threadStatus;
995  JDWP::JdwpSuspendStatus suspendStatus;
996  JdwpError error = Dbg::GetThreadStatus(thread_id, &threadStatus, &suspendStatus);
997  if (error != ERR_NONE) {
998    return error;
999  }
1000
1001  VLOG(jdwp) << "    --> " << threadStatus << ", " << suspendStatus;
1002
1003  expandBufAdd4BE(pReply, threadStatus);
1004  expandBufAdd4BE(pReply, suspendStatus);
1005
1006  return ERR_NONE;
1007}
1008
1009/*
1010 * Return the thread group that the specified thread is a member of.
1011 */
1012static JdwpError TR_ThreadGroup(JdwpState*, Request& request, ExpandBuf* pReply)
1013    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1014  ObjectId thread_id = request.ReadThreadId();
1015  return Dbg::GetThreadGroup(thread_id, pReply);
1016}
1017
1018/*
1019 * Return the current call stack of a suspended thread.
1020 *
1021 * If the thread isn't suspended, the error code isn't defined, but should
1022 * be THREAD_NOT_SUSPENDED.
1023 */
1024static JdwpError TR_Frames(JdwpState*, Request& request, ExpandBuf* pReply)
1025    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1026  ObjectId thread_id = request.ReadThreadId();
1027  uint32_t start_frame = request.ReadUnsigned32("start frame");
1028  uint32_t length = request.ReadUnsigned32("length");
1029
1030  size_t actual_frame_count;
1031  JdwpError error = Dbg::GetThreadFrameCount(thread_id, actual_frame_count);
1032  if (error != ERR_NONE) {
1033    return error;
1034  }
1035
1036  if (actual_frame_count <= 0) {
1037    return ERR_THREAD_NOT_SUSPENDED;  // 0 means no managed frames (which means "in native").
1038  }
1039
1040  if (start_frame > actual_frame_count) {
1041    return ERR_INVALID_INDEX;
1042  }
1043  if (length == static_cast<uint32_t>(-1)) {
1044    length = actual_frame_count - start_frame;
1045  }
1046  if (start_frame + length > actual_frame_count) {
1047    return ERR_INVALID_LENGTH;
1048  }
1049
1050  return Dbg::GetThreadFrames(thread_id, start_frame, length, pReply);
1051}
1052
1053/*
1054 * Returns the #of frames on the specified thread, which must be suspended.
1055 */
1056static JdwpError TR_FrameCount(JdwpState*, Request& request, ExpandBuf* pReply)
1057    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1058  ObjectId thread_id = request.ReadThreadId();
1059
1060  size_t frame_count;
1061  JdwpError rc = Dbg::GetThreadFrameCount(thread_id, frame_count);
1062  if (rc != ERR_NONE) {
1063    return rc;
1064  }
1065  expandBufAdd4BE(pReply, static_cast<uint32_t>(frame_count));
1066
1067  return ERR_NONE;
1068}
1069
1070static JdwpError TR_OwnedMonitors(Request& request, ExpandBuf* reply, bool with_stack_depths)
1071    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1072  ObjectId thread_id = request.ReadThreadId();
1073
1074  std::vector<ObjectId> monitors;
1075  std::vector<uint32_t> stack_depths;
1076  JdwpError rc = Dbg::GetOwnedMonitors(thread_id, monitors, stack_depths);
1077  if (rc != ERR_NONE) {
1078    return rc;
1079  }
1080
1081  expandBufAdd4BE(reply, monitors.size());
1082  for (size_t i = 0; i < monitors.size(); ++i) {
1083    rc = WriteTaggedObject(reply, monitors[i]);
1084    if (rc != ERR_NONE) {
1085      return rc;
1086    }
1087    if (with_stack_depths) {
1088      expandBufAdd4BE(reply, stack_depths[i]);
1089    }
1090  }
1091  return ERR_NONE;
1092}
1093
1094static JdwpError TR_OwnedMonitors(JdwpState*, Request& request, ExpandBuf* reply)
1095    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1096  return TR_OwnedMonitors(request, reply, false);
1097}
1098
1099static JdwpError TR_OwnedMonitorsStackDepthInfo(JdwpState*, Request& request, ExpandBuf* reply)
1100    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1101  return TR_OwnedMonitors(request, reply, true);
1102}
1103
1104static JdwpError TR_CurrentContendedMonitor(JdwpState*, Request& request, ExpandBuf* reply)
1105    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1106  ObjectId thread_id = request.ReadThreadId();
1107
1108  ObjectId contended_monitor;
1109  JdwpError rc = Dbg::GetContendedMonitor(thread_id, contended_monitor);
1110  if (rc != ERR_NONE) {
1111    return rc;
1112  }
1113  return WriteTaggedObject(reply, contended_monitor);
1114}
1115
1116static JdwpError TR_Interrupt(JdwpState*, Request& request, ExpandBuf* reply)
1117    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1118  ObjectId thread_id = request.ReadThreadId();
1119  return Dbg::Interrupt(thread_id);
1120}
1121
1122/*
1123 * Return the debug suspend count for the specified thread.
1124 *
1125 * (The thread *might* still be running -- it might not have examined
1126 * its suspend count recently.)
1127 */
1128static JdwpError TR_DebugSuspendCount(JdwpState*, Request& request, ExpandBuf* pReply)
1129    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1130  ObjectId thread_id = request.ReadThreadId();
1131  return Dbg::GetThreadDebugSuspendCount(thread_id, pReply);
1132}
1133
1134/*
1135 * Return the name of a thread group.
1136 *
1137 * The Eclipse debugger recognizes "main" and "system" as special.
1138 */
1139static JdwpError TGR_Name(JdwpState*, Request& request, ExpandBuf* pReply)
1140    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1141  ObjectId thread_group_id = request.ReadThreadGroupId();
1142
1143  expandBufAddUtf8String(pReply, Dbg::GetThreadGroupName(thread_group_id));
1144
1145  return ERR_NONE;
1146}
1147
1148/*
1149 * Returns the thread group -- if any -- that contains the specified
1150 * thread group.
1151 */
1152static JdwpError TGR_Parent(JdwpState*, Request& request, ExpandBuf* pReply)
1153    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1154  ObjectId thread_group_id = request.ReadThreadGroupId();
1155
1156  ObjectId parentGroup = Dbg::GetThreadGroupParent(thread_group_id);
1157  expandBufAddObjectId(pReply, parentGroup);
1158
1159  return ERR_NONE;
1160}
1161
1162/*
1163 * Return the active threads and thread groups that are part of the
1164 * specified thread group.
1165 */
1166static JdwpError TGR_Children(JdwpState*, Request& request, ExpandBuf* pReply)
1167    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1168  ObjectId thread_group_id = request.ReadThreadGroupId();
1169
1170  std::vector<ObjectId> thread_ids;
1171  Dbg::GetThreads(thread_group_id, thread_ids);
1172  expandBufAdd4BE(pReply, thread_ids.size());
1173  for (uint32_t i = 0; i < thread_ids.size(); ++i) {
1174    expandBufAddObjectId(pReply, thread_ids[i]);
1175  }
1176
1177  std::vector<ObjectId> child_thread_groups_ids;
1178  Dbg::GetChildThreadGroups(thread_group_id, child_thread_groups_ids);
1179  expandBufAdd4BE(pReply, child_thread_groups_ids.size());
1180  for (uint32_t i = 0; i < child_thread_groups_ids.size(); ++i) {
1181    expandBufAddObjectId(pReply, child_thread_groups_ids[i]);
1182  }
1183
1184  return ERR_NONE;
1185}
1186
1187/*
1188 * Return the #of components in the array.
1189 */
1190static JdwpError AR_Length(JdwpState*, Request& request, ExpandBuf* pReply)
1191    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1192  ObjectId array_id = request.ReadArrayId();
1193
1194  int length;
1195  JdwpError status = Dbg::GetArrayLength(array_id, length);
1196  if (status != ERR_NONE) {
1197    return status;
1198  }
1199  VLOG(jdwp) << "    --> " << length;
1200
1201  expandBufAdd4BE(pReply, length);
1202
1203  return ERR_NONE;
1204}
1205
1206/*
1207 * Return the values from an array.
1208 */
1209static JdwpError AR_GetValues(JdwpState*, Request& request, ExpandBuf* pReply)
1210    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1211  ObjectId array_id = request.ReadArrayId();
1212  uint32_t offset = request.ReadUnsigned32("offset");
1213  uint32_t length = request.ReadUnsigned32("length");
1214  return Dbg::OutputArray(array_id, offset, length, pReply);
1215}
1216
1217/*
1218 * Set values in an array.
1219 */
1220static JdwpError AR_SetValues(JdwpState*, Request& request, ExpandBuf*)
1221    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1222  ObjectId array_id = request.ReadArrayId();
1223  uint32_t offset = request.ReadUnsigned32("offset");
1224  uint32_t count = request.ReadUnsigned32("count");
1225  return Dbg::SetArrayElements(array_id, offset, count, request);
1226}
1227
1228static JdwpError CLR_VisibleClasses(JdwpState*, Request& request, ExpandBuf* pReply)
1229    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1230  request.ReadObjectId();  // classLoaderObject
1231  // TODO: we should only return classes which have the given class loader as a defining or
1232  // initiating loader. The former would be easy; the latter is hard, because we don't have
1233  // any such notion.
1234  return VM_AllClassesImpl(pReply, false, false);
1235}
1236
1237/*
1238 * Set an event trigger.
1239 *
1240 * Reply with a requestID.
1241 */
1242static JdwpError ER_Set(JdwpState* state, Request& request, ExpandBuf* pReply)
1243    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1244  JdwpEventKind event_kind = request.ReadEnum1<JdwpEventKind>("event kind");
1245  JdwpSuspendPolicy suspend_policy = request.ReadEnum1<JdwpSuspendPolicy>("suspend policy");
1246  int32_t modifier_count = request.ReadSigned32("modifier count");
1247
1248  CHECK_LT(modifier_count, 256);    /* reasonableness check */
1249
1250  JdwpEvent* pEvent = EventAlloc(modifier_count);
1251  pEvent->eventKind = event_kind;
1252  pEvent->suspend_policy = suspend_policy;
1253  pEvent->modCount = modifier_count;
1254
1255  /*
1256   * Read modifiers.  Ordering may be significant (see explanation of Count
1257   * mods in JDWP doc).
1258   */
1259  for (int32_t i = 0; i < modifier_count; ++i) {
1260    JdwpEventMod& mod = pEvent->mods[i];
1261    mod.modKind = request.ReadModKind();
1262    switch (mod.modKind) {
1263    case MK_COUNT:
1264      {
1265        // Report once, when "--count" reaches 0.
1266        uint32_t count = request.ReadUnsigned32("count");
1267        if (count == 0) {
1268          return ERR_INVALID_COUNT;
1269        }
1270        mod.count.count = count;
1271      }
1272      break;
1273    case MK_CONDITIONAL:
1274      {
1275        // Conditional on expression.
1276        uint32_t exprId = request.ReadUnsigned32("expr id");
1277        mod.conditional.exprId = exprId;
1278      }
1279      break;
1280    case MK_THREAD_ONLY:
1281      {
1282        // Only report events in specified thread.
1283        ObjectId thread_id = request.ReadThreadId();
1284        mod.threadOnly.threadId = thread_id;
1285      }
1286      break;
1287    case MK_CLASS_ONLY:
1288      {
1289        // For ClassPrepare, MethodEntry.
1290        RefTypeId class_id = request.ReadRefTypeId();
1291        mod.classOnly.refTypeId = class_id;
1292      }
1293      break;
1294    case MK_CLASS_MATCH:
1295      {
1296        // Restrict events to matching classes.
1297        // pattern is "java.foo.*", we want "java/foo/*".
1298        std::string pattern(request.ReadUtf8String());
1299        std::replace(pattern.begin(), pattern.end(), '.', '/');
1300        mod.classMatch.classPattern = strdup(pattern.c_str());
1301      }
1302      break;
1303    case MK_CLASS_EXCLUDE:
1304      {
1305        // Restrict events to non-matching classes.
1306        // pattern is "java.foo.*", we want "java/foo/*".
1307        std::string pattern(request.ReadUtf8String());
1308        std::replace(pattern.begin(), pattern.end(), '.', '/');
1309        mod.classExclude.classPattern = strdup(pattern.c_str());
1310      }
1311      break;
1312    case MK_LOCATION_ONLY:
1313      {
1314        // Restrict certain events based on location.
1315        JdwpLocation location = request.ReadLocation();
1316        mod.locationOnly.loc = location;
1317      }
1318      break;
1319    case MK_EXCEPTION_ONLY:
1320      {
1321        // Modifies EK_EXCEPTION events,
1322        mod.exceptionOnly.refTypeId = request.ReadRefTypeId();  // null => all exceptions.
1323        mod.exceptionOnly.caught = request.ReadEnum1<uint8_t>("caught");
1324        mod.exceptionOnly.uncaught = request.ReadEnum1<uint8_t>("uncaught");
1325      }
1326      break;
1327    case MK_FIELD_ONLY:
1328      {
1329        // For field access/modification events.
1330        RefTypeId declaring = request.ReadRefTypeId();
1331        FieldId fieldId = request.ReadFieldId();
1332        mod.fieldOnly.refTypeId = declaring;
1333        mod.fieldOnly.fieldId = fieldId;
1334      }
1335      break;
1336    case MK_STEP:
1337      {
1338        // For use with EK_SINGLE_STEP.
1339        ObjectId thread_id = request.ReadThreadId();
1340        uint32_t size = request.ReadUnsigned32("step size");
1341        uint32_t depth = request.ReadUnsigned32("step depth");
1342        VLOG(jdwp) << StringPrintf("    Step: thread=%#" PRIx64, thread_id)
1343                     << " size=" << JdwpStepSize(size) << " depth=" << JdwpStepDepth(depth);
1344
1345        mod.step.threadId = thread_id;
1346        mod.step.size = size;
1347        mod.step.depth = depth;
1348      }
1349      break;
1350    case MK_INSTANCE_ONLY:
1351      {
1352        // Report events related to a specific object.
1353        ObjectId instance = request.ReadObjectId();
1354        mod.instanceOnly.objectId = instance;
1355      }
1356      break;
1357    default:
1358      LOG(WARNING) << "GLITCH: unsupported modKind=" << mod.modKind;
1359      break;
1360    }
1361  }
1362
1363  /*
1364   * We reply with an integer "requestID".
1365   */
1366  uint32_t requestId = state->NextEventSerial();
1367  expandBufAdd4BE(pReply, requestId);
1368
1369  pEvent->requestId = requestId;
1370
1371  VLOG(jdwp) << StringPrintf("    --> event requestId=%#x", requestId);
1372
1373  /* add it to the list */
1374  JdwpError err = state->RegisterEvent(pEvent);
1375  if (err != ERR_NONE) {
1376    /* registration failed, probably because event is bogus */
1377    EventFree(pEvent);
1378    LOG(WARNING) << "WARNING: event request rejected";
1379  }
1380  return err;
1381}
1382
1383static JdwpError ER_Clear(JdwpState* state, Request& request, ExpandBuf*)
1384    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1385  request.ReadEnum1<JdwpEventKind>("event kind");
1386  uint32_t requestId = request.ReadUnsigned32("request id");
1387
1388  // Failure to find an event with a matching ID is a no-op
1389  // and does not return an error.
1390  state->UnregisterEventById(requestId);
1391  return ERR_NONE;
1392}
1393
1394/*
1395 * Return the values of arguments and local variables.
1396 */
1397static JdwpError SF_GetValues(JdwpState*, Request& request, ExpandBuf* pReply)
1398    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1399  ObjectId thread_id = request.ReadThreadId();
1400  FrameId frame_id = request.ReadFrameId();
1401  int32_t slot_count = request.ReadSigned32("slot count");
1402
1403  expandBufAdd4BE(pReply, slot_count);     /* "int values" */
1404  for (int32_t i = 0; i < slot_count; ++i) {
1405    uint32_t slot = request.ReadUnsigned32("slot");
1406    JDWP::JdwpTag reqSigByte = request.ReadTag();
1407
1408    VLOG(jdwp) << "    --> slot " << slot << " " << reqSigByte;
1409
1410    size_t width = Dbg::GetTagWidth(reqSigByte);
1411    uint8_t* ptr = expandBufAddSpace(pReply, width+1);
1412    JdwpError error = Dbg::GetLocalValue(thread_id, frame_id, slot, reqSigByte, ptr, width);
1413    if (error != ERR_NONE) {
1414      return error;
1415    }
1416  }
1417
1418  return ERR_NONE;
1419}
1420
1421/*
1422 * Set the values of arguments and local variables.
1423 */
1424static JdwpError SF_SetValues(JdwpState*, Request& request, ExpandBuf*)
1425    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1426  ObjectId thread_id = request.ReadThreadId();
1427  FrameId frame_id = request.ReadFrameId();
1428  int32_t slot_count = request.ReadSigned32("slot count");
1429
1430  for (int32_t i = 0; i < slot_count; ++i) {
1431    uint32_t slot = request.ReadUnsigned32("slot");
1432    JDWP::JdwpTag sigByte = request.ReadTag();
1433    size_t width = Dbg::GetTagWidth(sigByte);
1434    uint64_t value = request.ReadValue(width);
1435
1436    VLOG(jdwp) << "    --> slot " << slot << " " << sigByte << " " << value;
1437    JdwpError error = Dbg::SetLocalValue(thread_id, frame_id, slot, sigByte, value, width);
1438    if (error != ERR_NONE) {
1439      return error;
1440    }
1441  }
1442
1443  return ERR_NONE;
1444}
1445
1446static JdwpError SF_ThisObject(JdwpState*, Request& request, ExpandBuf* reply)
1447    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1448  ObjectId thread_id = request.ReadThreadId();
1449  FrameId frame_id = request.ReadFrameId();
1450
1451  ObjectId object_id;
1452  JdwpError rc = Dbg::GetThisObject(thread_id, frame_id, &object_id);
1453  if (rc != ERR_NONE) {
1454    return rc;
1455  }
1456
1457  return WriteTaggedObject(reply, object_id);
1458}
1459
1460/*
1461 * Return the reference type reflected by this class object.
1462 *
1463 * This appears to be required because ReferenceTypeId values are NEVER
1464 * reused, whereas ClassIds can be recycled like any other object.  (Either
1465 * that, or I have no idea what this is for.)
1466 */
1467static JdwpError COR_ReflectedType(JdwpState*, Request& request, ExpandBuf* pReply)
1468    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1469  RefTypeId class_object_id = request.ReadRefTypeId();
1470  return Dbg::GetReflectedType(class_object_id, pReply);
1471}
1472
1473/*
1474 * Handle a DDM packet with a single chunk in it.
1475 */
1476static JdwpError DDM_Chunk(JdwpState* state, Request& request, ExpandBuf* pReply)
1477    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1478  state->NotifyDdmsActive();
1479  uint8_t* replyBuf = NULL;
1480  int replyLen = -1;
1481  if (Dbg::DdmHandlePacket(request, &replyBuf, &replyLen)) {
1482    // If they want to send something back, we copy it into the buffer.
1483    // TODO: consider altering the JDWP stuff to hold the packet header
1484    // in a separate buffer.  That would allow us to writev() DDM traffic
1485    // instead of copying it into the expanding buffer.  The reduction in
1486    // heap requirements is probably more valuable than the efficiency.
1487    CHECK_GT(replyLen, 0);
1488    memcpy(expandBufAddSpace(pReply, replyLen), replyBuf, replyLen);
1489    free(replyBuf);
1490  }
1491  return ERR_NONE;
1492}
1493
1494/*
1495 * Handler map decl.
1496 */
1497typedef JdwpError (*JdwpRequestHandler)(JdwpState* state, Request& request, ExpandBuf* reply);
1498
1499struct JdwpHandlerMap {
1500  uint8_t cmdSet;
1501  uint8_t cmd;
1502  JdwpRequestHandler func;
1503  const char* name;
1504};
1505
1506/*
1507 * Map commands to functions.
1508 *
1509 * Command sets 0-63 are incoming requests, 64-127 are outbound requests,
1510 * and 128-256 are vendor-defined.
1511 */
1512static const JdwpHandlerMap gHandlers[] = {
1513  /* VirtualMachine command set (1) */
1514  { 1,    1,  VM_Version,               "VirtualMachine.Version" },
1515  { 1,    2,  VM_ClassesBySignature,    "VirtualMachine.ClassesBySignature" },
1516  { 1,    3,  VM_AllClasses,            "VirtualMachine.AllClasses" },
1517  { 1,    4,  VM_AllThreads,            "VirtualMachine.AllThreads" },
1518  { 1,    5,  VM_TopLevelThreadGroups,  "VirtualMachine.TopLevelThreadGroups" },
1519  { 1,    6,  VM_Dispose,               "VirtualMachine.Dispose" },
1520  { 1,    7,  VM_IDSizes,               "VirtualMachine.IDSizes" },
1521  { 1,    8,  VM_Suspend,               "VirtualMachine.Suspend" },
1522  { 1,    9,  VM_Resume,                "VirtualMachine.Resume" },
1523  { 1,    10, VM_Exit,                  "VirtualMachine.Exit" },
1524  { 1,    11, VM_CreateString,          "VirtualMachine.CreateString" },
1525  { 1,    12, VM_Capabilities,          "VirtualMachine.Capabilities" },
1526  { 1,    13, VM_ClassPaths,            "VirtualMachine.ClassPaths" },
1527  { 1,    14, VM_DisposeObjects,        "VirtualMachine.DisposeObjects" },
1528  { 1,    15, NULL,                     "VirtualMachine.HoldEvents" },
1529  { 1,    16, NULL,                     "VirtualMachine.ReleaseEvents" },
1530  { 1,    17, VM_CapabilitiesNew,       "VirtualMachine.CapabilitiesNew" },
1531  { 1,    18, NULL,                     "VirtualMachine.RedefineClasses" },
1532  { 1,    19, NULL,                     "VirtualMachine.SetDefaultStratum" },
1533  { 1,    20, VM_AllClassesWithGeneric, "VirtualMachine.AllClassesWithGeneric" },
1534  { 1,    21, VM_InstanceCounts,        "VirtualMachine.InstanceCounts" },
1535
1536  /* ReferenceType command set (2) */
1537  { 2,    1,  RT_Signature,            "ReferenceType.Signature" },
1538  { 2,    2,  RT_ClassLoader,          "ReferenceType.ClassLoader" },
1539  { 2,    3,  RT_Modifiers,            "ReferenceType.Modifiers" },
1540  { 2,    4,  RT_Fields,               "ReferenceType.Fields" },
1541  { 2,    5,  RT_Methods,              "ReferenceType.Methods" },
1542  { 2,    6,  RT_GetValues,            "ReferenceType.GetValues" },
1543  { 2,    7,  RT_SourceFile,           "ReferenceType.SourceFile" },
1544  { 2,    8,  NULL,                    "ReferenceType.NestedTypes" },
1545  { 2,    9,  RT_Status,               "ReferenceType.Status" },
1546  { 2,    10, RT_Interfaces,           "ReferenceType.Interfaces" },
1547  { 2,    11, RT_ClassObject,          "ReferenceType.ClassObject" },
1548  { 2,    12, RT_SourceDebugExtension, "ReferenceType.SourceDebugExtension" },
1549  { 2,    13, RT_SignatureWithGeneric, "ReferenceType.SignatureWithGeneric" },
1550  { 2,    14, RT_FieldsWithGeneric,    "ReferenceType.FieldsWithGeneric" },
1551  { 2,    15, RT_MethodsWithGeneric,   "ReferenceType.MethodsWithGeneric" },
1552  { 2,    16, RT_Instances,            "ReferenceType.Instances" },
1553  { 2,    17, NULL,                    "ReferenceType.ClassFileVersion" },
1554  { 2,    18, NULL,                    "ReferenceType.ConstantPool" },
1555
1556  /* ClassType command set (3) */
1557  { 3,    1,  CT_Superclass,    "ClassType.Superclass" },
1558  { 3,    2,  CT_SetValues,     "ClassType.SetValues" },
1559  { 3,    3,  CT_InvokeMethod,  "ClassType.InvokeMethod" },
1560  { 3,    4,  CT_NewInstance,   "ClassType.NewInstance" },
1561
1562  /* ArrayType command set (4) */
1563  { 4,    1,  AT_newInstance,   "ArrayType.NewInstance" },
1564
1565  /* InterfaceType command set (5) */
1566
1567  /* Method command set (6) */
1568  { 6,    1,  M_LineTable,                "Method.LineTable" },
1569  { 6,    2,  M_VariableTable,            "Method.VariableTable" },
1570  { 6,    3,  M_Bytecodes,                "Method.Bytecodes" },
1571  { 6,    4,  NULL,                       "Method.IsObsolete" },
1572  { 6,    5,  M_VariableTableWithGeneric, "Method.VariableTableWithGeneric" },
1573
1574  /* Field command set (8) */
1575
1576  /* ObjectReference command set (9) */
1577  { 9,    1,  OR_ReferenceType,     "ObjectReference.ReferenceType" },
1578  { 9,    2,  OR_GetValues,         "ObjectReference.GetValues" },
1579  { 9,    3,  OR_SetValues,         "ObjectReference.SetValues" },
1580  { 9,    4,  NULL,                 "ObjectReference.UNUSED" },
1581  { 9,    5,  OR_MonitorInfo,       "ObjectReference.MonitorInfo" },
1582  { 9,    6,  OR_InvokeMethod,      "ObjectReference.InvokeMethod" },
1583  { 9,    7,  OR_DisableCollection, "ObjectReference.DisableCollection" },
1584  { 9,    8,  OR_EnableCollection,  "ObjectReference.EnableCollection" },
1585  { 9,    9,  OR_IsCollected,       "ObjectReference.IsCollected" },
1586  { 9,    10, OR_ReferringObjects,  "ObjectReference.ReferringObjects" },
1587
1588  /* StringReference command set (10) */
1589  { 10,   1,  SR_Value,         "StringReference.Value" },
1590
1591  /* ThreadReference command set (11) */
1592  { 11,   1,  TR_Name,                        "ThreadReference.Name" },
1593  { 11,   2,  TR_Suspend,                     "ThreadReference.Suspend" },
1594  { 11,   3,  TR_Resume,                      "ThreadReference.Resume" },
1595  { 11,   4,  TR_Status,                      "ThreadReference.Status" },
1596  { 11,   5,  TR_ThreadGroup,                 "ThreadReference.ThreadGroup" },
1597  { 11,   6,  TR_Frames,                      "ThreadReference.Frames" },
1598  { 11,   7,  TR_FrameCount,                  "ThreadReference.FrameCount" },
1599  { 11,   8,  TR_OwnedMonitors,               "ThreadReference.OwnedMonitors" },
1600  { 11,   9,  TR_CurrentContendedMonitor,     "ThreadReference.CurrentContendedMonitor" },
1601  { 11,   10, NULL,                           "ThreadReference.Stop" },
1602  { 11,   11, TR_Interrupt,                   "ThreadReference.Interrupt" },
1603  { 11,   12, TR_DebugSuspendCount,           "ThreadReference.SuspendCount" },
1604  { 11,   13, TR_OwnedMonitorsStackDepthInfo, "ThreadReference.OwnedMonitorsStackDepthInfo" },
1605  { 11,   14, NULL,                           "ThreadReference.ForceEarlyReturn" },
1606
1607  /* ThreadGroupReference command set (12) */
1608  { 12,   1,  TGR_Name,         "ThreadGroupReference.Name" },
1609  { 12,   2,  TGR_Parent,       "ThreadGroupReference.Parent" },
1610  { 12,   3,  TGR_Children,     "ThreadGroupReference.Children" },
1611
1612  /* ArrayReference command set (13) */
1613  { 13,   1,  AR_Length,        "ArrayReference.Length" },
1614  { 13,   2,  AR_GetValues,     "ArrayReference.GetValues" },
1615  { 13,   3,  AR_SetValues,     "ArrayReference.SetValues" },
1616
1617  /* ClassLoaderReference command set (14) */
1618  { 14,   1,  CLR_VisibleClasses, "ClassLoaderReference.VisibleClasses" },
1619
1620  /* EventRequest command set (15) */
1621  { 15,   1,  ER_Set,           "EventRequest.Set" },
1622  { 15,   2,  ER_Clear,         "EventRequest.Clear" },
1623  { 15,   3,  NULL,             "EventRequest.ClearAllBreakpoints" },
1624
1625  /* StackFrame command set (16) */
1626  { 16,   1,  SF_GetValues,     "StackFrame.GetValues" },
1627  { 16,   2,  SF_SetValues,     "StackFrame.SetValues" },
1628  { 16,   3,  SF_ThisObject,    "StackFrame.ThisObject" },
1629  { 16,   4,  NULL,             "StackFrame.PopFrames" },
1630
1631  /* ClassObjectReference command set (17) */
1632  { 17,   1,  COR_ReflectedType, "ClassObjectReference.ReflectedType" },
1633
1634  /* Event command set (64) */
1635  { 64, 100,  NULL, "Event.Composite" },  // sent from VM to debugger, never received by VM
1636
1637  { 199,  1,  DDM_Chunk,        "DDM.Chunk" },
1638};
1639
1640static const char* GetCommandName(Request& request) {
1641  for (size_t i = 0; i < arraysize(gHandlers); ++i) {
1642    if (gHandlers[i].cmdSet == request.GetCommandSet() && gHandlers[i].cmd == request.GetCommand()) {
1643      return gHandlers[i].name;
1644    }
1645  }
1646  return "?UNKNOWN?";
1647}
1648
1649static std::string DescribeCommand(Request& request) {
1650  std::string result;
1651  result += "REQUEST: ";
1652  result += GetCommandName(request);
1653  result += StringPrintf(" (length=%zu id=0x%06x)", request.GetLength(), request.GetId());
1654  return result;
1655}
1656
1657/*
1658 * Process a request from the debugger.
1659 *
1660 * On entry, the JDWP thread is in VMWAIT.
1661 */
1662size_t JdwpState::ProcessRequest(Request& request, ExpandBuf* pReply) {
1663  JdwpError result = ERR_NONE;
1664
1665  if (request.GetCommandSet() != kJDWPDdmCmdSet) {
1666    /*
1667     * Activity from a debugger, not merely ddms.  Mark us as having an
1668     * active debugger session, and zero out the last-activity timestamp
1669     * so waitForDebugger() doesn't return if we stall for a bit here.
1670     */
1671    Dbg::GoActive();
1672    QuasiAtomic::Write64(&last_activity_time_ms_, 0);
1673  }
1674
1675  /*
1676   * If a debugger event has fired in another thread, wait until the
1677   * initiating thread has suspended itself before processing messages
1678   * from the debugger.  Otherwise we (the JDWP thread) could be told to
1679   * resume the thread before it has suspended.
1680   *
1681   * We call with an argument of zero to wait for the current event
1682   * thread to finish, and then clear the block.  Depending on the thread
1683   * suspend policy, this may allow events in other threads to fire,
1684   * but those events have no bearing on what the debugger has sent us
1685   * in the current request.
1686   *
1687   * Note that we MUST clear the event token before waking the event
1688   * thread up, or risk waiting for the thread to suspend after we've
1689   * told it to resume.
1690   */
1691  SetWaitForEventThread(0);
1692
1693  /*
1694   * We do not want events to be sent while we process a request. Indicate the JDWP thread starts
1695   * to process a request so other threads wait for it to finish before sending an event.
1696   */
1697  StartProcessingRequest();
1698
1699  /*
1700   * Tell the VM that we're running and shouldn't be interrupted by GC.
1701   * Do this after anything that can stall indefinitely.
1702   */
1703  Thread* self = Thread::Current();
1704  ThreadState old_state = self->TransitionFromSuspendedToRunnable();
1705
1706  expandBufAddSpace(pReply, kJDWPHeaderLen);
1707
1708  size_t i;
1709  for (i = 0; i < arraysize(gHandlers); ++i) {
1710    if (gHandlers[i].cmdSet == request.GetCommandSet() && gHandlers[i].cmd == request.GetCommand() && gHandlers[i].func != NULL) {
1711      VLOG(jdwp) << DescribeCommand(request);
1712      result = (*gHandlers[i].func)(this, request, pReply);
1713      if (result == ERR_NONE) {
1714        request.CheckConsumed();
1715      }
1716      break;
1717    }
1718  }
1719  if (i == arraysize(gHandlers)) {
1720    LOG(ERROR) << "Command not implemented: " << DescribeCommand(request);
1721    LOG(ERROR) << HexDump(request.data(), request.size(), false, "");
1722    result = ERR_NOT_IMPLEMENTED;
1723  }
1724
1725  /*
1726   * Set up the reply header.
1727   *
1728   * If we encountered an error, only send the header back.
1729   */
1730  uint8_t* replyBuf = expandBufGetBuffer(pReply);
1731  size_t replyLength = (result == ERR_NONE) ? expandBufGetLength(pReply) : kJDWPHeaderLen;
1732  Set4BE(replyBuf + 0, replyLength);
1733  Set4BE(replyBuf + 4, request.GetId());
1734  Set1(replyBuf + 8, kJDWPFlagReply);
1735  Set2BE(replyBuf + 9, result);
1736
1737  CHECK_GT(expandBufGetLength(pReply), 0U) << GetCommandName(request) << " " << request.GetId();
1738
1739  size_t respLen = expandBufGetLength(pReply) - kJDWPHeaderLen;
1740  VLOG(jdwp) << "REPLY: " << GetCommandName(request) << " " << result << " (length=" << respLen << ")";
1741  if (false) {
1742    VLOG(jdwp) << HexDump(expandBufGetBuffer(pReply) + kJDWPHeaderLen, respLen, false, "");
1743  }
1744
1745  VLOG(jdwp) << "----------";
1746
1747  /*
1748   * Update last-activity timestamp.  We really only need this during
1749   * the initial setup.  Only update if this is a non-DDMS packet.
1750   */
1751  if (request.GetCommandSet() != kJDWPDdmCmdSet) {
1752    QuasiAtomic::Write64(&last_activity_time_ms_, MilliTime());
1753  }
1754
1755  /* tell the VM that GC is okay again */
1756  self->TransitionFromRunnableToSuspended(old_state);
1757
1758  return replyLength;
1759}
1760
1761/*
1762 * Indicates a request is about to be processed. If a thread wants to send an event in the meantime,
1763 * it will need to wait until we processed this request (see EndProcessingRequest).
1764 */
1765void JdwpState::StartProcessingRequest() {
1766  Thread* self = Thread::Current();
1767  CHECK_EQ(self, GetDebugThread()) << "Requests are only processed by debug thread";
1768  MutexLock mu(self, process_request_lock_);
1769  CHECK_EQ(processing_request_, false);
1770  processing_request_ = true;
1771}
1772
1773/*
1774 * Indicates a request has been processed (and we sent its reply). All threads waiting for us (see
1775 * WaitForProcessingRequest) are waken up so they can send events again.
1776 */
1777void JdwpState::EndProcessingRequest() {
1778  Thread* self = Thread::Current();
1779  CHECK_EQ(self, GetDebugThread()) << "Requests are only processed by debug thread";
1780  MutexLock mu(self, process_request_lock_);
1781  CHECK_EQ(processing_request_, true);
1782  processing_request_ = false;
1783  process_request_cond_.Broadcast(self);
1784}
1785
1786/*
1787 * Waits for any request being processed so we do not send an event in the meantime.
1788 */
1789void JdwpState::WaitForProcessingRequest() {
1790  Thread* self = Thread::Current();
1791  CHECK_NE(self, GetDebugThread()) << "Events should not be posted by debug thread";
1792  MutexLock mu(self, process_request_lock_);
1793  bool waited = false;
1794  while (processing_request_) {
1795    VLOG(jdwp) << StringPrintf("wait for processing request");
1796    waited = true;
1797    process_request_cond_.Wait(self);
1798  }
1799  if (waited) {
1800    VLOG(jdwp) << StringPrintf("finished waiting for processing request");
1801  }
1802  CHECK_EQ(processing_request_, false);
1803}
1804
1805}  // namespace JDWP
1806
1807}  // namespace art
1808