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