xref: /aosp_15_r20/art/openjdkjvmti/ti_method.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /* Copyright (C) 2016 The Android Open Source Project
2*795d594fSAndroid Build Coastguard Worker  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * This file implements interfaces from the file jvmti.h. This implementation
5*795d594fSAndroid Build Coastguard Worker  * is licensed under the same terms as the file jvmti.h.  The
6*795d594fSAndroid Build Coastguard Worker  * copyright and license information for the file jvmti.h follows.
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
9*795d594fSAndroid Build Coastguard Worker  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10*795d594fSAndroid Build Coastguard Worker  *
11*795d594fSAndroid Build Coastguard Worker  * This code is free software; you can redistribute it and/or modify it
12*795d594fSAndroid Build Coastguard Worker  * under the terms of the GNU General Public License version 2 only, as
13*795d594fSAndroid Build Coastguard Worker  * published by the Free Software Foundation.  Oracle designates this
14*795d594fSAndroid Build Coastguard Worker  * particular file as subject to the "Classpath" exception as provided
15*795d594fSAndroid Build Coastguard Worker  * by Oracle in the LICENSE file that accompanied this code.
16*795d594fSAndroid Build Coastguard Worker  *
17*795d594fSAndroid Build Coastguard Worker  * This code is distributed in the hope that it will be useful, but WITHOUT
18*795d594fSAndroid Build Coastguard Worker  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19*795d594fSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20*795d594fSAndroid Build Coastguard Worker  * version 2 for more details (a copy is included in the LICENSE file that
21*795d594fSAndroid Build Coastguard Worker  * accompanied this code).
22*795d594fSAndroid Build Coastguard Worker  *
23*795d594fSAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License version
24*795d594fSAndroid Build Coastguard Worker  * 2 along with this work; if not, write to the Free Software Foundation,
25*795d594fSAndroid Build Coastguard Worker  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26*795d594fSAndroid Build Coastguard Worker  *
27*795d594fSAndroid Build Coastguard Worker  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28*795d594fSAndroid Build Coastguard Worker  * or visit www.oracle.com if you need additional information or have any
29*795d594fSAndroid Build Coastguard Worker  * questions.
30*795d594fSAndroid Build Coastguard Worker  */
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker #include "ti_method.h"
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker #include <initializer_list>
35*795d594fSAndroid Build Coastguard Worker #include <type_traits>
36*795d594fSAndroid Build Coastguard Worker #include <variant>
37*795d594fSAndroid Build Coastguard Worker 
38*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
39*795d594fSAndroid Build Coastguard Worker #include "arch/context.h"
40*795d594fSAndroid Build Coastguard Worker #include "art_jvmti.h"
41*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
42*795d594fSAndroid Build Coastguard Worker #include "base/globals.h"
43*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
44*795d594fSAndroid Build Coastguard Worker #include "base/mutex-inl.h"
45*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
46*795d594fSAndroid Build Coastguard Worker #include "deopt_manager.h"
47*795d594fSAndroid Build Coastguard Worker #include "dex/code_item_accessors-inl.h"
48*795d594fSAndroid Build Coastguard Worker #include "dex/code_item_accessors.h"
49*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_annotations.h"
50*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
51*795d594fSAndroid Build Coastguard Worker #include "dex/dex_instruction.h"
52*795d594fSAndroid Build Coastguard Worker #include "dex/dex_instruction_iterator.h"
53*795d594fSAndroid Build Coastguard Worker #include "dex/modifiers.h"
54*795d594fSAndroid Build Coastguard Worker #include "dex/primitive.h"
55*795d594fSAndroid Build Coastguard Worker #include "events-inl.h"
56*795d594fSAndroid Build Coastguard Worker #include "gc_root-inl.h"
57*795d594fSAndroid Build Coastguard Worker #include "handle.h"
58*795d594fSAndroid Build Coastguard Worker #include "jit/jit.h"
59*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
60*795d594fSAndroid Build Coastguard Worker #include "jvmti.h"
61*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
62*795d594fSAndroid Build Coastguard Worker #include "mirror/class_loader.h"
63*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
64*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
65*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_local_ref.h"
66*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file.h"
67*795d594fSAndroid Build Coastguard Worker #include "obj_ptr.h"
68*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
69*795d594fSAndroid Build Coastguard Worker #include "runtime_callbacks.h"
70*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
71*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change.h"
72*795d594fSAndroid Build Coastguard Worker #include "stack.h"
73*795d594fSAndroid Build Coastguard Worker #include "thread-current-inl.h"
74*795d594fSAndroid Build Coastguard Worker #include "thread.h"
75*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
76*795d594fSAndroid Build Coastguard Worker #include "ti_logging.h"
77*795d594fSAndroid Build Coastguard Worker #include "ti_stack.h"
78*795d594fSAndroid Build Coastguard Worker #include "ti_thread.h"
79*795d594fSAndroid Build Coastguard Worker #include "ti_phase.h"
80*795d594fSAndroid Build Coastguard Worker #include "verifier/register_line-inl.h"
81*795d594fSAndroid Build Coastguard Worker #include "verifier/reg_type-inl.h"
82*795d594fSAndroid Build Coastguard Worker #include "verifier/reg_type_cache.h"
83*795d594fSAndroid Build Coastguard Worker #include "verifier/method_verifier-inl.h"
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker namespace openjdkjvmti {
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker struct TiMethodCallback : public art::MethodCallback {
RegisterNativeMethodopenjdkjvmti::TiMethodCallback88*795d594fSAndroid Build Coastguard Worker   void RegisterNativeMethod(art::ArtMethod* method,
89*795d594fSAndroid Build Coastguard Worker                             const void* cur_method,
90*795d594fSAndroid Build Coastguard Worker                             /*out*/void** new_method)
91*795d594fSAndroid Build Coastguard Worker       override REQUIRES_SHARED(art::Locks::mutator_lock_) {
92*795d594fSAndroid Build Coastguard Worker     if (event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kNativeMethodBind)) {
93*795d594fSAndroid Build Coastguard Worker       art::Thread* thread = art::Thread::Current();
94*795d594fSAndroid Build Coastguard Worker       art::JNIEnvExt* jnienv = thread->GetJniEnv();
95*795d594fSAndroid Build Coastguard Worker       ScopedLocalRef<jthread> thread_jni(
96*795d594fSAndroid Build Coastguard Worker           jnienv, PhaseUtil::IsLivePhase() ? jnienv->AddLocalReference<jthread>(thread->GetPeer())
97*795d594fSAndroid Build Coastguard Worker                                            : nullptr);
98*795d594fSAndroid Build Coastguard Worker       jmethodID method_id = art::jni::EncodeArtMethod(method);
99*795d594fSAndroid Build Coastguard Worker       art::ScopedThreadSuspension sts(thread, art::ThreadState::kNative);
100*795d594fSAndroid Build Coastguard Worker       event_handler->DispatchEvent<ArtJvmtiEvent::kNativeMethodBind>(
101*795d594fSAndroid Build Coastguard Worker           thread,
102*795d594fSAndroid Build Coastguard Worker           static_cast<JNIEnv*>(jnienv),
103*795d594fSAndroid Build Coastguard Worker           thread_jni.get(),
104*795d594fSAndroid Build Coastguard Worker           method_id,
105*795d594fSAndroid Build Coastguard Worker           const_cast<void*>(cur_method),
106*795d594fSAndroid Build Coastguard Worker           new_method);
107*795d594fSAndroid Build Coastguard Worker     }
108*795d594fSAndroid Build Coastguard Worker   }
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker   EventHandler* event_handler = nullptr;
111*795d594fSAndroid Build Coastguard Worker };
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker TiMethodCallback gMethodCallback;
114*795d594fSAndroid Build Coastguard Worker 
Register(EventHandler * handler)115*795d594fSAndroid Build Coastguard Worker void MethodUtil::Register(EventHandler* handler) {
116*795d594fSAndroid Build Coastguard Worker   gMethodCallback.event_handler = handler;
117*795d594fSAndroid Build Coastguard Worker   art::ScopedThreadStateChange stsc(art::Thread::Current(),
118*795d594fSAndroid Build Coastguard Worker                                     art::ThreadState::kWaitingForDebuggerToAttach);
119*795d594fSAndroid Build Coastguard Worker   art::ScopedSuspendAll ssa("Add method callback");
120*795d594fSAndroid Build Coastguard Worker   art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks();
121*795d594fSAndroid Build Coastguard Worker   callbacks->AddMethodCallback(&gMethodCallback);
122*795d594fSAndroid Build Coastguard Worker }
123*795d594fSAndroid Build Coastguard Worker 
Unregister()124*795d594fSAndroid Build Coastguard Worker void MethodUtil::Unregister() {
125*795d594fSAndroid Build Coastguard Worker   art::ScopedThreadStateChange stsc(art::Thread::Current(),
126*795d594fSAndroid Build Coastguard Worker                                     art::ThreadState::kWaitingForDebuggerToAttach);
127*795d594fSAndroid Build Coastguard Worker   art::ScopedSuspendAll ssa("Remove method callback");
128*795d594fSAndroid Build Coastguard Worker   art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks();
129*795d594fSAndroid Build Coastguard Worker   callbacks->RemoveMethodCallback(&gMethodCallback);
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker 
GetBytecodes(jvmtiEnv * env,jmethodID method,jint * size_ptr,unsigned char ** bytecode_ptr)132*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetBytecodes(jvmtiEnv* env,
133*795d594fSAndroid Build Coastguard Worker                                     jmethodID method,
134*795d594fSAndroid Build Coastguard Worker                                     jint* size_ptr,
135*795d594fSAndroid Build Coastguard Worker                                     unsigned char** bytecode_ptr) {
136*795d594fSAndroid Build Coastguard Worker   if (method == nullptr) {
137*795d594fSAndroid Build Coastguard Worker     return ERR(INVALID_METHODID);
138*795d594fSAndroid Build Coastguard Worker   }
139*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
140*795d594fSAndroid Build Coastguard Worker 
141*795d594fSAndroid Build Coastguard Worker   if (art_method->IsNative()) {
142*795d594fSAndroid Build Coastguard Worker     return ERR(NATIVE_METHOD);
143*795d594fSAndroid Build Coastguard Worker   }
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker   if (size_ptr == nullptr || bytecode_ptr == nullptr) {
146*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
147*795d594fSAndroid Build Coastguard Worker   }
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
150*795d594fSAndroid Build Coastguard Worker   art::CodeItemInstructionAccessor accessor(art_method->DexInstructions());
151*795d594fSAndroid Build Coastguard Worker   if (!accessor.HasCodeItem()) {
152*795d594fSAndroid Build Coastguard Worker     *size_ptr = 0;
153*795d594fSAndroid Build Coastguard Worker     *bytecode_ptr = nullptr;
154*795d594fSAndroid Build Coastguard Worker     return OK;
155*795d594fSAndroid Build Coastguard Worker   }
156*795d594fSAndroid Build Coastguard Worker   // 2 bytes per instruction for dex code.
157*795d594fSAndroid Build Coastguard Worker   *size_ptr = accessor.InsnsSizeInCodeUnits() * 2;
158*795d594fSAndroid Build Coastguard Worker   jvmtiError err = env->Allocate(*size_ptr, bytecode_ptr);
159*795d594fSAndroid Build Coastguard Worker   if (err != OK) {
160*795d594fSAndroid Build Coastguard Worker     return err;
161*795d594fSAndroid Build Coastguard Worker   }
162*795d594fSAndroid Build Coastguard Worker   memcpy(*bytecode_ptr, accessor.Insns(), *size_ptr);
163*795d594fSAndroid Build Coastguard Worker   return OK;
164*795d594fSAndroid Build Coastguard Worker }
165*795d594fSAndroid Build Coastguard Worker 
GetArgumentsSize(jvmtiEnv * env,jmethodID method,jint * size_ptr)166*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetArgumentsSize([[maybe_unused]] jvmtiEnv* env,
167*795d594fSAndroid Build Coastguard Worker                                         jmethodID method,
168*795d594fSAndroid Build Coastguard Worker                                         jint* size_ptr) {
169*795d594fSAndroid Build Coastguard Worker   if (method == nullptr) {
170*795d594fSAndroid Build Coastguard Worker     return ERR(INVALID_METHODID);
171*795d594fSAndroid Build Coastguard Worker   }
172*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
173*795d594fSAndroid Build Coastguard Worker 
174*795d594fSAndroid Build Coastguard Worker   if (art_method->IsNative()) {
175*795d594fSAndroid Build Coastguard Worker     return ERR(NATIVE_METHOD);
176*795d594fSAndroid Build Coastguard Worker   }
177*795d594fSAndroid Build Coastguard Worker 
178*795d594fSAndroid Build Coastguard Worker   if (size_ptr == nullptr) {
179*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
180*795d594fSAndroid Build Coastguard Worker   }
181*795d594fSAndroid Build Coastguard Worker 
182*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
183*795d594fSAndroid Build Coastguard Worker   if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
184*795d594fSAndroid Build Coastguard Worker     // Use the shorty.
185*795d594fSAndroid Build Coastguard Worker     art::ArtMethod* base_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize);
186*795d594fSAndroid Build Coastguard Worker     size_t arg_count = art::ArtMethod::NumArgRegisters(base_method->GetShortyView());
187*795d594fSAndroid Build Coastguard Worker     if (!base_method->IsStatic()) {
188*795d594fSAndroid Build Coastguard Worker       arg_count++;
189*795d594fSAndroid Build Coastguard Worker     }
190*795d594fSAndroid Build Coastguard Worker     *size_ptr = static_cast<jint>(arg_count);
191*795d594fSAndroid Build Coastguard Worker     return ERR(NONE);
192*795d594fSAndroid Build Coastguard Worker   }
193*795d594fSAndroid Build Coastguard Worker 
194*795d594fSAndroid Build Coastguard Worker   DCHECK(art_method->HasCodeItem());
195*795d594fSAndroid Build Coastguard Worker   DCHECK_NE(art_method->GetCodeItem(), nullptr);
196*795d594fSAndroid Build Coastguard Worker   *size_ptr = art_method->DexInstructionData().InsSize();
197*795d594fSAndroid Build Coastguard Worker 
198*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
199*795d594fSAndroid Build Coastguard Worker }
200*795d594fSAndroid Build Coastguard Worker 
GetLocalVariableTable(jvmtiEnv * env,jmethodID method,jint * entry_count_ptr,jvmtiLocalVariableEntry ** table_ptr)201*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetLocalVariableTable(jvmtiEnv* env,
202*795d594fSAndroid Build Coastguard Worker                                              jmethodID method,
203*795d594fSAndroid Build Coastguard Worker                                              jint* entry_count_ptr,
204*795d594fSAndroid Build Coastguard Worker                                              jvmtiLocalVariableEntry** table_ptr) {
205*795d594fSAndroid Build Coastguard Worker   if (method == nullptr) {
206*795d594fSAndroid Build Coastguard Worker     return ERR(INVALID_METHODID);
207*795d594fSAndroid Build Coastguard Worker   }
208*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
209*795d594fSAndroid Build Coastguard Worker 
210*795d594fSAndroid Build Coastguard Worker   if (art_method->IsNative()) {
211*795d594fSAndroid Build Coastguard Worker     return ERR(NATIVE_METHOD);
212*795d594fSAndroid Build Coastguard Worker   }
213*795d594fSAndroid Build Coastguard Worker 
214*795d594fSAndroid Build Coastguard Worker   if (entry_count_ptr == nullptr || table_ptr == nullptr) {
215*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
216*795d594fSAndroid Build Coastguard Worker   }
217*795d594fSAndroid Build Coastguard Worker 
218*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
219*795d594fSAndroid Build Coastguard Worker 
220*795d594fSAndroid Build Coastguard Worker   const art::DexFile* const dex_file = art_method->GetDexFile();
221*795d594fSAndroid Build Coastguard Worker   if (dex_file == nullptr) {
222*795d594fSAndroid Build Coastguard Worker     return ERR(ABSENT_INFORMATION);
223*795d594fSAndroid Build Coastguard Worker   }
224*795d594fSAndroid Build Coastguard Worker 
225*795d594fSAndroid Build Coastguard Worker   // TODO HasCodeItem == false means that the method is abstract (or native, but we check that
226*795d594fSAndroid Build Coastguard Worker   // earlier). We should check what is returned by the RI in this situation since it's not clear
227*795d594fSAndroid Build Coastguard Worker   // what the appropriate return value is from the spec.
228*795d594fSAndroid Build Coastguard Worker   art::CodeItemDebugInfoAccessor accessor(art_method->DexInstructionDebugInfo());
229*795d594fSAndroid Build Coastguard Worker   if (!accessor.HasCodeItem()) {
230*795d594fSAndroid Build Coastguard Worker     return ERR(ABSENT_INFORMATION);
231*795d594fSAndroid Build Coastguard Worker   }
232*795d594fSAndroid Build Coastguard Worker 
233*795d594fSAndroid Build Coastguard Worker   std::vector<jvmtiLocalVariableEntry> variables;
234*795d594fSAndroid Build Coastguard Worker   jvmtiError err = OK;
235*795d594fSAndroid Build Coastguard Worker 
236*795d594fSAndroid Build Coastguard Worker   auto release = [&](jint* out_entry_count_ptr, jvmtiLocalVariableEntry** out_table_ptr) {
237*795d594fSAndroid Build Coastguard Worker     jlong table_size = sizeof(jvmtiLocalVariableEntry) * variables.size();
238*795d594fSAndroid Build Coastguard Worker     if (err != OK ||
239*795d594fSAndroid Build Coastguard Worker         (err = env->Allocate(table_size,
240*795d594fSAndroid Build Coastguard Worker                               reinterpret_cast<unsigned char**>(out_table_ptr))) != OK) {
241*795d594fSAndroid Build Coastguard Worker       for (jvmtiLocalVariableEntry& e : variables) {
242*795d594fSAndroid Build Coastguard Worker         env->Deallocate(reinterpret_cast<unsigned char*>(e.name));
243*795d594fSAndroid Build Coastguard Worker         env->Deallocate(reinterpret_cast<unsigned char*>(e.signature));
244*795d594fSAndroid Build Coastguard Worker         env->Deallocate(reinterpret_cast<unsigned char*>(e.generic_signature));
245*795d594fSAndroid Build Coastguard Worker       }
246*795d594fSAndroid Build Coastguard Worker       return err;
247*795d594fSAndroid Build Coastguard Worker     }
248*795d594fSAndroid Build Coastguard Worker     *out_entry_count_ptr = variables.size();
249*795d594fSAndroid Build Coastguard Worker     memcpy(*out_table_ptr, variables.data(), table_size);
250*795d594fSAndroid Build Coastguard Worker     return OK;
251*795d594fSAndroid Build Coastguard Worker   };
252*795d594fSAndroid Build Coastguard Worker 
253*795d594fSAndroid Build Coastguard Worker   // To avoid defining visitor in the same line as the `if`. We define the lambda and use std::move.
254*795d594fSAndroid Build Coastguard Worker   auto visitor = [&](const art::DexFile::LocalInfo& entry) {
255*795d594fSAndroid Build Coastguard Worker     if (err != OK) {
256*795d594fSAndroid Build Coastguard Worker       return;
257*795d594fSAndroid Build Coastguard Worker     }
258*795d594fSAndroid Build Coastguard Worker     JvmtiUniquePtr<char[]> name_str = CopyString(env, entry.name_, &err);
259*795d594fSAndroid Build Coastguard Worker     if (err != OK) {
260*795d594fSAndroid Build Coastguard Worker       return;
261*795d594fSAndroid Build Coastguard Worker     }
262*795d594fSAndroid Build Coastguard Worker     JvmtiUniquePtr<char[]> sig_str = CopyString(env, entry.descriptor_, &err);
263*795d594fSAndroid Build Coastguard Worker     if (err != OK) {
264*795d594fSAndroid Build Coastguard Worker       return;
265*795d594fSAndroid Build Coastguard Worker     }
266*795d594fSAndroid Build Coastguard Worker     JvmtiUniquePtr<char[]> generic_sig_str = CopyString(env, entry.signature_, &err);
267*795d594fSAndroid Build Coastguard Worker     if (err != OK) {
268*795d594fSAndroid Build Coastguard Worker       return;
269*795d594fSAndroid Build Coastguard Worker     }
270*795d594fSAndroid Build Coastguard Worker     variables.push_back({
271*795d594fSAndroid Build Coastguard Worker       .start_location = static_cast<jlocation>(entry.start_address_),
272*795d594fSAndroid Build Coastguard Worker       .length = static_cast<jint>(entry.end_address_ - entry.start_address_),
273*795d594fSAndroid Build Coastguard Worker       .name = name_str.release(),
274*795d594fSAndroid Build Coastguard Worker       .signature = sig_str.release(),
275*795d594fSAndroid Build Coastguard Worker       .generic_signature = generic_sig_str.release(),
276*795d594fSAndroid Build Coastguard Worker       .slot = entry.reg_,
277*795d594fSAndroid Build Coastguard Worker     });
278*795d594fSAndroid Build Coastguard Worker   };
279*795d594fSAndroid Build Coastguard Worker 
280*795d594fSAndroid Build Coastguard Worker   if (!accessor.DecodeDebugLocalInfo(
281*795d594fSAndroid Build Coastguard Worker           art_method->IsStatic(), art_method->GetDexMethodIndex(), std::move(visitor))) {
282*795d594fSAndroid Build Coastguard Worker     // Something went wrong with decoding the debug information. It might as well not be there.
283*795d594fSAndroid Build Coastguard Worker     return ERR(ABSENT_INFORMATION);
284*795d594fSAndroid Build Coastguard Worker   }
285*795d594fSAndroid Build Coastguard Worker   return release(entry_count_ptr, table_ptr);
286*795d594fSAndroid Build Coastguard Worker }
287*795d594fSAndroid Build Coastguard Worker 
GetMaxLocals(jvmtiEnv * env,jmethodID method,jint * max_ptr)288*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetMaxLocals([[maybe_unused]] jvmtiEnv* env,
289*795d594fSAndroid Build Coastguard Worker                                     jmethodID method,
290*795d594fSAndroid Build Coastguard Worker                                     jint* max_ptr) {
291*795d594fSAndroid Build Coastguard Worker   if (method == nullptr) {
292*795d594fSAndroid Build Coastguard Worker     return ERR(INVALID_METHODID);
293*795d594fSAndroid Build Coastguard Worker   }
294*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
295*795d594fSAndroid Build Coastguard Worker 
296*795d594fSAndroid Build Coastguard Worker   if (art_method->IsNative()) {
297*795d594fSAndroid Build Coastguard Worker     return ERR(NATIVE_METHOD);
298*795d594fSAndroid Build Coastguard Worker   }
299*795d594fSAndroid Build Coastguard Worker 
300*795d594fSAndroid Build Coastguard Worker   if (max_ptr == nullptr) {
301*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
302*795d594fSAndroid Build Coastguard Worker   }
303*795d594fSAndroid Build Coastguard Worker 
304*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
305*795d594fSAndroid Build Coastguard Worker   if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
306*795d594fSAndroid Build Coastguard Worker     // This isn't specified as an error case, so return 0.
307*795d594fSAndroid Build Coastguard Worker     *max_ptr = 0;
308*795d594fSAndroid Build Coastguard Worker     return ERR(NONE);
309*795d594fSAndroid Build Coastguard Worker   }
310*795d594fSAndroid Build Coastguard Worker 
311*795d594fSAndroid Build Coastguard Worker   DCHECK(art_method->HasCodeItem());
312*795d594fSAndroid Build Coastguard Worker   DCHECK_NE(art_method->GetCodeItem(), nullptr);
313*795d594fSAndroid Build Coastguard Worker   *max_ptr = art_method->DexInstructionData().RegistersSize();
314*795d594fSAndroid Build Coastguard Worker 
315*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
316*795d594fSAndroid Build Coastguard Worker }
317*795d594fSAndroid Build Coastguard Worker 
GetMethodName(jvmtiEnv * env,jmethodID method,char ** name_ptr,char ** signature_ptr,char ** generic_ptr)318*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetMethodName(jvmtiEnv* env,
319*795d594fSAndroid Build Coastguard Worker                                      jmethodID method,
320*795d594fSAndroid Build Coastguard Worker                                      char** name_ptr,
321*795d594fSAndroid Build Coastguard Worker                                      char** signature_ptr,
322*795d594fSAndroid Build Coastguard Worker                                      char** generic_ptr) {
323*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
324*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
325*795d594fSAndroid Build Coastguard Worker   art_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize);
326*795d594fSAndroid Build Coastguard Worker 
327*795d594fSAndroid Build Coastguard Worker   JvmtiUniquePtr<char[]> name_copy;
328*795d594fSAndroid Build Coastguard Worker   if (name_ptr != nullptr) {
329*795d594fSAndroid Build Coastguard Worker     const char* method_name = art_method->GetName();
330*795d594fSAndroid Build Coastguard Worker     if (method_name == nullptr) {
331*795d594fSAndroid Build Coastguard Worker       method_name = "<error>";
332*795d594fSAndroid Build Coastguard Worker     }
333*795d594fSAndroid Build Coastguard Worker     jvmtiError ret;
334*795d594fSAndroid Build Coastguard Worker     name_copy = CopyString(env, method_name, &ret);
335*795d594fSAndroid Build Coastguard Worker     if (name_copy == nullptr) {
336*795d594fSAndroid Build Coastguard Worker       return ret;
337*795d594fSAndroid Build Coastguard Worker     }
338*795d594fSAndroid Build Coastguard Worker     *name_ptr = name_copy.get();
339*795d594fSAndroid Build Coastguard Worker   }
340*795d594fSAndroid Build Coastguard Worker 
341*795d594fSAndroid Build Coastguard Worker   JvmtiUniquePtr<char[]> signature_copy;
342*795d594fSAndroid Build Coastguard Worker   if (signature_ptr != nullptr) {
343*795d594fSAndroid Build Coastguard Worker     const art::Signature sig = art_method->GetSignature();
344*795d594fSAndroid Build Coastguard Worker     std::string str = sig.ToString();
345*795d594fSAndroid Build Coastguard Worker     jvmtiError ret;
346*795d594fSAndroid Build Coastguard Worker     signature_copy = CopyString(env, str.c_str(), &ret);
347*795d594fSAndroid Build Coastguard Worker     if (signature_copy == nullptr) {
348*795d594fSAndroid Build Coastguard Worker       return ret;
349*795d594fSAndroid Build Coastguard Worker     }
350*795d594fSAndroid Build Coastguard Worker     *signature_ptr = signature_copy.get();
351*795d594fSAndroid Build Coastguard Worker   }
352*795d594fSAndroid Build Coastguard Worker 
353*795d594fSAndroid Build Coastguard Worker   if (generic_ptr != nullptr) {
354*795d594fSAndroid Build Coastguard Worker     *generic_ptr = nullptr;
355*795d594fSAndroid Build Coastguard Worker     if (!art_method->GetDeclaringClass()->IsProxyClass()) {
356*795d594fSAndroid Build Coastguard Worker       art::ObjPtr<art::mirror::ObjectArray<art::mirror::String>> str_array =
357*795d594fSAndroid Build Coastguard Worker           art::annotations::GetSignatureAnnotationForMethod(art_method);
358*795d594fSAndroid Build Coastguard Worker       if (str_array != nullptr) {
359*795d594fSAndroid Build Coastguard Worker         std::ostringstream oss;
360*795d594fSAndroid Build Coastguard Worker         for (auto str : str_array->Iterate()) {
361*795d594fSAndroid Build Coastguard Worker           oss << str->ToModifiedUtf8();
362*795d594fSAndroid Build Coastguard Worker         }
363*795d594fSAndroid Build Coastguard Worker         std::string output_string = oss.str();
364*795d594fSAndroid Build Coastguard Worker         jvmtiError ret;
365*795d594fSAndroid Build Coastguard Worker         JvmtiUniquePtr<char[]> generic_copy = CopyString(env, output_string.c_str(), &ret);
366*795d594fSAndroid Build Coastguard Worker         if (generic_copy == nullptr) {
367*795d594fSAndroid Build Coastguard Worker           return ret;
368*795d594fSAndroid Build Coastguard Worker         }
369*795d594fSAndroid Build Coastguard Worker         *generic_ptr = generic_copy.release();
370*795d594fSAndroid Build Coastguard Worker       } else if (soa.Self()->IsExceptionPending()) {
371*795d594fSAndroid Build Coastguard Worker         // TODO: Should we report an error here?
372*795d594fSAndroid Build Coastguard Worker         soa.Self()->ClearException();
373*795d594fSAndroid Build Coastguard Worker       }
374*795d594fSAndroid Build Coastguard Worker     }
375*795d594fSAndroid Build Coastguard Worker   }
376*795d594fSAndroid Build Coastguard Worker 
377*795d594fSAndroid Build Coastguard Worker   // Everything is fine, release the buffers.
378*795d594fSAndroid Build Coastguard Worker   name_copy.release();
379*795d594fSAndroid Build Coastguard Worker   signature_copy.release();
380*795d594fSAndroid Build Coastguard Worker 
381*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
382*795d594fSAndroid Build Coastguard Worker }
383*795d594fSAndroid Build Coastguard Worker 
GetMethodDeclaringClass(jvmtiEnv * env,jmethodID method,jclass * declaring_class_ptr)384*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetMethodDeclaringClass([[maybe_unused]] jvmtiEnv* env,
385*795d594fSAndroid Build Coastguard Worker                                                jmethodID method,
386*795d594fSAndroid Build Coastguard Worker                                                jclass* declaring_class_ptr) {
387*795d594fSAndroid Build Coastguard Worker   if (declaring_class_ptr == nullptr) {
388*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
389*795d594fSAndroid Build Coastguard Worker   }
390*795d594fSAndroid Build Coastguard Worker 
391*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
392*795d594fSAndroid Build Coastguard Worker   // Note: No GetInterfaceMethodIfProxy, we want to actual class.
393*795d594fSAndroid Build Coastguard Worker 
394*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
395*795d594fSAndroid Build Coastguard Worker   art::ObjPtr<art::mirror::Class> klass = art_method->GetDeclaringClass();
396*795d594fSAndroid Build Coastguard Worker   *declaring_class_ptr = soa.AddLocalReference<jclass>(klass);
397*795d594fSAndroid Build Coastguard Worker 
398*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
399*795d594fSAndroid Build Coastguard Worker }
400*795d594fSAndroid Build Coastguard Worker 
GetMethodLocation(jvmtiEnv * env,jmethodID method,jlocation * start_location_ptr,jlocation * end_location_ptr)401*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetMethodLocation([[maybe_unused]] jvmtiEnv* env,
402*795d594fSAndroid Build Coastguard Worker                                          jmethodID method,
403*795d594fSAndroid Build Coastguard Worker                                          jlocation* start_location_ptr,
404*795d594fSAndroid Build Coastguard Worker                                          jlocation* end_location_ptr) {
405*795d594fSAndroid Build Coastguard Worker   if (method == nullptr) {
406*795d594fSAndroid Build Coastguard Worker     return ERR(INVALID_METHODID);
407*795d594fSAndroid Build Coastguard Worker   }
408*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
409*795d594fSAndroid Build Coastguard Worker 
410*795d594fSAndroid Build Coastguard Worker   if (art_method->IsNative()) {
411*795d594fSAndroid Build Coastguard Worker     return ERR(NATIVE_METHOD);
412*795d594fSAndroid Build Coastguard Worker   }
413*795d594fSAndroid Build Coastguard Worker 
414*795d594fSAndroid Build Coastguard Worker   if (start_location_ptr == nullptr || end_location_ptr == nullptr) {
415*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
416*795d594fSAndroid Build Coastguard Worker   }
417*795d594fSAndroid Build Coastguard Worker 
418*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(art::Thread::Current());
419*795d594fSAndroid Build Coastguard Worker   if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
420*795d594fSAndroid Build Coastguard Worker     // This isn't specified as an error case, so return -1/-1 as the RI does.
421*795d594fSAndroid Build Coastguard Worker     *start_location_ptr = -1;
422*795d594fSAndroid Build Coastguard Worker     *end_location_ptr = -1;
423*795d594fSAndroid Build Coastguard Worker     return ERR(NONE);
424*795d594fSAndroid Build Coastguard Worker   }
425*795d594fSAndroid Build Coastguard Worker 
426*795d594fSAndroid Build Coastguard Worker   DCHECK(art_method->HasCodeItem());
427*795d594fSAndroid Build Coastguard Worker   DCHECK_NE(art_method->GetCodeItem(), nullptr);
428*795d594fSAndroid Build Coastguard Worker   *start_location_ptr = 0;
429*795d594fSAndroid Build Coastguard Worker   *end_location_ptr = art_method->DexInstructions().InsnsSizeInCodeUnits() - 1;
430*795d594fSAndroid Build Coastguard Worker 
431*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
432*795d594fSAndroid Build Coastguard Worker }
433*795d594fSAndroid Build Coastguard Worker 
GetMethodModifiers(jvmtiEnv * env,jmethodID method,jint * modifiers_ptr)434*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetMethodModifiers([[maybe_unused]] jvmtiEnv* env,
435*795d594fSAndroid Build Coastguard Worker                                           jmethodID method,
436*795d594fSAndroid Build Coastguard Worker                                           jint* modifiers_ptr) {
437*795d594fSAndroid Build Coastguard Worker   if (modifiers_ptr == nullptr) {
438*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
439*795d594fSAndroid Build Coastguard Worker   }
440*795d594fSAndroid Build Coastguard Worker 
441*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
442*795d594fSAndroid Build Coastguard Worker   uint32_t modifiers = art_method->GetAccessFlags();
443*795d594fSAndroid Build Coastguard Worker 
444*795d594fSAndroid Build Coastguard Worker   // Note: Keep this code in sync with Executable.fixMethodFlags.
445*795d594fSAndroid Build Coastguard Worker   if ((modifiers & art::kAccAbstract) != 0) {
446*795d594fSAndroid Build Coastguard Worker     modifiers &= ~art::kAccNative;
447*795d594fSAndroid Build Coastguard Worker   }
448*795d594fSAndroid Build Coastguard Worker   modifiers &= ~art::kAccSynchronized;
449*795d594fSAndroid Build Coastguard Worker   if ((modifiers & art::kAccDeclaredSynchronized) != 0) {
450*795d594fSAndroid Build Coastguard Worker     modifiers |= art::kAccSynchronized;
451*795d594fSAndroid Build Coastguard Worker   }
452*795d594fSAndroid Build Coastguard Worker   modifiers &= art::kAccJavaFlagsMask;
453*795d594fSAndroid Build Coastguard Worker 
454*795d594fSAndroid Build Coastguard Worker   *modifiers_ptr = modifiers;
455*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
456*795d594fSAndroid Build Coastguard Worker }
457*795d594fSAndroid Build Coastguard Worker 
GetLineNumberTable(jvmtiEnv * env,jmethodID method,jint * entry_count_ptr,jvmtiLineNumberEntry ** table_ptr)458*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetLineNumberTable(jvmtiEnv* env,
459*795d594fSAndroid Build Coastguard Worker                                           jmethodID method,
460*795d594fSAndroid Build Coastguard Worker                                           jint* entry_count_ptr,
461*795d594fSAndroid Build Coastguard Worker                                           jvmtiLineNumberEntry** table_ptr) {
462*795d594fSAndroid Build Coastguard Worker   if (method == nullptr) {
463*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
464*795d594fSAndroid Build Coastguard Worker   }
465*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
466*795d594fSAndroid Build Coastguard Worker   DCHECK(!art_method->IsRuntimeMethod());
467*795d594fSAndroid Build Coastguard Worker 
468*795d594fSAndroid Build Coastguard Worker   art::CodeItemDebugInfoAccessor accessor;
469*795d594fSAndroid Build Coastguard Worker   const art::DexFile* dex_file;
470*795d594fSAndroid Build Coastguard Worker   {
471*795d594fSAndroid Build Coastguard Worker     art::ScopedObjectAccess soa(art::Thread::Current());
472*795d594fSAndroid Build Coastguard Worker 
473*795d594fSAndroid Build Coastguard Worker     if (art_method->IsProxyMethod()) {
474*795d594fSAndroid Build Coastguard Worker       return ERR(ABSENT_INFORMATION);
475*795d594fSAndroid Build Coastguard Worker     }
476*795d594fSAndroid Build Coastguard Worker     if (art_method->IsNative()) {
477*795d594fSAndroid Build Coastguard Worker       return ERR(NATIVE_METHOD);
478*795d594fSAndroid Build Coastguard Worker     }
479*795d594fSAndroid Build Coastguard Worker     if (entry_count_ptr == nullptr || table_ptr == nullptr) {
480*795d594fSAndroid Build Coastguard Worker       return ERR(NULL_POINTER);
481*795d594fSAndroid Build Coastguard Worker     }
482*795d594fSAndroid Build Coastguard Worker 
483*795d594fSAndroid Build Coastguard Worker     accessor = art::CodeItemDebugInfoAccessor(art_method->DexInstructionDebugInfo());
484*795d594fSAndroid Build Coastguard Worker     dex_file = art_method->GetDexFile();
485*795d594fSAndroid Build Coastguard Worker     DCHECK(accessor.HasCodeItem()) << art_method->PrettyMethod() << " " << dex_file->GetLocation();
486*795d594fSAndroid Build Coastguard Worker   }
487*795d594fSAndroid Build Coastguard Worker 
488*795d594fSAndroid Build Coastguard Worker   std::vector<jvmtiLineNumberEntry> context;
489*795d594fSAndroid Build Coastguard Worker   bool success = accessor.DecodeDebugPositionInfo([&](const art::DexFile::PositionInfo& entry) {
490*795d594fSAndroid Build Coastguard Worker     context.push_back({static_cast<jlocation>(entry.address_), static_cast<jint>(entry.line_)});
491*795d594fSAndroid Build Coastguard Worker     return false;
492*795d594fSAndroid Build Coastguard Worker   });
493*795d594fSAndroid Build Coastguard Worker   if (!success) {
494*795d594fSAndroid Build Coastguard Worker     return ERR(ABSENT_INFORMATION);
495*795d594fSAndroid Build Coastguard Worker   }
496*795d594fSAndroid Build Coastguard Worker 
497*795d594fSAndroid Build Coastguard Worker   unsigned char* data;
498*795d594fSAndroid Build Coastguard Worker   jlong mem_size = context.size() * sizeof(jvmtiLineNumberEntry);
499*795d594fSAndroid Build Coastguard Worker   jvmtiError alloc_error = env->Allocate(mem_size, &data);
500*795d594fSAndroid Build Coastguard Worker   if (alloc_error != ERR(NONE)) {
501*795d594fSAndroid Build Coastguard Worker     return alloc_error;
502*795d594fSAndroid Build Coastguard Worker   }
503*795d594fSAndroid Build Coastguard Worker   *table_ptr = reinterpret_cast<jvmtiLineNumberEntry*>(data);
504*795d594fSAndroid Build Coastguard Worker   memcpy(*table_ptr, context.data(), mem_size);
505*795d594fSAndroid Build Coastguard Worker   *entry_count_ptr = static_cast<jint>(context.size());
506*795d594fSAndroid Build Coastguard Worker 
507*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
508*795d594fSAndroid Build Coastguard Worker }
509*795d594fSAndroid Build Coastguard Worker 
510*795d594fSAndroid Build Coastguard Worker template <typename T>
IsMethodT(jvmtiEnv * env,jmethodID method,T test,jboolean * is_t_ptr)511*795d594fSAndroid Build Coastguard Worker static jvmtiError IsMethodT([[maybe_unused]] jvmtiEnv* env,
512*795d594fSAndroid Build Coastguard Worker                             jmethodID method,
513*795d594fSAndroid Build Coastguard Worker                             T test,
514*795d594fSAndroid Build Coastguard Worker                             jboolean* is_t_ptr) {
515*795d594fSAndroid Build Coastguard Worker   if (method == nullptr) {
516*795d594fSAndroid Build Coastguard Worker     return ERR(INVALID_METHODID);
517*795d594fSAndroid Build Coastguard Worker   }
518*795d594fSAndroid Build Coastguard Worker   if (is_t_ptr == nullptr) {
519*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
520*795d594fSAndroid Build Coastguard Worker   }
521*795d594fSAndroid Build Coastguard Worker 
522*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
523*795d594fSAndroid Build Coastguard Worker   *is_t_ptr = test(art_method) ? JNI_TRUE : JNI_FALSE;
524*795d594fSAndroid Build Coastguard Worker 
525*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
526*795d594fSAndroid Build Coastguard Worker }
527*795d594fSAndroid Build Coastguard Worker 
IsMethodNative(jvmtiEnv * env,jmethodID m,jboolean * is_native_ptr)528*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::IsMethodNative(jvmtiEnv* env, jmethodID m, jboolean* is_native_ptr) {
529*795d594fSAndroid Build Coastguard Worker   auto test = [](art::ArtMethod* method) {
530*795d594fSAndroid Build Coastguard Worker     return method->IsNative();
531*795d594fSAndroid Build Coastguard Worker   };
532*795d594fSAndroid Build Coastguard Worker   return IsMethodT(env, m, test, is_native_ptr);
533*795d594fSAndroid Build Coastguard Worker }
534*795d594fSAndroid Build Coastguard Worker 
IsMethodObsolete(jvmtiEnv * env,jmethodID m,jboolean * is_obsolete_ptr)535*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::IsMethodObsolete(jvmtiEnv* env, jmethodID m, jboolean* is_obsolete_ptr) {
536*795d594fSAndroid Build Coastguard Worker   auto test = [](art::ArtMethod* method) {
537*795d594fSAndroid Build Coastguard Worker     return method->IsObsolete();
538*795d594fSAndroid Build Coastguard Worker   };
539*795d594fSAndroid Build Coastguard Worker   return IsMethodT(env, m, test, is_obsolete_ptr);
540*795d594fSAndroid Build Coastguard Worker }
541*795d594fSAndroid Build Coastguard Worker 
IsMethodSynthetic(jvmtiEnv * env,jmethodID m,jboolean * is_synthetic_ptr)542*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::IsMethodSynthetic(jvmtiEnv* env, jmethodID m, jboolean* is_synthetic_ptr) {
543*795d594fSAndroid Build Coastguard Worker   auto test = [](art::ArtMethod* method) {
544*795d594fSAndroid Build Coastguard Worker     return method->IsSynthetic();
545*795d594fSAndroid Build Coastguard Worker   };
546*795d594fSAndroid Build Coastguard Worker   return IsMethodT(env, m, test, is_synthetic_ptr);
547*795d594fSAndroid Build Coastguard Worker }
548*795d594fSAndroid Build Coastguard Worker 
549*795d594fSAndroid Build Coastguard Worker class CommonLocalVariableClosure : public art::Closure {
550*795d594fSAndroid Build Coastguard Worker  public:
551*795d594fSAndroid Build Coastguard Worker   // The verifier isn't always able to be as specific as the local-variable-table. We can only get
552*795d594fSAndroid Build Coastguard Worker   // 32-bit, 64-bit or reference.
553*795d594fSAndroid Build Coastguard Worker   enum class VerifierPrimitiveType {
554*795d594fSAndroid Build Coastguard Worker     k32BitValue,  // float, int, short, char, boolean, byte
555*795d594fSAndroid Build Coastguard Worker     k64BitValue,  // double, long
556*795d594fSAndroid Build Coastguard Worker     kReferenceValue,  // Object
557*795d594fSAndroid Build Coastguard Worker     kZeroValue,  // null or zero constant. Might be either k32BitValue or kReferenceValue
558*795d594fSAndroid Build Coastguard Worker   };
559*795d594fSAndroid Build Coastguard Worker 
560*795d594fSAndroid Build Coastguard Worker   using SlotType = std::variant<art::Primitive::Type, VerifierPrimitiveType>;
561*795d594fSAndroid Build Coastguard Worker 
CommonLocalVariableClosure(jvmtiEnv * jvmti,jint depth,jint slot)562*795d594fSAndroid Build Coastguard Worker   CommonLocalVariableClosure(jvmtiEnv* jvmti, jint depth, jint slot)
563*795d594fSAndroid Build Coastguard Worker       : jvmti_(jvmti), result_(ERR(INTERNAL)), depth_(depth), slot_(slot) {}
564*795d594fSAndroid Build Coastguard Worker 
Run(art::Thread * self)565*795d594fSAndroid Build Coastguard Worker   void Run(art::Thread* self) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
566*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current());
567*795d594fSAndroid Build Coastguard Worker     bool needs_instrument;
568*795d594fSAndroid Build Coastguard Worker     {
569*795d594fSAndroid Build Coastguard Worker       art::ScopedAssertNoThreadSuspension sants("CommonLocalVariableClosure::Run");
570*795d594fSAndroid Build Coastguard Worker       std::unique_ptr<art::Context> context(art::Context::Create());
571*795d594fSAndroid Build Coastguard Worker       FindFrameAtDepthVisitor visitor(self, context.get(), depth_);
572*795d594fSAndroid Build Coastguard Worker       visitor.WalkStack();
573*795d594fSAndroid Build Coastguard Worker       if (!visitor.FoundFrame()) {
574*795d594fSAndroid Build Coastguard Worker         // Must have been a bad depth.
575*795d594fSAndroid Build Coastguard Worker         result_ = ERR(NO_MORE_FRAMES);
576*795d594fSAndroid Build Coastguard Worker         return;
577*795d594fSAndroid Build Coastguard Worker       }
578*795d594fSAndroid Build Coastguard Worker       art::ArtMethod* method = visitor.GetMethod();
579*795d594fSAndroid Build Coastguard Worker       // Native and 'art' proxy methods don't have registers.
580*795d594fSAndroid Build Coastguard Worker       if (method->IsNative() || method->IsProxyMethod()) {
581*795d594fSAndroid Build Coastguard Worker         // TODO It might be useful to fake up support for get at least on proxy frames.
582*795d594fSAndroid Build Coastguard Worker         result_ = ERR(OPAQUE_FRAME);
583*795d594fSAndroid Build Coastguard Worker         return;
584*795d594fSAndroid Build Coastguard Worker       } else if (slot_ >= method->DexInstructionData().RegistersSize() || slot_ < 0) {
585*795d594fSAndroid Build Coastguard Worker         result_ = ERR(INVALID_SLOT);
586*795d594fSAndroid Build Coastguard Worker         return;
587*795d594fSAndroid Build Coastguard Worker       }
588*795d594fSAndroid Build Coastguard Worker       needs_instrument = !visitor.IsShadowFrame();
589*795d594fSAndroid Build Coastguard Worker       uint32_t pc = visitor.GetDexPc(/*abort_on_failure=*/false);
590*795d594fSAndroid Build Coastguard Worker       if (pc == art::dex::kDexNoIndex) {
591*795d594fSAndroid Build Coastguard Worker         // Cannot figure out current PC.
592*795d594fSAndroid Build Coastguard Worker         result_ = ERR(OPAQUE_FRAME);
593*795d594fSAndroid Build Coastguard Worker         return;
594*795d594fSAndroid Build Coastguard Worker       }
595*795d594fSAndroid Build Coastguard Worker       std::string descriptor;
596*795d594fSAndroid Build Coastguard Worker       SlotType slot_type{ art::Primitive::kPrimVoid };
597*795d594fSAndroid Build Coastguard Worker       jvmtiError err = GetSlotType(method, pc, &descriptor, &slot_type);
598*795d594fSAndroid Build Coastguard Worker       if (err != OK) {
599*795d594fSAndroid Build Coastguard Worker         result_ = err;
600*795d594fSAndroid Build Coastguard Worker         return;
601*795d594fSAndroid Build Coastguard Worker       }
602*795d594fSAndroid Build Coastguard Worker 
603*795d594fSAndroid Build Coastguard Worker       err = GetTypeError(method, slot_type, descriptor);
604*795d594fSAndroid Build Coastguard Worker       if (err != OK) {
605*795d594fSAndroid Build Coastguard Worker         result_ = err;
606*795d594fSAndroid Build Coastguard Worker         return;
607*795d594fSAndroid Build Coastguard Worker       }
608*795d594fSAndroid Build Coastguard Worker       result_ = Execute(method, visitor);
609*795d594fSAndroid Build Coastguard Worker     }
610*795d594fSAndroid Build Coastguard Worker     if (needs_instrument) {
611*795d594fSAndroid Build Coastguard Worker       DeoptManager::Get()->DeoptimizeThread(self);
612*795d594fSAndroid Build Coastguard Worker     }
613*795d594fSAndroid Build Coastguard Worker   }
614*795d594fSAndroid Build Coastguard Worker 
GetResult()615*795d594fSAndroid Build Coastguard Worker   virtual jvmtiError GetResult() {
616*795d594fSAndroid Build Coastguard Worker     return result_;
617*795d594fSAndroid Build Coastguard Worker   }
618*795d594fSAndroid Build Coastguard Worker 
619*795d594fSAndroid Build Coastguard Worker  protected:
620*795d594fSAndroid Build Coastguard Worker   virtual jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
621*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) = 0;
622*795d594fSAndroid Build Coastguard Worker   virtual jvmtiError GetTypeError(art::ArtMethod* method,
623*795d594fSAndroid Build Coastguard Worker                                   SlotType type,
624*795d594fSAndroid Build Coastguard Worker                                   const std::string& descriptor)
625*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_)  = 0;
626*795d594fSAndroid Build Coastguard Worker 
627*795d594fSAndroid Build Coastguard Worker   jvmtiError GetSlotType(art::ArtMethod* method,
628*795d594fSAndroid Build Coastguard Worker                          uint32_t dex_pc,
629*795d594fSAndroid Build Coastguard Worker                          /*out*/std::string* descriptor,
630*795d594fSAndroid Build Coastguard Worker                          /*out*/SlotType* type)
631*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_);
632*795d594fSAndroid Build Coastguard Worker 
InferSlotTypeFromVerifier(art::ArtMethod * method,uint32_t dex_pc,std::string * descriptor,SlotType * type)633*795d594fSAndroid Build Coastguard Worker   jvmtiError InferSlotTypeFromVerifier(art::ArtMethod* method,
634*795d594fSAndroid Build Coastguard Worker                                        uint32_t dex_pc,
635*795d594fSAndroid Build Coastguard Worker                                        /*out*/ std::string* descriptor,
636*795d594fSAndroid Build Coastguard Worker                                        /*out*/ SlotType* type)
637*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
638*795d594fSAndroid Build Coastguard Worker     art::StackHandleScope<2> hs(art::Thread::Current());
639*795d594fSAndroid Build Coastguard Worker     art::Handle<art::mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
640*795d594fSAndroid Build Coastguard Worker     art::Handle<art::mirror::ClassLoader> class_loader(hs.NewHandle(method->GetClassLoader()));
641*795d594fSAndroid Build Coastguard Worker     art::Thread* self = art::Thread::Current();
642*795d594fSAndroid Build Coastguard Worker     art::Runtime* runtime = art::Runtime::Current();
643*795d594fSAndroid Build Coastguard Worker     art::ClassLinker* class_linker = runtime->GetClassLinker();
644*795d594fSAndroid Build Coastguard Worker     art::ArenaPool* arena_pool = runtime->GetArenaPool();
645*795d594fSAndroid Build Coastguard Worker     art::verifier::RegTypeCache reg_types(self,
646*795d594fSAndroid Build Coastguard Worker                                           class_linker,
647*795d594fSAndroid Build Coastguard Worker                                           arena_pool,
648*795d594fSAndroid Build Coastguard Worker                                           class_loader,
649*795d594fSAndroid Build Coastguard Worker                                           dex_cache->GetDexFile(),
650*795d594fSAndroid Build Coastguard Worker                                           /* can_load_classes= */ false,
651*795d594fSAndroid Build Coastguard Worker                                           /* can_suspend= */ false);
652*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<art::verifier::MethodVerifier> verifier(
653*795d594fSAndroid Build Coastguard Worker         art::verifier::MethodVerifier::CalculateVerificationInfo(
654*795d594fSAndroid Build Coastguard Worker             self,
655*795d594fSAndroid Build Coastguard Worker             &reg_types,
656*795d594fSAndroid Build Coastguard Worker             method,
657*795d594fSAndroid Build Coastguard Worker             dex_cache,
658*795d594fSAndroid Build Coastguard Worker             dex_pc));
659*795d594fSAndroid Build Coastguard Worker     if (verifier == nullptr) {
660*795d594fSAndroid Build Coastguard Worker       JVMTI_LOG(WARNING, jvmti_) << "Unable to extract verification information from "
661*795d594fSAndroid Build Coastguard Worker                                  << method->PrettyMethod() << " due to hard verification failures! "
662*795d594fSAndroid Build Coastguard Worker                                  << "How did this method even get loaded!";
663*795d594fSAndroid Build Coastguard Worker       return ERR(INTERNAL);
664*795d594fSAndroid Build Coastguard Worker     }
665*795d594fSAndroid Build Coastguard Worker     art::verifier::RegisterLine* line = verifier->GetRegLine(dex_pc);
666*795d594fSAndroid Build Coastguard Worker     if (line == nullptr) {
667*795d594fSAndroid Build Coastguard Worker       JVMTI_LOG(WARNING, jvmti_) << "Unable to determine register line at dex-pc " << dex_pc
668*795d594fSAndroid Build Coastguard Worker                                  << " for method " << method->PrettyMethod();
669*795d594fSAndroid Build Coastguard Worker       return ERR(OPAQUE_FRAME);
670*795d594fSAndroid Build Coastguard Worker     }
671*795d594fSAndroid Build Coastguard Worker     const art::verifier::RegType& rt = line->GetRegisterType(verifier.get(), slot_);
672*795d594fSAndroid Build Coastguard Worker     if (rt.IsUndefined()) {
673*795d594fSAndroid Build Coastguard Worker       return ERR(INVALID_SLOT);
674*795d594fSAndroid Build Coastguard Worker     } else if (rt.IsNonZeroReferenceTypes() || rt.IsNull()) {
675*795d594fSAndroid Build Coastguard Worker       *descriptor = (rt.HasClass() ? rt.GetDescriptor() : "Ljava/lang/Object;");
676*795d594fSAndroid Build Coastguard Worker       *type = VerifierPrimitiveType::kReferenceValue;
677*795d594fSAndroid Build Coastguard Worker       return OK;
678*795d594fSAndroid Build Coastguard Worker     } else if (rt.IsZero()) {
679*795d594fSAndroid Build Coastguard Worker       *descriptor = "I";
680*795d594fSAndroid Build Coastguard Worker       *type = VerifierPrimitiveType::kZeroValue;
681*795d594fSAndroid Build Coastguard Worker       return OK;
682*795d594fSAndroid Build Coastguard Worker     } else if (rt.IsCategory1Types()) {
683*795d594fSAndroid Build Coastguard Worker       *descriptor = "I";
684*795d594fSAndroid Build Coastguard Worker       *type = VerifierPrimitiveType::k32BitValue;
685*795d594fSAndroid Build Coastguard Worker       return OK;
686*795d594fSAndroid Build Coastguard Worker     } else if (rt.IsCategory2Types() && rt.IsLowHalf()) {
687*795d594fSAndroid Build Coastguard Worker       *descriptor = "J";
688*795d594fSAndroid Build Coastguard Worker       *type = VerifierPrimitiveType::k64BitValue;
689*795d594fSAndroid Build Coastguard Worker       return OK;
690*795d594fSAndroid Build Coastguard Worker     } else {
691*795d594fSAndroid Build Coastguard Worker       // The slot doesn't have a type. Must not be valid here.
692*795d594fSAndroid Build Coastguard Worker       return ERR(INVALID_SLOT);
693*795d594fSAndroid Build Coastguard Worker     }
694*795d594fSAndroid Build Coastguard Worker   }
695*795d594fSAndroid Build Coastguard Worker 
SquashType(SlotType t)696*795d594fSAndroid Build Coastguard Worker   constexpr VerifierPrimitiveType SquashType(SlotType t) {
697*795d594fSAndroid Build Coastguard Worker     if (std::holds_alternative<art::Primitive::Type>(t)) {
698*795d594fSAndroid Build Coastguard Worker       switch (std::get<art::Primitive::Type>(t)) {
699*795d594fSAndroid Build Coastguard Worker         // 32-bit primitives
700*795d594fSAndroid Build Coastguard Worker         case art::Primitive::kPrimByte:
701*795d594fSAndroid Build Coastguard Worker         case art::Primitive::kPrimChar:
702*795d594fSAndroid Build Coastguard Worker         case art::Primitive::kPrimInt:
703*795d594fSAndroid Build Coastguard Worker         case art::Primitive::kPrimShort:
704*795d594fSAndroid Build Coastguard Worker         case art::Primitive::kPrimBoolean:
705*795d594fSAndroid Build Coastguard Worker         case art::Primitive::kPrimFloat:
706*795d594fSAndroid Build Coastguard Worker           return VerifierPrimitiveType::k32BitValue;
707*795d594fSAndroid Build Coastguard Worker         // 64-bit primitives
708*795d594fSAndroid Build Coastguard Worker         case art::Primitive::kPrimLong:
709*795d594fSAndroid Build Coastguard Worker         case art::Primitive::kPrimDouble:
710*795d594fSAndroid Build Coastguard Worker           return VerifierPrimitiveType::k64BitValue;
711*795d594fSAndroid Build Coastguard Worker         case art::Primitive::kPrimNot:
712*795d594fSAndroid Build Coastguard Worker           return VerifierPrimitiveType::kReferenceValue;
713*795d594fSAndroid Build Coastguard Worker         case art::Primitive::kPrimVoid:
714*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Got kPrimVoid";
715*795d594fSAndroid Build Coastguard Worker           UNREACHABLE();
716*795d594fSAndroid Build Coastguard Worker       }
717*795d594fSAndroid Build Coastguard Worker     } else {
718*795d594fSAndroid Build Coastguard Worker       return std::get<VerifierPrimitiveType>(t);
719*795d594fSAndroid Build Coastguard Worker     }
720*795d594fSAndroid Build Coastguard Worker   }
721*795d594fSAndroid Build Coastguard Worker 
722*795d594fSAndroid Build Coastguard Worker   jvmtiEnv* jvmti_;
723*795d594fSAndroid Build Coastguard Worker   jvmtiError result_;
724*795d594fSAndroid Build Coastguard Worker   jint depth_;
725*795d594fSAndroid Build Coastguard Worker   jint slot_;
726*795d594fSAndroid Build Coastguard Worker 
727*795d594fSAndroid Build Coastguard Worker  private:
728*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(CommonLocalVariableClosure);
729*795d594fSAndroid Build Coastguard Worker };
730*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,CommonLocalVariableClosure::VerifierPrimitiveType state)731*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os,
732*795d594fSAndroid Build Coastguard Worker                          CommonLocalVariableClosure::VerifierPrimitiveType state) {
733*795d594fSAndroid Build Coastguard Worker   switch (state) {
734*795d594fSAndroid Build Coastguard Worker     case CommonLocalVariableClosure::VerifierPrimitiveType::k32BitValue:
735*795d594fSAndroid Build Coastguard Worker       return os << "32BitValue";
736*795d594fSAndroid Build Coastguard Worker     case CommonLocalVariableClosure::VerifierPrimitiveType::k64BitValue:
737*795d594fSAndroid Build Coastguard Worker       return os << "64BitValue";
738*795d594fSAndroid Build Coastguard Worker     case CommonLocalVariableClosure::VerifierPrimitiveType::kReferenceValue:
739*795d594fSAndroid Build Coastguard Worker       return os << "ReferenceValue";
740*795d594fSAndroid Build Coastguard Worker     case CommonLocalVariableClosure::VerifierPrimitiveType::kZeroValue:
741*795d594fSAndroid Build Coastguard Worker       return os << "ZeroValue";
742*795d594fSAndroid Build Coastguard Worker   }
743*795d594fSAndroid Build Coastguard Worker }
744*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,CommonLocalVariableClosure::SlotType state)745*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, CommonLocalVariableClosure::SlotType state) {
746*795d594fSAndroid Build Coastguard Worker   if (std::holds_alternative<art::Primitive::Type>(state)) {
747*795d594fSAndroid Build Coastguard Worker     return os << "Primitive::Type[" << std::get<art::Primitive::Type>(state) << "]";
748*795d594fSAndroid Build Coastguard Worker   } else {
749*795d594fSAndroid Build Coastguard Worker     return os << "VerifierPrimitiveType["
750*795d594fSAndroid Build Coastguard Worker               << std::get<CommonLocalVariableClosure::VerifierPrimitiveType>(state) << "]";
751*795d594fSAndroid Build Coastguard Worker   }
752*795d594fSAndroid Build Coastguard Worker }
753*795d594fSAndroid Build Coastguard Worker 
GetSlotType(art::ArtMethod * method,uint32_t dex_pc,std::string * descriptor,SlotType * type)754*795d594fSAndroid Build Coastguard Worker jvmtiError CommonLocalVariableClosure::GetSlotType(art::ArtMethod* method,
755*795d594fSAndroid Build Coastguard Worker                                                    uint32_t dex_pc,
756*795d594fSAndroid Build Coastguard Worker                                                    /*out*/ std::string* descriptor,
757*795d594fSAndroid Build Coastguard Worker                                                    /*out*/ SlotType* type) {
758*795d594fSAndroid Build Coastguard Worker   const art::DexFile* dex_file = method->GetDexFile();
759*795d594fSAndroid Build Coastguard Worker   if (dex_file == nullptr) {
760*795d594fSAndroid Build Coastguard Worker     return ERR(OPAQUE_FRAME);
761*795d594fSAndroid Build Coastguard Worker   }
762*795d594fSAndroid Build Coastguard Worker   art::CodeItemDebugInfoAccessor accessor(method->DexInstructionDebugInfo());
763*795d594fSAndroid Build Coastguard Worker   if (!accessor.HasCodeItem()) {
764*795d594fSAndroid Build Coastguard Worker     return ERR(OPAQUE_FRAME);
765*795d594fSAndroid Build Coastguard Worker   }
766*795d594fSAndroid Build Coastguard Worker   bool found = false;
767*795d594fSAndroid Build Coastguard Worker   *type = art::Primitive::kPrimVoid;
768*795d594fSAndroid Build Coastguard Worker   descriptor->clear();
769*795d594fSAndroid Build Coastguard Worker   // To avoid defining visitor in the same line as the `if`. We define the lambda and use std::move.
770*795d594fSAndroid Build Coastguard Worker   auto visitor = [&](const art::DexFile::LocalInfo& entry) {
771*795d594fSAndroid Build Coastguard Worker     if (!found && entry.start_address_ <= dex_pc && entry.end_address_ > dex_pc &&
772*795d594fSAndroid Build Coastguard Worker         entry.reg_ == slot_) {
773*795d594fSAndroid Build Coastguard Worker       found = true;
774*795d594fSAndroid Build Coastguard Worker       *type = art::Primitive::GetType(entry.descriptor_[0]);
775*795d594fSAndroid Build Coastguard Worker       *descriptor = entry.descriptor_;
776*795d594fSAndroid Build Coastguard Worker     }
777*795d594fSAndroid Build Coastguard Worker   };
778*795d594fSAndroid Build Coastguard Worker   if (!accessor.DecodeDebugLocalInfo(
779*795d594fSAndroid Build Coastguard Worker           method->IsStatic(), method->GetDexMethodIndex(), std::move(visitor)) ||
780*795d594fSAndroid Build Coastguard Worker       !found) {
781*795d594fSAndroid Build Coastguard Worker     // Something went wrong with decoding the debug information. It might as well not be there.
782*795d594fSAndroid Build Coastguard Worker     // Try to find the type with the verifier.
783*795d594fSAndroid Build Coastguard Worker     // TODO This is very slow.
784*795d594fSAndroid Build Coastguard Worker     return InferSlotTypeFromVerifier(method, dex_pc, descriptor, type);
785*795d594fSAndroid Build Coastguard Worker   } else if (art::kIsDebugBuild) {
786*795d594fSAndroid Build Coastguard Worker     std::string type_unused;
787*795d594fSAndroid Build Coastguard Worker     SlotType verifier_type{ art::Primitive::kPrimVoid };
788*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(InferSlotTypeFromVerifier(method, dex_pc, &type_unused, &verifier_type), OK)
789*795d594fSAndroid Build Coastguard Worker         << method->PrettyMethod() << " failed to verify!";
790*795d594fSAndroid Build Coastguard Worker     if (*type == SlotType{ art::Primitive::kPrimNot }) {
791*795d594fSAndroid Build Coastguard Worker       // We cannot distinguish between a constant 0 and a null reference so we return that it is a
792*795d594fSAndroid Build Coastguard Worker       // 32bit value (Due to the way references are read by the interpreter this is safe even if
793*795d594fSAndroid Build Coastguard Worker       // it's modified, the value will remain null). This is not ideal since it prevents modifying
794*795d594fSAndroid Build Coastguard Worker       // locals in some circumstances but generally is not a big deal (since one can just modify it
795*795d594fSAndroid Build Coastguard Worker       // later once it's been determined to be a reference by a later instruction).
796*795d594fSAndroid Build Coastguard Worker       DCHECK(verifier_type == SlotType { VerifierPrimitiveType::kZeroValue } ||
797*795d594fSAndroid Build Coastguard Worker              verifier_type == SlotType { VerifierPrimitiveType::kReferenceValue })
798*795d594fSAndroid Build Coastguard Worker           << "Verifier disagrees on type of slot! debug: " << *type
799*795d594fSAndroid Build Coastguard Worker           << " verifier: " << verifier_type;
800*795d594fSAndroid Build Coastguard Worker     } else if (verifier_type == SlotType { VerifierPrimitiveType::kZeroValue }) {
801*795d594fSAndroid Build Coastguard Worker       DCHECK(VerifierPrimitiveType::k32BitValue == SquashType(*type) ||
802*795d594fSAndroid Build Coastguard Worker              VerifierPrimitiveType::kReferenceValue == SquashType(*type))
803*795d594fSAndroid Build Coastguard Worker           << "Verifier disagrees on type of slot! debug: " << *type
804*795d594fSAndroid Build Coastguard Worker           << " verifier: " << verifier_type;
805*795d594fSAndroid Build Coastguard Worker     } else {
806*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(SquashType(verifier_type), SquashType(*type))
807*795d594fSAndroid Build Coastguard Worker           << "Verifier disagrees on type of slot! debug: " << *type
808*795d594fSAndroid Build Coastguard Worker           << " verifier: " << verifier_type;
809*795d594fSAndroid Build Coastguard Worker     }
810*795d594fSAndroid Build Coastguard Worker   }
811*795d594fSAndroid Build Coastguard Worker   return OK;
812*795d594fSAndroid Build Coastguard Worker }
813*795d594fSAndroid Build Coastguard Worker 
814*795d594fSAndroid Build Coastguard Worker class GetLocalVariableClosure : public CommonLocalVariableClosure {
815*795d594fSAndroid Build Coastguard Worker  public:
GetLocalVariableClosure(jvmtiEnv * jvmti,jint depth,jint slot,art::Primitive::Type type,jvalue * val)816*795d594fSAndroid Build Coastguard Worker   GetLocalVariableClosure(jvmtiEnv* jvmti,
817*795d594fSAndroid Build Coastguard Worker                           jint depth,
818*795d594fSAndroid Build Coastguard Worker                           jint slot,
819*795d594fSAndroid Build Coastguard Worker                           art::Primitive::Type type,
820*795d594fSAndroid Build Coastguard Worker                           jvalue* val)
821*795d594fSAndroid Build Coastguard Worker       : CommonLocalVariableClosure(jvmti, depth, slot),
822*795d594fSAndroid Build Coastguard Worker         type_(type),
823*795d594fSAndroid Build Coastguard Worker         val_(val),
824*795d594fSAndroid Build Coastguard Worker         obj_val_(nullptr) {}
825*795d594fSAndroid Build Coastguard Worker 
GetResult()826*795d594fSAndroid Build Coastguard Worker   jvmtiError GetResult() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
827*795d594fSAndroid Build Coastguard Worker     if (result_ == OK && type_ == art::Primitive::kPrimNot) {
828*795d594fSAndroid Build Coastguard Worker       if (obj_val_ == nullptr) {
829*795d594fSAndroid Build Coastguard Worker         val_->l = nullptr;
830*795d594fSAndroid Build Coastguard Worker       } else {
831*795d594fSAndroid Build Coastguard Worker         art::JNIEnvExt* jni = art::Thread::Current()->GetJniEnv();
832*795d594fSAndroid Build Coastguard Worker         val_->l = static_cast<JNIEnv*>(jni)->NewLocalRef(obj_val_);
833*795d594fSAndroid Build Coastguard Worker         jni->DeleteGlobalRef(obj_val_);
834*795d594fSAndroid Build Coastguard Worker         obj_val_ = nullptr;
835*795d594fSAndroid Build Coastguard Worker       }
836*795d594fSAndroid Build Coastguard Worker     }
837*795d594fSAndroid Build Coastguard Worker     return CommonLocalVariableClosure::GetResult();
838*795d594fSAndroid Build Coastguard Worker   }
839*795d594fSAndroid Build Coastguard Worker 
840*795d594fSAndroid Build Coastguard Worker  protected:
841*795d594fSAndroid Build Coastguard Worker   jvmtiError
GetTypeError(art::ArtMethod * method,SlotType slot_type,const std::string & descriptor)842*795d594fSAndroid Build Coastguard Worker   GetTypeError(art::ArtMethod* method, SlotType slot_type, const std::string& descriptor) override
843*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
844*795d594fSAndroid Build Coastguard Worker     jvmtiError res = GetTypeErrorInner(method, slot_type, descriptor);
845*795d594fSAndroid Build Coastguard Worker     if (res == ERR(TYPE_MISMATCH)) {
846*795d594fSAndroid Build Coastguard Worker       JVMTI_LOG(INFO, jvmti_) << "Unable to Get local variable in slot " << slot_ << ". Expected"
847*795d594fSAndroid Build Coastguard Worker                               << " slot to be of type compatible with " << SlotType { type_ }
848*795d594fSAndroid Build Coastguard Worker                               << " but slot is " << slot_type;
849*795d594fSAndroid Build Coastguard Worker     } else if (res != OK) {
850*795d594fSAndroid Build Coastguard Worker       JVMTI_LOG(INFO, jvmti_) << "Unable to get local variable in slot " << slot_ << ".";
851*795d594fSAndroid Build Coastguard Worker     }
852*795d594fSAndroid Build Coastguard Worker     return res;
853*795d594fSAndroid Build Coastguard Worker   }
854*795d594fSAndroid Build Coastguard Worker 
GetTypeErrorInner(art::ArtMethod * method,SlotType slot_type,const std::string & descriptor)855*795d594fSAndroid Build Coastguard Worker   jvmtiError GetTypeErrorInner([[maybe_unused]] art::ArtMethod* method,
856*795d594fSAndroid Build Coastguard Worker                                SlotType slot_type,
857*795d594fSAndroid Build Coastguard Worker                                [[maybe_unused]] const std::string& descriptor)
858*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
859*795d594fSAndroid Build Coastguard Worker     switch (type_) {
860*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimFloat:
861*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimInt: {
862*795d594fSAndroid Build Coastguard Worker         if (std::holds_alternative<VerifierPrimitiveType>(slot_type)) {
863*795d594fSAndroid Build Coastguard Worker           return (slot_type == SlotType { VerifierPrimitiveType::k32BitValue } ||
864*795d594fSAndroid Build Coastguard Worker                   slot_type == SlotType { VerifierPrimitiveType::kZeroValue })
865*795d594fSAndroid Build Coastguard Worker                      ? OK
866*795d594fSAndroid Build Coastguard Worker                      : ERR(TYPE_MISMATCH);
867*795d594fSAndroid Build Coastguard Worker         } else if (type_ == art::Primitive::kPrimFloat ||
868*795d594fSAndroid Build Coastguard Worker                    slot_type == SlotType { art::Primitive::kPrimFloat }) {
869*795d594fSAndroid Build Coastguard Worker           // Check that we are actually a float.
870*795d594fSAndroid Build Coastguard Worker           return (SlotType { type_ } == slot_type) ? OK : ERR(TYPE_MISMATCH);
871*795d594fSAndroid Build Coastguard Worker         } else {
872*795d594fSAndroid Build Coastguard Worker           // Some smaller int type.
873*795d594fSAndroid Build Coastguard Worker           return SquashType(slot_type) == SquashType(SlotType { type_ }) ? OK : ERR(TYPE_MISMATCH);
874*795d594fSAndroid Build Coastguard Worker         }
875*795d594fSAndroid Build Coastguard Worker       }
876*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimLong:
877*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimDouble: {
878*795d594fSAndroid Build Coastguard Worker         // todo
879*795d594fSAndroid Build Coastguard Worker         if (std::holds_alternative<VerifierPrimitiveType>(slot_type)) {
880*795d594fSAndroid Build Coastguard Worker           return (slot_type == SlotType { VerifierPrimitiveType::k64BitValue })
881*795d594fSAndroid Build Coastguard Worker                      ? OK
882*795d594fSAndroid Build Coastguard Worker                      : ERR(TYPE_MISMATCH);
883*795d594fSAndroid Build Coastguard Worker         } else {
884*795d594fSAndroid Build Coastguard Worker           return slot_type == SlotType { type_ } ? OK : ERR(TYPE_MISMATCH);
885*795d594fSAndroid Build Coastguard Worker         }
886*795d594fSAndroid Build Coastguard Worker       }
887*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimNot:
888*795d594fSAndroid Build Coastguard Worker         return (SquashType(slot_type) == VerifierPrimitiveType::kReferenceValue ||
889*795d594fSAndroid Build Coastguard Worker                 SquashType(slot_type) == VerifierPrimitiveType::kZeroValue)
890*795d594fSAndroid Build Coastguard Worker                    ? OK
891*795d594fSAndroid Build Coastguard Worker                    : ERR(TYPE_MISMATCH);
892*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimShort:
893*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimChar:
894*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimByte:
895*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimBoolean:
896*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimVoid:
897*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Unexpected primitive type " << slot_type;
898*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
899*795d594fSAndroid Build Coastguard Worker     }
900*795d594fSAndroid Build Coastguard Worker   }
901*795d594fSAndroid Build Coastguard Worker 
Execute(art::ArtMethod * method,art::StackVisitor & visitor)902*795d594fSAndroid Build Coastguard Worker   jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
903*795d594fSAndroid Build Coastguard Worker       override REQUIRES_SHARED(art::Locks::mutator_lock_) {
904*795d594fSAndroid Build Coastguard Worker     switch (type_) {
905*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimNot: {
906*795d594fSAndroid Build Coastguard Worker         uint32_t ptr_val;
907*795d594fSAndroid Build Coastguard Worker         if (!visitor.GetVReg(method,
908*795d594fSAndroid Build Coastguard Worker                              static_cast<uint16_t>(slot_),
909*795d594fSAndroid Build Coastguard Worker                              art::kReferenceVReg,
910*795d594fSAndroid Build Coastguard Worker                              &ptr_val)) {
911*795d594fSAndroid Build Coastguard Worker           return ERR(OPAQUE_FRAME);
912*795d594fSAndroid Build Coastguard Worker         }
913*795d594fSAndroid Build Coastguard Worker         art::ObjPtr<art::mirror::Object> obj(reinterpret_cast<art::mirror::Object*>(ptr_val));
914*795d594fSAndroid Build Coastguard Worker         obj_val_ = art::Runtime::Current()->GetJavaVM()->AddGlobalRef(art::Thread::Current(), obj);
915*795d594fSAndroid Build Coastguard Worker         break;
916*795d594fSAndroid Build Coastguard Worker       }
917*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimInt:
918*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimFloat: {
919*795d594fSAndroid Build Coastguard Worker         if (!visitor.GetVReg(method,
920*795d594fSAndroid Build Coastguard Worker                              static_cast<uint16_t>(slot_),
921*795d594fSAndroid Build Coastguard Worker                              type_ == art::Primitive::kPrimFloat ? art::kFloatVReg : art::kIntVReg,
922*795d594fSAndroid Build Coastguard Worker                              reinterpret_cast<uint32_t*>(&val_->i))) {
923*795d594fSAndroid Build Coastguard Worker           return ERR(OPAQUE_FRAME);
924*795d594fSAndroid Build Coastguard Worker         }
925*795d594fSAndroid Build Coastguard Worker         break;
926*795d594fSAndroid Build Coastguard Worker       }
927*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimDouble:
928*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimLong: {
929*795d594fSAndroid Build Coastguard Worker         auto lo_type = type_ == art::Primitive::kPrimLong ? art::kLongLoVReg : art::kDoubleLoVReg;
930*795d594fSAndroid Build Coastguard Worker         auto high_type = type_ == art::Primitive::kPrimLong ? art::kLongHiVReg : art::kDoubleHiVReg;
931*795d594fSAndroid Build Coastguard Worker         if (!visitor.GetVRegPair(method,
932*795d594fSAndroid Build Coastguard Worker                                  static_cast<uint16_t>(slot_),
933*795d594fSAndroid Build Coastguard Worker                                  lo_type,
934*795d594fSAndroid Build Coastguard Worker                                  high_type,
935*795d594fSAndroid Build Coastguard Worker                                  reinterpret_cast<uint64_t*>(&val_->j))) {
936*795d594fSAndroid Build Coastguard Worker           return ERR(OPAQUE_FRAME);
937*795d594fSAndroid Build Coastguard Worker         }
938*795d594fSAndroid Build Coastguard Worker         break;
939*795d594fSAndroid Build Coastguard Worker       }
940*795d594fSAndroid Build Coastguard Worker       default: {
941*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "unexpected register type " << type_;
942*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
943*795d594fSAndroid Build Coastguard Worker       }
944*795d594fSAndroid Build Coastguard Worker     }
945*795d594fSAndroid Build Coastguard Worker     return OK;
946*795d594fSAndroid Build Coastguard Worker   }
947*795d594fSAndroid Build Coastguard Worker 
948*795d594fSAndroid Build Coastguard Worker  private:
949*795d594fSAndroid Build Coastguard Worker   art::Primitive::Type type_;
950*795d594fSAndroid Build Coastguard Worker   jvalue* val_;
951*795d594fSAndroid Build Coastguard Worker   // A global reference to the return value. We use the global reference to safely transfer the
952*795d594fSAndroid Build Coastguard Worker   // value between threads.
953*795d594fSAndroid Build Coastguard Worker   jobject obj_val_;
954*795d594fSAndroid Build Coastguard Worker };
955*795d594fSAndroid Build Coastguard Worker 
GetLocalVariableGeneric(jvmtiEnv * env,jthread thread,jint depth,jint slot,art::Primitive::Type type,jvalue * val)956*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetLocalVariableGeneric(jvmtiEnv* env,
957*795d594fSAndroid Build Coastguard Worker                                                jthread thread,
958*795d594fSAndroid Build Coastguard Worker                                                jint depth,
959*795d594fSAndroid Build Coastguard Worker                                                jint slot,
960*795d594fSAndroid Build Coastguard Worker                                                art::Primitive::Type type,
961*795d594fSAndroid Build Coastguard Worker                                                jvalue* val) {
962*795d594fSAndroid Build Coastguard Worker   if (depth < 0) {
963*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
964*795d594fSAndroid Build Coastguard Worker   }
965*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
966*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(self);
967*795d594fSAndroid Build Coastguard Worker   art::Locks::thread_list_lock_->ExclusiveLock(self);
968*795d594fSAndroid Build Coastguard Worker   art::Thread* target = nullptr;
969*795d594fSAndroid Build Coastguard Worker   jvmtiError err = ERR(INTERNAL);
970*795d594fSAndroid Build Coastguard Worker   if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
971*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
972*795d594fSAndroid Build Coastguard Worker     return err;
973*795d594fSAndroid Build Coastguard Worker   }
974*795d594fSAndroid Build Coastguard Worker   GetLocalVariableClosure c(env, depth, slot, type, val);
975*795d594fSAndroid Build Coastguard Worker   // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
976*795d594fSAndroid Build Coastguard Worker   if (!target->RequestSynchronousCheckpoint(&c)) {
977*795d594fSAndroid Build Coastguard Worker     return ERR(THREAD_NOT_ALIVE);
978*795d594fSAndroid Build Coastguard Worker   } else {
979*795d594fSAndroid Build Coastguard Worker     return c.GetResult();
980*795d594fSAndroid Build Coastguard Worker   }
981*795d594fSAndroid Build Coastguard Worker }
982*795d594fSAndroid Build Coastguard Worker 
983*795d594fSAndroid Build Coastguard Worker class SetLocalVariableClosure : public CommonLocalVariableClosure {
984*795d594fSAndroid Build Coastguard Worker  public:
SetLocalVariableClosure(jvmtiEnv * jvmti,art::Thread * caller,jint depth,jint slot,art::Primitive::Type type,jvalue val)985*795d594fSAndroid Build Coastguard Worker   SetLocalVariableClosure(jvmtiEnv* jvmti,
986*795d594fSAndroid Build Coastguard Worker                           art::Thread* caller,
987*795d594fSAndroid Build Coastguard Worker                           jint depth,
988*795d594fSAndroid Build Coastguard Worker                           jint slot,
989*795d594fSAndroid Build Coastguard Worker                           art::Primitive::Type type,
990*795d594fSAndroid Build Coastguard Worker                           jvalue val)
991*795d594fSAndroid Build Coastguard Worker       : CommonLocalVariableClosure(jvmti, depth, slot), caller_(caller), type_(type), val_(val) {}
992*795d594fSAndroid Build Coastguard Worker 
993*795d594fSAndroid Build Coastguard Worker  protected:
994*795d594fSAndroid Build Coastguard Worker   jvmtiError
GetTypeError(art::ArtMethod * method,SlotType slot_type,const std::string & descriptor)995*795d594fSAndroid Build Coastguard Worker   GetTypeError(art::ArtMethod* method, SlotType slot_type, const std::string& descriptor) override
996*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
997*795d594fSAndroid Build Coastguard Worker     jvmtiError res = GetTypeErrorInner(method, slot_type, descriptor);
998*795d594fSAndroid Build Coastguard Worker     if (res != OK) {
999*795d594fSAndroid Build Coastguard Worker       if (res == ERR(TYPE_MISMATCH)) {
1000*795d594fSAndroid Build Coastguard Worker         std::ostringstream desc_exp;
1001*795d594fSAndroid Build Coastguard Worker         std::ostringstream desc_set;
1002*795d594fSAndroid Build Coastguard Worker         if (type_ == art::Primitive::kPrimNot) {
1003*795d594fSAndroid Build Coastguard Worker           desc_exp << " (type: " << descriptor << ")";
1004*795d594fSAndroid Build Coastguard Worker           art::ObjPtr<art::mirror::Object> new_val(art::Thread::Current()->DecodeJObject(val_.l));
1005*795d594fSAndroid Build Coastguard Worker           desc_set << " (type: "
1006*795d594fSAndroid Build Coastguard Worker                   << (new_val.IsNull() ? "NULL" : new_val->GetClass()->PrettyDescriptor()) << ")";
1007*795d594fSAndroid Build Coastguard Worker         }
1008*795d594fSAndroid Build Coastguard Worker         JVMTI_LOG(INFO, jvmti_) << "Unable to Set local variable in slot " << slot_ << ". Expected"
1009*795d594fSAndroid Build Coastguard Worker                                 << " slot to be of type compatible with " << SlotType{ type_ }
1010*795d594fSAndroid Build Coastguard Worker                                 << desc_set.str() << " but slot is " << slot_type << desc_exp.str();
1011*795d594fSAndroid Build Coastguard Worker       } else {
1012*795d594fSAndroid Build Coastguard Worker         JVMTI_LOG(INFO, jvmti_) << "Unable to set local variable in slot " << slot_ << ". "
1013*795d594fSAndroid Build Coastguard Worker                                 << err_.str();
1014*795d594fSAndroid Build Coastguard Worker       }
1015*795d594fSAndroid Build Coastguard Worker     }
1016*795d594fSAndroid Build Coastguard Worker     return res;
1017*795d594fSAndroid Build Coastguard Worker   }
1018*795d594fSAndroid Build Coastguard Worker 
1019*795d594fSAndroid Build Coastguard Worker   jvmtiError
GetTypeErrorInner(art::ArtMethod * method,SlotType slot_type,const std::string & descriptor)1020*795d594fSAndroid Build Coastguard Worker   GetTypeErrorInner(art::ArtMethod* method, SlotType slot_type, const std::string& descriptor)
1021*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
1022*795d594fSAndroid Build Coastguard Worker     switch (SquashType(SlotType{ type_ })) {
1023*795d594fSAndroid Build Coastguard Worker       case VerifierPrimitiveType::k32BitValue: {
1024*795d594fSAndroid Build Coastguard Worker         if (slot_type == SlotType{ VerifierPrimitiveType::kZeroValue }) {
1025*795d594fSAndroid Build Coastguard Worker           if (val_.i == 0) {
1026*795d594fSAndroid Build Coastguard Worker             return OK;
1027*795d594fSAndroid Build Coastguard Worker           } else {
1028*795d594fSAndroid Build Coastguard Worker             err_ << "Cannot determine if slot " << slot_ << " is a null reference or 32bit "
1029*795d594fSAndroid Build Coastguard Worker                  << "constant. Cannot allow writing to slot.";
1030*795d594fSAndroid Build Coastguard Worker             return ERR(INTERNAL);
1031*795d594fSAndroid Build Coastguard Worker           }
1032*795d594fSAndroid Build Coastguard Worker         } else if (SquashType(slot_type) != VerifierPrimitiveType::k32BitValue) {
1033*795d594fSAndroid Build Coastguard Worker           return ERR(TYPE_MISMATCH);
1034*795d594fSAndroid Build Coastguard Worker         } else if (slot_type == SlotType { VerifierPrimitiveType::k32BitValue } ||
1035*795d594fSAndroid Build Coastguard Worker                    slot_type == SlotType { type_ }) {
1036*795d594fSAndroid Build Coastguard Worker           return OK;
1037*795d594fSAndroid Build Coastguard Worker         } else if (type_ == art::Primitive::kPrimFloat ||
1038*795d594fSAndroid Build Coastguard Worker                    slot_type == SlotType { art::Primitive::kPrimFloat }) {
1039*795d594fSAndroid Build Coastguard Worker           // we should have hit the get == type_ above
1040*795d594fSAndroid Build Coastguard Worker           return ERR(TYPE_MISMATCH);
1041*795d594fSAndroid Build Coastguard Worker         } else {
1042*795d594fSAndroid Build Coastguard Worker           // Some smaller type then int.
1043*795d594fSAndroid Build Coastguard Worker           return OK;
1044*795d594fSAndroid Build Coastguard Worker         }
1045*795d594fSAndroid Build Coastguard Worker       }
1046*795d594fSAndroid Build Coastguard Worker       case VerifierPrimitiveType::k64BitValue: {
1047*795d594fSAndroid Build Coastguard Worker         if (slot_type == SlotType { VerifierPrimitiveType::k64BitValue } ||
1048*795d594fSAndroid Build Coastguard Worker             slot_type == SlotType { type_ }) {
1049*795d594fSAndroid Build Coastguard Worker           return OK;
1050*795d594fSAndroid Build Coastguard Worker         } else {
1051*795d594fSAndroid Build Coastguard Worker           return ERR(TYPE_MISMATCH);
1052*795d594fSAndroid Build Coastguard Worker         }
1053*795d594fSAndroid Build Coastguard Worker       }
1054*795d594fSAndroid Build Coastguard Worker       case VerifierPrimitiveType::kReferenceValue: {
1055*795d594fSAndroid Build Coastguard Worker         if (SquashType(slot_type) != VerifierPrimitiveType::kReferenceValue &&
1056*795d594fSAndroid Build Coastguard Worker             SquashType(slot_type) != VerifierPrimitiveType::kZeroValue) {
1057*795d594fSAndroid Build Coastguard Worker           return ERR(TYPE_MISMATCH);
1058*795d594fSAndroid Build Coastguard Worker         } else if (val_.l == nullptr) {
1059*795d594fSAndroid Build Coastguard Worker           return OK;
1060*795d594fSAndroid Build Coastguard Worker         } else if (slot_type == SlotType { VerifierPrimitiveType::kZeroValue }) {
1061*795d594fSAndroid Build Coastguard Worker           err_ << "Cannot determine if slot " << slot_ << " is a null "
1062*795d594fSAndroid Build Coastguard Worker                << "reference or 32bit constant. Cannot allow writing to slot.";
1063*795d594fSAndroid Build Coastguard Worker           return ERR(INTERNAL);
1064*795d594fSAndroid Build Coastguard Worker         } else {
1065*795d594fSAndroid Build Coastguard Worker           art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
1066*795d594fSAndroid Build Coastguard Worker           art::ObjPtr<art::mirror::Class> set_class = caller_->DecodeJObject(val_.l)->GetClass();
1067*795d594fSAndroid Build Coastguard Worker           art::ObjPtr<art::mirror::ClassLoader> loader =
1068*795d594fSAndroid Build Coastguard Worker               method->GetDeclaringClass()->GetClassLoader();
1069*795d594fSAndroid Build Coastguard Worker           art::ObjPtr<art::mirror::Class> slot_class = cl->LookupClass(caller_, descriptor, loader);
1070*795d594fSAndroid Build Coastguard Worker           DCHECK(!slot_class.IsNull()) << descriptor << " slot: " << slot_type;
1071*795d594fSAndroid Build Coastguard Worker           return slot_class->IsAssignableFrom(set_class) ? OK : ERR(TYPE_MISMATCH);
1072*795d594fSAndroid Build Coastguard Worker         }
1073*795d594fSAndroid Build Coastguard Worker       }
1074*795d594fSAndroid Build Coastguard Worker       case VerifierPrimitiveType::kZeroValue: {
1075*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Illegal result from SquashType of art::Primitive::Type " << type_;
1076*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
1077*795d594fSAndroid Build Coastguard Worker       }
1078*795d594fSAndroid Build Coastguard Worker     }
1079*795d594fSAndroid Build Coastguard Worker   }
1080*795d594fSAndroid Build Coastguard Worker 
Execute(art::ArtMethod * method,art::StackVisitor & visitor)1081*795d594fSAndroid Build Coastguard Worker   jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
1082*795d594fSAndroid Build Coastguard Worker       override REQUIRES_SHARED(art::Locks::mutator_lock_) {
1083*795d594fSAndroid Build Coastguard Worker     switch (type_) {
1084*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimNot: {
1085*795d594fSAndroid Build Coastguard Worker         if (!visitor.SetVRegReference(method,
1086*795d594fSAndroid Build Coastguard Worker                                       static_cast<uint16_t>(slot_),
1087*795d594fSAndroid Build Coastguard Worker                                       caller_->DecodeJObject(val_.l))) {
1088*795d594fSAndroid Build Coastguard Worker           return ERR(OPAQUE_FRAME);
1089*795d594fSAndroid Build Coastguard Worker         }
1090*795d594fSAndroid Build Coastguard Worker         break;
1091*795d594fSAndroid Build Coastguard Worker       }
1092*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimInt:
1093*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimFloat: {
1094*795d594fSAndroid Build Coastguard Worker         if (!visitor.SetVReg(method,
1095*795d594fSAndroid Build Coastguard Worker                              static_cast<uint16_t>(slot_),
1096*795d594fSAndroid Build Coastguard Worker                              static_cast<uint32_t>(val_.i),
1097*795d594fSAndroid Build Coastguard Worker                              type_ == art::Primitive::kPrimFloat ? art::kFloatVReg
1098*795d594fSAndroid Build Coastguard Worker                                                                  : art::kIntVReg)) {
1099*795d594fSAndroid Build Coastguard Worker           return ERR(OPAQUE_FRAME);
1100*795d594fSAndroid Build Coastguard Worker         }
1101*795d594fSAndroid Build Coastguard Worker         break;
1102*795d594fSAndroid Build Coastguard Worker       }
1103*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimDouble:
1104*795d594fSAndroid Build Coastguard Worker       case art::Primitive::kPrimLong: {
1105*795d594fSAndroid Build Coastguard Worker         auto lo_type = type_ == art::Primitive::kPrimLong ? art::kLongLoVReg : art::kDoubleLoVReg;
1106*795d594fSAndroid Build Coastguard Worker         auto high_type = type_ == art::Primitive::kPrimLong ? art::kLongHiVReg : art::kDoubleHiVReg;
1107*795d594fSAndroid Build Coastguard Worker         if (!visitor.SetVRegPair(method,
1108*795d594fSAndroid Build Coastguard Worker                                  static_cast<uint16_t>(slot_),
1109*795d594fSAndroid Build Coastguard Worker                                  static_cast<uint64_t>(val_.j),
1110*795d594fSAndroid Build Coastguard Worker                                  lo_type,
1111*795d594fSAndroid Build Coastguard Worker                                  high_type)) {
1112*795d594fSAndroid Build Coastguard Worker           return ERR(OPAQUE_FRAME);
1113*795d594fSAndroid Build Coastguard Worker         }
1114*795d594fSAndroid Build Coastguard Worker         break;
1115*795d594fSAndroid Build Coastguard Worker       }
1116*795d594fSAndroid Build Coastguard Worker       default: {
1117*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "unexpected register type " << type_;
1118*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
1119*795d594fSAndroid Build Coastguard Worker       }
1120*795d594fSAndroid Build Coastguard Worker     }
1121*795d594fSAndroid Build Coastguard Worker     return OK;
1122*795d594fSAndroid Build Coastguard Worker   }
1123*795d594fSAndroid Build Coastguard Worker 
1124*795d594fSAndroid Build Coastguard Worker  private:
1125*795d594fSAndroid Build Coastguard Worker   art::Thread* caller_;
1126*795d594fSAndroid Build Coastguard Worker   art::Primitive::Type type_;
1127*795d594fSAndroid Build Coastguard Worker   jvalue val_;
1128*795d594fSAndroid Build Coastguard Worker   std::ostringstream err_;
1129*795d594fSAndroid Build Coastguard Worker };
1130*795d594fSAndroid Build Coastguard Worker 
SetLocalVariableGeneric(jvmtiEnv * env,jthread thread,jint depth,jint slot,art::Primitive::Type type,jvalue val)1131*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::SetLocalVariableGeneric(jvmtiEnv* env,
1132*795d594fSAndroid Build Coastguard Worker                                                jthread thread,
1133*795d594fSAndroid Build Coastguard Worker                                                jint depth,
1134*795d594fSAndroid Build Coastguard Worker                                                jint slot,
1135*795d594fSAndroid Build Coastguard Worker                                                art::Primitive::Type type,
1136*795d594fSAndroid Build Coastguard Worker                                                jvalue val) {
1137*795d594fSAndroid Build Coastguard Worker   if (depth < 0) {
1138*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
1139*795d594fSAndroid Build Coastguard Worker   }
1140*795d594fSAndroid Build Coastguard Worker   // Make sure that we know not to do any OSR anymore.
1141*795d594fSAndroid Build Coastguard Worker   // TODO We should really keep track of this at the Frame granularity.
1142*795d594fSAndroid Build Coastguard Worker   DeoptManager::Get()->SetLocalsUpdated();
1143*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
1144*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(self);
1145*795d594fSAndroid Build Coastguard Worker   art::Locks::thread_list_lock_->ExclusiveLock(self);
1146*795d594fSAndroid Build Coastguard Worker   art::Thread* target = nullptr;
1147*795d594fSAndroid Build Coastguard Worker   jvmtiError err = ERR(INTERNAL);
1148*795d594fSAndroid Build Coastguard Worker   if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
1149*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1150*795d594fSAndroid Build Coastguard Worker     return err;
1151*795d594fSAndroid Build Coastguard Worker   }
1152*795d594fSAndroid Build Coastguard Worker   SetLocalVariableClosure c(env, self, depth, slot, type, val);
1153*795d594fSAndroid Build Coastguard Worker   // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
1154*795d594fSAndroid Build Coastguard Worker   if (!target->RequestSynchronousCheckpoint(&c)) {
1155*795d594fSAndroid Build Coastguard Worker     return ERR(THREAD_NOT_ALIVE);
1156*795d594fSAndroid Build Coastguard Worker   } else {
1157*795d594fSAndroid Build Coastguard Worker     return c.GetResult();
1158*795d594fSAndroid Build Coastguard Worker   }
1159*795d594fSAndroid Build Coastguard Worker }
1160*795d594fSAndroid Build Coastguard Worker 
1161*795d594fSAndroid Build Coastguard Worker class GetLocalInstanceClosure : public art::Closure {
1162*795d594fSAndroid Build Coastguard Worker  public:
GetLocalInstanceClosure(jint depth)1163*795d594fSAndroid Build Coastguard Worker   explicit GetLocalInstanceClosure(jint depth)
1164*795d594fSAndroid Build Coastguard Worker       : result_(ERR(INTERNAL)),
1165*795d594fSAndroid Build Coastguard Worker         depth_(depth),
1166*795d594fSAndroid Build Coastguard Worker         val_(nullptr) {}
1167*795d594fSAndroid Build Coastguard Worker 
Run(art::Thread * self)1168*795d594fSAndroid Build Coastguard Worker   void Run(art::Thread* self) override REQUIRES(art::Locks::mutator_lock_) {
1169*795d594fSAndroid Build Coastguard Worker     art::ScopedAssertNoThreadSuspension sants("GetLocalInstanceClosure::Run");
1170*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current());
1171*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<art::Context> context(art::Context::Create());
1172*795d594fSAndroid Build Coastguard Worker     FindFrameAtDepthVisitor visitor(self, context.get(), depth_);
1173*795d594fSAndroid Build Coastguard Worker     visitor.WalkStack();
1174*795d594fSAndroid Build Coastguard Worker     if (!visitor.FoundFrame()) {
1175*795d594fSAndroid Build Coastguard Worker       // Must have been a bad depth.
1176*795d594fSAndroid Build Coastguard Worker       result_ = ERR(NO_MORE_FRAMES);
1177*795d594fSAndroid Build Coastguard Worker       return;
1178*795d594fSAndroid Build Coastguard Worker     }
1179*795d594fSAndroid Build Coastguard Worker     result_ = OK;
1180*795d594fSAndroid Build Coastguard Worker     val_ = art::GcRoot<art::mirror::Object>(visitor.GetThisObject());
1181*795d594fSAndroid Build Coastguard Worker   }
1182*795d594fSAndroid Build Coastguard Worker 
GetResult(jobject * data_out)1183*795d594fSAndroid Build Coastguard Worker   jvmtiError GetResult(jobject* data_out) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1184*795d594fSAndroid Build Coastguard Worker     if (result_ == OK) {
1185*795d594fSAndroid Build Coastguard Worker       *data_out = val_.IsNull()
1186*795d594fSAndroid Build Coastguard Worker           ? nullptr
1187*795d594fSAndroid Build Coastguard Worker           : art::Thread::Current()->GetJniEnv()->AddLocalReference<jobject>(val_.Read());
1188*795d594fSAndroid Build Coastguard Worker     }
1189*795d594fSAndroid Build Coastguard Worker     return result_;
1190*795d594fSAndroid Build Coastguard Worker   }
1191*795d594fSAndroid Build Coastguard Worker 
1192*795d594fSAndroid Build Coastguard Worker  private:
1193*795d594fSAndroid Build Coastguard Worker   jvmtiError result_;
1194*795d594fSAndroid Build Coastguard Worker   jint depth_;
1195*795d594fSAndroid Build Coastguard Worker   art::GcRoot<art::mirror::Object> val_;
1196*795d594fSAndroid Build Coastguard Worker };
1197*795d594fSAndroid Build Coastguard Worker 
GetLocalInstance(jvmtiEnv * env,jthread thread,jint depth,jobject * data)1198*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetLocalInstance([[maybe_unused]] jvmtiEnv* env,
1199*795d594fSAndroid Build Coastguard Worker                                         jthread thread,
1200*795d594fSAndroid Build Coastguard Worker                                         jint depth,
1201*795d594fSAndroid Build Coastguard Worker                                         jobject* data) {
1202*795d594fSAndroid Build Coastguard Worker   if (depth < 0) {
1203*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
1204*795d594fSAndroid Build Coastguard Worker   }
1205*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
1206*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(self);
1207*795d594fSAndroid Build Coastguard Worker   art::Locks::thread_list_lock_->ExclusiveLock(self);
1208*795d594fSAndroid Build Coastguard Worker   art::Thread* target = nullptr;
1209*795d594fSAndroid Build Coastguard Worker   jvmtiError err = ERR(INTERNAL);
1210*795d594fSAndroid Build Coastguard Worker   if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
1211*795d594fSAndroid Build Coastguard Worker     art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1212*795d594fSAndroid Build Coastguard Worker     return err;
1213*795d594fSAndroid Build Coastguard Worker   }
1214*795d594fSAndroid Build Coastguard Worker   art::ScopedAssertNoThreadSuspension sants("Performing GetLocalInstance");
1215*795d594fSAndroid Build Coastguard Worker   GetLocalInstanceClosure c(depth);
1216*795d594fSAndroid Build Coastguard Worker   // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.  We
1217*795d594fSAndroid Build Coastguard Worker   // need to avoid suspending as we wait for the checkpoint to occur since we are (potentially)
1218*795d594fSAndroid Build Coastguard Worker   // transfering a GcRoot across threads.
1219*795d594fSAndroid Build Coastguard Worker   if (!target->RequestSynchronousCheckpoint(&c, art::ThreadState::kRunnable)) {
1220*795d594fSAndroid Build Coastguard Worker     return ERR(THREAD_NOT_ALIVE);
1221*795d594fSAndroid Build Coastguard Worker   } else {
1222*795d594fSAndroid Build Coastguard Worker     return c.GetResult(data);
1223*795d594fSAndroid Build Coastguard Worker   }
1224*795d594fSAndroid Build Coastguard Worker }
1225*795d594fSAndroid Build Coastguard Worker 
1226*795d594fSAndroid Build Coastguard Worker #define FOR_JVMTI_JVALUE_TYPES(fn) \
1227*795d594fSAndroid Build Coastguard Worker     fn(jint, art::Primitive::kPrimInt, i) \
1228*795d594fSAndroid Build Coastguard Worker     fn(jlong, art::Primitive::kPrimLong, j) \
1229*795d594fSAndroid Build Coastguard Worker     fn(jfloat, art::Primitive::kPrimFloat, f) \
1230*795d594fSAndroid Build Coastguard Worker     fn(jdouble, art::Primitive::kPrimDouble, d) \
1231*795d594fSAndroid Build Coastguard Worker     fn(jobject, art::Primitive::kPrimNot, l)
1232*795d594fSAndroid Build Coastguard Worker 
1233*795d594fSAndroid Build Coastguard Worker namespace impl {
1234*795d594fSAndroid Build Coastguard Worker 
1235*795d594fSAndroid Build Coastguard Worker template<typename T> void WriteJvalue(T, jvalue*);
1236*795d594fSAndroid Build Coastguard Worker template<typename T> void ReadJvalue(jvalue, T*);
1237*795d594fSAndroid Build Coastguard Worker template<typename T> art::Primitive::Type GetJNIType();
1238*795d594fSAndroid Build Coastguard Worker 
1239*795d594fSAndroid Build Coastguard Worker #define JNI_TYPE_CHAR(type, prim, id) \
1240*795d594fSAndroid Build Coastguard Worker template<> art::Primitive::Type GetJNIType<type>() { \
1241*795d594fSAndroid Build Coastguard Worker   return prim; \
1242*795d594fSAndroid Build Coastguard Worker }
1243*795d594fSAndroid Build Coastguard Worker 
1244*795d594fSAndroid Build Coastguard Worker FOR_JVMTI_JVALUE_TYPES(JNI_TYPE_CHAR);
1245*795d594fSAndroid Build Coastguard Worker 
1246*795d594fSAndroid Build Coastguard Worker #undef JNI_TYPE_CHAR
1247*795d594fSAndroid Build Coastguard Worker 
1248*795d594fSAndroid Build Coastguard Worker #define RW_JVALUE(srctype, prim, id) \
1249*795d594fSAndroid Build Coastguard Worker     template<> void ReadJvalue<srctype>(jvalue in, std::add_pointer<srctype>::type out) { \
1250*795d594fSAndroid Build Coastguard Worker       *out = in.id; \
1251*795d594fSAndroid Build Coastguard Worker     } \
1252*795d594fSAndroid Build Coastguard Worker     template<> void WriteJvalue<srctype>(srctype in, jvalue* out) { \
1253*795d594fSAndroid Build Coastguard Worker       out->id = in; \
1254*795d594fSAndroid Build Coastguard Worker     }
1255*795d594fSAndroid Build Coastguard Worker 
1256*795d594fSAndroid Build Coastguard Worker FOR_JVMTI_JVALUE_TYPES(RW_JVALUE);
1257*795d594fSAndroid Build Coastguard Worker 
1258*795d594fSAndroid Build Coastguard Worker #undef RW_JVALUE
1259*795d594fSAndroid Build Coastguard Worker 
1260*795d594fSAndroid Build Coastguard Worker }  // namespace impl
1261*795d594fSAndroid Build Coastguard Worker 
1262*795d594fSAndroid Build Coastguard Worker template<typename T>
SetLocalVariable(jvmtiEnv * env,jthread thread,jint depth,jint slot,T data)1263*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::SetLocalVariable(jvmtiEnv* env,
1264*795d594fSAndroid Build Coastguard Worker                                         jthread thread,
1265*795d594fSAndroid Build Coastguard Worker                                         jint depth,
1266*795d594fSAndroid Build Coastguard Worker                                         jint slot,
1267*795d594fSAndroid Build Coastguard Worker                                         T data) {
1268*795d594fSAndroid Build Coastguard Worker   jvalue v = {.j = 0};
1269*795d594fSAndroid Build Coastguard Worker   art::Primitive::Type type = impl::GetJNIType<T>();
1270*795d594fSAndroid Build Coastguard Worker   impl::WriteJvalue(data, &v);
1271*795d594fSAndroid Build Coastguard Worker   return SetLocalVariableGeneric(env, thread, depth, slot, type, v);
1272*795d594fSAndroid Build Coastguard Worker }
1273*795d594fSAndroid Build Coastguard Worker 
1274*795d594fSAndroid Build Coastguard Worker template<typename T>
GetLocalVariable(jvmtiEnv * env,jthread thread,jint depth,jint slot,T * data)1275*795d594fSAndroid Build Coastguard Worker jvmtiError MethodUtil::GetLocalVariable(jvmtiEnv* env,
1276*795d594fSAndroid Build Coastguard Worker                                         jthread thread,
1277*795d594fSAndroid Build Coastguard Worker                                         jint depth,
1278*795d594fSAndroid Build Coastguard Worker                                         jint slot,
1279*795d594fSAndroid Build Coastguard Worker                                         T* data) {
1280*795d594fSAndroid Build Coastguard Worker   if (data == nullptr) {
1281*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
1282*795d594fSAndroid Build Coastguard Worker   }
1283*795d594fSAndroid Build Coastguard Worker   jvalue v = {.j = 0};
1284*795d594fSAndroid Build Coastguard Worker   art::Primitive::Type type = impl::GetJNIType<T>();
1285*795d594fSAndroid Build Coastguard Worker   jvmtiError err = GetLocalVariableGeneric(env, thread, depth, slot, type, &v);
1286*795d594fSAndroid Build Coastguard Worker   if (err != OK) {
1287*795d594fSAndroid Build Coastguard Worker     return err;
1288*795d594fSAndroid Build Coastguard Worker   } else {
1289*795d594fSAndroid Build Coastguard Worker     impl::ReadJvalue(v, data);
1290*795d594fSAndroid Build Coastguard Worker     return OK;
1291*795d594fSAndroid Build Coastguard Worker   }
1292*795d594fSAndroid Build Coastguard Worker }
1293*795d594fSAndroid Build Coastguard Worker 
1294*795d594fSAndroid Build Coastguard Worker #define GET_SET_LV(srctype, prim, id) \
1295*795d594fSAndroid Build Coastguard Worker     template jvmtiError MethodUtil::GetLocalVariable<srctype>(jvmtiEnv*, \
1296*795d594fSAndroid Build Coastguard Worker                                                               jthread, \
1297*795d594fSAndroid Build Coastguard Worker                                                               jint, \
1298*795d594fSAndroid Build Coastguard Worker                                                               jint, \
1299*795d594fSAndroid Build Coastguard Worker                                                               std::add_pointer<srctype>::type); \
1300*795d594fSAndroid Build Coastguard Worker     template jvmtiError MethodUtil::SetLocalVariable<srctype>(jvmtiEnv*, \
1301*795d594fSAndroid Build Coastguard Worker                                                               jthread, \
1302*795d594fSAndroid Build Coastguard Worker                                                               jint, \
1303*795d594fSAndroid Build Coastguard Worker                                                               jint, \
1304*795d594fSAndroid Build Coastguard Worker                                                               srctype);
1305*795d594fSAndroid Build Coastguard Worker 
1306*795d594fSAndroid Build Coastguard Worker FOR_JVMTI_JVALUE_TYPES(GET_SET_LV);
1307*795d594fSAndroid Build Coastguard Worker 
1308*795d594fSAndroid Build Coastguard Worker #undef GET_SET_LV
1309*795d594fSAndroid Build Coastguard Worker 
1310*795d594fSAndroid Build Coastguard Worker #undef FOR_JVMTI_JVALUE_TYPES
1311*795d594fSAndroid Build Coastguard Worker 
1312*795d594fSAndroid Build Coastguard Worker }  // namespace openjdkjvmti
1313