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