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