1 /* Copyright (C) 2016 The Android Open Source Project 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This file implements interfaces from the file jvmti.h. This implementation 5 * is licensed under the same terms as the file jvmti.h. The 6 * copyright and license information for the file jvmti.h follows. 7 * 8 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 9 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10 * 11 * This code is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License version 2 only, as 13 * published by the Free Software Foundation. Oracle designates this 14 * particular file as subject to the "Classpath" exception as provided 15 * by Oracle in the LICENSE file that accompanied this code. 16 * 17 * This code is distributed in the hope that it will be useful, but WITHOUT 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 20 * version 2 for more details (a copy is included in the LICENSE file that 21 * accompanied this code). 22 * 23 * You should have received a copy of the GNU General Public License version 24 * 2 along with this work; if not, write to the Free Software Foundation, 25 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 26 * 27 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 28 * or visit www.oracle.com if you need additional information or have any 29 * questions. 30 */ 31 32 #include "ti_method.h" 33 34 #include <type_traits> 35 36 #include "arch/context.h" 37 #include "art_jvmti.h" 38 #include "art_method-inl.h" 39 #include "base/enums.h" 40 #include "base/mutex-inl.h" 41 #include "deopt_manager.h" 42 #include "dex/code_item_accessors-inl.h" 43 #include "dex/dex_file_annotations.h" 44 #include "dex/dex_file_types.h" 45 #include "dex/modifiers.h" 46 #include "events-inl.h" 47 #include "gc_root-inl.h" 48 #include "jit/jit.h" 49 #include "jni/jni_internal.h" 50 #include "mirror/class-inl.h" 51 #include "mirror/class_loader.h" 52 #include "mirror/object-inl.h" 53 #include "mirror/object_array-inl.h" 54 #include "nativehelper/scoped_local_ref.h" 55 #include "oat_file.h" 56 #include "obj_ptr.h" 57 #include "runtime_callbacks.h" 58 #include "scoped_thread_state_change-inl.h" 59 #include "stack.h" 60 #include "thread-current-inl.h" 61 #include "thread.h" 62 #include "thread_list.h" 63 #include "ti_stack.h" 64 #include "ti_thread.h" 65 #include "ti_phase.h" 66 67 namespace openjdkjvmti { 68 69 struct TiMethodCallback : public art::MethodCallback { 70 void RegisterNativeMethod(art::ArtMethod* method, 71 const void* cur_method, 72 /*out*/void** new_method) 73 override REQUIRES_SHARED(art::Locks::mutator_lock_) { 74 if (event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kNativeMethodBind)) { 75 art::Thread* thread = art::Thread::Current(); 76 art::JNIEnvExt* jnienv = thread->GetJniEnv(); 77 ScopedLocalRef<jthread> thread_jni( 78 jnienv, PhaseUtil::IsLivePhase() ? jnienv->AddLocalReference<jthread>(thread->GetPeer()) 79 : nullptr); 80 art::ScopedThreadSuspension sts(thread, art::ThreadState::kNative); 81 event_handler->DispatchEvent<ArtJvmtiEvent::kNativeMethodBind>( 82 thread, 83 static_cast<JNIEnv*>(jnienv), 84 thread_jni.get(), 85 art::jni::EncodeArtMethod(method), 86 const_cast<void*>(cur_method), 87 new_method); 88 } 89 } 90 91 EventHandler* event_handler = nullptr; 92 }; 93 94 TiMethodCallback gMethodCallback; 95 96 void MethodUtil::Register(EventHandler* handler) { 97 gMethodCallback.event_handler = handler; 98 art::ScopedThreadStateChange stsc(art::Thread::Current(), 99 art::ThreadState::kWaitingForDebuggerToAttach); 100 art::ScopedSuspendAll ssa("Add method callback"); 101 art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks(); 102 callbacks->AddMethodCallback(&gMethodCallback); 103 } 104 105 void MethodUtil::Unregister() { 106 art::ScopedThreadStateChange stsc(art::Thread::Current(), 107 art::ThreadState::kWaitingForDebuggerToAttach); 108 art::ScopedSuspendAll ssa("Remove method callback"); 109 art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks(); 110 callbacks->RemoveMethodCallback(&gMethodCallback); 111 } 112 113 jvmtiError MethodUtil::GetBytecodes(jvmtiEnv* env, 114 jmethodID method, 115 jint* size_ptr, 116 unsigned char** bytecode_ptr) { 117 if (method == nullptr) { 118 return ERR(INVALID_METHODID); 119 } 120 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); 121 122 if (art_method->IsNative()) { 123 return ERR(NATIVE_METHOD); 124 } 125 126 if (size_ptr == nullptr || bytecode_ptr == nullptr) { 127 return ERR(NULL_POINTER); 128 } 129 130 art::ScopedObjectAccess soa(art::Thread::Current()); 131 art::CodeItemInstructionAccessor accessor(art_method->DexInstructions()); 132 if (!accessor.HasCodeItem()) { 133 *size_ptr = 0; 134 *bytecode_ptr = nullptr; 135 return OK; 136 } 137 // 2 bytes per instruction for dex code. 138 *size_ptr = accessor.InsnsSizeInCodeUnits() * 2; 139 jvmtiError err = env->Allocate(*size_ptr, bytecode_ptr); 140 if (err != OK) { 141 return err; 142 } 143 memcpy(*bytecode_ptr, accessor.Insns(), *size_ptr); 144 return OK; 145 } 146 147 jvmtiError MethodUtil::GetArgumentsSize(jvmtiEnv* env ATTRIBUTE_UNUSED, 148 jmethodID method, 149 jint* size_ptr) { 150 if (method == nullptr) { 151 return ERR(INVALID_METHODID); 152 } 153 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); 154 155 if (art_method->IsNative()) { 156 return ERR(NATIVE_METHOD); 157 } 158 159 if (size_ptr == nullptr) { 160 return ERR(NULL_POINTER); 161 } 162 163 art::ScopedObjectAccess soa(art::Thread::Current()); 164 if (art_method->IsProxyMethod() || art_method->IsAbstract()) { 165 // Use the shorty. 166 art::ArtMethod* base_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize); 167 size_t arg_count = art::ArtMethod::NumArgRegisters(base_method->GetShorty()); 168 if (!base_method->IsStatic()) { 169 arg_count++; 170 } 171 *size_ptr = static_cast<jint>(arg_count); 172 return ERR(NONE); 173 } 174 175 DCHECK_NE(art_method->GetCodeItemOffset(), 0u); 176 *size_ptr = art_method->DexInstructionData().InsSize(); 177 178 return ERR(NONE); 179 } 180 181 jvmtiError MethodUtil::GetLocalVariableTable(jvmtiEnv* env, 182 jmethodID method, 183 jint* entry_count_ptr, 184 jvmtiLocalVariableEntry** table_ptr) { 185 if (method == nullptr) { 186 return ERR(INVALID_METHODID); 187 } 188 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); 189 190 if (art_method->IsNative()) { 191 return ERR(NATIVE_METHOD); 192 } 193 194 if (entry_count_ptr == nullptr || table_ptr == nullptr) { 195 return ERR(NULL_POINTER); 196 } 197 198 art::ScopedObjectAccess soa(art::Thread::Current()); 199 200 const art::DexFile* const dex_file = art_method->GetDexFile(); 201 if (dex_file == nullptr) { 202 return ERR(ABSENT_INFORMATION); 203 } 204 205 // TODO HasCodeItem == false means that the method is abstract (or native, but we check that 206 // earlier). We should check what is returned by the RI in this situation since it's not clear 207 // what the appropriate return value is from the spec. 208 art::CodeItemDebugInfoAccessor accessor(art_method->DexInstructionDebugInfo()); 209 if (!accessor.HasCodeItem()) { 210 return ERR(ABSENT_INFORMATION); 211 } 212 213 std::vector<jvmtiLocalVariableEntry> variables; 214 jvmtiError err = OK; 215 216 auto release = [&](jint* out_entry_count_ptr, jvmtiLocalVariableEntry** out_table_ptr) { 217 jlong table_size = sizeof(jvmtiLocalVariableEntry) * variables.size(); 218 if (err != OK || 219 (err = env->Allocate(table_size, 220 reinterpret_cast<unsigned char**>(out_table_ptr))) != OK) { 221 for (jvmtiLocalVariableEntry& e : variables) { 222 env->Deallocate(reinterpret_cast<unsigned char*>(e.name)); 223 env->Deallocate(reinterpret_cast<unsigned char*>(e.signature)); 224 env->Deallocate(reinterpret_cast<unsigned char*>(e.generic_signature)); 225 } 226 return err; 227 } 228 *out_entry_count_ptr = variables.size(); 229 memcpy(*out_table_ptr, variables.data(), table_size); 230 return OK; 231 }; 232 233 auto visitor = [&](const art::DexFile::LocalInfo& entry) { 234 if (err != OK) { 235 return; 236 } 237 JvmtiUniquePtr<char[]> name_str = CopyString(env, entry.name_, &err); 238 if (err != OK) { 239 return; 240 } 241 JvmtiUniquePtr<char[]> sig_str = CopyString(env, entry.descriptor_, &err); 242 if (err != OK) { 243 return; 244 } 245 JvmtiUniquePtr<char[]> generic_sig_str = CopyString(env, entry.signature_, &err); 246 if (err != OK) { 247 return; 248 } 249 variables.push_back({ 250 .start_location = static_cast<jlocation>(entry.start_address_), 251 .length = static_cast<jint>(entry.end_address_ - entry.start_address_), 252 .name = name_str.release(), 253 .signature = sig_str.release(), 254 .generic_signature = generic_sig_str.release(), 255 .slot = entry.reg_, 256 }); 257 }; 258 259 if (!accessor.DecodeDebugLocalInfo(art_method->IsStatic(), 260 art_method->GetDexMethodIndex(), 261 visitor)) { 262 // Something went wrong with decoding the debug information. It might as well not be there. 263 return ERR(ABSENT_INFORMATION); 264 } 265 return release(entry_count_ptr, table_ptr); 266 } 267 268 jvmtiError MethodUtil::GetMaxLocals(jvmtiEnv* env ATTRIBUTE_UNUSED, 269 jmethodID method, 270 jint* max_ptr) { 271 if (method == nullptr) { 272 return ERR(INVALID_METHODID); 273 } 274 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); 275 276 if (art_method->IsNative()) { 277 return ERR(NATIVE_METHOD); 278 } 279 280 if (max_ptr == nullptr) { 281 return ERR(NULL_POINTER); 282 } 283 284 art::ScopedObjectAccess soa(art::Thread::Current()); 285 if (art_method->IsProxyMethod() || art_method->IsAbstract()) { 286 // This isn't specified as an error case, so return 0. 287 *max_ptr = 0; 288 return ERR(NONE); 289 } 290 291 DCHECK_NE(art_method->GetCodeItemOffset(), 0u); 292 *max_ptr = art_method->DexInstructionData().RegistersSize(); 293 294 return ERR(NONE); 295 } 296 297 jvmtiError MethodUtil::GetMethodName(jvmtiEnv* env, 298 jmethodID method, 299 char** name_ptr, 300 char** signature_ptr, 301 char** generic_ptr) { 302 art::ScopedObjectAccess soa(art::Thread::Current()); 303 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); 304 art_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize); 305 306 JvmtiUniquePtr<char[]> name_copy; 307 if (name_ptr != nullptr) { 308 const char* method_name = art_method->GetName(); 309 if (method_name == nullptr) { 310 method_name = "<error>"; 311 } 312 jvmtiError ret; 313 name_copy = CopyString(env, method_name, &ret); 314 if (name_copy == nullptr) { 315 return ret; 316 } 317 *name_ptr = name_copy.get(); 318 } 319 320 JvmtiUniquePtr<char[]> signature_copy; 321 if (signature_ptr != nullptr) { 322 const art::Signature sig = art_method->GetSignature(); 323 std::string str = sig.ToString(); 324 jvmtiError ret; 325 signature_copy = CopyString(env, str.c_str(), &ret); 326 if (signature_copy == nullptr) { 327 return ret; 328 } 329 *signature_ptr = signature_copy.get(); 330 } 331 332 if (generic_ptr != nullptr) { 333 *generic_ptr = nullptr; 334 if (!art_method->GetDeclaringClass()->IsProxyClass()) { 335 art::ObjPtr<art::mirror::ObjectArray<art::mirror::String>> str_array = 336 art::annotations::GetSignatureAnnotationForMethod(art_method); 337 if (str_array != nullptr) { 338 std::ostringstream oss; 339 for (int32_t i = 0; i != str_array->GetLength(); ++i) { 340 oss << str_array->Get(i)->ToModifiedUtf8(); 341 } 342 std::string output_string = oss.str(); 343 jvmtiError ret; 344 JvmtiUniquePtr<char[]> generic_copy = CopyString(env, output_string.c_str(), &ret); 345 if (generic_copy == nullptr) { 346 return ret; 347 } 348 *generic_ptr = generic_copy.release(); 349 } else if (soa.Self()->IsExceptionPending()) { 350 // TODO: Should we report an error here? 351 soa.Self()->ClearException(); 352 } 353 } 354 } 355 356 // Everything is fine, release the buffers. 357 name_copy.release(); 358 signature_copy.release(); 359 360 return ERR(NONE); 361 } 362 363 jvmtiError MethodUtil::GetMethodDeclaringClass(jvmtiEnv* env ATTRIBUTE_UNUSED, 364 jmethodID method, 365 jclass* declaring_class_ptr) { 366 if (declaring_class_ptr == nullptr) { 367 return ERR(NULL_POINTER); 368 } 369 370 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); 371 // Note: No GetInterfaceMethodIfProxy, we want to actual class. 372 373 art::ScopedObjectAccess soa(art::Thread::Current()); 374 art::ObjPtr<art::mirror::Class> klass = art_method->GetDeclaringClass(); 375 *declaring_class_ptr = soa.AddLocalReference<jclass>(klass); 376 377 return ERR(NONE); 378 } 379 380 jvmtiError MethodUtil::GetMethodLocation(jvmtiEnv* env ATTRIBUTE_UNUSED, 381 jmethodID method, 382 jlocation* start_location_ptr, 383 jlocation* end_location_ptr) { 384 if (method == nullptr) { 385 return ERR(INVALID_METHODID); 386 } 387 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); 388 389 if (art_method->IsNative()) { 390 return ERR(NATIVE_METHOD); 391 } 392 393 if (start_location_ptr == nullptr || end_location_ptr == nullptr) { 394 return ERR(NULL_POINTER); 395 } 396 397 art::ScopedObjectAccess soa(art::Thread::Current()); 398 if (art_method->IsProxyMethod() || art_method->IsAbstract()) { 399 // This isn't specified as an error case, so return -1/-1 as the RI does. 400 *start_location_ptr = -1; 401 *end_location_ptr = -1; 402 return ERR(NONE); 403 } 404 405 DCHECK_NE(art_method->GetCodeItemOffset(), 0u); 406 *start_location_ptr = 0; 407 *end_location_ptr = art_method->DexInstructions().InsnsSizeInCodeUnits() - 1; 408 409 return ERR(NONE); 410 } 411 412 jvmtiError MethodUtil::GetMethodModifiers(jvmtiEnv* env ATTRIBUTE_UNUSED, 413 jmethodID method, 414 jint* modifiers_ptr) { 415 if (modifiers_ptr == nullptr) { 416 return ERR(NULL_POINTER); 417 } 418 419 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); 420 uint32_t modifiers = art_method->GetAccessFlags(); 421 422 // Note: Keep this code in sync with Executable.fixMethodFlags. 423 if ((modifiers & art::kAccAbstract) != 0) { 424 modifiers &= ~art::kAccNative; 425 } 426 modifiers &= ~art::kAccSynchronized; 427 if ((modifiers & art::kAccDeclaredSynchronized) != 0) { 428 modifiers |= art::kAccSynchronized; 429 } 430 modifiers &= art::kAccJavaFlagsMask; 431 432 *modifiers_ptr = modifiers; 433 return ERR(NONE); 434 } 435 436 jvmtiError MethodUtil::GetLineNumberTable(jvmtiEnv* env, 437 jmethodID method, 438 jint* entry_count_ptr, 439 jvmtiLineNumberEntry** table_ptr) { 440 if (method == nullptr) { 441 return ERR(NULL_POINTER); 442 } 443 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); 444 DCHECK(!art_method->IsRuntimeMethod()); 445 446 art::CodeItemDebugInfoAccessor accessor; 447 const art::DexFile* dex_file; 448 { 449 art::ScopedObjectAccess soa(art::Thread::Current()); 450 451 if (art_method->IsProxyMethod()) { 452 return ERR(ABSENT_INFORMATION); 453 } 454 if (art_method->IsNative()) { 455 return ERR(NATIVE_METHOD); 456 } 457 if (entry_count_ptr == nullptr || table_ptr == nullptr) { 458 return ERR(NULL_POINTER); 459 } 460 461 accessor = art::CodeItemDebugInfoAccessor(art_method->DexInstructionDebugInfo()); 462 dex_file = art_method->GetDexFile(); 463 DCHECK(accessor.HasCodeItem()) << art_method->PrettyMethod() << " " << dex_file->GetLocation(); 464 } 465 466 std::vector<jvmtiLineNumberEntry> context; 467 bool success = accessor.DecodeDebugPositionInfo([&](const art::DexFile::PositionInfo& entry) { 468 context.push_back({static_cast<jlocation>(entry.address_), static_cast<jint>(entry.line_)}); 469 return false; 470 }); 471 if (!success) { 472 return ERR(ABSENT_INFORMATION); 473 } 474 475 unsigned char* data; 476 jlong mem_size = context.size() * sizeof(jvmtiLineNumberEntry); 477 jvmtiError alloc_error = env->Allocate(mem_size, &data); 478 if (alloc_error != ERR(NONE)) { 479 return alloc_error; 480 } 481 *table_ptr = reinterpret_cast<jvmtiLineNumberEntry*>(data); 482 memcpy(*table_ptr, context.data(), mem_size); 483 *entry_count_ptr = static_cast<jint>(context.size()); 484 485 return ERR(NONE); 486 } 487 488 template <typename T> 489 static jvmtiError IsMethodT(jvmtiEnv* env ATTRIBUTE_UNUSED, 490 jmethodID method, 491 T test, 492 jboolean* is_t_ptr) { 493 if (method == nullptr) { 494 return ERR(INVALID_METHODID); 495 } 496 if (is_t_ptr == nullptr) { 497 return ERR(NULL_POINTER); 498 } 499 500 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); 501 *is_t_ptr = test(art_method) ? JNI_TRUE : JNI_FALSE; 502 503 return ERR(NONE); 504 } 505 506 jvmtiError MethodUtil::IsMethodNative(jvmtiEnv* env, jmethodID m, jboolean* is_native_ptr) { 507 auto test = [](art::ArtMethod* method) { 508 return method->IsNative(); 509 }; 510 return IsMethodT(env, m, test, is_native_ptr); 511 } 512 513 jvmtiError MethodUtil::IsMethodObsolete(jvmtiEnv* env, jmethodID m, jboolean* is_obsolete_ptr) { 514 auto test = [](art::ArtMethod* method) { 515 return method->IsObsolete(); 516 }; 517 return IsMethodT(env, m, test, is_obsolete_ptr); 518 } 519 520 jvmtiError MethodUtil::IsMethodSynthetic(jvmtiEnv* env, jmethodID m, jboolean* is_synthetic_ptr) { 521 auto test = [](art::ArtMethod* method) { 522 return method->IsSynthetic(); 523 }; 524 return IsMethodT(env, m, test, is_synthetic_ptr); 525 } 526 527 class CommonLocalVariableClosure : public art::Closure { 528 public: 529 CommonLocalVariableClosure(jint depth, jint slot) 530 : result_(ERR(INTERNAL)), depth_(depth), slot_(slot) {} 531 532 void Run(art::Thread* self) override REQUIRES(art::Locks::mutator_lock_) { 533 art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current()); 534 bool needs_instrument; 535 { 536 art::ScopedAssertNoThreadSuspension sants("CommonLocalVariableClosure::Run"); 537 std::unique_ptr<art::Context> context(art::Context::Create()); 538 FindFrameAtDepthVisitor visitor(self, context.get(), depth_); 539 visitor.WalkStack(); 540 if (!visitor.FoundFrame()) { 541 // Must have been a bad depth. 542 result_ = ERR(NO_MORE_FRAMES); 543 return; 544 } 545 art::ArtMethod* method = visitor.GetMethod(); 546 // Native and 'art' proxy methods don't have registers. 547 if (method->IsNative() || method->IsProxyMethod()) { 548 // TODO It might be useful to fake up support for get at least on proxy frames. 549 result_ = ERR(OPAQUE_FRAME); 550 return; 551 } else if (method->DexInstructionData().RegistersSize() <= slot_) { 552 result_ = ERR(INVALID_SLOT); 553 return; 554 } 555 needs_instrument = !visitor.IsShadowFrame(); 556 uint32_t pc = visitor.GetDexPc(/*abort_on_failure=*/false); 557 if (pc == art::dex::kDexNoIndex) { 558 // Cannot figure out current PC. 559 result_ = ERR(OPAQUE_FRAME); 560 return; 561 } 562 std::string descriptor; 563 art::Primitive::Type slot_type = art::Primitive::kPrimVoid; 564 jvmtiError err = GetSlotType(method, pc, &descriptor, &slot_type); 565 if (err != OK) { 566 result_ = err; 567 return; 568 } 569 570 err = GetTypeError(method, slot_type, descriptor); 571 if (err != OK) { 572 result_ = err; 573 return; 574 } 575 result_ = Execute(method, visitor); 576 } 577 if (needs_instrument) { 578 DeoptManager::Get()->DeoptimizeThread(self); 579 } 580 } 581 582 virtual jvmtiError GetResult() { 583 return result_; 584 } 585 586 protected: 587 virtual jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor) 588 REQUIRES_SHARED(art::Locks::mutator_lock_) = 0; 589 virtual jvmtiError GetTypeError(art::ArtMethod* method, 590 art::Primitive::Type type, 591 const std::string& descriptor) 592 REQUIRES_SHARED(art::Locks::mutator_lock_) = 0; 593 594 jvmtiError GetSlotType(art::ArtMethod* method, 595 uint32_t dex_pc, 596 /*out*/std::string* descriptor, 597 /*out*/art::Primitive::Type* type) 598 REQUIRES(art::Locks::mutator_lock_) { 599 const art::DexFile* dex_file = method->GetDexFile(); 600 if (dex_file == nullptr) { 601 return ERR(OPAQUE_FRAME); 602 } 603 art::CodeItemDebugInfoAccessor accessor(method->DexInstructionDebugInfo()); 604 if (!accessor.HasCodeItem()) { 605 return ERR(OPAQUE_FRAME); 606 } 607 bool found = false; 608 *type = art::Primitive::kPrimVoid; 609 descriptor->clear(); 610 auto visitor = [&](const art::DexFile::LocalInfo& entry) { 611 if (!found && 612 entry.start_address_ <= dex_pc && 613 entry.end_address_ > dex_pc && 614 entry.reg_ == slot_) { 615 found = true; 616 *type = art::Primitive::GetType(entry.descriptor_[0]); 617 *descriptor = entry.descriptor_; 618 } 619 }; 620 if (!accessor.DecodeDebugLocalInfo(method->IsStatic(), method->GetDexMethodIndex(), visitor) || 621 !found) { 622 // Something went wrong with decoding the debug information. It might as well not be there. 623 return ERR(INVALID_SLOT); 624 } 625 return OK; 626 } 627 628 jvmtiError result_; 629 jint depth_; 630 jint slot_; 631 }; 632 633 class GetLocalVariableClosure : public CommonLocalVariableClosure { 634 public: 635 GetLocalVariableClosure(jint depth, 636 jint slot, 637 art::Primitive::Type type, 638 jvalue* val) 639 : CommonLocalVariableClosure(depth, slot), 640 type_(type), 641 val_(val), 642 obj_val_(nullptr) {} 643 644 jvmtiError GetResult() override REQUIRES_SHARED(art::Locks::mutator_lock_) { 645 if (result_ == OK && type_ == art::Primitive::kPrimNot) { 646 if (obj_val_ == nullptr) { 647 val_->l = nullptr; 648 } else { 649 art::JNIEnvExt* jni = art::Thread::Current()->GetJniEnv(); 650 val_->l = static_cast<JNIEnv*>(jni)->NewLocalRef(obj_val_); 651 jni->DeleteGlobalRef(obj_val_); 652 obj_val_ = nullptr; 653 } 654 } 655 return CommonLocalVariableClosure::GetResult(); 656 } 657 658 protected: 659 jvmtiError GetTypeError(art::ArtMethod* method ATTRIBUTE_UNUSED, 660 art::Primitive::Type slot_type, 661 const std::string& descriptor ATTRIBUTE_UNUSED) 662 override REQUIRES_SHARED(art::Locks::mutator_lock_) { 663 switch (slot_type) { 664 case art::Primitive::kPrimByte: 665 case art::Primitive::kPrimChar: 666 case art::Primitive::kPrimInt: 667 case art::Primitive::kPrimShort: 668 case art::Primitive::kPrimBoolean: 669 return type_ == art::Primitive::kPrimInt ? OK : ERR(TYPE_MISMATCH); 670 case art::Primitive::kPrimLong: 671 case art::Primitive::kPrimFloat: 672 case art::Primitive::kPrimDouble: 673 case art::Primitive::kPrimNot: 674 return type_ == slot_type ? OK : ERR(TYPE_MISMATCH); 675 case art::Primitive::kPrimVoid: 676 LOG(FATAL) << "Unexpected primitive type " << slot_type; 677 UNREACHABLE(); 678 } 679 } 680 681 jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor) 682 override REQUIRES_SHARED(art::Locks::mutator_lock_) { 683 switch (type_) { 684 case art::Primitive::kPrimNot: { 685 uint32_t ptr_val; 686 if (!visitor.GetVReg(method, 687 static_cast<uint16_t>(slot_), 688 art::kReferenceVReg, 689 &ptr_val)) { 690 return ERR(OPAQUE_FRAME); 691 } 692 art::JNIEnvExt* jni = art::Thread::Current()->GetJniEnv(); 693 art::ObjPtr<art::mirror::Object> obj(reinterpret_cast<art::mirror::Object*>(ptr_val)); 694 ScopedLocalRef<jobject> local( 695 jni, obj.IsNull() ? nullptr : jni->AddLocalReference<jobject>(obj)); 696 obj_val_ = jni->NewGlobalRef(local.get()); 697 break; 698 } 699 case art::Primitive::kPrimInt: 700 case art::Primitive::kPrimFloat: { 701 if (!visitor.GetVReg(method, 702 static_cast<uint16_t>(slot_), 703 type_ == art::Primitive::kPrimFloat ? art::kFloatVReg : art::kIntVReg, 704 reinterpret_cast<uint32_t*>(&val_->i))) { 705 return ERR(OPAQUE_FRAME); 706 } 707 break; 708 } 709 case art::Primitive::kPrimDouble: 710 case art::Primitive::kPrimLong: { 711 auto lo_type = type_ == art::Primitive::kPrimLong ? art::kLongLoVReg : art::kDoubleLoVReg; 712 auto high_type = type_ == art::Primitive::kPrimLong ? art::kLongHiVReg : art::kDoubleHiVReg; 713 if (!visitor.GetVRegPair(method, 714 static_cast<uint16_t>(slot_), 715 lo_type, 716 high_type, 717 reinterpret_cast<uint64_t*>(&val_->j))) { 718 return ERR(OPAQUE_FRAME); 719 } 720 break; 721 } 722 default: { 723 LOG(FATAL) << "unexpected register type " << type_; 724 UNREACHABLE(); 725 } 726 } 727 return OK; 728 } 729 730 private: 731 art::Primitive::Type type_; 732 jvalue* val_; 733 // A global reference to the return value. We use the global reference to safely transfer the 734 // value between threads. 735 jobject obj_val_; 736 }; 737 738 jvmtiError MethodUtil::GetLocalVariableGeneric(jvmtiEnv* env ATTRIBUTE_UNUSED, 739 jthread thread, 740 jint depth, 741 jint slot, 742 art::Primitive::Type type, 743 jvalue* val) { 744 if (depth < 0) { 745 return ERR(ILLEGAL_ARGUMENT); 746 } 747 art::Thread* self = art::Thread::Current(); 748 art::ScopedObjectAccess soa(self); 749 art::Locks::thread_list_lock_->ExclusiveLock(self); 750 art::Thread* target = nullptr; 751 jvmtiError err = ERR(INTERNAL); 752 if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { 753 art::Locks::thread_list_lock_->ExclusiveUnlock(self); 754 return err; 755 } 756 GetLocalVariableClosure c(depth, slot, type, val); 757 // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution. 758 if (!target->RequestSynchronousCheckpoint(&c)) { 759 return ERR(THREAD_NOT_ALIVE); 760 } else { 761 return c.GetResult(); 762 } 763 } 764 765 class SetLocalVariableClosure : public CommonLocalVariableClosure { 766 public: 767 SetLocalVariableClosure(art::Thread* caller, 768 jint depth, 769 jint slot, 770 art::Primitive::Type type, 771 jvalue val) 772 : CommonLocalVariableClosure(depth, slot), caller_(caller), type_(type), val_(val) {} 773 774 protected: 775 jvmtiError GetTypeError(art::ArtMethod* method, 776 art::Primitive::Type slot_type, 777 const std::string& descriptor) 778 override REQUIRES_SHARED(art::Locks::mutator_lock_) { 779 switch (slot_type) { 780 case art::Primitive::kPrimNot: { 781 if (type_ != art::Primitive::kPrimNot) { 782 return ERR(TYPE_MISMATCH); 783 } else if (val_.l == nullptr) { 784 return OK; 785 } else { 786 art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker(); 787 art::ObjPtr<art::mirror::Class> set_class = 788 caller_->DecodeJObject(val_.l)->GetClass(); 789 art::ObjPtr<art::mirror::ClassLoader> loader = 790 method->GetDeclaringClass()->GetClassLoader(); 791 art::ObjPtr<art::mirror::Class> slot_class = 792 cl->LookupClass(caller_, descriptor.c_str(), loader); 793 DCHECK(!slot_class.IsNull()); 794 return slot_class->IsAssignableFrom(set_class) ? OK : ERR(TYPE_MISMATCH); 795 } 796 } 797 case art::Primitive::kPrimByte: 798 case art::Primitive::kPrimChar: 799 case art::Primitive::kPrimInt: 800 case art::Primitive::kPrimShort: 801 case art::Primitive::kPrimBoolean: 802 return type_ == art::Primitive::kPrimInt ? OK : ERR(TYPE_MISMATCH); 803 case art::Primitive::kPrimLong: 804 case art::Primitive::kPrimFloat: 805 case art::Primitive::kPrimDouble: 806 return type_ == slot_type ? OK : ERR(TYPE_MISMATCH); 807 case art::Primitive::kPrimVoid: 808 LOG(FATAL) << "Unexpected primitive type " << slot_type; 809 UNREACHABLE(); 810 } 811 } 812 813 jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor) 814 override REQUIRES_SHARED(art::Locks::mutator_lock_) { 815 switch (type_) { 816 case art::Primitive::kPrimNot: { 817 uint32_t ptr_val; 818 art::ObjPtr<art::mirror::Object> obj(caller_->DecodeJObject(val_.l)); 819 ptr_val = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(obj.Ptr())); 820 if (!visitor.SetVReg(method, 821 static_cast<uint16_t>(slot_), 822 ptr_val, 823 art::kReferenceVReg)) { 824 return ERR(OPAQUE_FRAME); 825 } 826 break; 827 } 828 case art::Primitive::kPrimInt: 829 case art::Primitive::kPrimFloat: { 830 if (!visitor.SetVReg(method, 831 static_cast<uint16_t>(slot_), 832 static_cast<uint32_t>(val_.i), 833 type_ == art::Primitive::kPrimFloat ? art::kFloatVReg 834 : art::kIntVReg)) { 835 return ERR(OPAQUE_FRAME); 836 } 837 break; 838 } 839 case art::Primitive::kPrimDouble: 840 case art::Primitive::kPrimLong: { 841 auto lo_type = type_ == art::Primitive::kPrimLong ? art::kLongLoVReg : art::kDoubleLoVReg; 842 auto high_type = type_ == art::Primitive::kPrimLong ? art::kLongHiVReg : art::kDoubleHiVReg; 843 if (!visitor.SetVRegPair(method, 844 static_cast<uint16_t>(slot_), 845 static_cast<uint64_t>(val_.j), 846 lo_type, 847 high_type)) { 848 return ERR(OPAQUE_FRAME); 849 } 850 break; 851 } 852 default: { 853 LOG(FATAL) << "unexpected register type " << type_; 854 UNREACHABLE(); 855 } 856 } 857 return OK; 858 } 859 860 private: 861 art::Thread* caller_; 862 art::Primitive::Type type_; 863 jvalue val_; 864 }; 865 866 jvmtiError MethodUtil::SetLocalVariableGeneric(jvmtiEnv* env ATTRIBUTE_UNUSED, 867 jthread thread, 868 jint depth, 869 jint slot, 870 art::Primitive::Type type, 871 jvalue val) { 872 if (depth < 0) { 873 return ERR(ILLEGAL_ARGUMENT); 874 } 875 // Make sure that we know not to do any OSR anymore. 876 // TODO We should really keep track of this at the Frame granularity. 877 DeoptManager::Get()->SetLocalsUpdated(); 878 art::Thread* self = art::Thread::Current(); 879 art::ScopedObjectAccess soa(self); 880 art::Locks::thread_list_lock_->ExclusiveLock(self); 881 art::Thread* target = nullptr; 882 jvmtiError err = ERR(INTERNAL); 883 if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { 884 art::Locks::thread_list_lock_->ExclusiveUnlock(self); 885 return err; 886 } 887 SetLocalVariableClosure c(self, depth, slot, type, val); 888 // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution. 889 if (!target->RequestSynchronousCheckpoint(&c)) { 890 return ERR(THREAD_NOT_ALIVE); 891 } else { 892 return c.GetResult(); 893 } 894 } 895 896 class GetLocalInstanceClosure : public art::Closure { 897 public: 898 explicit GetLocalInstanceClosure(jint depth) 899 : result_(ERR(INTERNAL)), 900 depth_(depth), 901 val_(nullptr) {} 902 903 void Run(art::Thread* self) override REQUIRES(art::Locks::mutator_lock_) { 904 art::ScopedAssertNoThreadSuspension sants("GetLocalInstanceClosure::Run"); 905 art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current()); 906 std::unique_ptr<art::Context> context(art::Context::Create()); 907 FindFrameAtDepthVisitor visitor(self, context.get(), depth_); 908 visitor.WalkStack(); 909 if (!visitor.FoundFrame()) { 910 // Must have been a bad depth. 911 result_ = ERR(NO_MORE_FRAMES); 912 return; 913 } 914 result_ = OK; 915 val_ = art::GcRoot<art::mirror::Object>(visitor.GetThisObject()); 916 } 917 918 jvmtiError GetResult(jobject* data_out) REQUIRES_SHARED(art::Locks::mutator_lock_) { 919 if (result_ == OK) { 920 *data_out = val_.IsNull() 921 ? nullptr 922 : art::Thread::Current()->GetJniEnv()->AddLocalReference<jobject>(val_.Read()); 923 } 924 return result_; 925 } 926 927 private: 928 jvmtiError result_; 929 jint depth_; 930 art::GcRoot<art::mirror::Object> val_; 931 }; 932 933 jvmtiError MethodUtil::GetLocalInstance(jvmtiEnv* env ATTRIBUTE_UNUSED, 934 jthread thread, 935 jint depth, 936 jobject* data) { 937 if (depth < 0) { 938 return ERR(ILLEGAL_ARGUMENT); 939 } 940 art::Thread* self = art::Thread::Current(); 941 art::ScopedObjectAccess soa(self); 942 art::Locks::thread_list_lock_->ExclusiveLock(self); 943 art::Thread* target = nullptr; 944 jvmtiError err = ERR(INTERNAL); 945 if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { 946 art::Locks::thread_list_lock_->ExclusiveUnlock(self); 947 return err; 948 } 949 art::ScopedAssertNoThreadSuspension sants("Performing GetLocalInstance"); 950 GetLocalInstanceClosure c(depth); 951 // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution. We 952 // need to avoid suspending as we wait for the checkpoint to occur since we are (potentially) 953 // transfering a GcRoot across threads. 954 if (!target->RequestSynchronousCheckpoint(&c, art::ThreadState::kRunnable)) { 955 return ERR(THREAD_NOT_ALIVE); 956 } else { 957 return c.GetResult(data); 958 } 959 } 960 961 #define FOR_JVMTI_JVALUE_TYPES(fn) \ 962 fn(jint, art::Primitive::kPrimInt, i) \ 963 fn(jlong, art::Primitive::kPrimLong, j) \ 964 fn(jfloat, art::Primitive::kPrimFloat, f) \ 965 fn(jdouble, art::Primitive::kPrimDouble, d) \ 966 fn(jobject, art::Primitive::kPrimNot, l) 967 968 namespace impl { 969 970 template<typename T> void WriteJvalue(T, jvalue*); 971 template<typename T> void ReadJvalue(jvalue, T*); 972 template<typename T> art::Primitive::Type GetJNIType(); 973 974 #define JNI_TYPE_CHAR(type, prim, id) \ 975 template<> art::Primitive::Type GetJNIType<type>() { \ 976 return prim; \ 977 } 978 979 FOR_JVMTI_JVALUE_TYPES(JNI_TYPE_CHAR); 980 981 #undef JNI_TYPE_CHAR 982 983 #define RW_JVALUE(srctype, prim, id) \ 984 template<> void ReadJvalue<srctype>(jvalue in, std::add_pointer<srctype>::type out) { \ 985 *out = in.id; \ 986 } \ 987 template<> void WriteJvalue<srctype>(srctype in, jvalue* out) { \ 988 out->id = in; \ 989 } 990 991 FOR_JVMTI_JVALUE_TYPES(RW_JVALUE); 992 993 #undef RW_JVALUE 994 995 } // namespace impl 996 997 template<typename T> 998 jvmtiError MethodUtil::SetLocalVariable(jvmtiEnv* env, 999 jthread thread, 1000 jint depth, 1001 jint slot, 1002 T data) { 1003 jvalue v = {.j = 0}; 1004 art::Primitive::Type type = impl::GetJNIType<T>(); 1005 impl::WriteJvalue(data, &v); 1006 return SetLocalVariableGeneric(env, thread, depth, slot, type, v); 1007 } 1008 1009 template<typename T> 1010 jvmtiError MethodUtil::GetLocalVariable(jvmtiEnv* env, 1011 jthread thread, 1012 jint depth, 1013 jint slot, 1014 T* data) { 1015 if (data == nullptr) { 1016 return ERR(NULL_POINTER); 1017 } 1018 jvalue v = {.j = 0}; 1019 art::Primitive::Type type = impl::GetJNIType<T>(); 1020 jvmtiError err = GetLocalVariableGeneric(env, thread, depth, slot, type, &v); 1021 if (err != OK) { 1022 return err; 1023 } else { 1024 impl::ReadJvalue(v, data); 1025 return OK; 1026 } 1027 } 1028 1029 #define GET_SET_LV(srctype, prim, id) \ 1030 template jvmtiError MethodUtil::GetLocalVariable<srctype>(jvmtiEnv*, \ 1031 jthread, \ 1032 jint, \ 1033 jint, \ 1034 std::add_pointer<srctype>::type); \ 1035 template jvmtiError MethodUtil::SetLocalVariable<srctype>(jvmtiEnv*, \ 1036 jthread, \ 1037 jint, \ 1038 jint, \ 1039 srctype); 1040 1041 FOR_JVMTI_JVALUE_TYPES(GET_SET_LV); 1042 1043 #undef GET_SET_LV 1044 1045 #undef FOR_JVMTI_JVALUE_TYPES 1046 1047 } // namespace openjdkjvmti 1048