Home | History | Annotate | Download | only in openjdkjvmti
      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