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