blob: e34a85609bc01ccee071918a828d134df337d56e [file] [log] [blame]
Andreas Gampe3c252f02016-10-27 18:25:17 -07001/* Copyright (C) 2016 The Android Open Source Project
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This file implements interfaces from the file jvmti.h. This implementation
5 * is licensed under the same terms as the file jvmti.h. The
6 * copyright and license information for the file jvmti.h follows.
7 *
8 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
9 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10 *
11 * This code is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 only, as
13 * published by the Free Software Foundation. Oracle designates this
14 * particular file as subject to the "Classpath" exception as provided
15 * by Oracle in the LICENSE file that accompanied this code.
16 *
17 * This code is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * version 2 for more details (a copy is included in the LICENSE file that
21 * accompanied this code).
22 *
23 * You should have received a copy of the GNU General Public License version
24 * 2 along with this work; if not, write to the Free Software Foundation,
25 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 *
27 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28 * or visit www.oracle.com if you need additional information or have any
29 * questions.
30 */
31
32#include "ti_method.h"
33
Andreas Gampe49fc60e2017-08-24 13:19:59 -070034#include <type_traits>
35
Andreas Gampee5d23982019-01-08 10:34:26 -080036#include "arch/context.h"
Andreas Gampe3c252f02016-10-27 18:25:17 -070037#include "art_jvmti.h"
38#include "art_method-inl.h"
39#include "base/enums.h"
Alex Lightbebd7bd2017-07-25 14:05:52 -070040#include "base/mutex-inl.h"
Alex Lighta4cdd362019-04-18 09:17:10 -070041#include "deopt_manager.h"
David Sehr9e734c72018-01-04 17:56:19 -080042#include "dex/code_item_accessors-inl.h"
43#include "dex/dex_file_annotations.h"
44#include "dex/dex_file_types.h"
David Sehr8c0961f2018-01-23 16:11:38 -080045#include "dex/modifiers.h"
Alex Lightd78ddec2017-04-18 15:20:38 -070046#include "events-inl.h"
Alex Light318afe62018-03-22 16:50:10 -070047#include "gc_root-inl.h"
Alex Light0a5ec3d2017-07-25 16:50:26 -070048#include "jit/jit.h"
Vladimir Markoa3ad0cd2018-05-04 10:06:38 +010049#include "jni/jni_internal.h"
Alex Lightbebd7bd2017-07-25 14:05:52 -070050#include "mirror/class-inl.h"
51#include "mirror/class_loader.h"
52#include "mirror/object-inl.h"
Andreas Gampe27dfa052017-02-16 15:04:36 -080053#include "mirror/object_array-inl.h"
Andreas Gampe373a9b52017-10-18 09:01:57 -070054#include "nativehelper/scoped_local_ref.h"
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +000055#include "oat_file.h"
Alex Lighta4cdd362019-04-18 09:17:10 -070056#include "obj_ptr.h"
Alex Lightd78ddec2017-04-18 15:20:38 -070057#include "runtime_callbacks.h"
Andreas Gampe3c252f02016-10-27 18:25:17 -070058#include "scoped_thread_state_change-inl.h"
Alex Lightbebd7bd2017-07-25 14:05:52 -070059#include "stack.h"
Andreas Gampeb486a982017-06-01 13:45:54 -070060#include "thread-current-inl.h"
Alex Lighta4cdd362019-04-18 09:17:10 -070061#include "thread.h"
Alex Lightd78ddec2017-04-18 15:20:38 -070062#include "thread_list.h"
Alex Lighte814f9d2017-07-31 16:14:39 -070063#include "ti_stack.h"
Alex Lightbebd7bd2017-07-25 14:05:52 -070064#include "ti_thread.h"
Alex Light0af8cde2017-04-20 13:35:05 -070065#include "ti_phase.h"
Andreas Gampe3c252f02016-10-27 18:25:17 -070066
67namespace openjdkjvmti {
68
Alex Lightd78ddec2017-04-18 15:20:38 -070069struct TiMethodCallback : public art::MethodCallback {
70 void RegisterNativeMethod(art::ArtMethod* method,
71 const void* cur_method,
72 /*out*/void** new_method)
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010073 override REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightd78ddec2017-04-18 15:20:38 -070074 if (event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kNativeMethodBind)) {
75 art::Thread* thread = art::Thread::Current();
Alex Light0af8cde2017-04-20 13:35:05 -070076 art::JNIEnvExt* jnienv = thread->GetJniEnv();
Alex Lightd78ddec2017-04-18 15:20:38 -070077 ScopedLocalRef<jthread> thread_jni(
Alex Light0af8cde2017-04-20 13:35:05 -070078 jnienv, PhaseUtil::IsLivePhase() ? jnienv->AddLocalReference<jthread>(thread->GetPeer())
79 : nullptr);
Alex Lightd78ddec2017-04-18 15:20:38 -070080 art::ScopedThreadSuspension sts(thread, art::ThreadState::kNative);
81 event_handler->DispatchEvent<ArtJvmtiEvent::kNativeMethodBind>(
82 thread,
Alex Light0af8cde2017-04-20 13:35:05 -070083 static_cast<JNIEnv*>(jnienv),
Alex Lightd78ddec2017-04-18 15:20:38 -070084 thread_jni.get(),
85 art::jni::EncodeArtMethod(method),
86 const_cast<void*>(cur_method),
87 new_method);
88 }
89 }
90
91 EventHandler* event_handler = nullptr;
92};
93
94TiMethodCallback gMethodCallback;
95
96void MethodUtil::Register(EventHandler* handler) {
97 gMethodCallback.event_handler = handler;
98 art::ScopedThreadStateChange stsc(art::Thread::Current(),
99 art::ThreadState::kWaitingForDebuggerToAttach);
100 art::ScopedSuspendAll ssa("Add method callback");
Alex Light21611932017-09-26 13:07:39 -0700101 art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks();
102 callbacks->AddMethodCallback(&gMethodCallback);
Alex Lightd78ddec2017-04-18 15:20:38 -0700103}
104
105void MethodUtil::Unregister() {
106 art::ScopedThreadStateChange stsc(art::Thread::Current(),
107 art::ThreadState::kWaitingForDebuggerToAttach);
108 art::ScopedSuspendAll ssa("Remove method callback");
Alex Light21611932017-09-26 13:07:39 -0700109 art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks();
110 callbacks->RemoveMethodCallback(&gMethodCallback);
Alex Lightd78ddec2017-04-18 15:20:38 -0700111}
112
Alex Light4c174282017-07-05 10:18:18 -0700113jvmtiError MethodUtil::GetBytecodes(jvmtiEnv* env,
114 jmethodID method,
115 jint* size_ptr,
116 unsigned char** bytecode_ptr) {
117 if (method == nullptr) {
118 return ERR(INVALID_METHODID);
119 }
120 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
121
122 if (art_method->IsNative()) {
123 return ERR(NATIVE_METHOD);
124 }
125
126 if (size_ptr == nullptr || bytecode_ptr == nullptr) {
127 return ERR(NULL_POINTER);
128 }
129
130 art::ScopedObjectAccess soa(art::Thread::Current());
David Sehr0225f8e2018-01-31 08:52:24 +0000131 art::CodeItemInstructionAccessor accessor(art_method->DexInstructions());
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800132 if (!accessor.HasCodeItem()) {
Alex Light4c174282017-07-05 10:18:18 -0700133 *size_ptr = 0;
134 *bytecode_ptr = nullptr;
135 return OK;
136 }
137 // 2 bytes per instruction for dex code.
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800138 *size_ptr = accessor.InsnsSizeInCodeUnits() * 2;
Alex Light4c174282017-07-05 10:18:18 -0700139 jvmtiError err = env->Allocate(*size_ptr, bytecode_ptr);
140 if (err != OK) {
141 return err;
142 }
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800143 memcpy(*bytecode_ptr, accessor.Insns(), *size_ptr);
Alex Light4c174282017-07-05 10:18:18 -0700144 return OK;
145}
146
Andreas Gampef71832e2017-01-09 11:38:04 -0800147jvmtiError MethodUtil::GetArgumentsSize(jvmtiEnv* env ATTRIBUTE_UNUSED,
148 jmethodID method,
149 jint* size_ptr) {
150 if (method == nullptr) {
151 return ERR(INVALID_METHODID);
152 }
153 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
154
155 if (art_method->IsNative()) {
156 return ERR(NATIVE_METHOD);
157 }
158
159 if (size_ptr == nullptr) {
160 return ERR(NULL_POINTER);
161 }
162
163 art::ScopedObjectAccess soa(art::Thread::Current());
164 if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
Andreas Gampee1f79b62017-04-12 21:11:28 -0700165 // Use the shorty.
166 art::ArtMethod* base_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize);
167 size_t arg_count = art::ArtMethod::NumArgRegisters(base_method->GetShorty());
168 if (!base_method->IsStatic()) {
169 arg_count++;
170 }
171 *size_ptr = static_cast<jint>(arg_count);
Andreas Gampef71832e2017-01-09 11:38:04 -0800172 return ERR(NONE);
173 }
174
175 DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
David Sehr0225f8e2018-01-31 08:52:24 +0000176 *size_ptr = art_method->DexInstructionData().InsSize();
Andreas Gampef71832e2017-01-09 11:38:04 -0800177
178 return ERR(NONE);
179}
180
Alex Lightce68cc62017-07-26 10:30:38 -0700181jvmtiError MethodUtil::GetLocalVariableTable(jvmtiEnv* env,
182 jmethodID method,
183 jint* entry_count_ptr,
184 jvmtiLocalVariableEntry** table_ptr) {
185 if (method == nullptr) {
186 return ERR(INVALID_METHODID);
187 }
188 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
189
190 if (art_method->IsNative()) {
191 return ERR(NATIVE_METHOD);
192 }
193
194 if (entry_count_ptr == nullptr || table_ptr == nullptr) {
195 return ERR(NULL_POINTER);
196 }
197
198 art::ScopedObjectAccess soa(art::Thread::Current());
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800199
200 const art::DexFile* const dex_file = art_method->GetDexFile();
201 if (dex_file == nullptr) {
202 return ERR(ABSENT_INFORMATION);
203 }
204
205 // TODO HasCodeItem == false means that the method is abstract (or native, but we check that
Alex Lightce68cc62017-07-26 10:30:38 -0700206 // earlier). We should check what is returned by the RI in this situation since it's not clear
207 // what the appropriate return value is from the spec.
David Sehr0225f8e2018-01-31 08:52:24 +0000208 art::CodeItemDebugInfoAccessor accessor(art_method->DexInstructionDebugInfo());
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800209 if (!accessor.HasCodeItem()) {
Alex Lightce68cc62017-07-26 10:30:38 -0700210 return ERR(ABSENT_INFORMATION);
211 }
212
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700213 std::vector<jvmtiLocalVariableEntry> variables;
214 jvmtiError err = OK;
Alex Lightce68cc62017-07-26 10:30:38 -0700215
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700216 auto release = [&](jint* out_entry_count_ptr, jvmtiLocalVariableEntry** out_table_ptr) {
217 jlong table_size = sizeof(jvmtiLocalVariableEntry) * variables.size();
218 if (err != OK ||
219 (err = env->Allocate(table_size,
220 reinterpret_cast<unsigned char**>(out_table_ptr))) != OK) {
221 for (jvmtiLocalVariableEntry& e : variables) {
222 env->Deallocate(reinterpret_cast<unsigned char*>(e.name));
223 env->Deallocate(reinterpret_cast<unsigned char*>(e.signature));
224 env->Deallocate(reinterpret_cast<unsigned char*>(e.generic_signature));
225 }
226 return err;
Alex Lightce68cc62017-07-26 10:30:38 -0700227 }
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700228 *out_entry_count_ptr = variables.size();
229 memcpy(*out_table_ptr, variables.data(), table_size);
230 return OK;
Alex Lightce68cc62017-07-26 10:30:38 -0700231 };
232
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700233 auto visitor = [&](const art::DexFile::LocalInfo& entry) {
234 if (err != OK) {
235 return;
236 }
237 JvmtiUniquePtr<char[]> name_str = CopyString(env, entry.name_, &err);
238 if (err != OK) {
239 return;
240 }
241 JvmtiUniquePtr<char[]> sig_str = CopyString(env, entry.descriptor_, &err);
242 if (err != OK) {
243 return;
244 }
245 JvmtiUniquePtr<char[]> generic_sig_str = CopyString(env, entry.signature_, &err);
246 if (err != OK) {
247 return;
248 }
249 variables.push_back({
250 .start_location = static_cast<jlocation>(entry.start_address_),
251 .length = static_cast<jint>(entry.end_address_ - entry.start_address_),
252 .name = name_str.release(),
253 .signature = sig_str.release(),
254 .generic_signature = generic_sig_str.release(),
255 .slot = entry.reg_,
256 });
257 };
258
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800259 if (!accessor.DecodeDebugLocalInfo(art_method->IsStatic(),
260 art_method->GetDexMethodIndex(),
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700261 visitor)) {
Alex Lightce68cc62017-07-26 10:30:38 -0700262 // Something went wrong with decoding the debug information. It might as well not be there.
263 return ERR(ABSENT_INFORMATION);
Alex Lightce68cc62017-07-26 10:30:38 -0700264 }
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700265 return release(entry_count_ptr, table_ptr);
Alex Lightce68cc62017-07-26 10:30:38 -0700266}
267
Andreas Gampef71832e2017-01-09 11:38:04 -0800268jvmtiError MethodUtil::GetMaxLocals(jvmtiEnv* env ATTRIBUTE_UNUSED,
269 jmethodID method,
270 jint* max_ptr) {
271 if (method == nullptr) {
272 return ERR(INVALID_METHODID);
273 }
274 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
275
276 if (art_method->IsNative()) {
277 return ERR(NATIVE_METHOD);
278 }
279
280 if (max_ptr == nullptr) {
281 return ERR(NULL_POINTER);
282 }
283
284 art::ScopedObjectAccess soa(art::Thread::Current());
285 if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
286 // This isn't specified as an error case, so return 0.
287 *max_ptr = 0;
288 return ERR(NONE);
289 }
290
291 DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
David Sehr0225f8e2018-01-31 08:52:24 +0000292 *max_ptr = art_method->DexInstructionData().RegistersSize();
Andreas Gampef71832e2017-01-09 11:38:04 -0800293
294 return ERR(NONE);
295}
296
Andreas Gampe3c252f02016-10-27 18:25:17 -0700297jvmtiError MethodUtil::GetMethodName(jvmtiEnv* env,
298 jmethodID method,
299 char** name_ptr,
300 char** signature_ptr,
301 char** generic_ptr) {
302 art::ScopedObjectAccess soa(art::Thread::Current());
Andreas Gampe13b27842016-11-07 16:48:23 -0800303 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
Andreas Gampe3c252f02016-10-27 18:25:17 -0700304 art_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize);
305
Andreas Gampe54711412017-02-21 12:41:43 -0800306 JvmtiUniquePtr<char[]> name_copy;
Andreas Gampe3c252f02016-10-27 18:25:17 -0700307 if (name_ptr != nullptr) {
308 const char* method_name = art_method->GetName();
309 if (method_name == nullptr) {
310 method_name = "<error>";
311 }
Andreas Gampe54711412017-02-21 12:41:43 -0800312 jvmtiError ret;
313 name_copy = CopyString(env, method_name, &ret);
314 if (name_copy == nullptr) {
Andreas Gampe3c252f02016-10-27 18:25:17 -0700315 return ret;
316 }
Andreas Gampe54711412017-02-21 12:41:43 -0800317 *name_ptr = name_copy.get();
Andreas Gampe3c252f02016-10-27 18:25:17 -0700318 }
319
Andreas Gampe54711412017-02-21 12:41:43 -0800320 JvmtiUniquePtr<char[]> signature_copy;
Andreas Gampe3c252f02016-10-27 18:25:17 -0700321 if (signature_ptr != nullptr) {
322 const art::Signature sig = art_method->GetSignature();
323 std::string str = sig.ToString();
Andreas Gampe54711412017-02-21 12:41:43 -0800324 jvmtiError ret;
325 signature_copy = CopyString(env, str.c_str(), &ret);
326 if (signature_copy == nullptr) {
Andreas Gampe3c252f02016-10-27 18:25:17 -0700327 return ret;
328 }
Andreas Gampe54711412017-02-21 12:41:43 -0800329 *signature_ptr = signature_copy.get();
Andreas Gampe3c252f02016-10-27 18:25:17 -0700330 }
331
Andreas Gampe862bdd82016-11-18 13:31:13 -0800332 if (generic_ptr != nullptr) {
333 *generic_ptr = nullptr;
Andreas Gampe27dfa052017-02-16 15:04:36 -0800334 if (!art_method->GetDeclaringClass()->IsProxyClass()) {
Vladimir Markoacb906d2018-05-30 10:23:49 +0100335 art::ObjPtr<art::mirror::ObjectArray<art::mirror::String>> str_array =
Andreas Gampe27dfa052017-02-16 15:04:36 -0800336 art::annotations::GetSignatureAnnotationForMethod(art_method);
337 if (str_array != nullptr) {
338 std::ostringstream oss;
339 for (int32_t i = 0; i != str_array->GetLength(); ++i) {
340 oss << str_array->Get(i)->ToModifiedUtf8();
341 }
342 std::string output_string = oss.str();
Andreas Gampe54711412017-02-21 12:41:43 -0800343 jvmtiError ret;
344 JvmtiUniquePtr<char[]> generic_copy = CopyString(env, output_string.c_str(), &ret);
345 if (generic_copy == nullptr) {
Andreas Gampe27dfa052017-02-16 15:04:36 -0800346 return ret;
347 }
Andreas Gampe54711412017-02-21 12:41:43 -0800348 *generic_ptr = generic_copy.release();
Andreas Gampe27dfa052017-02-16 15:04:36 -0800349 } else if (soa.Self()->IsExceptionPending()) {
350 // TODO: Should we report an error here?
351 soa.Self()->ClearException();
352 }
353 }
Andreas Gampe862bdd82016-11-18 13:31:13 -0800354 }
Andreas Gampe3c252f02016-10-27 18:25:17 -0700355
356 // Everything is fine, release the buffers.
357 name_copy.release();
358 signature_copy.release();
359
360 return ERR(NONE);
361}
362
Andreas Gampe368a2082016-10-28 17:33:13 -0700363jvmtiError MethodUtil::GetMethodDeclaringClass(jvmtiEnv* env ATTRIBUTE_UNUSED,
364 jmethodID method,
365 jclass* declaring_class_ptr) {
366 if (declaring_class_ptr == nullptr) {
367 return ERR(NULL_POINTER);
368 }
369
Andreas Gampe13b27842016-11-07 16:48:23 -0800370 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
Andreas Gampe368a2082016-10-28 17:33:13 -0700371 // Note: No GetInterfaceMethodIfProxy, we want to actual class.
372
Andreas Gampe13b27842016-11-07 16:48:23 -0800373 art::ScopedObjectAccess soa(art::Thread::Current());
Vladimir Markod93e3742018-07-18 10:58:13 +0100374 art::ObjPtr<art::mirror::Class> klass = art_method->GetDeclaringClass();
Andreas Gampe368a2082016-10-28 17:33:13 -0700375 *declaring_class_ptr = soa.AddLocalReference<jclass>(klass);
376
377 return ERR(NONE);
378}
379
Andreas Gampef71832e2017-01-09 11:38:04 -0800380jvmtiError MethodUtil::GetMethodLocation(jvmtiEnv* env ATTRIBUTE_UNUSED,
381 jmethodID method,
382 jlocation* start_location_ptr,
383 jlocation* end_location_ptr) {
384 if (method == nullptr) {
385 return ERR(INVALID_METHODID);
386 }
387 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
388
389 if (art_method->IsNative()) {
390 return ERR(NATIVE_METHOD);
391 }
392
393 if (start_location_ptr == nullptr || end_location_ptr == nullptr) {
394 return ERR(NULL_POINTER);
395 }
396
397 art::ScopedObjectAccess soa(art::Thread::Current());
398 if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
Andreas Gampee1f79b62017-04-12 21:11:28 -0700399 // This isn't specified as an error case, so return -1/-1 as the RI does.
400 *start_location_ptr = -1;
401 *end_location_ptr = -1;
Andreas Gampef71832e2017-01-09 11:38:04 -0800402 return ERR(NONE);
403 }
404
405 DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
406 *start_location_ptr = 0;
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800407 *end_location_ptr = art_method->DexInstructions().InsnsSizeInCodeUnits() - 1;
Andreas Gampef71832e2017-01-09 11:38:04 -0800408
409 return ERR(NONE);
410}
411
Andreas Gampe36bcd4f2016-10-28 18:07:18 -0700412jvmtiError MethodUtil::GetMethodModifiers(jvmtiEnv* env ATTRIBUTE_UNUSED,
413 jmethodID method,
414 jint* modifiers_ptr) {
415 if (modifiers_ptr == nullptr) {
416 return ERR(NULL_POINTER);
417 }
418
Andreas Gampe13b27842016-11-07 16:48:23 -0800419 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
Andreas Gampe36bcd4f2016-10-28 18:07:18 -0700420 uint32_t modifiers = art_method->GetAccessFlags();
421
422 // Note: Keep this code in sync with Executable.fixMethodFlags.
423 if ((modifiers & art::kAccAbstract) != 0) {
424 modifiers &= ~art::kAccNative;
425 }
426 modifiers &= ~art::kAccSynchronized;
427 if ((modifiers & art::kAccDeclaredSynchronized) != 0) {
428 modifiers |= art::kAccSynchronized;
429 }
430 modifiers &= art::kAccJavaFlagsMask;
431
432 *modifiers_ptr = modifiers;
433 return ERR(NONE);
434}
435
Andreas Gampeda3e5612016-12-13 19:00:53 -0800436jvmtiError MethodUtil::GetLineNumberTable(jvmtiEnv* env,
437 jmethodID method,
438 jint* entry_count_ptr,
439 jvmtiLineNumberEntry** table_ptr) {
440 if (method == nullptr) {
441 return ERR(NULL_POINTER);
442 }
443 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
444 DCHECK(!art_method->IsRuntimeMethod());
445
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800446 art::CodeItemDebugInfoAccessor accessor;
Andreas Gampeda3e5612016-12-13 19:00:53 -0800447 const art::DexFile* dex_file;
448 {
449 art::ScopedObjectAccess soa(art::Thread::Current());
450
451 if (art_method->IsProxyMethod()) {
452 return ERR(ABSENT_INFORMATION);
453 }
454 if (art_method->IsNative()) {
455 return ERR(NATIVE_METHOD);
456 }
457 if (entry_count_ptr == nullptr || table_ptr == nullptr) {
458 return ERR(NULL_POINTER);
459 }
460
David Sehr0225f8e2018-01-31 08:52:24 +0000461 accessor = art::CodeItemDebugInfoAccessor(art_method->DexInstructionDebugInfo());
Andreas Gampeda3e5612016-12-13 19:00:53 -0800462 dex_file = art_method->GetDexFile();
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800463 DCHECK(accessor.HasCodeItem()) << art_method->PrettyMethod() << " " << dex_file->GetLocation();
Andreas Gampeda3e5612016-12-13 19:00:53 -0800464 }
465
Mathieu Chartier3e2e1232018-09-11 12:35:30 -0700466 std::vector<jvmtiLineNumberEntry> context;
467 bool success = accessor.DecodeDebugPositionInfo([&](const art::DexFile::PositionInfo& entry) {
468 context.push_back({static_cast<jlocation>(entry.address_), static_cast<jint>(entry.line_)});
469 return false;
470 });
Andreas Gampeda3e5612016-12-13 19:00:53 -0800471 if (!success) {
472 return ERR(ABSENT_INFORMATION);
473 }
474
475 unsigned char* data;
476 jlong mem_size = context.size() * sizeof(jvmtiLineNumberEntry);
477 jvmtiError alloc_error = env->Allocate(mem_size, &data);
478 if (alloc_error != ERR(NONE)) {
479 return alloc_error;
480 }
481 *table_ptr = reinterpret_cast<jvmtiLineNumberEntry*>(data);
482 memcpy(*table_ptr, context.data(), mem_size);
483 *entry_count_ptr = static_cast<jint>(context.size());
484
485 return ERR(NONE);
486}
487
Andreas Gampefdeef522017-01-09 14:40:25 -0800488template <typename T>
489static jvmtiError IsMethodT(jvmtiEnv* env ATTRIBUTE_UNUSED,
490 jmethodID method,
491 T test,
492 jboolean* is_t_ptr) {
493 if (method == nullptr) {
494 return ERR(INVALID_METHODID);
495 }
496 if (is_t_ptr == nullptr) {
497 return ERR(NULL_POINTER);
498 }
499
500 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
501 *is_t_ptr = test(art_method) ? JNI_TRUE : JNI_FALSE;
502
503 return ERR(NONE);
504}
505
506jvmtiError MethodUtil::IsMethodNative(jvmtiEnv* env, jmethodID m, jboolean* is_native_ptr) {
507 auto test = [](art::ArtMethod* method) {
508 return method->IsNative();
509 };
510 return IsMethodT(env, m, test, is_native_ptr);
511}
512
513jvmtiError MethodUtil::IsMethodObsolete(jvmtiEnv* env, jmethodID m, jboolean* is_obsolete_ptr) {
514 auto test = [](art::ArtMethod* method) {
515 return method->IsObsolete();
516 };
517 return IsMethodT(env, m, test, is_obsolete_ptr);
518}
519
520jvmtiError MethodUtil::IsMethodSynthetic(jvmtiEnv* env, jmethodID m, jboolean* is_synthetic_ptr) {
521 auto test = [](art::ArtMethod* method) {
522 return method->IsSynthetic();
523 };
524 return IsMethodT(env, m, test, is_synthetic_ptr);
525}
526
Alex Lightbebd7bd2017-07-25 14:05:52 -0700527class CommonLocalVariableClosure : public art::Closure {
528 public:
David Srbecky99cbfb52019-05-22 11:39:45 +0000529 CommonLocalVariableClosure(jint depth, jint slot)
530 : result_(ERR(INTERNAL)), depth_(depth), slot_(slot) {}
Alex Lightbebd7bd2017-07-25 14:05:52 -0700531
David Srbecky99cbfb52019-05-22 11:39:45 +0000532 void Run(art::Thread* self) override REQUIRES(art::Locks::mutator_lock_) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700533 art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current());
Alex Lighta4cdd362019-04-18 09:17:10 -0700534 bool needs_instrument;
535 {
536 art::ScopedAssertNoThreadSuspension sants("CommonLocalVariableClosure::Run");
537 std::unique_ptr<art::Context> context(art::Context::Create());
538 FindFrameAtDepthVisitor visitor(self, context.get(), depth_);
539 visitor.WalkStack();
540 if (!visitor.FoundFrame()) {
541 // Must have been a bad depth.
542 result_ = ERR(NO_MORE_FRAMES);
543 return;
544 }
545 art::ArtMethod* method = visitor.GetMethod();
546 // Native and 'art' proxy methods don't have registers.
547 if (method->IsNative() || method->IsProxyMethod()) {
548 // TODO It might be useful to fake up support for get at least on proxy frames.
549 result_ = ERR(OPAQUE_FRAME);
550 return;
Alex Light6045bc22019-05-22 08:33:30 -0700551 } else if (slot_ >= method->DexInstructionData().RegistersSize() || slot_ < 0) {
Alex Lighta4cdd362019-04-18 09:17:10 -0700552 result_ = ERR(INVALID_SLOT);
553 return;
554 }
555 needs_instrument = !visitor.IsShadowFrame();
556 uint32_t pc = visitor.GetDexPc(/*abort_on_failure=*/false);
557 if (pc == art::dex::kDexNoIndex) {
558 // Cannot figure out current PC.
559 result_ = ERR(OPAQUE_FRAME);
560 return;
561 }
562 std::string descriptor;
David Srbecky99cbfb52019-05-22 11:39:45 +0000563 art::Primitive::Type slot_type = art::Primitive::kPrimVoid;
Alex Lighta4cdd362019-04-18 09:17:10 -0700564 jvmtiError err = GetSlotType(method, pc, &descriptor, &slot_type);
565 if (err != OK) {
566 result_ = err;
567 return;
568 }
Alex Lightbebd7bd2017-07-25 14:05:52 -0700569
Alex Lighta4cdd362019-04-18 09:17:10 -0700570 err = GetTypeError(method, slot_type, descriptor);
571 if (err != OK) {
572 result_ = err;
573 return;
574 }
575 result_ = Execute(method, visitor);
Alex Lightbebd7bd2017-07-25 14:05:52 -0700576 }
Alex Light0a5ec3d2017-07-25 16:50:26 -0700577 if (needs_instrument) {
Alex Lighta4cdd362019-04-18 09:17:10 -0700578 DeoptManager::Get()->DeoptimizeThread(self);
Alex Light0a5ec3d2017-07-25 16:50:26 -0700579 }
Alex Lightbebd7bd2017-07-25 14:05:52 -0700580 }
581
Alex Light318afe62018-03-22 16:50:10 -0700582 virtual jvmtiError GetResult() {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700583 return result_;
584 }
585
586 protected:
587 virtual jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
Alex Light318afe62018-03-22 16:50:10 -0700588 REQUIRES_SHARED(art::Locks::mutator_lock_) = 0;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700589 virtual jvmtiError GetTypeError(art::ArtMethod* method,
David Srbecky99cbfb52019-05-22 11:39:45 +0000590 art::Primitive::Type type,
Alex Lightbebd7bd2017-07-25 14:05:52 -0700591 const std::string& descriptor)
Alex Light318afe62018-03-22 16:50:10 -0700592 REQUIRES_SHARED(art::Locks::mutator_lock_) = 0;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700593
594 jvmtiError GetSlotType(art::ArtMethod* method,
595 uint32_t dex_pc,
596 /*out*/std::string* descriptor,
David Srbecky99cbfb52019-05-22 11:39:45 +0000597 /*out*/art::Primitive::Type* type)
598 REQUIRES(art::Locks::mutator_lock_) {
599 const art::DexFile* dex_file = method->GetDexFile();
600 if (dex_file == nullptr) {
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800601 return ERR(OPAQUE_FRAME);
602 }
David Srbecky99cbfb52019-05-22 11:39:45 +0000603 art::CodeItemDebugInfoAccessor accessor(method->DexInstructionDebugInfo());
604 if (!accessor.HasCodeItem()) {
605 return ERR(OPAQUE_FRAME);
Alex Lightbebd7bd2017-07-25 14:05:52 -0700606 }
David Srbecky99cbfb52019-05-22 11:39:45 +0000607 bool found = false;
608 *type = art::Primitive::kPrimVoid;
609 descriptor->clear();
610 auto visitor = [&](const art::DexFile::LocalInfo& entry) {
611 if (!found &&
612 entry.start_address_ <= dex_pc &&
613 entry.end_address_ > dex_pc &&
614 entry.reg_ == slot_) {
615 found = true;
616 *type = art::Primitive::GetType(entry.descriptor_[0]);
617 *descriptor = entry.descriptor_;
Alex Lighte48fd0b2019-05-20 10:04:44 -0700618 }
David Srbecky99cbfb52019-05-22 11:39:45 +0000619 };
620 if (!accessor.DecodeDebugLocalInfo(method->IsStatic(), method->GetDexMethodIndex(), visitor) ||
621 !found) {
622 // Something went wrong with decoding the debug information. It might as well not be there.
623 return ERR(INVALID_SLOT);
Alex Lighte48fd0b2019-05-20 10:04:44 -0700624 }
David Srbecky99cbfb52019-05-22 11:39:45 +0000625 return OK;
Alex Lighte48fd0b2019-05-20 10:04:44 -0700626 }
627
Alex Lightbebd7bd2017-07-25 14:05:52 -0700628 jvmtiError result_;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700629 jint depth_;
630 jint slot_;
631};
632
633class GetLocalVariableClosure : public CommonLocalVariableClosure {
634 public:
David Srbecky99cbfb52019-05-22 11:39:45 +0000635 GetLocalVariableClosure(jint depth,
Alex Lightbebd7bd2017-07-25 14:05:52 -0700636 jint slot,
637 art::Primitive::Type type,
638 jvalue* val)
David Srbecky99cbfb52019-05-22 11:39:45 +0000639 : CommonLocalVariableClosure(depth, slot),
Alex Light318afe62018-03-22 16:50:10 -0700640 type_(type),
641 val_(val),
642 obj_val_(nullptr) {}
643
Andreas Gampefa6a1b02018-09-07 08:11:55 -0700644 jvmtiError GetResult() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light318afe62018-03-22 16:50:10 -0700645 if (result_ == OK && type_ == art::Primitive::kPrimNot) {
Alex Lighta4cdd362019-04-18 09:17:10 -0700646 if (obj_val_ == nullptr) {
647 val_->l = nullptr;
648 } else {
649 art::JNIEnvExt* jni = art::Thread::Current()->GetJniEnv();
650 val_->l = static_cast<JNIEnv*>(jni)->NewLocalRef(obj_val_);
651 jni->DeleteGlobalRef(obj_val_);
652 obj_val_ = nullptr;
653 }
Alex Light318afe62018-03-22 16:50:10 -0700654 }
655 return CommonLocalVariableClosure::GetResult();
656 }
Alex Lightbebd7bd2017-07-25 14:05:52 -0700657
658 protected:
David Srbecky99cbfb52019-05-22 11:39:45 +0000659 jvmtiError GetTypeError(art::ArtMethod* method ATTRIBUTE_UNUSED,
660 art::Primitive::Type slot_type,
661 const std::string& descriptor ATTRIBUTE_UNUSED)
662 override REQUIRES_SHARED(art::Locks::mutator_lock_) {
663 switch (slot_type) {
Alex Lighte48fd0b2019-05-20 10:04:44 -0700664 case art::Primitive::kPrimByte:
David Srbecky99cbfb52019-05-22 11:39:45 +0000665 case art::Primitive::kPrimChar:
666 case art::Primitive::kPrimInt:
667 case art::Primitive::kPrimShort:
Alex Lighte48fd0b2019-05-20 10:04:44 -0700668 case art::Primitive::kPrimBoolean:
David Srbecky99cbfb52019-05-22 11:39:45 +0000669 return type_ == art::Primitive::kPrimInt ? OK : ERR(TYPE_MISMATCH);
670 case art::Primitive::kPrimLong:
671 case art::Primitive::kPrimFloat:
672 case art::Primitive::kPrimDouble:
673 case art::Primitive::kPrimNot:
674 return type_ == slot_type ? OK : ERR(TYPE_MISMATCH);
Alex Lightbebd7bd2017-07-25 14:05:52 -0700675 case art::Primitive::kPrimVoid:
676 LOG(FATAL) << "Unexpected primitive type " << slot_type;
677 UNREACHABLE();
678 }
679 }
680
681 jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100682 override REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700683 switch (type_) {
684 case art::Primitive::kPrimNot: {
685 uint32_t ptr_val;
686 if (!visitor.GetVReg(method,
687 static_cast<uint16_t>(slot_),
688 art::kReferenceVReg,
689 &ptr_val)) {
690 return ERR(OPAQUE_FRAME);
691 }
Alex Lighta4cdd362019-04-18 09:17:10 -0700692 art::JNIEnvExt* jni = art::Thread::Current()->GetJniEnv();
693 art::ObjPtr<art::mirror::Object> obj(reinterpret_cast<art::mirror::Object*>(ptr_val));
Alex Light02353362019-05-03 11:27:07 -0700694 ScopedLocalRef<jobject> local(
695 jni, obj.IsNull() ? nullptr : jni->AddLocalReference<jobject>(obj));
Alex Lighta4cdd362019-04-18 09:17:10 -0700696 obj_val_ = jni->NewGlobalRef(local.get());
Alex Lightbebd7bd2017-07-25 14:05:52 -0700697 break;
698 }
699 case art::Primitive::kPrimInt:
700 case art::Primitive::kPrimFloat: {
701 if (!visitor.GetVReg(method,
702 static_cast<uint16_t>(slot_),
703 type_ == art::Primitive::kPrimFloat ? art::kFloatVReg : art::kIntVReg,
704 reinterpret_cast<uint32_t*>(&val_->i))) {
705 return ERR(OPAQUE_FRAME);
706 }
707 break;
708 }
709 case art::Primitive::kPrimDouble:
710 case art::Primitive::kPrimLong: {
711 auto lo_type = type_ == art::Primitive::kPrimLong ? art::kLongLoVReg : art::kDoubleLoVReg;
712 auto high_type = type_ == art::Primitive::kPrimLong ? art::kLongHiVReg : art::kDoubleHiVReg;
713 if (!visitor.GetVRegPair(method,
714 static_cast<uint16_t>(slot_),
715 lo_type,
716 high_type,
717 reinterpret_cast<uint64_t*>(&val_->j))) {
718 return ERR(OPAQUE_FRAME);
719 }
720 break;
721 }
722 default: {
723 LOG(FATAL) << "unexpected register type " << type_;
724 UNREACHABLE();
725 }
726 }
727 return OK;
728 }
729
730 private:
731 art::Primitive::Type type_;
732 jvalue* val_;
Alex Lighta4cdd362019-04-18 09:17:10 -0700733 // A global reference to the return value. We use the global reference to safely transfer the
734 // value between threads.
735 jobject obj_val_;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700736};
737
David Srbecky99cbfb52019-05-22 11:39:45 +0000738jvmtiError MethodUtil::GetLocalVariableGeneric(jvmtiEnv* env ATTRIBUTE_UNUSED,
Alex Lightbebd7bd2017-07-25 14:05:52 -0700739 jthread thread,
740 jint depth,
741 jint slot,
742 art::Primitive::Type type,
743 jvalue* val) {
744 if (depth < 0) {
745 return ERR(ILLEGAL_ARGUMENT);
746 }
747 art::Thread* self = art::Thread::Current();
748 art::ScopedObjectAccess soa(self);
Alex Lightb1e31a82017-10-04 16:57:36 -0700749 art::Locks::thread_list_lock_->ExclusiveLock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700750 art::Thread* target = nullptr;
751 jvmtiError err = ERR(INTERNAL);
752 if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
Alex Lightb1e31a82017-10-04 16:57:36 -0700753 art::Locks::thread_list_lock_->ExclusiveUnlock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700754 return err;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700755 }
David Srbecky99cbfb52019-05-22 11:39:45 +0000756 GetLocalVariableClosure c(depth, slot, type, val);
Alex Lighta4cdd362019-04-18 09:17:10 -0700757 // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
758 if (!target->RequestSynchronousCheckpoint(&c)) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700759 return ERR(THREAD_NOT_ALIVE);
760 } else {
761 return c.GetResult();
762 }
763}
764
765class SetLocalVariableClosure : public CommonLocalVariableClosure {
766 public:
David Srbecky99cbfb52019-05-22 11:39:45 +0000767 SetLocalVariableClosure(art::Thread* caller,
Alex Lightbebd7bd2017-07-25 14:05:52 -0700768 jint depth,
769 jint slot,
770 art::Primitive::Type type,
771 jvalue val)
David Srbecky99cbfb52019-05-22 11:39:45 +0000772 : CommonLocalVariableClosure(depth, slot), caller_(caller), type_(type), val_(val) {}
Alex Lightbebd7bd2017-07-25 14:05:52 -0700773
774 protected:
David Srbecky99cbfb52019-05-22 11:39:45 +0000775 jvmtiError GetTypeError(art::ArtMethod* method,
776 art::Primitive::Type slot_type,
777 const std::string& descriptor)
778 override REQUIRES_SHARED(art::Locks::mutator_lock_) {
779 switch (slot_type) {
780 case art::Primitive::kPrimNot: {
781 if (type_ != art::Primitive::kPrimNot) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700782 return ERR(TYPE_MISMATCH);
783 } else if (val_.l == nullptr) {
784 return OK;
785 } else {
786 art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
David Srbecky99cbfb52019-05-22 11:39:45 +0000787 art::ObjPtr<art::mirror::Class> set_class =
788 caller_->DecodeJObject(val_.l)->GetClass();
Alex Lightbebd7bd2017-07-25 14:05:52 -0700789 art::ObjPtr<art::mirror::ClassLoader> loader =
790 method->GetDeclaringClass()->GetClassLoader();
791 art::ObjPtr<art::mirror::Class> slot_class =
792 cl->LookupClass(caller_, descriptor.c_str(), loader);
David Srbecky99cbfb52019-05-22 11:39:45 +0000793 DCHECK(!slot_class.IsNull());
Alex Lightbebd7bd2017-07-25 14:05:52 -0700794 return slot_class->IsAssignableFrom(set_class) ? OK : ERR(TYPE_MISMATCH);
795 }
796 }
David Srbecky99cbfb52019-05-22 11:39:45 +0000797 case art::Primitive::kPrimByte:
798 case art::Primitive::kPrimChar:
799 case art::Primitive::kPrimInt:
800 case art::Primitive::kPrimShort:
801 case art::Primitive::kPrimBoolean:
802 return type_ == art::Primitive::kPrimInt ? OK : ERR(TYPE_MISMATCH);
803 case art::Primitive::kPrimLong:
804 case art::Primitive::kPrimFloat:
805 case art::Primitive::kPrimDouble:
806 return type_ == slot_type ? OK : ERR(TYPE_MISMATCH);
807 case art::Primitive::kPrimVoid:
808 LOG(FATAL) << "Unexpected primitive type " << slot_type;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700809 UNREACHABLE();
810 }
811 }
812
813 jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100814 override REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700815 switch (type_) {
816 case art::Primitive::kPrimNot: {
Vladimir Marko439d1262019-04-12 14:45:07 +0100817 if (!visitor.SetVRegReference(method,
818 static_cast<uint16_t>(slot_),
819 caller_->DecodeJObject(val_.l))) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700820 return ERR(OPAQUE_FRAME);
821 }
822 break;
823 }
824 case art::Primitive::kPrimInt:
825 case art::Primitive::kPrimFloat: {
826 if (!visitor.SetVReg(method,
827 static_cast<uint16_t>(slot_),
828 static_cast<uint32_t>(val_.i),
829 type_ == art::Primitive::kPrimFloat ? art::kFloatVReg
830 : art::kIntVReg)) {
831 return ERR(OPAQUE_FRAME);
832 }
833 break;
834 }
835 case art::Primitive::kPrimDouble:
836 case art::Primitive::kPrimLong: {
837 auto lo_type = type_ == art::Primitive::kPrimLong ? art::kLongLoVReg : art::kDoubleLoVReg;
838 auto high_type = type_ == art::Primitive::kPrimLong ? art::kLongHiVReg : art::kDoubleHiVReg;
839 if (!visitor.SetVRegPair(method,
840 static_cast<uint16_t>(slot_),
841 static_cast<uint64_t>(val_.j),
842 lo_type,
843 high_type)) {
844 return ERR(OPAQUE_FRAME);
845 }
846 break;
847 }
848 default: {
849 LOG(FATAL) << "unexpected register type " << type_;
850 UNREACHABLE();
851 }
852 }
853 return OK;
854 }
855
856 private:
Alex Light318afe62018-03-22 16:50:10 -0700857 art::Thread* caller_;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700858 art::Primitive::Type type_;
859 jvalue val_;
860};
861
David Srbecky99cbfb52019-05-22 11:39:45 +0000862jvmtiError MethodUtil::SetLocalVariableGeneric(jvmtiEnv* env ATTRIBUTE_UNUSED,
Alex Lightbebd7bd2017-07-25 14:05:52 -0700863 jthread thread,
864 jint depth,
865 jint slot,
866 art::Primitive::Type type,
867 jvalue val) {
868 if (depth < 0) {
869 return ERR(ILLEGAL_ARGUMENT);
870 }
Alex Lightf2858632018-04-02 11:28:50 -0700871 // Make sure that we know not to do any OSR anymore.
872 // TODO We should really keep track of this at the Frame granularity.
873 DeoptManager::Get()->SetLocalsUpdated();
Alex Lightbebd7bd2017-07-25 14:05:52 -0700874 art::Thread* self = art::Thread::Current();
875 art::ScopedObjectAccess soa(self);
Alex Lightb1e31a82017-10-04 16:57:36 -0700876 art::Locks::thread_list_lock_->ExclusiveLock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700877 art::Thread* target = nullptr;
878 jvmtiError err = ERR(INTERNAL);
879 if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
Alex Lightb1e31a82017-10-04 16:57:36 -0700880 art::Locks::thread_list_lock_->ExclusiveUnlock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700881 return err;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700882 }
David Srbecky99cbfb52019-05-22 11:39:45 +0000883 SetLocalVariableClosure c(self, depth, slot, type, val);
Alex Lightb1e31a82017-10-04 16:57:36 -0700884 // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
Alex Light318afe62018-03-22 16:50:10 -0700885 if (!target->RequestSynchronousCheckpoint(&c)) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700886 return ERR(THREAD_NOT_ALIVE);
887 } else {
888 return c.GetResult();
889 }
890}
891
892class GetLocalInstanceClosure : public art::Closure {
893 public:
Alex Light318afe62018-03-22 16:50:10 -0700894 explicit GetLocalInstanceClosure(jint depth)
Alex Lightbebd7bd2017-07-25 14:05:52 -0700895 : result_(ERR(INTERNAL)),
Alex Lightbebd7bd2017-07-25 14:05:52 -0700896 depth_(depth),
Alex Light318afe62018-03-22 16:50:10 -0700897 val_(nullptr) {}
Alex Lightbebd7bd2017-07-25 14:05:52 -0700898
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100899 void Run(art::Thread* self) override REQUIRES(art::Locks::mutator_lock_) {
Alex Light318afe62018-03-22 16:50:10 -0700900 art::ScopedAssertNoThreadSuspension sants("GetLocalInstanceClosure::Run");
Alex Lightbebd7bd2017-07-25 14:05:52 -0700901 art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current());
902 std::unique_ptr<art::Context> context(art::Context::Create());
903 FindFrameAtDepthVisitor visitor(self, context.get(), depth_);
904 visitor.WalkStack();
905 if (!visitor.FoundFrame()) {
906 // Must have been a bad depth.
907 result_ = ERR(NO_MORE_FRAMES);
908 return;
909 }
Alex Lightbebd7bd2017-07-25 14:05:52 -0700910 result_ = OK;
Alex Light318afe62018-03-22 16:50:10 -0700911 val_ = art::GcRoot<art::mirror::Object>(visitor.GetThisObject());
Alex Lightbebd7bd2017-07-25 14:05:52 -0700912 }
913
Alex Light318afe62018-03-22 16:50:10 -0700914 jvmtiError GetResult(jobject* data_out) REQUIRES_SHARED(art::Locks::mutator_lock_) {
915 if (result_ == OK) {
916 *data_out = val_.IsNull()
917 ? nullptr
918 : art::Thread::Current()->GetJniEnv()->AddLocalReference<jobject>(val_.Read());
919 }
Alex Lightbebd7bd2017-07-25 14:05:52 -0700920 return result_;
921 }
922
923 private:
924 jvmtiError result_;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700925 jint depth_;
Alex Light318afe62018-03-22 16:50:10 -0700926 art::GcRoot<art::mirror::Object> val_;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700927};
928
929jvmtiError MethodUtil::GetLocalInstance(jvmtiEnv* env ATTRIBUTE_UNUSED,
930 jthread thread,
931 jint depth,
932 jobject* data) {
933 if (depth < 0) {
934 return ERR(ILLEGAL_ARGUMENT);
935 }
936 art::Thread* self = art::Thread::Current();
937 art::ScopedObjectAccess soa(self);
Alex Lightb1e31a82017-10-04 16:57:36 -0700938 art::Locks::thread_list_lock_->ExclusiveLock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700939 art::Thread* target = nullptr;
940 jvmtiError err = ERR(INTERNAL);
941 if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
Alex Lightb1e31a82017-10-04 16:57:36 -0700942 art::Locks::thread_list_lock_->ExclusiveUnlock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700943 return err;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700944 }
Alex Light318afe62018-03-22 16:50:10 -0700945 art::ScopedAssertNoThreadSuspension sants("Performing GetLocalInstance");
946 GetLocalInstanceClosure c(depth);
947 // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution. We
948 // need to avoid suspending as we wait for the checkpoint to occur since we are (potentially)
949 // transfering a GcRoot across threads.
950 if (!target->RequestSynchronousCheckpoint(&c, art::ThreadState::kRunnable)) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700951 return ERR(THREAD_NOT_ALIVE);
952 } else {
Alex Light318afe62018-03-22 16:50:10 -0700953 return c.GetResult(data);
Alex Lightbebd7bd2017-07-25 14:05:52 -0700954 }
955}
956
957#define FOR_JVMTI_JVALUE_TYPES(fn) \
958 fn(jint, art::Primitive::kPrimInt, i) \
959 fn(jlong, art::Primitive::kPrimLong, j) \
960 fn(jfloat, art::Primitive::kPrimFloat, f) \
961 fn(jdouble, art::Primitive::kPrimDouble, d) \
962 fn(jobject, art::Primitive::kPrimNot, l)
963
964namespace impl {
965
966template<typename T> void WriteJvalue(T, jvalue*);
967template<typename T> void ReadJvalue(jvalue, T*);
968template<typename T> art::Primitive::Type GetJNIType();
969
970#define JNI_TYPE_CHAR(type, prim, id) \
971template<> art::Primitive::Type GetJNIType<type>() { \
972 return prim; \
973}
974
975FOR_JVMTI_JVALUE_TYPES(JNI_TYPE_CHAR);
976
977#undef JNI_TYPE_CHAR
978
Andreas Gampe49fc60e2017-08-24 13:19:59 -0700979#define RW_JVALUE(srctype, prim, id) \
980 template<> void ReadJvalue<srctype>(jvalue in, std::add_pointer<srctype>::type out) { \
Alex Lightbebd7bd2017-07-25 14:05:52 -0700981 *out = in.id; \
982 } \
Andreas Gampe49fc60e2017-08-24 13:19:59 -0700983 template<> void WriteJvalue<srctype>(srctype in, jvalue* out) { \
Alex Lightbebd7bd2017-07-25 14:05:52 -0700984 out->id = in; \
985 }
986
987FOR_JVMTI_JVALUE_TYPES(RW_JVALUE);
988
989#undef RW_JVALUE
990
991} // namespace impl
992
993template<typename T>
994jvmtiError MethodUtil::SetLocalVariable(jvmtiEnv* env,
995 jthread thread,
996 jint depth,
997 jint slot,
998 T data) {
999 jvalue v = {.j = 0};
1000 art::Primitive::Type type = impl::GetJNIType<T>();
1001 impl::WriteJvalue(data, &v);
1002 return SetLocalVariableGeneric(env, thread, depth, slot, type, v);
1003}
1004
1005template<typename T>
1006jvmtiError MethodUtil::GetLocalVariable(jvmtiEnv* env,
1007 jthread thread,
1008 jint depth,
1009 jint slot,
1010 T* data) {
1011 if (data == nullptr) {
1012 return ERR(NULL_POINTER);
1013 }
1014 jvalue v = {.j = 0};
1015 art::Primitive::Type type = impl::GetJNIType<T>();
1016 jvmtiError err = GetLocalVariableGeneric(env, thread, depth, slot, type, &v);
1017 if (err != OK) {
1018 return err;
1019 } else {
1020 impl::ReadJvalue(v, data);
1021 return OK;
1022 }
1023}
1024
Andreas Gampe49fc60e2017-08-24 13:19:59 -07001025#define GET_SET_LV(srctype, prim, id) \
1026 template jvmtiError MethodUtil::GetLocalVariable<srctype>(jvmtiEnv*, \
1027 jthread, \
1028 jint, \
1029 jint, \
1030 std::add_pointer<srctype>::type); \
1031 template jvmtiError MethodUtil::SetLocalVariable<srctype>(jvmtiEnv*, \
1032 jthread, \
1033 jint, \
1034 jint, \
1035 srctype);
Alex Lightbebd7bd2017-07-25 14:05:52 -07001036
1037FOR_JVMTI_JVALUE_TYPES(GET_SET_LV);
1038
1039#undef GET_SET_LV
1040
1041#undef FOR_JVMTI_JVALUE_TYPES
1042
Andreas Gampe3c252f02016-10-27 18:25:17 -07001043} // namespace openjdkjvmti