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;
296   Split(Runtime::Current()->GetBootClassPathString(), ':', &boot_class_path);
297   expandBufAdd4BE(pReply, boot_class_path.size());
298   for (const std::string& str : boot_class_path) {
299     expandBufAddUtf8String(pReply, str);
300   }
301 
302   return ERR_NONE;
303 }
304 
VM_DisposeObjects(JdwpState *,Request * request,ExpandBuf *)305 static JdwpError VM_DisposeObjects(JdwpState*, Request* request, ExpandBuf*)
306     REQUIRES_SHARED(Locks::mutator_lock_) {
307   size_t object_count = request->ReadUnsigned32("object_count");
308   for (size_t i = 0; i < object_count; ++i) {
309     ObjectId object_id = request->ReadObjectId();
310     uint32_t reference_count = request->ReadUnsigned32("reference_count");
311     Dbg::DisposeObject(object_id, reference_count);
312   }
313   return ERR_NONE;
314 }
315 
VM_Capabilities(JdwpState *,Request *,ExpandBuf * reply)316 static JdwpError VM_Capabilities(JdwpState*, Request*, ExpandBuf* reply)
317     REQUIRES_SHARED(Locks::mutator_lock_) {
318   expandBufAdd1(reply, true);    // canWatchFieldModification
319   expandBufAdd1(reply, true);    // canWatchFieldAccess
320   expandBufAdd1(reply, true);    // canGetBytecodes
321   expandBufAdd1(reply, true);    // canGetSyntheticAttribute
322   expandBufAdd1(reply, true);    // canGetOwnedMonitorInfo
323   expandBufAdd1(reply, true);    // canGetCurrentContendedMonitor
324   expandBufAdd1(reply, true);    // canGetMonitorInfo
325   return ERR_NONE;
326 }
327 
VM_CapabilitiesNew(JdwpState *,Request * request,ExpandBuf * reply)328 static JdwpError VM_CapabilitiesNew(JdwpState*, Request* request, ExpandBuf* reply)
329     REQUIRES_SHARED(Locks::mutator_lock_) {
330   // The first few capabilities are the same as those reported by the older call.
331   VM_Capabilities(nullptr, request, reply);
332 
333   expandBufAdd1(reply, false);   // canRedefineClasses
334   expandBufAdd1(reply, false);   // canAddMethod
335   expandBufAdd1(reply, false);   // canUnrestrictedlyRedefineClasses
336   expandBufAdd1(reply, false);   // canPopFrames
337   expandBufAdd1(reply, true);    // canUseInstanceFilters
338   expandBufAdd1(reply, true);    // canGetSourceDebugExtension
339   expandBufAdd1(reply, false);   // canRequestVMDeathEvent
340   expandBufAdd1(reply, false);   // canSetDefaultStratum
341   expandBufAdd1(reply, true);    // 1.6: canGetInstanceInfo
342   expandBufAdd1(reply, false);   // 1.6: canRequestMonitorEvents
343   expandBufAdd1(reply, true);    // 1.6: canGetMonitorFrameInfo
344   expandBufAdd1(reply, false);   // 1.6: canUseSourceNameFilters
345   expandBufAdd1(reply, false);   // 1.6: canGetConstantPool
346   expandBufAdd1(reply, false);   // 1.6: canForceEarlyReturn
347 
348   // Fill in reserved22 through reserved32; note count started at 1.
349   for (size_t i = 22; i <= 32; ++i) {
350     expandBufAdd1(reply, false);
351   }
352   return ERR_NONE;
353 }
354 
VM_AllClassesImpl(ExpandBuf * pReply,bool descriptor_and_status,bool generic)355 static JdwpError VM_AllClassesImpl(ExpandBuf* pReply, bool descriptor_and_status, bool generic)
356     REQUIRES_SHARED(Locks::mutator_lock_) {
357   std::vector<JDWP::RefTypeId> classes;
358   Dbg::GetClassList(&classes);
359 
360   expandBufAdd4BE(pReply, classes.size());
361 
362   for (size_t i = 0; i < classes.size(); ++i) {
363     static const char genericSignature[1] = "";
364     JDWP::JdwpTypeTag type_tag;
365     std::string descriptor;
366     uint32_t class_status;
367     JDWP::JdwpError status = Dbg::GetClassInfo(classes[i], &type_tag, &class_status, &descriptor);
368     if (status != ERR_NONE) {
369       return status;
370     }
371 
372     expandBufAdd1(pReply, type_tag);
373     expandBufAddRefTypeId(pReply, classes[i]);
374     if (descriptor_and_status) {
375       expandBufAddUtf8String(pReply, descriptor);
376       if (generic) {
377         expandBufAddUtf8String(pReply, genericSignature);
378       }
379       expandBufAdd4BE(pReply, class_status);
380     }
381   }
382 
383   return ERR_NONE;
384 }
385 
VM_AllClasses(JdwpState *,Request *,ExpandBuf * pReply)386 static JdwpError VM_AllClasses(JdwpState*, Request*, ExpandBuf* pReply)
387     REQUIRES_SHARED(Locks::mutator_lock_) {
388   return VM_AllClassesImpl(pReply, true, false);
389 }
390 
VM_AllClassesWithGeneric(JdwpState *,Request *,ExpandBuf * pReply)391 static JdwpError VM_AllClassesWithGeneric(JdwpState*, Request*, ExpandBuf* pReply)
392     REQUIRES_SHARED(Locks::mutator_lock_) {
393   return VM_AllClassesImpl(pReply, true, true);
394 }
395 
VM_InstanceCounts(JdwpState *,Request * request,ExpandBuf * pReply)396 static JdwpError VM_InstanceCounts(JdwpState*, Request* request, ExpandBuf* pReply)
397     REQUIRES_SHARED(Locks::mutator_lock_) {
398   int32_t class_count = request->ReadSigned32("class count");
399   if (class_count < 0) {
400     return ERR_ILLEGAL_ARGUMENT;
401   }
402   std::vector<RefTypeId> class_ids;
403   for (int32_t i = 0; i < class_count; ++i) {
404     class_ids.push_back(request->ReadRefTypeId());
405   }
406 
407   std::vector<uint64_t> counts;
408   JdwpError rc = Dbg::GetInstanceCounts(class_ids, &counts);
409   if (rc != ERR_NONE) {
410     return rc;
411   }
412 
413   expandBufAdd4BE(pReply, counts.size());
414   for (size_t i = 0; i < counts.size(); ++i) {
415     expandBufAdd8BE(pReply, counts[i]);
416   }
417   return ERR_NONE;
418 }
419 
RT_Modifiers(JdwpState *,Request * request,ExpandBuf * pReply)420 static JdwpError RT_Modifiers(JdwpState*, Request* request, ExpandBuf* pReply)
421     REQUIRES_SHARED(Locks::mutator_lock_) {
422   RefTypeId refTypeId = request->ReadRefTypeId();
423   return Dbg::GetModifiers(refTypeId, pReply);
424 }
425 
426 /*
427  * Get values from static fields in a reference type.
428  */
RT_GetValues(JdwpState *,Request * request,ExpandBuf * pReply)429 static JdwpError RT_GetValues(JdwpState*, Request* request, ExpandBuf* pReply)
430     REQUIRES_SHARED(Locks::mutator_lock_) {
431   RefTypeId refTypeId = request->ReadRefTypeId();
432   int32_t field_count = request->ReadSigned32("field count");
433   expandBufAdd4BE(pReply, field_count);
434   for (int32_t i = 0; i < field_count; ++i) {
435     FieldId fieldId = request->ReadFieldId();
436     JdwpError status = Dbg::GetStaticFieldValue(refTypeId, fieldId, pReply);
437     if (status != ERR_NONE) {
438       return status;
439     }
440   }
441   return ERR_NONE;
442 }
443 
444 /*
445  * Get the name of the source file in which a reference type was declared.
446  */
RT_SourceFile(JdwpState *,Request * request,ExpandBuf * pReply)447 static JdwpError RT_SourceFile(JdwpState*, Request* request, ExpandBuf* pReply)
448     REQUIRES_SHARED(Locks::mutator_lock_) {
449   RefTypeId refTypeId = request->ReadRefTypeId();
450   std::string source_file;
451   JdwpError status = Dbg::GetSourceFile(refTypeId, &source_file);
452   if (status != ERR_NONE) {
453     return status;
454   }
455   expandBufAddUtf8String(pReply, source_file);
456   return ERR_NONE;
457 }
458 
459 /*
460  * Return the current status of the reference type.
461  */
RT_Status(JdwpState *,Request * request,ExpandBuf * pReply)462 static JdwpError RT_Status(JdwpState*, Request* request, ExpandBuf* pReply)
463     REQUIRES_SHARED(Locks::mutator_lock_) {
464   RefTypeId refTypeId = request->ReadRefTypeId();
465   JDWP::JdwpTypeTag type_tag;
466   uint32_t class_status;
467   JDWP::JdwpError status = Dbg::GetClassInfo(refTypeId, &type_tag, &class_status, nullptr);
468   if (status != ERR_NONE) {
469     return status;
470   }
471   expandBufAdd4BE(pReply, class_status);
472   return ERR_NONE;
473 }
474 
475 /*
476  * Return interfaces implemented directly by this class.
477  */
RT_Interfaces(JdwpState *,Request * request,ExpandBuf * pReply)478 static JdwpError RT_Interfaces(JdwpState*, Request* request, ExpandBuf* pReply)
479     REQUIRES_SHARED(Locks::mutator_lock_) {
480   RefTypeId refTypeId = request->ReadRefTypeId();
481   return Dbg::OutputDeclaredInterfaces(refTypeId, pReply);
482 }
483 
484 /*
485  * Return the class object corresponding to this type.
486  */
RT_ClassObject(JdwpState *,Request * request,ExpandBuf * pReply)487 static JdwpError RT_ClassObject(JdwpState*, Request* request, ExpandBuf* pReply)
488     REQUIRES_SHARED(Locks::mutator_lock_) {
489   RefTypeId refTypeId = request->ReadRefTypeId();
490   ObjectId class_object_id;
491   JdwpError status = Dbg::GetClassObject(refTypeId, &class_object_id);
492   if (status != ERR_NONE) {
493     return status;
494   }
495   VLOG(jdwp) << StringPrintf("    --> ObjectId %#" PRIx64, class_object_id);
496   expandBufAddObjectId(pReply, class_object_id);
497   return ERR_NONE;
498 }
499 
500 /*
501  * Returns the value of the SourceDebugExtension attribute.
502  */
RT_SourceDebugExtension(JdwpState *,Request * request,ExpandBuf * pReply)503 static JdwpError RT_SourceDebugExtension(JdwpState*, Request* request, ExpandBuf* pReply)
504     REQUIRES_SHARED(Locks::mutator_lock_) {
505   /* referenceTypeId in, string out */
506   RefTypeId refTypeId = request->ReadRefTypeId();
507   std::string extension_data;
508   JdwpError status = Dbg::GetSourceDebugExtension(refTypeId, &extension_data);
509   if (status != ERR_NONE) {
510     return status;
511   }
512   expandBufAddUtf8String(pReply, extension_data);
513   return ERR_NONE;
514 }
515 
RT_Signature(JdwpState *,Request * request,ExpandBuf * pReply,bool with_generic)516 static JdwpError RT_Signature(JdwpState*, Request* request, ExpandBuf* pReply, bool with_generic)
517     REQUIRES_SHARED(Locks::mutator_lock_) {
518   RefTypeId refTypeId = request->ReadRefTypeId();
519 
520   std::string signature;
521   JdwpError status = Dbg::GetSignature(refTypeId, &signature);
522   if (status != ERR_NONE) {
523     return status;
524   }
525   expandBufAddUtf8String(pReply, signature);
526   if (with_generic) {
527     expandBufAddUtf8String(pReply, "");
528   }
529   return ERR_NONE;
530 }
531 
RT_Signature(JdwpState * state,Request * request,ExpandBuf * pReply)532 static JdwpError RT_Signature(JdwpState* state, Request* request, ExpandBuf* pReply)
533     REQUIRES_SHARED(Locks::mutator_lock_) {
534   return RT_Signature(state, request, pReply, false);
535 }
536 
RT_SignatureWithGeneric(JdwpState * state,Request * request,ExpandBuf * pReply)537 static JdwpError RT_SignatureWithGeneric(JdwpState* state, Request* request, ExpandBuf* pReply)
538     REQUIRES_SHARED(Locks::mutator_lock_) {
539   return RT_Signature(state, request, pReply, true);
540 }
541 
542 /*
543  * Return the instance of java.lang.ClassLoader that loaded the specified
544  * reference type, or null if it was loaded by the system loader.
545  */
RT_ClassLoader(JdwpState *,Request * request,ExpandBuf * pReply)546 static JdwpError RT_ClassLoader(JdwpState*, Request* request, ExpandBuf* pReply)
547     REQUIRES_SHARED(Locks::mutator_lock_) {
548   RefTypeId refTypeId = request->ReadRefTypeId();
549   return Dbg::GetClassLoader(refTypeId, pReply);
550 }
551 
552 /*
553  * Given a referenceTypeId, return a block of stuff that describes the
554  * fields declared by a class.
555  */
RT_FieldsWithGeneric(JdwpState *,Request * request,ExpandBuf * pReply)556 static JdwpError RT_FieldsWithGeneric(JdwpState*, Request* request, ExpandBuf* pReply)
557     REQUIRES_SHARED(Locks::mutator_lock_) {
558   RefTypeId refTypeId = request->ReadRefTypeId();
559   return Dbg::OutputDeclaredFields(refTypeId, true, pReply);
560 }
561 
562 // Obsolete equivalent of FieldsWithGeneric, without the generic type information.
RT_Fields(JdwpState *,Request * request,ExpandBuf * pReply)563 static JdwpError RT_Fields(JdwpState*, Request* request, ExpandBuf* pReply)
564     REQUIRES_SHARED(Locks::mutator_lock_) {
565   RefTypeId refTypeId = request->ReadRefTypeId();
566   return Dbg::OutputDeclaredFields(refTypeId, false, pReply);
567 }
568 
569 /*
570  * Given a referenceTypeID, return a block of goodies describing the
571  * methods declared by a class.
572  */
RT_MethodsWithGeneric(JdwpState *,Request * request,ExpandBuf * pReply)573 static JdwpError RT_MethodsWithGeneric(JdwpState*, Request* request, ExpandBuf* pReply)
574     REQUIRES_SHARED(Locks::mutator_lock_) {
575   RefTypeId refTypeId = request->ReadRefTypeId();
576   return Dbg::OutputDeclaredMethods(refTypeId, true, pReply);
577 }
578 
579 // Obsolete equivalent of MethodsWithGeneric, without the generic type information.
RT_Methods(JdwpState *,Request * request,ExpandBuf * pReply)580 static JdwpError RT_Methods(JdwpState*, Request* request, ExpandBuf* pReply)
581     REQUIRES_SHARED(Locks::mutator_lock_) {
582   RefTypeId refTypeId = request->ReadRefTypeId();
583   return Dbg::OutputDeclaredMethods(refTypeId, false, pReply);
584 }
585 
RT_Instances(JdwpState *,Request * request,ExpandBuf * reply)586 static JdwpError RT_Instances(JdwpState*, Request* request, ExpandBuf* reply)
587     REQUIRES_SHARED(Locks::mutator_lock_) {
588   RefTypeId class_id = request->ReadRefTypeId();
589   int32_t max_count = request->ReadSigned32("max count");
590   if (max_count < 0) {
591     return ERR_ILLEGAL_ARGUMENT;
592   }
593 
594   std::vector<ObjectId> instances;
595   JdwpError rc = Dbg::GetInstances(class_id, max_count, &instances);
596   if (rc != ERR_NONE) {
597     return rc;
598   }
599 
600   return WriteTaggedObjectList(reply, instances);
601 }
602 
603 /*
604  * Return the immediate superclass of a class.
605  */
CT_Superclass(JdwpState *,Request * request,ExpandBuf * pReply)606 static JdwpError CT_Superclass(JdwpState*, Request* request, ExpandBuf* pReply)
607     REQUIRES_SHARED(Locks::mutator_lock_) {
608   RefTypeId class_id = request->ReadRefTypeId();
609   RefTypeId superClassId;
610   JdwpError status = Dbg::GetSuperclass(class_id, &superClassId);
611   if (status != ERR_NONE) {
612     return status;
613   }
614   expandBufAddRefTypeId(pReply, superClassId);
615   return ERR_NONE;
616 }
617 
618 /*
619  * Set static class values.
620  */
CT_SetValues(JdwpState *,Request * request,ExpandBuf *)621 static JdwpError CT_SetValues(JdwpState* , Request* request, ExpandBuf*)
622     REQUIRES_SHARED(Locks::mutator_lock_) {
623   RefTypeId class_id = request->ReadRefTypeId();
624   int32_t values_count = request->ReadSigned32("values count");
625 
626   UNUSED(class_id);
627 
628   for (int32_t i = 0; i < values_count; ++i) {
629     FieldId fieldId = request->ReadFieldId();
630     JDWP::JdwpTag fieldTag = Dbg::GetStaticFieldBasicTag(fieldId);
631     size_t width = Dbg::GetTagWidth(fieldTag);
632     uint64_t value = request->ReadValue(width);
633 
634     VLOG(jdwp) << "    --> field=" << fieldId << " tag=" << fieldTag << " --> " << value;
635     JdwpError status = Dbg::SetStaticFieldValue(fieldId, value, width);
636     if (status != ERR_NONE) {
637       return status;
638     }
639   }
640 
641   return ERR_NONE;
642 }
643 
644 /*
645  * Invoke a static method.
646  *
647  * Example: Eclipse sometimes uses java/lang/Class.forName(String s) on
648  * values in the "variables" display.
649  */
CT_InvokeMethod(JdwpState * state,Request * request,ExpandBuf * pReply ATTRIBUTE_UNUSED)650 static JdwpError CT_InvokeMethod(JdwpState* state, Request* request,
651                                  ExpandBuf* pReply ATTRIBUTE_UNUSED)
652     REQUIRES_SHARED(Locks::mutator_lock_) {
653   RefTypeId class_id = request->ReadRefTypeId();
654   ObjectId thread_id = request->ReadThreadId();
655   MethodId method_id = request->ReadMethodId();
656 
657   return RequestInvoke(state, request, thread_id, 0, class_id, method_id, false);
658 }
659 
660 /*
661  * Create a new object of the requested type, and invoke the specified
662  * constructor.
663  *
664  * Example: in IntelliJ, create a watch on "new String(myByteArray)" to
665  * see the contents of a byte[] as a string.
666  */
CT_NewInstance(JdwpState * state,Request * request,ExpandBuf * pReply ATTRIBUTE_UNUSED)667 static JdwpError CT_NewInstance(JdwpState* state, Request* request,
668                                 ExpandBuf* pReply ATTRIBUTE_UNUSED)
669     REQUIRES_SHARED(Locks::mutator_lock_) {
670   RefTypeId class_id = request->ReadRefTypeId();
671   ObjectId thread_id = request->ReadThreadId();
672   MethodId method_id = request->ReadMethodId();
673 
674   ObjectId object_id;
675   JdwpError status = Dbg::CreateObject(class_id, &object_id);
676   if (status != ERR_NONE) {
677     return status;
678   }
679   return RequestInvoke(state, request, thread_id, object_id, class_id, method_id, true);
680 }
681 
682 /*
683  * Create a new array object of the requested type and length.
684  */
AT_newInstance(JdwpState *,Request * request,ExpandBuf * pReply)685 static JdwpError AT_newInstance(JdwpState*, Request* request, ExpandBuf* pReply)
686     REQUIRES_SHARED(Locks::mutator_lock_) {
687   RefTypeId arrayTypeId = request->ReadRefTypeId();
688   int32_t length = request->ReadSigned32("length");
689 
690   ObjectId object_id;
691   JdwpError status = Dbg::CreateArrayObject(arrayTypeId, length, &object_id);
692   if (status != ERR_NONE) {
693     return status;
694   }
695   expandBufAdd1(pReply, JT_ARRAY);
696   expandBufAddObjectId(pReply, object_id);
697   return ERR_NONE;
698 }
699 
700 /*
701  * Invoke a static method on an interface.
702  */
IT_InvokeMethod(JdwpState * state,Request * request,ExpandBuf * pReply ATTRIBUTE_UNUSED)703 static JdwpError IT_InvokeMethod(JdwpState* state, Request* request,
704                                  ExpandBuf* pReply ATTRIBUTE_UNUSED)
705     REQUIRES_SHARED(Locks::mutator_lock_) {
706   RefTypeId class_id = request->ReadRefTypeId();
707   ObjectId thread_id = request->ReadThreadId();
708   MethodId method_id = request->ReadMethodId();
709 
710   return RequestInvoke(state, request, thread_id, 0, class_id, method_id, false);
711 }
712 
713 /*
714  * Return line number information for the method, if present.
715  */
M_LineTable(JdwpState *,Request * request,ExpandBuf * pReply)716 static JdwpError M_LineTable(JdwpState*, Request* request, ExpandBuf* pReply)
717     REQUIRES_SHARED(Locks::mutator_lock_) {
718   RefTypeId refTypeId = request->ReadRefTypeId();
719   MethodId method_id = request->ReadMethodId();
720 
721   Dbg::OutputLineTable(refTypeId, method_id, pReply);
722 
723   return ERR_NONE;
724 }
725 
M_VariableTable(JdwpState *,Request * request,ExpandBuf * pReply,bool generic)726 static JdwpError M_VariableTable(JdwpState*, Request* request, ExpandBuf* pReply,
727                                  bool generic)
728     REQUIRES_SHARED(Locks::mutator_lock_) {
729   RefTypeId class_id = request->ReadRefTypeId();
730   MethodId method_id = request->ReadMethodId();
731 
732   // We could return ERR_ABSENT_INFORMATION here if the DEX file was built without local variable
733   // information. That will cause Eclipse to make a best-effort attempt at displaying local
734   // variables anonymously. However, the attempt isn't very good, so we're probably better off just
735   // not showing anything.
736   Dbg::OutputVariableTable(class_id, method_id, generic, pReply);
737   return ERR_NONE;
738 }
739 
M_VariableTable(JdwpState * state,Request * request,ExpandBuf * pReply)740 static JdwpError M_VariableTable(JdwpState* state, Request* request, ExpandBuf* pReply)
741     REQUIRES_SHARED(Locks::mutator_lock_) {
742   return M_VariableTable(state, request, pReply, false);
743 }
744 
M_VariableTableWithGeneric(JdwpState * state,Request * request,ExpandBuf * pReply)745 static JdwpError M_VariableTableWithGeneric(JdwpState* state, Request* request, ExpandBuf* pReply)
746     REQUIRES_SHARED(Locks::mutator_lock_) {
747   return M_VariableTable(state, request, pReply, true);
748 }
749 
M_Bytecodes(JdwpState *,Request * request,ExpandBuf * reply)750 static JdwpError M_Bytecodes(JdwpState*, Request* request, ExpandBuf* reply)
751     REQUIRES_SHARED(Locks::mutator_lock_) {
752   RefTypeId class_id = request->ReadRefTypeId();
753   MethodId method_id = request->ReadMethodId();
754 
755   std::vector<uint8_t> bytecodes;
756   JdwpError rc = Dbg::GetBytecodes(class_id, method_id, &bytecodes);
757   if (rc != ERR_NONE) {
758     return rc;
759   }
760 
761   expandBufAdd4BE(reply, bytecodes.size());
762   for (size_t i = 0; i < bytecodes.size(); ++i) {
763     expandBufAdd1(reply, bytecodes[i]);
764   }
765 
766   return ERR_NONE;
767 }
768 
M_IsObsolete(JdwpState *,Request * request,ExpandBuf * reply)769 static JdwpError M_IsObsolete(JdwpState*, Request* request, ExpandBuf* reply)
770     REQUIRES_SHARED(Locks::mutator_lock_) {
771   request->ReadRefTypeId();  // unused reference type ID
772   MethodId id = request->ReadMethodId();
773   expandBufAdd1(reply, Dbg::IsMethodObsolete(id));
774   return ERR_NONE;
775 }
776 
777 /*
778  * Given an object reference, return the runtime type of the object
779  * (class or array).
780  *
781  * This can get called on different things, e.g. thread_id gets
782  * passed in here.
783  */
OR_ReferenceType(JdwpState *,Request * request,ExpandBuf * pReply)784 static JdwpError OR_ReferenceType(JdwpState*, Request* request, ExpandBuf* pReply)
785     REQUIRES_SHARED(Locks::mutator_lock_) {
786   ObjectId object_id = request->ReadObjectId();
787   return Dbg::GetReferenceType(object_id, pReply);
788 }
789 
790 /*
791  * Get values from the fields of an object.
792  */
OR_GetValues(JdwpState *,Request * request,ExpandBuf * pReply)793 static JdwpError OR_GetValues(JdwpState*, Request* request, ExpandBuf* pReply)
794     REQUIRES_SHARED(Locks::mutator_lock_) {
795   ObjectId object_id = request->ReadObjectId();
796   int32_t field_count = request->ReadSigned32("field count");
797 
798   expandBufAdd4BE(pReply, field_count);
799   for (int32_t i = 0; i < field_count; ++i) {
800     FieldId fieldId = request->ReadFieldId();
801     JdwpError status = Dbg::GetFieldValue(object_id, fieldId, pReply);
802     if (status != ERR_NONE) {
803       return status;
804     }
805   }
806 
807   return ERR_NONE;
808 }
809 
810 /*
811  * Set values in the fields of an object.
812  */
OR_SetValues(JdwpState *,Request * request,ExpandBuf *)813 static JdwpError OR_SetValues(JdwpState*, Request* request, ExpandBuf*)
814     REQUIRES_SHARED(Locks::mutator_lock_) {
815   ObjectId object_id = request->ReadObjectId();
816   int32_t field_count = request->ReadSigned32("field count");
817 
818   for (int32_t i = 0; i < field_count; ++i) {
819     FieldId fieldId = request->ReadFieldId();
820 
821     JDWP::JdwpTag fieldTag = Dbg::GetFieldBasicTag(fieldId);
822     size_t width = Dbg::GetTagWidth(fieldTag);
823     uint64_t value = request->ReadValue(width);
824 
825     VLOG(jdwp) << "    --> fieldId=" << fieldId << " tag=" << fieldTag << "(" << width << ") value=" << value;
826     JdwpError status = Dbg::SetFieldValue(object_id, fieldId, value, width);
827     if (status != ERR_NONE) {
828       return status;
829     }
830   }
831 
832   return ERR_NONE;
833 }
834 
OR_MonitorInfo(JdwpState *,Request * request,ExpandBuf * reply)835 static JdwpError OR_MonitorInfo(JdwpState*, Request* request, ExpandBuf* reply)
836     REQUIRES_SHARED(Locks::mutator_lock_) {
837   ObjectId object_id = request->ReadObjectId();
838   return Dbg::GetMonitorInfo(object_id, reply);
839 }
840 
841 /*
842  * Invoke an instance method.  The invocation must occur in the specified
843  * thread, which must have been suspended by an event.
844  *
845  * The call is synchronous.  All threads in the VM are resumed, unless the
846  * SINGLE_THREADED flag is set.
847  *
848  * If you ask Eclipse to "inspect" an object (or ask JDB to "print" an
849  * object), it will try to invoke the object's toString() function.  This
850  * feature becomes crucial when examining ArrayLists with Eclipse.
851  */
OR_InvokeMethod(JdwpState * state,Request * request,ExpandBuf * pReply ATTRIBUTE_UNUSED)852 static JdwpError OR_InvokeMethod(JdwpState* state, Request* request,
853                                  ExpandBuf* pReply ATTRIBUTE_UNUSED)
854     REQUIRES_SHARED(Locks::mutator_lock_) {
855   ObjectId object_id = request->ReadObjectId();
856   ObjectId thread_id = request->ReadThreadId();
857   RefTypeId class_id = request->ReadRefTypeId();
858   MethodId method_id = request->ReadMethodId();
859 
860   return RequestInvoke(state, request, thread_id, object_id, class_id, method_id, false);
861 }
862 
OR_DisableCollection(JdwpState *,Request * request,ExpandBuf *)863 static JdwpError OR_DisableCollection(JdwpState*, Request* request, ExpandBuf*)
864     REQUIRES_SHARED(Locks::mutator_lock_) {
865   ObjectId object_id = request->ReadObjectId();
866   return Dbg::DisableCollection(object_id);
867 }
868 
OR_EnableCollection(JdwpState *,Request * request,ExpandBuf *)869 static JdwpError OR_EnableCollection(JdwpState*, Request* request, ExpandBuf*)
870     REQUIRES_SHARED(Locks::mutator_lock_) {
871   ObjectId object_id = request->ReadObjectId();
872   return Dbg::EnableCollection(object_id);
873 }
874 
OR_IsCollected(JdwpState *,Request * request,ExpandBuf * pReply)875 static JdwpError OR_IsCollected(JdwpState*, Request* request, ExpandBuf* pReply)
876     REQUIRES_SHARED(Locks::mutator_lock_) {
877   ObjectId object_id = request->ReadObjectId();
878   bool is_collected;
879   JdwpError rc = Dbg::IsCollected(object_id, &is_collected);
880   expandBufAdd1(pReply, is_collected ? 1 : 0);
881   return rc;
882 }
883 
OR_ReferringObjects(JdwpState *,Request * request,ExpandBuf * reply)884 static JdwpError OR_ReferringObjects(JdwpState*, Request* request, ExpandBuf* reply)
885     REQUIRES_SHARED(Locks::mutator_lock_) {
886   ObjectId object_id = request->ReadObjectId();
887   int32_t max_count = request->ReadSigned32("max count");
888   if (max_count < 0) {
889     return ERR_ILLEGAL_ARGUMENT;
890   }
891 
892   std::vector<ObjectId> referring_objects;
893   JdwpError rc = Dbg::GetReferringObjects(object_id, max_count, &referring_objects);
894   if (rc != ERR_NONE) {
895     return rc;
896   }
897 
898   return WriteTaggedObjectList(reply, referring_objects);
899 }
900 
901 /*
902  * Return the string value in a string object.
903  */
SR_Value(JdwpState *,Request * request,ExpandBuf * pReply)904 static JdwpError SR_Value(JdwpState*, Request* request, ExpandBuf* pReply)
905     REQUIRES_SHARED(Locks::mutator_lock_) {
906   ObjectId stringObject = request->ReadObjectId();
907   std::string str;
908   JDWP::JdwpError error = Dbg::StringToUtf8(stringObject, &str);
909   if (error != JDWP::ERR_NONE) {
910     return error;
911   }
912 
913   VLOG(jdwp) << StringPrintf("    --> %s", PrintableString(str.c_str()).c_str());
914 
915   expandBufAddUtf8String(pReply, str);
916 
917   return ERR_NONE;
918 }
919 
920 /*
921  * Return a thread's name.
922  */
TR_Name(JdwpState *,Request * request,ExpandBuf * pReply)923 static JdwpError TR_Name(JdwpState*, Request* request, ExpandBuf* pReply)
924     REQUIRES_SHARED(Locks::mutator_lock_) {
925   ObjectId thread_id = request->ReadThreadId();
926 
927   std::string name;
928   JdwpError error = Dbg::GetThreadName(thread_id, &name);
929   if (error != ERR_NONE) {
930     return error;
931   }
932   VLOG(jdwp) << StringPrintf("  Name of thread %#" PRIx64 " is \"%s\"", thread_id, name.c_str());
933   expandBufAddUtf8String(pReply, name);
934 
935   return ERR_NONE;
936 }
937 
938 /*
939  * Suspend the specified thread.
940  *
941  * It's supposed to remain suspended even if interpreted code wants to
942  * resume it; only the JDI is allowed to resume it.
943  */
TR_Suspend(JdwpState *,Request * request,ExpandBuf *)944 static JdwpError TR_Suspend(JdwpState*, Request* request, ExpandBuf*)
945     REQUIRES_SHARED(Locks::mutator_lock_) {
946   ObjectId thread_id = request->ReadThreadId();
947 
948   if (thread_id == Dbg::GetThreadSelfId()) {
949     LOG(INFO) << "  Warning: ignoring request to suspend self";
950     return ERR_THREAD_NOT_SUSPENDED;
951   }
952 
953   Thread* self = Thread::Current();
954   ScopedThreadSuspension sts(self, kWaitingForDebuggerSend);
955   JdwpError result = Dbg::SuspendThread(thread_id);
956   return result;
957 }
958 
959 /*
960  * Resume the specified thread.
961  */
TR_Resume(JdwpState *,Request * request,ExpandBuf *)962 static JdwpError TR_Resume(JdwpState*, Request* request, ExpandBuf*)
963     REQUIRES_SHARED(Locks::mutator_lock_) {
964   ObjectId thread_id = request->ReadThreadId();
965 
966   if (thread_id == Dbg::GetThreadSelfId()) {
967     LOG(INFO) << "  Warning: ignoring request to resume self";
968     return ERR_NONE;
969   }
970 
971   Dbg::ResumeThread(thread_id);
972   return ERR_NONE;
973 }
974 
975 /*
976  * Return status of specified thread.
977  */
TR_Status(JdwpState *,Request * request,ExpandBuf * pReply)978 static JdwpError TR_Status(JdwpState*, Request* request, ExpandBuf* pReply)
979     REQUIRES_SHARED(Locks::mutator_lock_) {
980   ObjectId thread_id = request->ReadThreadId();
981 
982   JDWP::JdwpThreadStatus threadStatus;
983   JDWP::JdwpSuspendStatus suspendStatus;
984   JdwpError error = Dbg::GetThreadStatus(thread_id, &threadStatus, &suspendStatus);
985   if (error != ERR_NONE) {
986     return error;
987   }
988 
989   VLOG(jdwp) << "    --> " << threadStatus << ", " << suspendStatus;
990 
991   expandBufAdd4BE(pReply, threadStatus);
992   expandBufAdd4BE(pReply, suspendStatus);
993 
994   return ERR_NONE;
995 }
996 
997 /*
998  * Return the thread group that the specified thread is a member of.
999  */
TR_ThreadGroup(JdwpState *,Request * request,ExpandBuf * pReply)1000 static JdwpError TR_ThreadGroup(JdwpState*, Request* request, ExpandBuf* pReply)
1001     REQUIRES_SHARED(Locks::mutator_lock_) {
1002   ObjectId thread_id = request->ReadThreadId();
1003   return Dbg::GetThreadGroup(thread_id, pReply);
1004 }
1005 
1006 /*
1007  * Return the current call stack of a suspended thread.
1008  *
1009  * If the thread isn't suspended, the error code isn't defined, but should
1010  * be THREAD_NOT_SUSPENDED.
1011  */
TR_Frames(JdwpState *,Request * request,ExpandBuf * pReply)1012 static JdwpError TR_Frames(JdwpState*, Request* request, ExpandBuf* pReply)
1013     REQUIRES_SHARED(Locks::mutator_lock_) {
1014   ObjectId thread_id = request->ReadThreadId();
1015   uint32_t start_frame = request->ReadUnsigned32("start frame");
1016   uint32_t length = request->ReadUnsigned32("length");
1017 
1018   size_t actual_frame_count;
1019   JdwpError error = Dbg::GetThreadFrameCount(thread_id, &actual_frame_count);
1020   if (error != ERR_NONE) {
1021     return error;
1022   }
1023 
1024   if (actual_frame_count <= 0) {
1025     return ERR_THREAD_NOT_SUSPENDED;  // 0 means no managed frames (which means "in native").
1026   }
1027 
1028   if (start_frame > actual_frame_count) {
1029     return ERR_INVALID_INDEX;
1030   }
1031   if (length == static_cast<uint32_t>(-1)) {
1032     length = actual_frame_count - start_frame;
1033   }
1034   if (start_frame + length > actual_frame_count) {
1035     return ERR_INVALID_LENGTH;
1036   }
1037 
1038   return Dbg::GetThreadFrames(thread_id, start_frame, length, pReply);
1039 }
1040 
1041 /*
1042  * Returns the #of frames on the specified thread, which must be suspended.
1043  */
TR_FrameCount(JdwpState *,Request * request,ExpandBuf * pReply)1044 static JdwpError TR_FrameCount(JdwpState*, Request* request, ExpandBuf* pReply)
1045     REQUIRES_SHARED(Locks::mutator_lock_) {
1046   ObjectId thread_id = request->ReadThreadId();
1047 
1048   size_t frame_count;
1049   JdwpError rc = Dbg::GetThreadFrameCount(thread_id, &frame_count);
1050   if (rc != ERR_NONE) {
1051     return rc;
1052   }
1053   expandBufAdd4BE(pReply, static_cast<uint32_t>(frame_count));
1054 
1055   return ERR_NONE;
1056 }
1057 
TR_OwnedMonitors(Request * request,ExpandBuf * reply,bool with_stack_depths)1058 static JdwpError TR_OwnedMonitors(Request* request, ExpandBuf* reply, bool with_stack_depths)
1059     REQUIRES_SHARED(Locks::mutator_lock_) {
1060   ObjectId thread_id = request->ReadThreadId();
1061 
1062   std::vector<ObjectId> monitors;
1063   std::vector<uint32_t> stack_depths;
1064   JdwpError rc = Dbg::GetOwnedMonitors(thread_id, &monitors, &stack_depths);
1065   if (rc != ERR_NONE) {
1066     return rc;
1067   }
1068 
1069   expandBufAdd4BE(reply, monitors.size());
1070   for (size_t i = 0; i < monitors.size(); ++i) {
1071     rc = WriteTaggedObject(reply, monitors[i]);
1072     if (rc != ERR_NONE) {
1073       return rc;
1074     }
1075     if (with_stack_depths) {
1076       expandBufAdd4BE(reply, stack_depths[i]);
1077     }
1078   }
1079   return ERR_NONE;
1080 }
1081 
TR_OwnedMonitors(JdwpState *,Request * request,ExpandBuf * reply)1082 static JdwpError TR_OwnedMonitors(JdwpState*, Request* request, ExpandBuf* reply)
1083     REQUIRES_SHARED(Locks::mutator_lock_) {
1084   return TR_OwnedMonitors(request, reply, false);
1085 }
1086 
TR_OwnedMonitorsStackDepthInfo(JdwpState *,Request * request,ExpandBuf * reply)1087 static JdwpError TR_OwnedMonitorsStackDepthInfo(JdwpState*, Request* request, ExpandBuf* reply)
1088     REQUIRES_SHARED(Locks::mutator_lock_) {
1089   return TR_OwnedMonitors(request, reply, true);
1090 }
1091 
TR_CurrentContendedMonitor(JdwpState *,Request * request,ExpandBuf * reply)1092 static JdwpError TR_CurrentContendedMonitor(JdwpState*, Request* request, ExpandBuf* reply)
1093     REQUIRES_SHARED(Locks::mutator_lock_) {
1094   ObjectId thread_id = request->ReadThreadId();
1095 
1096   ObjectId contended_monitor;
1097   JdwpError rc = Dbg::GetContendedMonitor(thread_id, &contended_monitor);
1098   if (rc != ERR_NONE) {
1099     return rc;
1100   }
1101   return WriteTaggedObject(reply, contended_monitor);
1102 }
1103 
TR_Interrupt(JdwpState *,Request * request,ExpandBuf * reply ATTRIBUTE_UNUSED)1104 static JdwpError TR_Interrupt(JdwpState*, Request* request, ExpandBuf* reply ATTRIBUTE_UNUSED)
1105     REQUIRES_SHARED(Locks::mutator_lock_) {
1106   ObjectId thread_id = request->ReadThreadId();
1107   return Dbg::Interrupt(thread_id);
1108 }
1109 
1110 /*
1111  * Return the debug suspend count for the specified thread.
1112  *
1113  * (The thread *might* still be running -- it might not have examined
1114  * its suspend count recently.)
1115  */
TR_DebugSuspendCount(JdwpState *,Request * request,ExpandBuf * pReply)1116 static JdwpError TR_DebugSuspendCount(JdwpState*, Request* request, ExpandBuf* pReply)
1117     REQUIRES_SHARED(Locks::mutator_lock_) {
1118   ObjectId thread_id = request->ReadThreadId();
1119   return Dbg::GetThreadDebugSuspendCount(thread_id, pReply);
1120 }
1121 
1122 /*
1123  * Return the name of a thread group.
1124  *
1125  * The Eclipse debugger recognizes "main" and "system" as special.
1126  */
TGR_Name(JdwpState *,Request * request,ExpandBuf * pReply)1127 static JdwpError TGR_Name(JdwpState*, Request* request, ExpandBuf* pReply)
1128     REQUIRES_SHARED(Locks::mutator_lock_) {
1129   ObjectId thread_group_id = request->ReadThreadGroupId();
1130   return Dbg::GetThreadGroupName(thread_group_id, pReply);
1131 }
1132 
1133 /*
1134  * Returns the thread group -- if any -- that contains the specified
1135  * thread group.
1136  */
TGR_Parent(JdwpState *,Request * request,ExpandBuf * pReply)1137 static JdwpError TGR_Parent(JdwpState*, Request* request, ExpandBuf* pReply)
1138     REQUIRES_SHARED(Locks::mutator_lock_) {
1139   ObjectId thread_group_id = request->ReadThreadGroupId();
1140   return Dbg::GetThreadGroupParent(thread_group_id, pReply);
1141 }
1142 
1143 /*
1144  * Return the active threads and thread groups that are part of the
1145  * specified thread group.
1146  */
TGR_Children(JdwpState *,Request * request,ExpandBuf * pReply)1147 static JdwpError TGR_Children(JdwpState*, Request* request, ExpandBuf* pReply)
1148     REQUIRES_SHARED(Locks::mutator_lock_) {
1149   ObjectId thread_group_id = request->ReadThreadGroupId();
1150   return Dbg::GetThreadGroupChildren(thread_group_id, pReply);
1151 }
1152 
1153 /*
1154  * Return the #of components in the array.
1155  */
AR_Length(JdwpState *,Request * request,ExpandBuf * pReply)1156 static JdwpError AR_Length(JdwpState*, Request* request, ExpandBuf* pReply)
1157     REQUIRES_SHARED(Locks::mutator_lock_) {
1158   ObjectId array_id = request->ReadArrayId();
1159 
1160   int32_t length;
1161   JdwpError status = Dbg::GetArrayLength(array_id, &length);
1162   if (status != ERR_NONE) {
1163     return status;
1164   }
1165   VLOG(jdwp) << "    --> " << length;
1166 
1167   expandBufAdd4BE(pReply, length);
1168 
1169   return ERR_NONE;
1170 }
1171 
1172 /*
1173  * Return the values from an array.
1174  */
AR_GetValues(JdwpState *,Request * request,ExpandBuf * pReply)1175 static JdwpError AR_GetValues(JdwpState*, Request* request, ExpandBuf* pReply)
1176     REQUIRES_SHARED(Locks::mutator_lock_) {
1177   ObjectId array_id = request->ReadArrayId();
1178   uint32_t offset = request->ReadUnsigned32("offset");
1179   uint32_t length = request->ReadUnsigned32("length");
1180   return Dbg::OutputArray(array_id, offset, length, pReply);
1181 }
1182 
1183 /*
1184  * Set values in an array.
1185  */
AR_SetValues(JdwpState *,Request * request,ExpandBuf *)1186 static JdwpError AR_SetValues(JdwpState*, Request* request, ExpandBuf*)
1187     REQUIRES_SHARED(Locks::mutator_lock_) {
1188   ObjectId array_id = request->ReadArrayId();
1189   uint32_t offset = request->ReadUnsigned32("offset");
1190   uint32_t count = request->ReadUnsigned32("count");
1191   return Dbg::SetArrayElements(array_id, offset, count, request);
1192 }
1193 
CLR_VisibleClasses(JdwpState *,Request * request,ExpandBuf * pReply)1194 static JdwpError CLR_VisibleClasses(JdwpState*, Request* request, ExpandBuf* pReply)
1195     REQUIRES_SHARED(Locks::mutator_lock_) {
1196   request->ReadObjectId();  // classLoaderObject
1197   // TODO: we should only return classes which have the given class loader as a defining or
1198   // initiating loader. The former would be easy; the latter is hard, because we don't have
1199   // any such notion.
1200   return VM_AllClassesImpl(pReply, false, false);
1201 }
1202 
1203 // Delete function class to use std::unique_ptr with JdwpEvent.
1204 struct JdwpEventDeleter {
operator ()art::JDWP::JdwpEventDeleter1205   void operator()(JdwpEvent* event) {
1206     EventFree(event);
1207   }
1208 };
1209 
1210 /*
1211  * Set an event trigger.
1212  *
1213  * Reply with a requestID.
1214  */
ER_Set(JdwpState * state,Request * request,ExpandBuf * pReply)1215 static JdwpError ER_Set(JdwpState* state, Request* request, ExpandBuf* pReply)
1216     REQUIRES_SHARED(Locks::mutator_lock_) {
1217   JdwpEventKind event_kind = request->ReadEnum1<JdwpEventKind>("event kind");
1218   JdwpSuspendPolicy suspend_policy = request->ReadEnum1<JdwpSuspendPolicy>("suspend policy");
1219   int32_t modifier_count = request->ReadSigned32("modifier count");
1220 
1221   CHECK_LT(modifier_count, 256);    /* reasonableness check */
1222 
1223   std::unique_ptr<JDWP::JdwpEvent, JdwpEventDeleter> pEvent(EventAlloc(modifier_count));
1224   pEvent->eventKind = event_kind;
1225   pEvent->suspend_policy = suspend_policy;
1226   pEvent->modCount = modifier_count;
1227 
1228   /*
1229    * Read modifiers.  Ordering may be significant (see explanation of Count
1230    * mods in JDWP doc).
1231    */
1232   for (int32_t i = 0; i < modifier_count; ++i) {
1233     JdwpEventMod& mod = pEvent->mods[i];
1234     mod.modKind = request->ReadModKind();
1235     switch (mod.modKind) {
1236     case MK_COUNT:
1237       {
1238         // Report once, when "--count" reaches 0.
1239         uint32_t count = request->ReadUnsigned32("count");
1240         if (count == 0) {
1241           return ERR_INVALID_COUNT;
1242         }
1243         mod.count.count = count;
1244       }
1245       break;
1246     case MK_CONDITIONAL:
1247       {
1248         // Conditional on expression.
1249         uint32_t exprId = request->ReadUnsigned32("expr id");
1250         mod.conditional.exprId = exprId;
1251       }
1252       break;
1253     case MK_THREAD_ONLY:
1254       {
1255         // Only report events in specified thread.
1256         ObjectId thread_id = request->ReadThreadId();
1257         mod.threadOnly.threadId = thread_id;
1258       }
1259       break;
1260     case MK_CLASS_ONLY:
1261       {
1262         // For ClassPrepare, MethodEntry.
1263         RefTypeId class_id = request->ReadRefTypeId();
1264         mod.classOnly.refTypeId = class_id;
1265       }
1266       break;
1267     case MK_CLASS_MATCH:
1268       {
1269         // Restrict events to matching classes.
1270         // pattern is "java.foo.*", we want "java/foo/*".
1271         std::string pattern(request->ReadUtf8String());
1272         std::replace(pattern.begin(), pattern.end(), '.', '/');
1273         mod.classMatch.classPattern = strdup(pattern.c_str());
1274       }
1275       break;
1276     case MK_CLASS_EXCLUDE:
1277       {
1278         // Restrict events to non-matching classes.
1279         // pattern is "java.foo.*", we want "java/foo/*".
1280         std::string pattern(request->ReadUtf8String());
1281         std::replace(pattern.begin(), pattern.end(), '.', '/');
1282         mod.classExclude.classPattern = strdup(pattern.c_str());
1283       }
1284       break;
1285     case MK_LOCATION_ONLY:
1286       {
1287         // Restrict certain events based on location.
1288         JdwpLocation location = request->ReadLocation();
1289         mod.locationOnly.loc = location;
1290       }
1291       break;
1292     case MK_EXCEPTION_ONLY:
1293       {
1294         // Modifies EK_EXCEPTION events,
1295         mod.exceptionOnly.refTypeId = request->ReadRefTypeId();  // null => all exceptions.
1296         mod.exceptionOnly.caught = request->ReadEnum1<uint8_t>("caught");
1297         mod.exceptionOnly.uncaught = request->ReadEnum1<uint8_t>("uncaught");
1298       }
1299       break;
1300     case MK_FIELD_ONLY:
1301       {
1302         // For field access/modification events.
1303         RefTypeId declaring = request->ReadRefTypeId();
1304         FieldId fieldId = request->ReadFieldId();
1305         mod.fieldOnly.refTypeId = declaring;
1306         mod.fieldOnly.fieldId = fieldId;
1307       }
1308       break;
1309     case MK_STEP:
1310       {
1311         // For use with EK_SINGLE_STEP.
1312         ObjectId thread_id = request->ReadThreadId();
1313         uint32_t size = request->ReadUnsigned32("step size");
1314         uint32_t depth = request->ReadUnsigned32("step depth");
1315         VLOG(jdwp) << StringPrintf("    Step: thread=%#" PRIx64, thread_id)
1316                      << " size=" << JdwpStepSize(size) << " depth=" << JdwpStepDepth(depth);
1317 
1318         mod.step.threadId = thread_id;
1319         mod.step.size = size;
1320         mod.step.depth = depth;
1321       }
1322       break;
1323     case MK_INSTANCE_ONLY:
1324       {
1325         // Report events related to a specific object.
1326         ObjectId instance = request->ReadObjectId();
1327         mod.instanceOnly.objectId = instance;
1328       }
1329       break;
1330     default:
1331       LOG(WARNING) << "Unsupported modifier " << mod.modKind << " for event " << pEvent->eventKind;
1332       return JDWP::ERR_NOT_IMPLEMENTED;
1333     }
1334   }
1335 
1336   /*
1337    * We reply with an integer "requestID".
1338    */
1339   uint32_t requestId = state->NextEventSerial();
1340   expandBufAdd4BE(pReply, requestId);
1341 
1342   pEvent->requestId = requestId;
1343 
1344   VLOG(jdwp) << StringPrintf("    --> event requestId=%#x", requestId);
1345 
1346   /* add it to the list */
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();
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 typedef JdwpError (*JdwpRequestHandler)(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_.StoreSequentiallyConsistent(0);
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_.StoreSequentiallyConsistent(MilliTime());
1707   }
1708 
1709   return replyLength;
1710 }
1711 
1712 }  // namespace JDWP
1713 
1714 }  // namespace art
1715