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