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