blob: e88539f6c2b3bb922a821c6f79eb7821a62586fb [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"
David Sehr9e734c72018-01-04 17:56:19 -080041#include "dex/code_item_accessors-inl.h"
42#include "dex/dex_file_annotations.h"
43#include "dex/dex_file_types.h"
David Sehr8c0961f2018-01-23 16:11:38 -080044#include "dex/modifiers.h"
Alex Lightd78ddec2017-04-18 15:20:38 -070045#include "events-inl.h"
Alex Light318afe62018-03-22 16:50:10 -070046#include "gc_root-inl.h"
Alex Light0a5ec3d2017-07-25 16:50:26 -070047#include "jit/jit.h"
Vladimir Markoa3ad0cd2018-05-04 10:06:38 +010048#include "jni/jni_internal.h"
Alex Lightbebd7bd2017-07-25 14:05:52 -070049#include "mirror/class-inl.h"
50#include "mirror/class_loader.h"
51#include "mirror/object-inl.h"
Andreas Gampe27dfa052017-02-16 15:04:36 -080052#include "mirror/object_array-inl.h"
Andreas Gampe373a9b52017-10-18 09:01:57 -070053#include "nativehelper/scoped_local_ref.h"
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +000054#include "oat_file.h"
Alex Lightd78ddec2017-04-18 15:20:38 -070055#include "runtime_callbacks.h"
Andreas Gampe3c252f02016-10-27 18:25:17 -070056#include "scoped_thread_state_change-inl.h"
Alex Lightbebd7bd2017-07-25 14:05:52 -070057#include "stack.h"
Andreas Gampeb486a982017-06-01 13:45:54 -070058#include "thread-current-inl.h"
Alex Lightd78ddec2017-04-18 15:20:38 -070059#include "thread_list.h"
Alex Lighte814f9d2017-07-31 16:14:39 -070060#include "ti_stack.h"
Alex Lightbebd7bd2017-07-25 14:05:52 -070061#include "ti_thread.h"
Alex Light0af8cde2017-04-20 13:35:05 -070062#include "ti_phase.h"
Andreas Gampe3c252f02016-10-27 18:25:17 -070063
64namespace openjdkjvmti {
65
Alex Lightd78ddec2017-04-18 15:20:38 -070066struct TiMethodCallback : public art::MethodCallback {
67 void RegisterNativeMethod(art::ArtMethod* method,
68 const void* cur_method,
69 /*out*/void** new_method)
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010070 override REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightd78ddec2017-04-18 15:20:38 -070071 if (event_handler->IsEventEnabledAnywhere(ArtJvmtiEvent::kNativeMethodBind)) {
72 art::Thread* thread = art::Thread::Current();
Alex Light0af8cde2017-04-20 13:35:05 -070073 art::JNIEnvExt* jnienv = thread->GetJniEnv();
Alex Lightd78ddec2017-04-18 15:20:38 -070074 ScopedLocalRef<jthread> thread_jni(
Alex Light0af8cde2017-04-20 13:35:05 -070075 jnienv, PhaseUtil::IsLivePhase() ? jnienv->AddLocalReference<jthread>(thread->GetPeer())
76 : nullptr);
Alex Lightd78ddec2017-04-18 15:20:38 -070077 art::ScopedThreadSuspension sts(thread, art::ThreadState::kNative);
78 event_handler->DispatchEvent<ArtJvmtiEvent::kNativeMethodBind>(
79 thread,
Alex Light0af8cde2017-04-20 13:35:05 -070080 static_cast<JNIEnv*>(jnienv),
Alex Lightd78ddec2017-04-18 15:20:38 -070081 thread_jni.get(),
82 art::jni::EncodeArtMethod(method),
83 const_cast<void*>(cur_method),
84 new_method);
85 }
86 }
87
88 EventHandler* event_handler = nullptr;
89};
90
91TiMethodCallback gMethodCallback;
92
93void MethodUtil::Register(EventHandler* handler) {
94 gMethodCallback.event_handler = handler;
95 art::ScopedThreadStateChange stsc(art::Thread::Current(),
96 art::ThreadState::kWaitingForDebuggerToAttach);
97 art::ScopedSuspendAll ssa("Add method callback");
Alex Light21611932017-09-26 13:07:39 -070098 art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks();
99 callbacks->AddMethodCallback(&gMethodCallback);
Alex Lightd78ddec2017-04-18 15:20:38 -0700100}
101
102void MethodUtil::Unregister() {
103 art::ScopedThreadStateChange stsc(art::Thread::Current(),
104 art::ThreadState::kWaitingForDebuggerToAttach);
105 art::ScopedSuspendAll ssa("Remove method callback");
Alex Light21611932017-09-26 13:07:39 -0700106 art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks();
107 callbacks->RemoveMethodCallback(&gMethodCallback);
Alex Lightd78ddec2017-04-18 15:20:38 -0700108}
109
Alex Light4c174282017-07-05 10:18:18 -0700110jvmtiError MethodUtil::GetBytecodes(jvmtiEnv* env,
111 jmethodID method,
112 jint* size_ptr,
113 unsigned char** bytecode_ptr) {
114 if (method == nullptr) {
115 return ERR(INVALID_METHODID);
116 }
117 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
118
119 if (art_method->IsNative()) {
120 return ERR(NATIVE_METHOD);
121 }
122
123 if (size_ptr == nullptr || bytecode_ptr == nullptr) {
124 return ERR(NULL_POINTER);
125 }
126
127 art::ScopedObjectAccess soa(art::Thread::Current());
David Sehr0225f8e2018-01-31 08:52:24 +0000128 art::CodeItemInstructionAccessor accessor(art_method->DexInstructions());
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800129 if (!accessor.HasCodeItem()) {
Alex Light4c174282017-07-05 10:18:18 -0700130 *size_ptr = 0;
131 *bytecode_ptr = nullptr;
132 return OK;
133 }
134 // 2 bytes per instruction for dex code.
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800135 *size_ptr = accessor.InsnsSizeInCodeUnits() * 2;
Alex Light4c174282017-07-05 10:18:18 -0700136 jvmtiError err = env->Allocate(*size_ptr, bytecode_ptr);
137 if (err != OK) {
138 return err;
139 }
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800140 memcpy(*bytecode_ptr, accessor.Insns(), *size_ptr);
Alex Light4c174282017-07-05 10:18:18 -0700141 return OK;
142}
143
Andreas Gampef71832e2017-01-09 11:38:04 -0800144jvmtiError MethodUtil::GetArgumentsSize(jvmtiEnv* env ATTRIBUTE_UNUSED,
145 jmethodID method,
146 jint* size_ptr) {
147 if (method == nullptr) {
148 return ERR(INVALID_METHODID);
149 }
150 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
151
152 if (art_method->IsNative()) {
153 return ERR(NATIVE_METHOD);
154 }
155
156 if (size_ptr == nullptr) {
157 return ERR(NULL_POINTER);
158 }
159
160 art::ScopedObjectAccess soa(art::Thread::Current());
161 if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
Andreas Gampee1f79b62017-04-12 21:11:28 -0700162 // Use the shorty.
163 art::ArtMethod* base_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize);
164 size_t arg_count = art::ArtMethod::NumArgRegisters(base_method->GetShorty());
165 if (!base_method->IsStatic()) {
166 arg_count++;
167 }
168 *size_ptr = static_cast<jint>(arg_count);
Andreas Gampef71832e2017-01-09 11:38:04 -0800169 return ERR(NONE);
170 }
171
172 DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
David Sehr0225f8e2018-01-31 08:52:24 +0000173 *size_ptr = art_method->DexInstructionData().InsSize();
Andreas Gampef71832e2017-01-09 11:38:04 -0800174
175 return ERR(NONE);
176}
177
Alex Lightce68cc62017-07-26 10:30:38 -0700178jvmtiError MethodUtil::GetLocalVariableTable(jvmtiEnv* env,
179 jmethodID method,
180 jint* entry_count_ptr,
181 jvmtiLocalVariableEntry** table_ptr) {
182 if (method == nullptr) {
183 return ERR(INVALID_METHODID);
184 }
185 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
186
187 if (art_method->IsNative()) {
188 return ERR(NATIVE_METHOD);
189 }
190
191 if (entry_count_ptr == nullptr || table_ptr == nullptr) {
192 return ERR(NULL_POINTER);
193 }
194
195 art::ScopedObjectAccess soa(art::Thread::Current());
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800196
197 const art::DexFile* const dex_file = art_method->GetDexFile();
198 if (dex_file == nullptr) {
199 return ERR(ABSENT_INFORMATION);
200 }
201
202 // TODO HasCodeItem == false means that the method is abstract (or native, but we check that
Alex Lightce68cc62017-07-26 10:30:38 -0700203 // earlier). We should check what is returned by the RI in this situation since it's not clear
204 // what the appropriate return value is from the spec.
David Sehr0225f8e2018-01-31 08:52:24 +0000205 art::CodeItemDebugInfoAccessor accessor(art_method->DexInstructionDebugInfo());
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800206 if (!accessor.HasCodeItem()) {
Alex Lightce68cc62017-07-26 10:30:38 -0700207 return ERR(ABSENT_INFORMATION);
208 }
209
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700210 std::vector<jvmtiLocalVariableEntry> variables;
211 jvmtiError err = OK;
Alex Lightce68cc62017-07-26 10:30:38 -0700212
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700213 auto release = [&](jint* out_entry_count_ptr, jvmtiLocalVariableEntry** out_table_ptr) {
214 jlong table_size = sizeof(jvmtiLocalVariableEntry) * variables.size();
215 if (err != OK ||
216 (err = env->Allocate(table_size,
217 reinterpret_cast<unsigned char**>(out_table_ptr))) != OK) {
218 for (jvmtiLocalVariableEntry& e : variables) {
219 env->Deallocate(reinterpret_cast<unsigned char*>(e.name));
220 env->Deallocate(reinterpret_cast<unsigned char*>(e.signature));
221 env->Deallocate(reinterpret_cast<unsigned char*>(e.generic_signature));
222 }
223 return err;
Alex Lightce68cc62017-07-26 10:30:38 -0700224 }
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700225 *out_entry_count_ptr = variables.size();
226 memcpy(*out_table_ptr, variables.data(), table_size);
227 return OK;
Alex Lightce68cc62017-07-26 10:30:38 -0700228 };
229
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700230 auto visitor = [&](const art::DexFile::LocalInfo& entry) {
231 if (err != OK) {
232 return;
233 }
234 JvmtiUniquePtr<char[]> name_str = CopyString(env, entry.name_, &err);
235 if (err != OK) {
236 return;
237 }
238 JvmtiUniquePtr<char[]> sig_str = CopyString(env, entry.descriptor_, &err);
239 if (err != OK) {
240 return;
241 }
242 JvmtiUniquePtr<char[]> generic_sig_str = CopyString(env, entry.signature_, &err);
243 if (err != OK) {
244 return;
245 }
246 variables.push_back({
247 .start_location = static_cast<jlocation>(entry.start_address_),
248 .length = static_cast<jint>(entry.end_address_ - entry.start_address_),
249 .name = name_str.release(),
250 .signature = sig_str.release(),
251 .generic_signature = generic_sig_str.release(),
252 .slot = entry.reg_,
253 });
254 };
255
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800256 if (!accessor.DecodeDebugLocalInfo(art_method->IsStatic(),
257 art_method->GetDexMethodIndex(),
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700258 visitor)) {
Alex Lightce68cc62017-07-26 10:30:38 -0700259 // Something went wrong with decoding the debug information. It might as well not be there.
260 return ERR(ABSENT_INFORMATION);
Alex Lightce68cc62017-07-26 10:30:38 -0700261 }
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700262 return release(entry_count_ptr, table_ptr);
Alex Lightce68cc62017-07-26 10:30:38 -0700263}
264
Andreas Gampef71832e2017-01-09 11:38:04 -0800265jvmtiError MethodUtil::GetMaxLocals(jvmtiEnv* env ATTRIBUTE_UNUSED,
266 jmethodID method,
267 jint* max_ptr) {
268 if (method == nullptr) {
269 return ERR(INVALID_METHODID);
270 }
271 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
272
273 if (art_method->IsNative()) {
274 return ERR(NATIVE_METHOD);
275 }
276
277 if (max_ptr == nullptr) {
278 return ERR(NULL_POINTER);
279 }
280
281 art::ScopedObjectAccess soa(art::Thread::Current());
282 if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
283 // This isn't specified as an error case, so return 0.
284 *max_ptr = 0;
285 return ERR(NONE);
286 }
287
288 DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
David Sehr0225f8e2018-01-31 08:52:24 +0000289 *max_ptr = art_method->DexInstructionData().RegistersSize();
Andreas Gampef71832e2017-01-09 11:38:04 -0800290
291 return ERR(NONE);
292}
293
Andreas Gampe3c252f02016-10-27 18:25:17 -0700294jvmtiError MethodUtil::GetMethodName(jvmtiEnv* env,
295 jmethodID method,
296 char** name_ptr,
297 char** signature_ptr,
298 char** generic_ptr) {
299 art::ScopedObjectAccess soa(art::Thread::Current());
Andreas Gampe13b27842016-11-07 16:48:23 -0800300 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
Andreas Gampe3c252f02016-10-27 18:25:17 -0700301 art_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize);
302
Andreas Gampe54711412017-02-21 12:41:43 -0800303 JvmtiUniquePtr<char[]> name_copy;
Andreas Gampe3c252f02016-10-27 18:25:17 -0700304 if (name_ptr != nullptr) {
305 const char* method_name = art_method->GetName();
306 if (method_name == nullptr) {
307 method_name = "<error>";
308 }
Andreas Gampe54711412017-02-21 12:41:43 -0800309 jvmtiError ret;
310 name_copy = CopyString(env, method_name, &ret);
311 if (name_copy == nullptr) {
Andreas Gampe3c252f02016-10-27 18:25:17 -0700312 return ret;
313 }
Andreas Gampe54711412017-02-21 12:41:43 -0800314 *name_ptr = name_copy.get();
Andreas Gampe3c252f02016-10-27 18:25:17 -0700315 }
316
Andreas Gampe54711412017-02-21 12:41:43 -0800317 JvmtiUniquePtr<char[]> signature_copy;
Andreas Gampe3c252f02016-10-27 18:25:17 -0700318 if (signature_ptr != nullptr) {
319 const art::Signature sig = art_method->GetSignature();
320 std::string str = sig.ToString();
Andreas Gampe54711412017-02-21 12:41:43 -0800321 jvmtiError ret;
322 signature_copy = CopyString(env, str.c_str(), &ret);
323 if (signature_copy == nullptr) {
Andreas Gampe3c252f02016-10-27 18:25:17 -0700324 return ret;
325 }
Andreas Gampe54711412017-02-21 12:41:43 -0800326 *signature_ptr = signature_copy.get();
Andreas Gampe3c252f02016-10-27 18:25:17 -0700327 }
328
Andreas Gampe862bdd82016-11-18 13:31:13 -0800329 if (generic_ptr != nullptr) {
330 *generic_ptr = nullptr;
Andreas Gampe27dfa052017-02-16 15:04:36 -0800331 if (!art_method->GetDeclaringClass()->IsProxyClass()) {
Vladimir Markoacb906d2018-05-30 10:23:49 +0100332 art::ObjPtr<art::mirror::ObjectArray<art::mirror::String>> str_array =
Andreas Gampe27dfa052017-02-16 15:04:36 -0800333 art::annotations::GetSignatureAnnotationForMethod(art_method);
334 if (str_array != nullptr) {
335 std::ostringstream oss;
336 for (int32_t i = 0; i != str_array->GetLength(); ++i) {
337 oss << str_array->Get(i)->ToModifiedUtf8();
338 }
339 std::string output_string = oss.str();
Andreas Gampe54711412017-02-21 12:41:43 -0800340 jvmtiError ret;
341 JvmtiUniquePtr<char[]> generic_copy = CopyString(env, output_string.c_str(), &ret);
342 if (generic_copy == nullptr) {
Andreas Gampe27dfa052017-02-16 15:04:36 -0800343 return ret;
344 }
Andreas Gampe54711412017-02-21 12:41:43 -0800345 *generic_ptr = generic_copy.release();
Andreas Gampe27dfa052017-02-16 15:04:36 -0800346 } else if (soa.Self()->IsExceptionPending()) {
347 // TODO: Should we report an error here?
348 soa.Self()->ClearException();
349 }
350 }
Andreas Gampe862bdd82016-11-18 13:31:13 -0800351 }
Andreas Gampe3c252f02016-10-27 18:25:17 -0700352
353 // Everything is fine, release the buffers.
354 name_copy.release();
355 signature_copy.release();
356
357 return ERR(NONE);
358}
359
Andreas Gampe368a2082016-10-28 17:33:13 -0700360jvmtiError MethodUtil::GetMethodDeclaringClass(jvmtiEnv* env ATTRIBUTE_UNUSED,
361 jmethodID method,
362 jclass* declaring_class_ptr) {
363 if (declaring_class_ptr == nullptr) {
364 return ERR(NULL_POINTER);
365 }
366
Andreas Gampe13b27842016-11-07 16:48:23 -0800367 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
Andreas Gampe368a2082016-10-28 17:33:13 -0700368 // Note: No GetInterfaceMethodIfProxy, we want to actual class.
369
Andreas Gampe13b27842016-11-07 16:48:23 -0800370 art::ScopedObjectAccess soa(art::Thread::Current());
Vladimir Markod93e3742018-07-18 10:58:13 +0100371 art::ObjPtr<art::mirror::Class> klass = art_method->GetDeclaringClass();
Andreas Gampe368a2082016-10-28 17:33:13 -0700372 *declaring_class_ptr = soa.AddLocalReference<jclass>(klass);
373
374 return ERR(NONE);
375}
376
Andreas Gampef71832e2017-01-09 11:38:04 -0800377jvmtiError MethodUtil::GetMethodLocation(jvmtiEnv* env ATTRIBUTE_UNUSED,
378 jmethodID method,
379 jlocation* start_location_ptr,
380 jlocation* end_location_ptr) {
381 if (method == nullptr) {
382 return ERR(INVALID_METHODID);
383 }
384 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
385
386 if (art_method->IsNative()) {
387 return ERR(NATIVE_METHOD);
388 }
389
390 if (start_location_ptr == nullptr || end_location_ptr == nullptr) {
391 return ERR(NULL_POINTER);
392 }
393
394 art::ScopedObjectAccess soa(art::Thread::Current());
395 if (art_method->IsProxyMethod() || art_method->IsAbstract()) {
Andreas Gampee1f79b62017-04-12 21:11:28 -0700396 // This isn't specified as an error case, so return -1/-1 as the RI does.
397 *start_location_ptr = -1;
398 *end_location_ptr = -1;
Andreas Gampef71832e2017-01-09 11:38:04 -0800399 return ERR(NONE);
400 }
401
402 DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
403 *start_location_ptr = 0;
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800404 *end_location_ptr = art_method->DexInstructions().InsnsSizeInCodeUnits() - 1;
Andreas Gampef71832e2017-01-09 11:38:04 -0800405
406 return ERR(NONE);
407}
408
Andreas Gampe36bcd4f2016-10-28 18:07:18 -0700409jvmtiError MethodUtil::GetMethodModifiers(jvmtiEnv* env ATTRIBUTE_UNUSED,
410 jmethodID method,
411 jint* modifiers_ptr) {
412 if (modifiers_ptr == nullptr) {
413 return ERR(NULL_POINTER);
414 }
415
Andreas Gampe13b27842016-11-07 16:48:23 -0800416 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
Andreas Gampe36bcd4f2016-10-28 18:07:18 -0700417 uint32_t modifiers = art_method->GetAccessFlags();
418
419 // Note: Keep this code in sync with Executable.fixMethodFlags.
420 if ((modifiers & art::kAccAbstract) != 0) {
421 modifiers &= ~art::kAccNative;
422 }
423 modifiers &= ~art::kAccSynchronized;
424 if ((modifiers & art::kAccDeclaredSynchronized) != 0) {
425 modifiers |= art::kAccSynchronized;
426 }
427 modifiers &= art::kAccJavaFlagsMask;
428
429 *modifiers_ptr = modifiers;
430 return ERR(NONE);
431}
432
Andreas Gampeda3e5612016-12-13 19:00:53 -0800433jvmtiError MethodUtil::GetLineNumberTable(jvmtiEnv* env,
434 jmethodID method,
435 jint* entry_count_ptr,
436 jvmtiLineNumberEntry** table_ptr) {
437 if (method == nullptr) {
438 return ERR(NULL_POINTER);
439 }
440 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
441 DCHECK(!art_method->IsRuntimeMethod());
442
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800443 art::CodeItemDebugInfoAccessor accessor;
Andreas Gampeda3e5612016-12-13 19:00:53 -0800444 const art::DexFile* dex_file;
445 {
446 art::ScopedObjectAccess soa(art::Thread::Current());
447
448 if (art_method->IsProxyMethod()) {
449 return ERR(ABSENT_INFORMATION);
450 }
451 if (art_method->IsNative()) {
452 return ERR(NATIVE_METHOD);
453 }
454 if (entry_count_ptr == nullptr || table_ptr == nullptr) {
455 return ERR(NULL_POINTER);
456 }
457
David Sehr0225f8e2018-01-31 08:52:24 +0000458 accessor = art::CodeItemDebugInfoAccessor(art_method->DexInstructionDebugInfo());
Andreas Gampeda3e5612016-12-13 19:00:53 -0800459 dex_file = art_method->GetDexFile();
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800460 DCHECK(accessor.HasCodeItem()) << art_method->PrettyMethod() << " " << dex_file->GetLocation();
Andreas Gampeda3e5612016-12-13 19:00:53 -0800461 }
462
Mathieu Chartier3e2e1232018-09-11 12:35:30 -0700463 std::vector<jvmtiLineNumberEntry> context;
464 bool success = accessor.DecodeDebugPositionInfo([&](const art::DexFile::PositionInfo& entry) {
465 context.push_back({static_cast<jlocation>(entry.address_), static_cast<jint>(entry.line_)});
466 return false;
467 });
Andreas Gampeda3e5612016-12-13 19:00:53 -0800468 if (!success) {
469 return ERR(ABSENT_INFORMATION);
470 }
471
472 unsigned char* data;
473 jlong mem_size = context.size() * sizeof(jvmtiLineNumberEntry);
474 jvmtiError alloc_error = env->Allocate(mem_size, &data);
475 if (alloc_error != ERR(NONE)) {
476 return alloc_error;
477 }
478 *table_ptr = reinterpret_cast<jvmtiLineNumberEntry*>(data);
479 memcpy(*table_ptr, context.data(), mem_size);
480 *entry_count_ptr = static_cast<jint>(context.size());
481
482 return ERR(NONE);
483}
484
Andreas Gampefdeef522017-01-09 14:40:25 -0800485template <typename T>
486static jvmtiError IsMethodT(jvmtiEnv* env ATTRIBUTE_UNUSED,
487 jmethodID method,
488 T test,
489 jboolean* is_t_ptr) {
490 if (method == nullptr) {
491 return ERR(INVALID_METHODID);
492 }
493 if (is_t_ptr == nullptr) {
494 return ERR(NULL_POINTER);
495 }
496
497 art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
498 *is_t_ptr = test(art_method) ? JNI_TRUE : JNI_FALSE;
499
500 return ERR(NONE);
501}
502
503jvmtiError MethodUtil::IsMethodNative(jvmtiEnv* env, jmethodID m, jboolean* is_native_ptr) {
504 auto test = [](art::ArtMethod* method) {
505 return method->IsNative();
506 };
507 return IsMethodT(env, m, test, is_native_ptr);
508}
509
510jvmtiError MethodUtil::IsMethodObsolete(jvmtiEnv* env, jmethodID m, jboolean* is_obsolete_ptr) {
511 auto test = [](art::ArtMethod* method) {
512 return method->IsObsolete();
513 };
514 return IsMethodT(env, m, test, is_obsolete_ptr);
515}
516
517jvmtiError MethodUtil::IsMethodSynthetic(jvmtiEnv* env, jmethodID m, jboolean* is_synthetic_ptr) {
518 auto test = [](art::ArtMethod* method) {
519 return method->IsSynthetic();
520 };
521 return IsMethodT(env, m, test, is_synthetic_ptr);
522}
523
Alex Lightbebd7bd2017-07-25 14:05:52 -0700524class CommonLocalVariableClosure : public art::Closure {
525 public:
Alex Light318afe62018-03-22 16:50:10 -0700526 CommonLocalVariableClosure(jint depth, jint slot)
527 : result_(ERR(INTERNAL)), depth_(depth), slot_(slot) {}
Alex Lightbebd7bd2017-07-25 14:05:52 -0700528
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100529 void Run(art::Thread* self) override REQUIRES(art::Locks::mutator_lock_) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700530 art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current());
Alex Light318afe62018-03-22 16:50:10 -0700531 art::ScopedAssertNoThreadSuspension sants("CommonLocalVariableClosure::Run");
Alex Lightbebd7bd2017-07-25 14:05:52 -0700532 std::unique_ptr<art::Context> context(art::Context::Create());
533 FindFrameAtDepthVisitor visitor(self, context.get(), depth_);
534 visitor.WalkStack();
535 if (!visitor.FoundFrame()) {
536 // Must have been a bad depth.
537 result_ = ERR(NO_MORE_FRAMES);
538 return;
539 }
540 art::ArtMethod* method = visitor.GetMethod();
Alex Light3dea2122017-10-11 15:56:48 +0000541 // Native and 'art' proxy methods don't have registers.
542 if (method->IsNative() || method->IsProxyMethod()) {
543 // TODO It might be useful to fake up support for get at least on proxy frames.
Alex Lightbebd7bd2017-07-25 14:05:52 -0700544 result_ = ERR(OPAQUE_FRAME);
545 return;
David Sehr0225f8e2018-01-31 08:52:24 +0000546 } else if (method->DexInstructionData().RegistersSize() <= slot_) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700547 result_ = ERR(INVALID_SLOT);
548 return;
549 }
Alex Light0a5ec3d2017-07-25 16:50:26 -0700550 bool needs_instrument = !visitor.IsShadowFrame();
Andreas Gampe6e897762018-10-16 13:09:32 -0700551 uint32_t pc = visitor.GetDexPc(/*abort_on_failure=*/ false);
Andreas Gampee2abbc62017-09-15 11:59:26 -0700552 if (pc == art::dex::kDexNoIndex) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700553 // Cannot figure out current PC.
554 result_ = ERR(OPAQUE_FRAME);
555 return;
556 }
557 std::string descriptor;
558 art::Primitive::Type slot_type = art::Primitive::kPrimVoid;
559 jvmtiError err = GetSlotType(method, pc, &descriptor, &slot_type);
560 if (err != OK) {
561 result_ = err;
562 return;
563 }
564
565 err = GetTypeError(method, slot_type, descriptor);
566 if (err != OK) {
567 result_ = err;
568 return;
569 }
570 result_ = Execute(method, visitor);
Alex Light0a5ec3d2017-07-25 16:50:26 -0700571 if (needs_instrument) {
572 art::Runtime::Current()->GetInstrumentation()->InstrumentThreadStack(self);
573 }
Alex Lightbebd7bd2017-07-25 14:05:52 -0700574 }
575
Alex Light318afe62018-03-22 16:50:10 -0700576 virtual jvmtiError GetResult() {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700577 return result_;
578 }
579
580 protected:
581 virtual jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
Alex Light318afe62018-03-22 16:50:10 -0700582 REQUIRES_SHARED(art::Locks::mutator_lock_) = 0;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700583 virtual jvmtiError GetTypeError(art::ArtMethod* method,
584 art::Primitive::Type type,
585 const std::string& descriptor)
Alex Light318afe62018-03-22 16:50:10 -0700586 REQUIRES_SHARED(art::Locks::mutator_lock_) = 0;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700587
588 jvmtiError GetSlotType(art::ArtMethod* method,
589 uint32_t dex_pc,
590 /*out*/std::string* descriptor,
591 /*out*/art::Primitive::Type* type)
592 REQUIRES(art::Locks::mutator_lock_) {
593 const art::DexFile* dex_file = method->GetDexFile();
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800594 if (dex_file == nullptr) {
595 return ERR(OPAQUE_FRAME);
596 }
David Sehr0225f8e2018-01-31 08:52:24 +0000597 art::CodeItemDebugInfoAccessor accessor(method->DexInstructionDebugInfo());
Mathieu Chartier31f4c9f2017-12-08 15:46:11 -0800598 if (!accessor.HasCodeItem()) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700599 return ERR(OPAQUE_FRAME);
600 }
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700601 bool found = false;
602 *type = art::Primitive::kPrimVoid;
603 descriptor->clear();
604 auto visitor = [&](const art::DexFile::LocalInfo& entry) {
605 if (!found &&
606 entry.start_address_ <= dex_pc &&
607 entry.end_address_ > dex_pc &&
608 entry.reg_ == slot_) {
609 found = true;
610 *type = art::Primitive::GetType(entry.descriptor_[0]);
611 *descriptor = entry.descriptor_;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700612 }
Alex Lightbebd7bd2017-07-25 14:05:52 -0700613 };
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700614 if (!accessor.DecodeDebugLocalInfo(method->IsStatic(), method->GetDexMethodIndex(), visitor) ||
615 !found) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700616 // Something went wrong with decoding the debug information. It might as well not be there.
617 return ERR(INVALID_SLOT);
Alex Lightbebd7bd2017-07-25 14:05:52 -0700618 }
Mathieu Chartiere5afbf32018-09-12 17:51:54 -0700619 return OK;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700620 }
621
622 jvmtiError result_;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700623 jint depth_;
624 jint slot_;
625};
626
627class GetLocalVariableClosure : public CommonLocalVariableClosure {
628 public:
Alex Light318afe62018-03-22 16:50:10 -0700629 GetLocalVariableClosure(jint depth,
Alex Lightbebd7bd2017-07-25 14:05:52 -0700630 jint slot,
631 art::Primitive::Type type,
632 jvalue* val)
Alex Light318afe62018-03-22 16:50:10 -0700633 : CommonLocalVariableClosure(depth, slot),
634 type_(type),
635 val_(val),
636 obj_val_(nullptr) {}
637
Andreas Gampefa6a1b02018-09-07 08:11:55 -0700638 jvmtiError GetResult() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light318afe62018-03-22 16:50:10 -0700639 if (result_ == OK && type_ == art::Primitive::kPrimNot) {
640 val_->l = obj_val_.IsNull()
641 ? nullptr
642 : art::Thread::Current()->GetJniEnv()->AddLocalReference<jobject>(obj_val_.Read());
643 }
644 return CommonLocalVariableClosure::GetResult();
645 }
Alex Lightbebd7bd2017-07-25 14:05:52 -0700646
647 protected:
648 jvmtiError GetTypeError(art::ArtMethod* method ATTRIBUTE_UNUSED,
649 art::Primitive::Type slot_type,
650 const std::string& descriptor ATTRIBUTE_UNUSED)
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100651 override REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700652 switch (slot_type) {
653 case art::Primitive::kPrimByte:
654 case art::Primitive::kPrimChar:
655 case art::Primitive::kPrimInt:
656 case art::Primitive::kPrimShort:
657 case art::Primitive::kPrimBoolean:
658 return type_ == art::Primitive::kPrimInt ? OK : ERR(TYPE_MISMATCH);
659 case art::Primitive::kPrimLong:
660 case art::Primitive::kPrimFloat:
661 case art::Primitive::kPrimDouble:
662 case art::Primitive::kPrimNot:
663 return type_ == slot_type ? OK : ERR(TYPE_MISMATCH);
664 case art::Primitive::kPrimVoid:
665 LOG(FATAL) << "Unexpected primitive type " << slot_type;
666 UNREACHABLE();
667 }
668 }
669
670 jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100671 override REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700672 switch (type_) {
673 case art::Primitive::kPrimNot: {
674 uint32_t ptr_val;
675 if (!visitor.GetVReg(method,
676 static_cast<uint16_t>(slot_),
677 art::kReferenceVReg,
678 &ptr_val)) {
679 return ERR(OPAQUE_FRAME);
680 }
Alex Light318afe62018-03-22 16:50:10 -0700681 obj_val_ = art::GcRoot<art::mirror::Object>(
682 reinterpret_cast<art::mirror::Object*>(ptr_val));
Alex Lightbebd7bd2017-07-25 14:05:52 -0700683 break;
684 }
685 case art::Primitive::kPrimInt:
686 case art::Primitive::kPrimFloat: {
687 if (!visitor.GetVReg(method,
688 static_cast<uint16_t>(slot_),
689 type_ == art::Primitive::kPrimFloat ? art::kFloatVReg : art::kIntVReg,
690 reinterpret_cast<uint32_t*>(&val_->i))) {
691 return ERR(OPAQUE_FRAME);
692 }
693 break;
694 }
695 case art::Primitive::kPrimDouble:
696 case art::Primitive::kPrimLong: {
697 auto lo_type = type_ == art::Primitive::kPrimLong ? art::kLongLoVReg : art::kDoubleLoVReg;
698 auto high_type = type_ == art::Primitive::kPrimLong ? art::kLongHiVReg : art::kDoubleHiVReg;
699 if (!visitor.GetVRegPair(method,
700 static_cast<uint16_t>(slot_),
701 lo_type,
702 high_type,
703 reinterpret_cast<uint64_t*>(&val_->j))) {
704 return ERR(OPAQUE_FRAME);
705 }
706 break;
707 }
708 default: {
709 LOG(FATAL) << "unexpected register type " << type_;
710 UNREACHABLE();
711 }
712 }
713 return OK;
714 }
715
716 private:
717 art::Primitive::Type type_;
718 jvalue* val_;
Alex Light318afe62018-03-22 16:50:10 -0700719 art::GcRoot<art::mirror::Object> obj_val_;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700720};
721
722jvmtiError MethodUtil::GetLocalVariableGeneric(jvmtiEnv* env ATTRIBUTE_UNUSED,
723 jthread thread,
724 jint depth,
725 jint slot,
726 art::Primitive::Type type,
727 jvalue* val) {
728 if (depth < 0) {
729 return ERR(ILLEGAL_ARGUMENT);
730 }
731 art::Thread* self = art::Thread::Current();
732 art::ScopedObjectAccess soa(self);
Alex Lightb1e31a82017-10-04 16:57:36 -0700733 art::Locks::thread_list_lock_->ExclusiveLock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700734 art::Thread* target = nullptr;
735 jvmtiError err = ERR(INTERNAL);
736 if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
Alex Lightb1e31a82017-10-04 16:57:36 -0700737 art::Locks::thread_list_lock_->ExclusiveUnlock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700738 return err;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700739 }
Alex Light318afe62018-03-22 16:50:10 -0700740 art::ScopedAssertNoThreadSuspension sants("Performing GetLocalVariable");
741 GetLocalVariableClosure c(depth, slot, type, val);
742 // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution. We
743 // need to avoid suspending as we wait for the checkpoint to occur since we are (potentially)
744 // transfering a GcRoot across threads.
745 if (!target->RequestSynchronousCheckpoint(&c, art::ThreadState::kRunnable)) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700746 return ERR(THREAD_NOT_ALIVE);
747 } else {
748 return c.GetResult();
749 }
750}
751
752class SetLocalVariableClosure : public CommonLocalVariableClosure {
753 public:
754 SetLocalVariableClosure(art::Thread* caller,
755 jint depth,
756 jint slot,
757 art::Primitive::Type type,
758 jvalue val)
Alex Light318afe62018-03-22 16:50:10 -0700759 : CommonLocalVariableClosure(depth, slot), caller_(caller), type_(type), val_(val) {}
Alex Lightbebd7bd2017-07-25 14:05:52 -0700760
761 protected:
762 jvmtiError GetTypeError(art::ArtMethod* method,
763 art::Primitive::Type slot_type,
764 const std::string& descriptor)
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100765 override REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700766 switch (slot_type) {
767 case art::Primitive::kPrimNot: {
768 if (type_ != art::Primitive::kPrimNot) {
769 return ERR(TYPE_MISMATCH);
770 } else if (val_.l == nullptr) {
771 return OK;
772 } else {
773 art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
774 art::ObjPtr<art::mirror::Class> set_class =
775 caller_->DecodeJObject(val_.l)->GetClass();
776 art::ObjPtr<art::mirror::ClassLoader> loader =
777 method->GetDeclaringClass()->GetClassLoader();
778 art::ObjPtr<art::mirror::Class> slot_class =
779 cl->LookupClass(caller_, descriptor.c_str(), loader);
780 DCHECK(!slot_class.IsNull());
781 return slot_class->IsAssignableFrom(set_class) ? OK : ERR(TYPE_MISMATCH);
782 }
783 }
784 case art::Primitive::kPrimByte:
785 case art::Primitive::kPrimChar:
786 case art::Primitive::kPrimInt:
787 case art::Primitive::kPrimShort:
788 case art::Primitive::kPrimBoolean:
789 return type_ == art::Primitive::kPrimInt ? OK : ERR(TYPE_MISMATCH);
790 case art::Primitive::kPrimLong:
791 case art::Primitive::kPrimFloat:
792 case art::Primitive::kPrimDouble:
793 return type_ == slot_type ? OK : ERR(TYPE_MISMATCH);
794 case art::Primitive::kPrimVoid:
795 LOG(FATAL) << "Unexpected primitive type " << slot_type;
796 UNREACHABLE();
797 }
798 }
799
800 jvmtiError Execute(art::ArtMethod* method, art::StackVisitor& visitor)
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100801 override REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700802 switch (type_) {
803 case art::Primitive::kPrimNot: {
804 uint32_t ptr_val;
805 art::ObjPtr<art::mirror::Object> obj(caller_->DecodeJObject(val_.l));
806 ptr_val = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(obj.Ptr()));
807 if (!visitor.SetVReg(method,
808 static_cast<uint16_t>(slot_),
809 ptr_val,
810 art::kReferenceVReg)) {
811 return ERR(OPAQUE_FRAME);
812 }
813 break;
814 }
815 case art::Primitive::kPrimInt:
816 case art::Primitive::kPrimFloat: {
817 if (!visitor.SetVReg(method,
818 static_cast<uint16_t>(slot_),
819 static_cast<uint32_t>(val_.i),
820 type_ == art::Primitive::kPrimFloat ? art::kFloatVReg
821 : art::kIntVReg)) {
822 return ERR(OPAQUE_FRAME);
823 }
824 break;
825 }
826 case art::Primitive::kPrimDouble:
827 case art::Primitive::kPrimLong: {
828 auto lo_type = type_ == art::Primitive::kPrimLong ? art::kLongLoVReg : art::kDoubleLoVReg;
829 auto high_type = type_ == art::Primitive::kPrimLong ? art::kLongHiVReg : art::kDoubleHiVReg;
830 if (!visitor.SetVRegPair(method,
831 static_cast<uint16_t>(slot_),
832 static_cast<uint64_t>(val_.j),
833 lo_type,
834 high_type)) {
835 return ERR(OPAQUE_FRAME);
836 }
837 break;
838 }
839 default: {
840 LOG(FATAL) << "unexpected register type " << type_;
841 UNREACHABLE();
842 }
843 }
844 return OK;
845 }
846
847 private:
Alex Light318afe62018-03-22 16:50:10 -0700848 art::Thread* caller_;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700849 art::Primitive::Type type_;
850 jvalue val_;
851};
852
853jvmtiError MethodUtil::SetLocalVariableGeneric(jvmtiEnv* env ATTRIBUTE_UNUSED,
854 jthread thread,
855 jint depth,
856 jint slot,
857 art::Primitive::Type type,
858 jvalue val) {
859 if (depth < 0) {
860 return ERR(ILLEGAL_ARGUMENT);
861 }
Alex Lightf2858632018-04-02 11:28:50 -0700862 // Make sure that we know not to do any OSR anymore.
863 // TODO We should really keep track of this at the Frame granularity.
864 DeoptManager::Get()->SetLocalsUpdated();
Alex Lightbebd7bd2017-07-25 14:05:52 -0700865 art::Thread* self = art::Thread::Current();
866 art::ScopedObjectAccess soa(self);
Alex Lightb1e31a82017-10-04 16:57:36 -0700867 art::Locks::thread_list_lock_->ExclusiveLock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700868 art::Thread* target = nullptr;
869 jvmtiError err = ERR(INTERNAL);
870 if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
Alex Lightb1e31a82017-10-04 16:57:36 -0700871 art::Locks::thread_list_lock_->ExclusiveUnlock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700872 return err;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700873 }
874 SetLocalVariableClosure c(self, depth, slot, type, val);
Alex Lightb1e31a82017-10-04 16:57:36 -0700875 // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
Alex Light318afe62018-03-22 16:50:10 -0700876 if (!target->RequestSynchronousCheckpoint(&c)) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700877 return ERR(THREAD_NOT_ALIVE);
878 } else {
879 return c.GetResult();
880 }
881}
882
883class GetLocalInstanceClosure : public art::Closure {
884 public:
Alex Light318afe62018-03-22 16:50:10 -0700885 explicit GetLocalInstanceClosure(jint depth)
Alex Lightbebd7bd2017-07-25 14:05:52 -0700886 : result_(ERR(INTERNAL)),
Alex Lightbebd7bd2017-07-25 14:05:52 -0700887 depth_(depth),
Alex Light318afe62018-03-22 16:50:10 -0700888 val_(nullptr) {}
Alex Lightbebd7bd2017-07-25 14:05:52 -0700889
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100890 void Run(art::Thread* self) override REQUIRES(art::Locks::mutator_lock_) {
Alex Light318afe62018-03-22 16:50:10 -0700891 art::ScopedAssertNoThreadSuspension sants("GetLocalInstanceClosure::Run");
Alex Lightbebd7bd2017-07-25 14:05:52 -0700892 art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current());
893 std::unique_ptr<art::Context> context(art::Context::Create());
894 FindFrameAtDepthVisitor visitor(self, context.get(), depth_);
895 visitor.WalkStack();
896 if (!visitor.FoundFrame()) {
897 // Must have been a bad depth.
898 result_ = ERR(NO_MORE_FRAMES);
899 return;
900 }
Alex Lightbebd7bd2017-07-25 14:05:52 -0700901 result_ = OK;
Alex Light318afe62018-03-22 16:50:10 -0700902 val_ = art::GcRoot<art::mirror::Object>(visitor.GetThisObject());
Alex Lightbebd7bd2017-07-25 14:05:52 -0700903 }
904
Alex Light318afe62018-03-22 16:50:10 -0700905 jvmtiError GetResult(jobject* data_out) REQUIRES_SHARED(art::Locks::mutator_lock_) {
906 if (result_ == OK) {
907 *data_out = val_.IsNull()
908 ? nullptr
909 : art::Thread::Current()->GetJniEnv()->AddLocalReference<jobject>(val_.Read());
910 }
Alex Lightbebd7bd2017-07-25 14:05:52 -0700911 return result_;
912 }
913
914 private:
915 jvmtiError result_;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700916 jint depth_;
Alex Light318afe62018-03-22 16:50:10 -0700917 art::GcRoot<art::mirror::Object> val_;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700918};
919
920jvmtiError MethodUtil::GetLocalInstance(jvmtiEnv* env ATTRIBUTE_UNUSED,
921 jthread thread,
922 jint depth,
923 jobject* data) {
924 if (depth < 0) {
925 return ERR(ILLEGAL_ARGUMENT);
926 }
927 art::Thread* self = art::Thread::Current();
928 art::ScopedObjectAccess soa(self);
Alex Lightb1e31a82017-10-04 16:57:36 -0700929 art::Locks::thread_list_lock_->ExclusiveLock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700930 art::Thread* target = nullptr;
931 jvmtiError err = ERR(INTERNAL);
932 if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
Alex Lightb1e31a82017-10-04 16:57:36 -0700933 art::Locks::thread_list_lock_->ExclusiveUnlock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700934 return err;
Alex Lightbebd7bd2017-07-25 14:05:52 -0700935 }
Alex Light318afe62018-03-22 16:50:10 -0700936 art::ScopedAssertNoThreadSuspension sants("Performing GetLocalInstance");
937 GetLocalInstanceClosure c(depth);
938 // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution. We
939 // need to avoid suspending as we wait for the checkpoint to occur since we are (potentially)
940 // transfering a GcRoot across threads.
941 if (!target->RequestSynchronousCheckpoint(&c, art::ThreadState::kRunnable)) {
Alex Lightbebd7bd2017-07-25 14:05:52 -0700942 return ERR(THREAD_NOT_ALIVE);
943 } else {
Alex Light318afe62018-03-22 16:50:10 -0700944 return c.GetResult(data);
Alex Lightbebd7bd2017-07-25 14:05:52 -0700945 }
946}
947
948#define FOR_JVMTI_JVALUE_TYPES(fn) \
949 fn(jint, art::Primitive::kPrimInt, i) \
950 fn(jlong, art::Primitive::kPrimLong, j) \
951 fn(jfloat, art::Primitive::kPrimFloat, f) \
952 fn(jdouble, art::Primitive::kPrimDouble, d) \
953 fn(jobject, art::Primitive::kPrimNot, l)
954
955namespace impl {
956
957template<typename T> void WriteJvalue(T, jvalue*);
958template<typename T> void ReadJvalue(jvalue, T*);
959template<typename T> art::Primitive::Type GetJNIType();
960
961#define JNI_TYPE_CHAR(type, prim, id) \
962template<> art::Primitive::Type GetJNIType<type>() { \
963 return prim; \
964}
965
966FOR_JVMTI_JVALUE_TYPES(JNI_TYPE_CHAR);
967
968#undef JNI_TYPE_CHAR
969
Andreas Gampe49fc60e2017-08-24 13:19:59 -0700970#define RW_JVALUE(srctype, prim, id) \
971 template<> void ReadJvalue<srctype>(jvalue in, std::add_pointer<srctype>::type out) { \
Alex Lightbebd7bd2017-07-25 14:05:52 -0700972 *out = in.id; \
973 } \
Andreas Gampe49fc60e2017-08-24 13:19:59 -0700974 template<> void WriteJvalue<srctype>(srctype in, jvalue* out) { \
Alex Lightbebd7bd2017-07-25 14:05:52 -0700975 out->id = in; \
976 }
977
978FOR_JVMTI_JVALUE_TYPES(RW_JVALUE);
979
980#undef RW_JVALUE
981
982} // namespace impl
983
984template<typename T>
985jvmtiError MethodUtil::SetLocalVariable(jvmtiEnv* env,
986 jthread thread,
987 jint depth,
988 jint slot,
989 T data) {
990 jvalue v = {.j = 0};
991 art::Primitive::Type type = impl::GetJNIType<T>();
992 impl::WriteJvalue(data, &v);
993 return SetLocalVariableGeneric(env, thread, depth, slot, type, v);
994}
995
996template<typename T>
997jvmtiError MethodUtil::GetLocalVariable(jvmtiEnv* env,
998 jthread thread,
999 jint depth,
1000 jint slot,
1001 T* data) {
1002 if (data == nullptr) {
1003 return ERR(NULL_POINTER);
1004 }
1005 jvalue v = {.j = 0};
1006 art::Primitive::Type type = impl::GetJNIType<T>();
1007 jvmtiError err = GetLocalVariableGeneric(env, thread, depth, slot, type, &v);
1008 if (err != OK) {
1009 return err;
1010 } else {
1011 impl::ReadJvalue(v, data);
1012 return OK;
1013 }
1014}
1015
Andreas Gampe49fc60e2017-08-24 13:19:59 -07001016#define GET_SET_LV(srctype, prim, id) \
1017 template jvmtiError MethodUtil::GetLocalVariable<srctype>(jvmtiEnv*, \
1018 jthread, \
1019 jint, \
1020 jint, \
1021 std::add_pointer<srctype>::type); \
1022 template jvmtiError MethodUtil::SetLocalVariable<srctype>(jvmtiEnv*, \
1023 jthread, \
1024 jint, \
1025 jint, \
1026 srctype);
Alex Lightbebd7bd2017-07-25 14:05:52 -07001027
1028FOR_JVMTI_JVALUE_TYPES(GET_SET_LV);
1029
1030#undef GET_SET_LV
1031
1032#undef FOR_JVMTI_JVALUE_TYPES
1033
Andreas Gampe3c252f02016-10-27 18:25:17 -07001034} // namespace openjdkjvmti