xref: /aosp_15_r20/art/openjdkjvmti/ti_extension.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /* Copyright (C) 2017 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  *
26*795d594fSAndroid Build Coastguard Worker  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
27*795d594fSAndroid Build Coastguard Worker  * or visit www.oracle.com if you need additional information or have any
28*795d594fSAndroid Build Coastguard Worker  * questions.
29*795d594fSAndroid Build Coastguard Worker  */
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker #include <vector>
32*795d594fSAndroid Build Coastguard Worker 
33*795d594fSAndroid Build Coastguard Worker #include "jvmti.h"
34*795d594fSAndroid Build Coastguard Worker #include "ti_extension.h"
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker #include "art_jvmti.h"
37*795d594fSAndroid Build Coastguard Worker #include "events.h"
38*795d594fSAndroid Build Coastguard Worker #include "jni_id_type.h"
39*795d594fSAndroid Build Coastguard Worker #include "runtime-inl.h"
40*795d594fSAndroid Build Coastguard Worker #include "ti_allocator.h"
41*795d594fSAndroid Build Coastguard Worker #include "ti_class.h"
42*795d594fSAndroid Build Coastguard Worker #include "ti_ddms.h"
43*795d594fSAndroid Build Coastguard Worker #include "ti_dump.h"
44*795d594fSAndroid Build Coastguard Worker #include "ti_heap.h"
45*795d594fSAndroid Build Coastguard Worker #include "ti_logging.h"
46*795d594fSAndroid Build Coastguard Worker #include "ti_monitor.h"
47*795d594fSAndroid Build Coastguard Worker #include "ti_redefine.h"
48*795d594fSAndroid Build Coastguard Worker #include "ti_search.h"
49*795d594fSAndroid Build Coastguard Worker #include "transform.h"
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
52*795d594fSAndroid Build Coastguard Worker 
53*795d594fSAndroid Build Coastguard Worker namespace openjdkjvmti {
54*795d594fSAndroid Build Coastguard Worker 
55*795d594fSAndroid Build Coastguard Worker struct CParamInfo {
56*795d594fSAndroid Build Coastguard Worker   const char* name;
57*795d594fSAndroid Build Coastguard Worker   jvmtiParamKind kind;
58*795d594fSAndroid Build Coastguard Worker   jvmtiParamTypes base_type;
59*795d594fSAndroid Build Coastguard Worker   jboolean null_ok;
60*795d594fSAndroid Build Coastguard Worker 
ToParamInfoopenjdkjvmti::CParamInfo61*795d594fSAndroid Build Coastguard Worker   jvmtiParamInfo ToParamInfo(jvmtiEnv* env,
62*795d594fSAndroid Build Coastguard Worker                              /*out*/std::vector<JvmtiUniquePtr<char[]>>* char_buffers,
63*795d594fSAndroid Build Coastguard Worker                              /*out*/jvmtiError* err) const {
64*795d594fSAndroid Build Coastguard Worker     JvmtiUniquePtr<char[]> param_name = CopyString(env, name, err);
65*795d594fSAndroid Build Coastguard Worker     char* name_ptr = param_name.get();
66*795d594fSAndroid Build Coastguard Worker     char_buffers->push_back(std::move(param_name));
67*795d594fSAndroid Build Coastguard Worker     return jvmtiParamInfo{ name_ptr, kind, base_type, null_ok };
68*795d594fSAndroid Build Coastguard Worker   }
69*795d594fSAndroid Build Coastguard Worker };
70*795d594fSAndroid Build Coastguard Worker 
GetExtensionFunctions(jvmtiEnv * env,jint * extension_count_ptr,jvmtiExtensionFunctionInfo ** extensions)71*795d594fSAndroid Build Coastguard Worker jvmtiError ExtensionUtil::GetExtensionFunctions(jvmtiEnv* env,
72*795d594fSAndroid Build Coastguard Worker                                                 jint* extension_count_ptr,
73*795d594fSAndroid Build Coastguard Worker                                                 jvmtiExtensionFunctionInfo** extensions) {
74*795d594fSAndroid Build Coastguard Worker   if (extension_count_ptr == nullptr || extensions == nullptr) {
75*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
76*795d594fSAndroid Build Coastguard Worker   }
77*795d594fSAndroid Build Coastguard Worker 
78*795d594fSAndroid Build Coastguard Worker   std::vector<jvmtiExtensionFunctionInfo> ext_vector;
79*795d594fSAndroid Build Coastguard Worker 
80*795d594fSAndroid Build Coastguard Worker   // Holders for allocated values.
81*795d594fSAndroid Build Coastguard Worker   std::vector<JvmtiUniquePtr<char[]>> char_buffers;
82*795d594fSAndroid Build Coastguard Worker   std::vector<JvmtiUniquePtr<jvmtiParamInfo[]>> param_buffers;
83*795d594fSAndroid Build Coastguard Worker   std::vector<JvmtiUniquePtr<jvmtiError[]>> error_buffers;
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker   auto add_extension = [&](jvmtiExtensionFunction func,
86*795d594fSAndroid Build Coastguard Worker                            const char* id,
87*795d594fSAndroid Build Coastguard Worker                            const char* short_description,
88*795d594fSAndroid Build Coastguard Worker                            const std::vector<CParamInfo>& params,
89*795d594fSAndroid Build Coastguard Worker                            const std::vector<jvmtiError>& errors) {
90*795d594fSAndroid Build Coastguard Worker     jvmtiExtensionFunctionInfo func_info;
91*795d594fSAndroid Build Coastguard Worker     jvmtiError error;
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker     func_info.func = func;
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker     JvmtiUniquePtr<char[]> id_ptr = CopyString(env, id, &error);
96*795d594fSAndroid Build Coastguard Worker     if (id_ptr == nullptr) {
97*795d594fSAndroid Build Coastguard Worker       return error;
98*795d594fSAndroid Build Coastguard Worker     }
99*795d594fSAndroid Build Coastguard Worker     func_info.id = id_ptr.get();
100*795d594fSAndroid Build Coastguard Worker     char_buffers.push_back(std::move(id_ptr));
101*795d594fSAndroid Build Coastguard Worker 
102*795d594fSAndroid Build Coastguard Worker     JvmtiUniquePtr<char[]> descr = CopyString(env, short_description, &error);
103*795d594fSAndroid Build Coastguard Worker     if (descr == nullptr) {
104*795d594fSAndroid Build Coastguard Worker       return error;
105*795d594fSAndroid Build Coastguard Worker     }
106*795d594fSAndroid Build Coastguard Worker     func_info.short_description = descr.get();
107*795d594fSAndroid Build Coastguard Worker     char_buffers.push_back(std::move(descr));
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker     func_info.param_count = params.size();
110*795d594fSAndroid Build Coastguard Worker     if (!params.empty()) {
111*795d594fSAndroid Build Coastguard Worker       JvmtiUniquePtr<jvmtiParamInfo[]> params_ptr =
112*795d594fSAndroid Build Coastguard Worker           AllocJvmtiUniquePtr<jvmtiParamInfo[]>(env, params.size(), &error);
113*795d594fSAndroid Build Coastguard Worker       if (params_ptr == nullptr) {
114*795d594fSAndroid Build Coastguard Worker         return error;
115*795d594fSAndroid Build Coastguard Worker       }
116*795d594fSAndroid Build Coastguard Worker       func_info.params = params_ptr.get();
117*795d594fSAndroid Build Coastguard Worker       param_buffers.push_back(std::move(params_ptr));
118*795d594fSAndroid Build Coastguard Worker 
119*795d594fSAndroid Build Coastguard Worker       for (jint i = 0; i != func_info.param_count; ++i) {
120*795d594fSAndroid Build Coastguard Worker         func_info.params[i] = params[i].ToParamInfo(env, &char_buffers, &error);
121*795d594fSAndroid Build Coastguard Worker         if (error != OK) {
122*795d594fSAndroid Build Coastguard Worker           return error;
123*795d594fSAndroid Build Coastguard Worker         }
124*795d594fSAndroid Build Coastguard Worker       }
125*795d594fSAndroid Build Coastguard Worker     } else {
126*795d594fSAndroid Build Coastguard Worker       func_info.params = nullptr;
127*795d594fSAndroid Build Coastguard Worker     }
128*795d594fSAndroid Build Coastguard Worker 
129*795d594fSAndroid Build Coastguard Worker     func_info.error_count = errors.size();
130*795d594fSAndroid Build Coastguard Worker     if (!errors.empty()) {
131*795d594fSAndroid Build Coastguard Worker       JvmtiUniquePtr<jvmtiError[]> errors_ptr =
132*795d594fSAndroid Build Coastguard Worker           AllocJvmtiUniquePtr<jvmtiError[]>(env, errors.size(), &error);
133*795d594fSAndroid Build Coastguard Worker       if (errors_ptr == nullptr) {
134*795d594fSAndroid Build Coastguard Worker         return error;
135*795d594fSAndroid Build Coastguard Worker       }
136*795d594fSAndroid Build Coastguard Worker       func_info.errors = errors_ptr.get();
137*795d594fSAndroid Build Coastguard Worker       error_buffers.push_back(std::move(errors_ptr));
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker       for (jint i = 0; i != func_info.error_count; ++i) {
140*795d594fSAndroid Build Coastguard Worker         func_info.errors[i] = errors[i];
141*795d594fSAndroid Build Coastguard Worker       }
142*795d594fSAndroid Build Coastguard Worker     } else {
143*795d594fSAndroid Build Coastguard Worker       func_info.errors = nullptr;
144*795d594fSAndroid Build Coastguard Worker     }
145*795d594fSAndroid Build Coastguard Worker 
146*795d594fSAndroid Build Coastguard Worker     ext_vector.push_back(func_info);
147*795d594fSAndroid Build Coastguard Worker 
148*795d594fSAndroid Build Coastguard Worker     return ERR(NONE);
149*795d594fSAndroid Build Coastguard Worker   };
150*795d594fSAndroid Build Coastguard Worker 
151*795d594fSAndroid Build Coastguard Worker   jvmtiError error;
152*795d594fSAndroid Build Coastguard Worker 
153*795d594fSAndroid Build Coastguard Worker   // Heap extensions.
154*795d594fSAndroid Build Coastguard Worker   error = add_extension(
155*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(HeapExtensions::GetObjectHeapId),
156*795d594fSAndroid Build Coastguard Worker       "com.android.art.heap.get_object_heap_id",
157*795d594fSAndroid Build Coastguard Worker       "Retrieve the heap id of the the object tagged with the given argument. An "
158*795d594fSAndroid Build Coastguard Worker           "arbitrary object is chosen if multiple objects exist with the same tag.",
159*795d594fSAndroid Build Coastguard Worker       {
160*795d594fSAndroid Build Coastguard Worker           { "tag", JVMTI_KIND_IN, JVMTI_TYPE_JLONG, false},
161*795d594fSAndroid Build Coastguard Worker           { "heap_id", JVMTI_KIND_OUT, JVMTI_TYPE_JINT, false}
162*795d594fSAndroid Build Coastguard Worker       },
163*795d594fSAndroid Build Coastguard Worker       { JVMTI_ERROR_NOT_FOUND });
164*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
165*795d594fSAndroid Build Coastguard Worker     return error;
166*795d594fSAndroid Build Coastguard Worker   }
167*795d594fSAndroid Build Coastguard Worker 
168*795d594fSAndroid Build Coastguard Worker   error = add_extension(
169*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(HeapExtensions::GetHeapName),
170*795d594fSAndroid Build Coastguard Worker       "com.android.art.heap.get_heap_name",
171*795d594fSAndroid Build Coastguard Worker       "Retrieve the name of the heap with the given id.",
172*795d594fSAndroid Build Coastguard Worker       {
173*795d594fSAndroid Build Coastguard Worker           { "heap_id", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false},
174*795d594fSAndroid Build Coastguard Worker           { "heap_name", JVMTI_KIND_ALLOC_BUF, JVMTI_TYPE_CCHAR, false}
175*795d594fSAndroid Build Coastguard Worker       },
176*795d594fSAndroid Build Coastguard Worker       { JVMTI_ERROR_ILLEGAL_ARGUMENT });
177*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
178*795d594fSAndroid Build Coastguard Worker     return error;
179*795d594fSAndroid Build Coastguard Worker   }
180*795d594fSAndroid Build Coastguard Worker 
181*795d594fSAndroid Build Coastguard Worker   error = add_extension(
182*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(HeapExtensions::IterateThroughHeapExt),
183*795d594fSAndroid Build Coastguard Worker       "com.android.art.heap.iterate_through_heap_ext",
184*795d594fSAndroid Build Coastguard Worker       "Iterate through a heap. This is equivalent to the standard IterateThroughHeap function,"
185*795d594fSAndroid Build Coastguard Worker       " except for additionally passing the heap id of the current object. The jvmtiHeapCallbacks"
186*795d594fSAndroid Build Coastguard Worker       " structure is reused, with the callbacks field overloaded to a signature of "
187*795d594fSAndroid Build Coastguard Worker       "jint (*)(jlong, jlong, jlong*, jint length, void*, jint).",
188*795d594fSAndroid Build Coastguard Worker       {
189*795d594fSAndroid Build Coastguard Worker           { "heap_filter", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false},
190*795d594fSAndroid Build Coastguard Worker           { "klass", JVMTI_KIND_IN, JVMTI_TYPE_JCLASS, true},
191*795d594fSAndroid Build Coastguard Worker           { "callbacks", JVMTI_KIND_IN_PTR, JVMTI_TYPE_CVOID, false},
192*795d594fSAndroid Build Coastguard Worker           { "user_data", JVMTI_KIND_IN_PTR, JVMTI_TYPE_CVOID, true}
193*795d594fSAndroid Build Coastguard Worker       },
194*795d594fSAndroid Build Coastguard Worker       {
195*795d594fSAndroid Build Coastguard Worker           ERR(MUST_POSSESS_CAPABILITY),
196*795d594fSAndroid Build Coastguard Worker           ERR(INVALID_CLASS),
197*795d594fSAndroid Build Coastguard Worker           ERR(NULL_POINTER),
198*795d594fSAndroid Build Coastguard Worker       });
199*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
200*795d594fSAndroid Build Coastguard Worker     return error;
201*795d594fSAndroid Build Coastguard Worker   }
202*795d594fSAndroid Build Coastguard Worker 
203*795d594fSAndroid Build Coastguard Worker   error = add_extension(
204*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(AllocUtil::GetGlobalJvmtiAllocationState),
205*795d594fSAndroid Build Coastguard Worker       "com.android.art.alloc.get_global_jvmti_allocation_state",
206*795d594fSAndroid Build Coastguard Worker       "Returns the total amount of memory currently allocated by all jvmtiEnvs through the"
207*795d594fSAndroid Build Coastguard Worker       " 'Allocate' jvmti function. This does not include any memory that has been deallocated"
208*795d594fSAndroid Build Coastguard Worker       " through the 'Deallocate' function. This number is approximate and might not correspond"
209*795d594fSAndroid Build Coastguard Worker       " exactly to the sum of the sizes of all not freed allocations.",
210*795d594fSAndroid Build Coastguard Worker       {
211*795d594fSAndroid Build Coastguard Worker           { "currently_allocated", JVMTI_KIND_OUT, JVMTI_TYPE_JLONG, false},
212*795d594fSAndroid Build Coastguard Worker       },
213*795d594fSAndroid Build Coastguard Worker       { ERR(NULL_POINTER) });
214*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
215*795d594fSAndroid Build Coastguard Worker     return error;
216*795d594fSAndroid Build Coastguard Worker   }
217*795d594fSAndroid Build Coastguard Worker 
218*795d594fSAndroid Build Coastguard Worker   // DDMS extension
219*795d594fSAndroid Build Coastguard Worker   error = add_extension(
220*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(DDMSUtil::HandleChunk),
221*795d594fSAndroid Build Coastguard Worker       "com.android.art.internal.ddm.process_chunk",
222*795d594fSAndroid Build Coastguard Worker       "Handles a single ddms chunk request and returns a response. The reply data is in the ddms"
223*795d594fSAndroid Build Coastguard Worker       " chunk format. It returns the processed chunk. This is provided for backwards compatibility"
224*795d594fSAndroid Build Coastguard Worker       " reasons only. Agents should avoid making use of this extension when possible and instead"
225*795d594fSAndroid Build Coastguard Worker       " use the other JVMTI entrypoints explicitly.",
226*795d594fSAndroid Build Coastguard Worker       {
227*795d594fSAndroid Build Coastguard Worker         { "type_in", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
228*795d594fSAndroid Build Coastguard Worker         { "length_in", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
229*795d594fSAndroid Build Coastguard Worker         { "data_in", JVMTI_KIND_IN_BUF, JVMTI_TYPE_JBYTE, true },
230*795d594fSAndroid Build Coastguard Worker         { "type_out", JVMTI_KIND_OUT, JVMTI_TYPE_JINT, false },
231*795d594fSAndroid Build Coastguard Worker         { "data_len_out", JVMTI_KIND_OUT, JVMTI_TYPE_JINT, false },
232*795d594fSAndroid Build Coastguard Worker         { "data_out", JVMTI_KIND_ALLOC_BUF, JVMTI_TYPE_JBYTE, false }
233*795d594fSAndroid Build Coastguard Worker       },
234*795d594fSAndroid Build Coastguard Worker       { ERR(NULL_POINTER), ERR(ILLEGAL_ARGUMENT), ERR(OUT_OF_MEMORY) });
235*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
236*795d594fSAndroid Build Coastguard Worker     return error;
237*795d594fSAndroid Build Coastguard Worker   }
238*795d594fSAndroid Build Coastguard Worker 
239*795d594fSAndroid Build Coastguard Worker   // GetClassLoaderClassDescriptors extension
240*795d594fSAndroid Build Coastguard Worker   error = add_extension(
241*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(ClassUtil::GetClassLoaderClassDescriptors),
242*795d594fSAndroid Build Coastguard Worker       "com.android.art.class.get_class_loader_class_descriptors",
243*795d594fSAndroid Build Coastguard Worker       "Retrieves a list of all the classes (as class descriptors) that the given class loader is"
244*795d594fSAndroid Build Coastguard Worker       " capable of being the defining class loader for. The return format is a list of"
245*795d594fSAndroid Build Coastguard Worker       " null-terminated descriptor strings of the form \"L/java/lang/Object;\". Each descriptor"
246*795d594fSAndroid Build Coastguard Worker       " will be in the list at most once. If the class_loader is null the bootclassloader will be"
247*795d594fSAndroid Build Coastguard Worker       " used. If the class_loader is not null it must either be a java.lang.BootClassLoader, a"
248*795d594fSAndroid Build Coastguard Worker       " dalvik.system.BaseDexClassLoader or a derived type. The data_out list and all elements"
249*795d594fSAndroid Build Coastguard Worker       " must be deallocated by the caller.",
250*795d594fSAndroid Build Coastguard Worker       {
251*795d594fSAndroid Build Coastguard Worker         { "class_loader", JVMTI_KIND_IN, JVMTI_TYPE_JOBJECT, true },
252*795d594fSAndroid Build Coastguard Worker         { "class_descriptor_count_out", JVMTI_KIND_OUT, JVMTI_TYPE_JINT, false },
253*795d594fSAndroid Build Coastguard Worker         { "data_out", JVMTI_KIND_ALLOC_ALLOC_BUF, JVMTI_TYPE_CCHAR, false },
254*795d594fSAndroid Build Coastguard Worker       },
255*795d594fSAndroid Build Coastguard Worker       {
256*795d594fSAndroid Build Coastguard Worker         ERR(NULL_POINTER),
257*795d594fSAndroid Build Coastguard Worker         ERR(ILLEGAL_ARGUMENT),
258*795d594fSAndroid Build Coastguard Worker         ERR(OUT_OF_MEMORY),
259*795d594fSAndroid Build Coastguard Worker         ERR(NOT_IMPLEMENTED),
260*795d594fSAndroid Build Coastguard Worker       });
261*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
262*795d594fSAndroid Build Coastguard Worker     return error;
263*795d594fSAndroid Build Coastguard Worker   }
264*795d594fSAndroid Build Coastguard Worker 
265*795d594fSAndroid Build Coastguard Worker   // Raw monitors no suspend
266*795d594fSAndroid Build Coastguard Worker   error = add_extension(
267*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(MonitorUtil::RawMonitorEnterNoSuspend),
268*795d594fSAndroid Build Coastguard Worker       "com.android.art.concurrent.raw_monitor_enter_no_suspend",
269*795d594fSAndroid Build Coastguard Worker       "Normally entering a monitor will not return until both the monitor is locked and the"
270*795d594fSAndroid Build Coastguard Worker       " current thread is not suspended. This method will return once the monitor is locked"
271*795d594fSAndroid Build Coastguard Worker       " even if the thread is suspended. Note that using rawMonitorWait will wait until the"
272*795d594fSAndroid Build Coastguard Worker       " thread is not suspended again on wakeup and so should be avoided.",
273*795d594fSAndroid Build Coastguard Worker       {
274*795d594fSAndroid Build Coastguard Worker           { "raw_monitor", JVMTI_KIND_IN_PTR, JVMTI_TYPE_CVOID, false },
275*795d594fSAndroid Build Coastguard Worker       },
276*795d594fSAndroid Build Coastguard Worker       {
277*795d594fSAndroid Build Coastguard Worker         ERR(NULL_POINTER),
278*795d594fSAndroid Build Coastguard Worker         ERR(INVALID_MONITOR),
279*795d594fSAndroid Build Coastguard Worker       });
280*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
281*795d594fSAndroid Build Coastguard Worker     return error;
282*795d594fSAndroid Build Coastguard Worker   }
283*795d594fSAndroid Build Coastguard Worker 
284*795d594fSAndroid Build Coastguard Worker   // GetLastError extension
285*795d594fSAndroid Build Coastguard Worker   error = add_extension(
286*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(LogUtil::GetLastError),
287*795d594fSAndroid Build Coastguard Worker       "com.android.art.misc.get_last_error_message",
288*795d594fSAndroid Build Coastguard Worker       "In some cases the jvmti plugin will log data about errors to the android logcat. These can"
289*795d594fSAndroid Build Coastguard Worker       " be useful to tools so we make (some) of the messages available here as well. This will"
290*795d594fSAndroid Build Coastguard Worker       " fill the given 'msg' buffer with the last non-fatal message associated with this"
291*795d594fSAndroid Build Coastguard Worker       " jvmti-env. Note this is best-effort only, not all log messages will be accessible through"
292*795d594fSAndroid Build Coastguard Worker       " this API. This will return the last error-message from all threads. Care should be taken"
293*795d594fSAndroid Build Coastguard Worker       " interpreting the return value when used with a multi-threaded program. The error message"
294*795d594fSAndroid Build Coastguard Worker       " will only be cleared by a call to 'com.android.art.misc.clear_last_error_message' and will"
295*795d594fSAndroid Build Coastguard Worker       " not be cleared by intervening successful calls. If no (tracked) error message has been"
296*795d594fSAndroid Build Coastguard Worker       " sent since the last call to clear_last_error_message this API will return"
297*795d594fSAndroid Build Coastguard Worker       " JVMTI_ERROR_ABSENT_INFORMATION. Not all failures will cause an error message to be"
298*795d594fSAndroid Build Coastguard Worker       " recorded.",
299*795d594fSAndroid Build Coastguard Worker       {
300*795d594fSAndroid Build Coastguard Worker           { "msg", JVMTI_KIND_ALLOC_BUF, JVMTI_TYPE_CCHAR, false },
301*795d594fSAndroid Build Coastguard Worker       },
302*795d594fSAndroid Build Coastguard Worker       {
303*795d594fSAndroid Build Coastguard Worker         ERR(NULL_POINTER),
304*795d594fSAndroid Build Coastguard Worker         ERR(ABSENT_INFORMATION),
305*795d594fSAndroid Build Coastguard Worker       });
306*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
307*795d594fSAndroid Build Coastguard Worker     return error;
308*795d594fSAndroid Build Coastguard Worker   }
309*795d594fSAndroid Build Coastguard Worker 
310*795d594fSAndroid Build Coastguard Worker   // ClearLastError extension
311*795d594fSAndroid Build Coastguard Worker   error = add_extension(
312*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(LogUtil::ClearLastError),
313*795d594fSAndroid Build Coastguard Worker       "com.android.art.misc.clear_last_error_message",
314*795d594fSAndroid Build Coastguard Worker       "Clears the error message returned by 'com.android.art.misc.get_last_error_message'.",
315*795d594fSAndroid Build Coastguard Worker       { },
316*795d594fSAndroid Build Coastguard Worker       { });
317*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
318*795d594fSAndroid Build Coastguard Worker     return error;
319*795d594fSAndroid Build Coastguard Worker   }
320*795d594fSAndroid Build Coastguard Worker 
321*795d594fSAndroid Build Coastguard Worker   // DumpInternalState
322*795d594fSAndroid Build Coastguard Worker   error = add_extension(
323*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(DumpUtil::DumpInternalState),
324*795d594fSAndroid Build Coastguard Worker       "com.android.art.misc.get_plugin_internal_state",
325*795d594fSAndroid Build Coastguard Worker       "Gets internal state about the plugin and serializes it to the given msg. "
326*795d594fSAndroid Build Coastguard Worker       "There is no particular format to this message beyond being human readable.",
327*795d594fSAndroid Build Coastguard Worker       {
328*795d594fSAndroid Build Coastguard Worker           { "msg", JVMTI_KIND_ALLOC_BUF, JVMTI_TYPE_CCHAR, false },
329*795d594fSAndroid Build Coastguard Worker       },
330*795d594fSAndroid Build Coastguard Worker       { ERR(NULL_POINTER) });
331*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
332*795d594fSAndroid Build Coastguard Worker     return error;
333*795d594fSAndroid Build Coastguard Worker   }
334*795d594fSAndroid Build Coastguard Worker 
335*795d594fSAndroid Build Coastguard Worker   // AddToDexClassLoader
336*795d594fSAndroid Build Coastguard Worker   error = add_extension(
337*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(SearchUtil::AddToDexClassLoader),
338*795d594fSAndroid Build Coastguard Worker       "com.android.art.classloader.add_to_dex_class_loader",
339*795d594fSAndroid Build Coastguard Worker       "Adds a dexfile to a given dalvik.system.BaseDexClassLoader in a manner similar to"
340*795d594fSAndroid Build Coastguard Worker       " AddToSystemClassLoader.",
341*795d594fSAndroid Build Coastguard Worker       {
342*795d594fSAndroid Build Coastguard Worker         { "classloader", JVMTI_KIND_IN, JVMTI_TYPE_JOBJECT, false },
343*795d594fSAndroid Build Coastguard Worker         { "segment", JVMTI_KIND_IN_PTR, JVMTI_TYPE_CCHAR, false },
344*795d594fSAndroid Build Coastguard Worker       },
345*795d594fSAndroid Build Coastguard Worker       {
346*795d594fSAndroid Build Coastguard Worker          ERR(NULL_POINTER),
347*795d594fSAndroid Build Coastguard Worker          ERR(CLASS_LOADER_UNSUPPORTED),
348*795d594fSAndroid Build Coastguard Worker          ERR(ILLEGAL_ARGUMENT),
349*795d594fSAndroid Build Coastguard Worker          ERR(WRONG_PHASE),
350*795d594fSAndroid Build Coastguard Worker       });
351*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
352*795d594fSAndroid Build Coastguard Worker     return error;
353*795d594fSAndroid Build Coastguard Worker   }
354*795d594fSAndroid Build Coastguard Worker 
355*795d594fSAndroid Build Coastguard Worker   // AddToDexClassLoaderInMemory
356*795d594fSAndroid Build Coastguard Worker   error = add_extension(
357*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(SearchUtil::AddToDexClassLoaderInMemory),
358*795d594fSAndroid Build Coastguard Worker       "com.android.art.classloader.add_to_dex_class_loader_in_memory",
359*795d594fSAndroid Build Coastguard Worker       "Adds a dexfile buffer to a given dalvik.system.BaseDexClassLoader in a manner similar to"
360*795d594fSAndroid Build Coastguard Worker       " AddToSystemClassLoader. This may only be done during the LIVE phase. The buffer is copied"
361*795d594fSAndroid Build Coastguard Worker       " and the caller is responsible for deallocating it after this call.",
362*795d594fSAndroid Build Coastguard Worker       {
363*795d594fSAndroid Build Coastguard Worker         { "classloader", JVMTI_KIND_IN, JVMTI_TYPE_JOBJECT, false },
364*795d594fSAndroid Build Coastguard Worker         { "dex_bytes", JVMTI_KIND_IN_BUF, JVMTI_TYPE_CCHAR, false },
365*795d594fSAndroid Build Coastguard Worker         { "dex_bytes_len", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
366*795d594fSAndroid Build Coastguard Worker       },
367*795d594fSAndroid Build Coastguard Worker       {
368*795d594fSAndroid Build Coastguard Worker          ERR(NULL_POINTER),
369*795d594fSAndroid Build Coastguard Worker          ERR(CLASS_LOADER_UNSUPPORTED),
370*795d594fSAndroid Build Coastguard Worker          ERR(ILLEGAL_ARGUMENT),
371*795d594fSAndroid Build Coastguard Worker          ERR(WRONG_PHASE),
372*795d594fSAndroid Build Coastguard Worker       });
373*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
374*795d594fSAndroid Build Coastguard Worker     return error;
375*795d594fSAndroid Build Coastguard Worker   }
376*795d594fSAndroid Build Coastguard Worker 
377*795d594fSAndroid Build Coastguard Worker   // ChangeArraySize
378*795d594fSAndroid Build Coastguard Worker   error = add_extension(
379*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(HeapExtensions::ChangeArraySize),
380*795d594fSAndroid Build Coastguard Worker       "com.android.art.heap.change_array_size",
381*795d594fSAndroid Build Coastguard Worker       "Changes the size of a java array. As far as all JNI and java code is concerned this is"
382*795d594fSAndroid Build Coastguard Worker       " atomic. Must have can_tag_objects capability. If the new length of the array is smaller"
383*795d594fSAndroid Build Coastguard Worker       " than the original length, then the array will be truncated to the new length. Otherwise,"
384*795d594fSAndroid Build Coastguard Worker       " all new slots will be filled with null, 0, or False as appropriate for the array type.",
385*795d594fSAndroid Build Coastguard Worker       {
386*795d594fSAndroid Build Coastguard Worker         { "array", JVMTI_KIND_IN, JVMTI_TYPE_JOBJECT, false },
387*795d594fSAndroid Build Coastguard Worker         { "new_size", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
388*795d594fSAndroid Build Coastguard Worker       },
389*795d594fSAndroid Build Coastguard Worker       {
390*795d594fSAndroid Build Coastguard Worker          ERR(NULL_POINTER),
391*795d594fSAndroid Build Coastguard Worker          ERR(MUST_POSSESS_CAPABILITY),
392*795d594fSAndroid Build Coastguard Worker          ERR(ILLEGAL_ARGUMENT),
393*795d594fSAndroid Build Coastguard Worker          ERR(OUT_OF_MEMORY),
394*795d594fSAndroid Build Coastguard Worker       });
395*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
396*795d594fSAndroid Build Coastguard Worker     return error;
397*795d594fSAndroid Build Coastguard Worker   }
398*795d594fSAndroid Build Coastguard Worker 
399*795d594fSAndroid Build Coastguard Worker   // These require index-ids and debuggable to function
400*795d594fSAndroid Build Coastguard Worker   art::Runtime* runtime = art::Runtime::Current();
401*795d594fSAndroid Build Coastguard Worker   if (runtime->GetJniIdType() == art::JniIdType::kIndices && IsFullJvmtiAvailable()) {
402*795d594fSAndroid Build Coastguard Worker     // IsStructurallyModifiableClass
403*795d594fSAndroid Build Coastguard Worker     error = add_extension(
404*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<jvmtiExtensionFunction>(Redefiner::IsStructurallyModifiableClass),
405*795d594fSAndroid Build Coastguard Worker         "com.android.art.class.is_structurally_modifiable_class",
406*795d594fSAndroid Build Coastguard Worker         "Returns whether a class can potentially be 'structurally' redefined using the various"
407*795d594fSAndroid Build Coastguard Worker         " structural redefinition extensions provided.",
408*795d594fSAndroid Build Coastguard Worker         {
409*795d594fSAndroid Build Coastguard Worker           { "klass", JVMTI_KIND_IN, JVMTI_TYPE_JCLASS, false },
410*795d594fSAndroid Build Coastguard Worker           { "result", JVMTI_KIND_OUT, JVMTI_TYPE_JBOOLEAN, false },
411*795d594fSAndroid Build Coastguard Worker         },
412*795d594fSAndroid Build Coastguard Worker         {
413*795d594fSAndroid Build Coastguard Worker           ERR(INVALID_CLASS),
414*795d594fSAndroid Build Coastguard Worker           ERR(NULL_POINTER),
415*795d594fSAndroid Build Coastguard Worker         });
416*795d594fSAndroid Build Coastguard Worker     if (error != ERR(NONE)) {
417*795d594fSAndroid Build Coastguard Worker       return error;
418*795d594fSAndroid Build Coastguard Worker     }
419*795d594fSAndroid Build Coastguard Worker 
420*795d594fSAndroid Build Coastguard Worker     // StructurallyRedefineClasses
421*795d594fSAndroid Build Coastguard Worker     error = add_extension(
422*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<jvmtiExtensionFunction>(Redefiner::StructurallyRedefineClasses),
423*795d594fSAndroid Build Coastguard Worker         "com.android.art.class.structurally_redefine_classes",
424*795d594fSAndroid Build Coastguard Worker         "Entrypoint for structural class redefinition. Has the same signature as RedefineClasses."
425*795d594fSAndroid Build Coastguard Worker         " Only supports additive changes, methods and fields may not be removed. Supertypes and"
426*795d594fSAndroid Build Coastguard Worker         " implemented interfaces may not be changed. After calling this"
427*795d594fSAndroid Build Coastguard Worker         " com.android.art.structural_dex_file_load_hook events will be triggered, followed by"
428*795d594fSAndroid Build Coastguard Worker         " re-transformable ClassFileLoadHook events. After this method completes subsequent"
429*795d594fSAndroid Build Coastguard Worker         " RetransformClasses calls will use the input to this function as the initial class"
430*795d594fSAndroid Build Coastguard Worker         " definition.",
431*795d594fSAndroid Build Coastguard Worker         {
432*795d594fSAndroid Build Coastguard Worker             { "num_classes", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
433*795d594fSAndroid Build Coastguard Worker             { "class_definitions", JVMTI_KIND_IN_BUF, JVMTI_TYPE_CVOID, false },
434*795d594fSAndroid Build Coastguard Worker         },
435*795d594fSAndroid Build Coastguard Worker         {
436*795d594fSAndroid Build Coastguard Worker             ERR(CLASS_LOADER_UNSUPPORTED),
437*795d594fSAndroid Build Coastguard Worker             ERR(FAILS_VERIFICATION),
438*795d594fSAndroid Build Coastguard Worker             ERR(ILLEGAL_ARGUMENT),
439*795d594fSAndroid Build Coastguard Worker             ERR(INVALID_CLASS),
440*795d594fSAndroid Build Coastguard Worker             ERR(MUST_POSSESS_CAPABILITY),
441*795d594fSAndroid Build Coastguard Worker             ERR(MUST_POSSESS_CAPABILITY),
442*795d594fSAndroid Build Coastguard Worker             ERR(NULL_POINTER),
443*795d594fSAndroid Build Coastguard Worker             ERR(OUT_OF_MEMORY),
444*795d594fSAndroid Build Coastguard Worker             ERR(UNMODIFIABLE_CLASS),
445*795d594fSAndroid Build Coastguard Worker             ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED),
446*795d594fSAndroid Build Coastguard Worker             ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED),
447*795d594fSAndroid Build Coastguard Worker             ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED),
448*795d594fSAndroid Build Coastguard Worker             ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
449*795d594fSAndroid Build Coastguard Worker         });
450*795d594fSAndroid Build Coastguard Worker     if (error != ERR(NONE)) {
451*795d594fSAndroid Build Coastguard Worker       return error;
452*795d594fSAndroid Build Coastguard Worker     }
453*795d594fSAndroid Build Coastguard Worker 
454*795d594fSAndroid Build Coastguard Worker   } else {
455*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "debuggable & jni-type indices are required to implement structural "
456*795d594fSAndroid Build Coastguard Worker               << "class redefinition extensions.";
457*795d594fSAndroid Build Coastguard Worker   }
458*795d594fSAndroid Build Coastguard Worker   // SetVerboseFlagExt
459*795d594fSAndroid Build Coastguard Worker   error = add_extension(
460*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(LogUtil::SetVerboseFlagExt),
461*795d594fSAndroid Build Coastguard Worker       "com.android.art.misc.set_verbose_flag_ext",
462*795d594fSAndroid Build Coastguard Worker       "Sets the verbose flags selected by the 'option' c-string. Valid options are anything that"
463*795d594fSAndroid Build Coastguard Worker       " would be accepted by the -verbose:<option> runtime flag. The verbose selections are turned"
464*795d594fSAndroid Build Coastguard Worker       " on if 'enable' is set to true and disabled otherwise. You may select multiple options at"
465*795d594fSAndroid Build Coastguard Worker       " once using commas just like with the -verbose:<option> flag. For example \"class,deopt,gc\""
466*795d594fSAndroid Build Coastguard Worker       " is equivalent to turning on all of the VLOG(class_linker), VLOG(deopt) and VLOG(gc)"
467*795d594fSAndroid Build Coastguard Worker       " messages.",
468*795d594fSAndroid Build Coastguard Worker       {
469*795d594fSAndroid Build Coastguard Worker         { "option", JVMTI_KIND_IN_BUF, JVMTI_TYPE_CCHAR, false },
470*795d594fSAndroid Build Coastguard Worker         { "enable", JVMTI_KIND_IN, JVMTI_TYPE_JBOOLEAN, false },
471*795d594fSAndroid Build Coastguard Worker       },
472*795d594fSAndroid Build Coastguard Worker       {
473*795d594fSAndroid Build Coastguard Worker          ERR(NULL_POINTER),
474*795d594fSAndroid Build Coastguard Worker          ERR(ILLEGAL_ARGUMENT),
475*795d594fSAndroid Build Coastguard Worker       });
476*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
477*795d594fSAndroid Build Coastguard Worker     return error;
478*795d594fSAndroid Build Coastguard Worker   }
479*795d594fSAndroid Build Coastguard Worker   // GetHiddenApiEnforcementPolicy
480*795d594fSAndroid Build Coastguard Worker   error = add_extension(
481*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(ClassUtil::GetHiddenApiEnforcementPolicy),
482*795d594fSAndroid Build Coastguard Worker       "com.android.art.misc.get_hidden_api_enforcement_policy",
483*795d594fSAndroid Build Coastguard Worker       "Gets the current hiddenapi enforcement policy. Policy values are defined in"
484*795d594fSAndroid Build Coastguard Worker       " `frameworks/base/core/java/android/content/pm/ApplicationInfo.java` as the"
485*795d594fSAndroid Build Coastguard Worker       " HIDDEN_API_ENFORCEMENT_ static fields. See the comments in `art/runtime/hidden_api.h` for"
486*795d594fSAndroid Build Coastguard Worker       " more information. This should be used with"
487*795d594fSAndroid Build Coastguard Worker       " `com.android.art.misc.set_hidden_api_enforcement_policy` in order to restore the"
488*795d594fSAndroid Build Coastguard Worker       " hidden-api state after temporarily toggling it.",
489*795d594fSAndroid Build Coastguard Worker       {
490*795d594fSAndroid Build Coastguard Worker         { "policy", JVMTI_KIND_OUT, JVMTI_TYPE_JINT, false },
491*795d594fSAndroid Build Coastguard Worker       },
492*795d594fSAndroid Build Coastguard Worker       {
493*795d594fSAndroid Build Coastguard Worker          ERR(NULL_POINTER),
494*795d594fSAndroid Build Coastguard Worker       });
495*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
496*795d594fSAndroid Build Coastguard Worker     return error;
497*795d594fSAndroid Build Coastguard Worker   }
498*795d594fSAndroid Build Coastguard Worker   // SetHiddenApiEnforcementPolicy
499*795d594fSAndroid Build Coastguard Worker   error = add_extension(
500*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(ClassUtil::SetHiddenApiEnforcementPolicy),
501*795d594fSAndroid Build Coastguard Worker       "com.android.art.misc.set_hidden_api_enforcement_policy",
502*795d594fSAndroid Build Coastguard Worker       "Sets the hiddenapi enforcement policy to the given value. Policy values are defined in"
503*795d594fSAndroid Build Coastguard Worker       " `frameworks/base/core/java/android/content/pm/ApplicationInfo.java` as the"
504*795d594fSAndroid Build Coastguard Worker       " HIDDEN_API_ENFORCEMENT_ static fields. See the comments in `art/runtime/hidden_api.h` for"
505*795d594fSAndroid Build Coastguard Worker       " more information. This API should always be used sparingly and in conjunction with"
506*795d594fSAndroid Build Coastguard Worker       " `com.android.art.misc.get_hidden_api_enforcement_policy` to temporarily toggle"
507*795d594fSAndroid Build Coastguard Worker       " hidden-api on and off as changes are required.",
508*795d594fSAndroid Build Coastguard Worker       {
509*795d594fSAndroid Build Coastguard Worker         { "policy", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
510*795d594fSAndroid Build Coastguard Worker       },
511*795d594fSAndroid Build Coastguard Worker       {
512*795d594fSAndroid Build Coastguard Worker          ERR(ILLEGAL_ARGUMENT),
513*795d594fSAndroid Build Coastguard Worker       });
514*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
515*795d594fSAndroid Build Coastguard Worker     return error;
516*795d594fSAndroid Build Coastguard Worker   }
517*795d594fSAndroid Build Coastguard Worker   // DisableHiddenApiEnforcementPolicy
518*795d594fSAndroid Build Coastguard Worker   error = add_extension(
519*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<jvmtiExtensionFunction>(ClassUtil::DisableHiddenApiEnforcementPolicy),
520*795d594fSAndroid Build Coastguard Worker       "com.android.art.misc.disable_hidden_api_enforcement_policy",
521*795d594fSAndroid Build Coastguard Worker       "Sets the hiddenapi enforcement policy to disabled. This API should always be"
522*795d594fSAndroid Build Coastguard Worker       " used sparingly and in conjunction with"
523*795d594fSAndroid Build Coastguard Worker       " `com.android.art.misc.get_hidden_api_enforcement_policy` and"
524*795d594fSAndroid Build Coastguard Worker       " `com.android.art.misc.set_hidden_api_enforcement_policy` to temporarily"
525*795d594fSAndroid Build Coastguard Worker       " toggle hidden-api on and off as changes are required.",
526*795d594fSAndroid Build Coastguard Worker       {},
527*795d594fSAndroid Build Coastguard Worker       {});
528*795d594fSAndroid Build Coastguard Worker   if (error != ERR(NONE)) {
529*795d594fSAndroid Build Coastguard Worker     return error;
530*795d594fSAndroid Build Coastguard Worker   }
531*795d594fSAndroid Build Coastguard Worker 
532*795d594fSAndroid Build Coastguard Worker   // Copy into output buffer.
533*795d594fSAndroid Build Coastguard Worker 
534*795d594fSAndroid Build Coastguard Worker   *extension_count_ptr = ext_vector.size();
535*795d594fSAndroid Build Coastguard Worker   JvmtiUniquePtr<jvmtiExtensionFunctionInfo[]> out_data =
536*795d594fSAndroid Build Coastguard Worker       AllocJvmtiUniquePtr<jvmtiExtensionFunctionInfo[]>(env, ext_vector.size(), &error);
537*795d594fSAndroid Build Coastguard Worker   if (out_data == nullptr) {
538*795d594fSAndroid Build Coastguard Worker     return error;
539*795d594fSAndroid Build Coastguard Worker   }
540*795d594fSAndroid Build Coastguard Worker   memcpy(out_data.get(),
541*795d594fSAndroid Build Coastguard Worker           ext_vector.data(),
542*795d594fSAndroid Build Coastguard Worker           ext_vector.size() * sizeof(jvmtiExtensionFunctionInfo));
543*795d594fSAndroid Build Coastguard Worker   *extensions = out_data.release();
544*795d594fSAndroid Build Coastguard Worker 
545*795d594fSAndroid Build Coastguard Worker   // Release all the buffer holders, we're OK now.
546*795d594fSAndroid Build Coastguard Worker   for (auto& holder : char_buffers) {
547*795d594fSAndroid Build Coastguard Worker     holder.release();
548*795d594fSAndroid Build Coastguard Worker   }
549*795d594fSAndroid Build Coastguard Worker   for (auto& holder : param_buffers) {
550*795d594fSAndroid Build Coastguard Worker     holder.release();
551*795d594fSAndroid Build Coastguard Worker   }
552*795d594fSAndroid Build Coastguard Worker   for (auto& holder : error_buffers) {
553*795d594fSAndroid Build Coastguard Worker     holder.release();
554*795d594fSAndroid Build Coastguard Worker   }
555*795d594fSAndroid Build Coastguard Worker 
556*795d594fSAndroid Build Coastguard Worker   return OK;
557*795d594fSAndroid Build Coastguard Worker }
558*795d594fSAndroid Build Coastguard Worker 
559*795d594fSAndroid Build Coastguard Worker 
GetExtensionEvents(jvmtiEnv * env,jint * extension_count_ptr,jvmtiExtensionEventInfo ** extensions)560*795d594fSAndroid Build Coastguard Worker jvmtiError ExtensionUtil::GetExtensionEvents(jvmtiEnv* env,
561*795d594fSAndroid Build Coastguard Worker                                              jint* extension_count_ptr,
562*795d594fSAndroid Build Coastguard Worker                                              jvmtiExtensionEventInfo** extensions) {
563*795d594fSAndroid Build Coastguard Worker   std::vector<jvmtiExtensionEventInfo> ext_vector;
564*795d594fSAndroid Build Coastguard Worker 
565*795d594fSAndroid Build Coastguard Worker   // Holders for allocated values.
566*795d594fSAndroid Build Coastguard Worker   std::vector<JvmtiUniquePtr<char[]>> char_buffers;
567*795d594fSAndroid Build Coastguard Worker   std::vector<JvmtiUniquePtr<jvmtiParamInfo[]>> param_buffers;
568*795d594fSAndroid Build Coastguard Worker 
569*795d594fSAndroid Build Coastguard Worker   auto add_extension = [&](ArtJvmtiEvent extension_event_index,
570*795d594fSAndroid Build Coastguard Worker                            const char* id,
571*795d594fSAndroid Build Coastguard Worker                            const char* short_description,
572*795d594fSAndroid Build Coastguard Worker                            const std::vector<CParamInfo>& params) {
573*795d594fSAndroid Build Coastguard Worker     DCHECK(IsExtensionEvent(extension_event_index)) << static_cast<jint>(extension_event_index);
574*795d594fSAndroid Build Coastguard Worker     jvmtiExtensionEventInfo event_info;
575*795d594fSAndroid Build Coastguard Worker     jvmtiError error;
576*795d594fSAndroid Build Coastguard Worker 
577*795d594fSAndroid Build Coastguard Worker     event_info.extension_event_index = static_cast<jint>(extension_event_index);
578*795d594fSAndroid Build Coastguard Worker 
579*795d594fSAndroid Build Coastguard Worker     JvmtiUniquePtr<char[]> id_ptr = CopyString(env, id, &error);
580*795d594fSAndroid Build Coastguard Worker     if (id_ptr == nullptr) {
581*795d594fSAndroid Build Coastguard Worker       return error;
582*795d594fSAndroid Build Coastguard Worker     }
583*795d594fSAndroid Build Coastguard Worker     event_info.id = id_ptr.get();
584*795d594fSAndroid Build Coastguard Worker     char_buffers.push_back(std::move(id_ptr));
585*795d594fSAndroid Build Coastguard Worker 
586*795d594fSAndroid Build Coastguard Worker     JvmtiUniquePtr<char[]> descr = CopyString(env, short_description, &error);
587*795d594fSAndroid Build Coastguard Worker     if (descr == nullptr) {
588*795d594fSAndroid Build Coastguard Worker       return error;
589*795d594fSAndroid Build Coastguard Worker     }
590*795d594fSAndroid Build Coastguard Worker     event_info.short_description = descr.get();
591*795d594fSAndroid Build Coastguard Worker     char_buffers.push_back(std::move(descr));
592*795d594fSAndroid Build Coastguard Worker 
593*795d594fSAndroid Build Coastguard Worker     event_info.param_count = params.size();
594*795d594fSAndroid Build Coastguard Worker     if (!params.empty()) {
595*795d594fSAndroid Build Coastguard Worker       JvmtiUniquePtr<jvmtiParamInfo[]> params_ptr =
596*795d594fSAndroid Build Coastguard Worker           AllocJvmtiUniquePtr<jvmtiParamInfo[]>(env, params.size(), &error);
597*795d594fSAndroid Build Coastguard Worker       if (params_ptr == nullptr) {
598*795d594fSAndroid Build Coastguard Worker         return error;
599*795d594fSAndroid Build Coastguard Worker       }
600*795d594fSAndroid Build Coastguard Worker       event_info.params = params_ptr.get();
601*795d594fSAndroid Build Coastguard Worker       param_buffers.push_back(std::move(params_ptr));
602*795d594fSAndroid Build Coastguard Worker 
603*795d594fSAndroid Build Coastguard Worker       for (jint i = 0; i != event_info.param_count; ++i) {
604*795d594fSAndroid Build Coastguard Worker         event_info.params[i] = params[i].ToParamInfo(env, &char_buffers, &error);
605*795d594fSAndroid Build Coastguard Worker         if (error != OK) {
606*795d594fSAndroid Build Coastguard Worker           return error;
607*795d594fSAndroid Build Coastguard Worker         }
608*795d594fSAndroid Build Coastguard Worker       }
609*795d594fSAndroid Build Coastguard Worker     } else {
610*795d594fSAndroid Build Coastguard Worker       event_info.params = nullptr;
611*795d594fSAndroid Build Coastguard Worker     }
612*795d594fSAndroid Build Coastguard Worker 
613*795d594fSAndroid Build Coastguard Worker     ext_vector.push_back(event_info);
614*795d594fSAndroid Build Coastguard Worker 
615*795d594fSAndroid Build Coastguard Worker     return ERR(NONE);
616*795d594fSAndroid Build Coastguard Worker   };
617*795d594fSAndroid Build Coastguard Worker 
618*795d594fSAndroid Build Coastguard Worker   jvmtiError error;
619*795d594fSAndroid Build Coastguard Worker   error = add_extension(
620*795d594fSAndroid Build Coastguard Worker       ArtJvmtiEvent::kDdmPublishChunk,
621*795d594fSAndroid Build Coastguard Worker       "com.android.art.internal.ddm.publish_chunk_safe",
622*795d594fSAndroid Build Coastguard Worker       "Called when there is new ddms information that the agent or other clients can use. The"
623*795d594fSAndroid Build Coastguard Worker       " agent is given the 'type' of the ddms chunk and a 'data_size' byte-buffer in 'data'."
624*795d594fSAndroid Build Coastguard Worker       " The 'data' pointer is only valid for the duration of the publish_chunk event. The agent"
625*795d594fSAndroid Build Coastguard Worker       " is responsible for interpreting the information present in the 'data' buffer. This is"
626*795d594fSAndroid Build Coastguard Worker       " provided for backwards-compatibility support only. Agents should prefer to use relevant"
627*795d594fSAndroid Build Coastguard Worker       " JVMTI events and functions above listening for this event. Previous publish_chunk"
628*795d594fSAndroid Build Coastguard Worker       " event was inherently unsafe since using the JNIEnv could cause deadlocks in some scenarios."
629*795d594fSAndroid Build Coastguard Worker       " The current version does not have these issues.",
630*795d594fSAndroid Build Coastguard Worker       {
631*795d594fSAndroid Build Coastguard Worker         { "type", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
632*795d594fSAndroid Build Coastguard Worker         { "data_size", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
633*795d594fSAndroid Build Coastguard Worker         { "data",  JVMTI_KIND_IN_BUF, JVMTI_TYPE_JBYTE, false },
634*795d594fSAndroid Build Coastguard Worker       });
635*795d594fSAndroid Build Coastguard Worker   if (error != OK) {
636*795d594fSAndroid Build Coastguard Worker     return error;
637*795d594fSAndroid Build Coastguard Worker   }
638*795d594fSAndroid Build Coastguard Worker   error = add_extension(
639*795d594fSAndroid Build Coastguard Worker       ArtJvmtiEvent::kObsoleteObjectCreated,
640*795d594fSAndroid Build Coastguard Worker       "com.android.art.heap.obsolete_object_created",
641*795d594fSAndroid Build Coastguard Worker       "Called when an obsolete object is created.\n"
642*795d594fSAndroid Build Coastguard Worker       "An object becomes obsolete when, due to some jvmti function call all references to the"
643*795d594fSAndroid Build Coastguard Worker       " object are replaced with a reference to a different object. After this call finishes there"
644*795d594fSAndroid Build Coastguard Worker       " will be no strong references to the obsolete object anywere. If the object is retrieved"
645*795d594fSAndroid Build Coastguard Worker       " using GetObjectsWithTags its type (class) may have changed and any data it contains may"
646*795d594fSAndroid Build Coastguard Worker       " have been deleted. This is primarily designed to support memory tracking agents which make"
647*795d594fSAndroid Build Coastguard Worker       " use of the ObjectFree and VMObjectAlloc events for tracking. To support this use-case if"
648*795d594fSAndroid Build Coastguard Worker       " this event is not being handled it will by default act as though the following code was"
649*795d594fSAndroid Build Coastguard Worker       " registered as a handler:\n"
650*795d594fSAndroid Build Coastguard Worker       "\n"
651*795d594fSAndroid Build Coastguard Worker       "  void HandleObsoleteObjectCreated(jvmtiEnv* env, jlong* obsolete_tag, jlong* new_tag) {\n"
652*795d594fSAndroid Build Coastguard Worker       "    jlong temp = *obsolete_tag;\n"
653*795d594fSAndroid Build Coastguard Worker       "    *obsolete_tag = *new_tag;\n"
654*795d594fSAndroid Build Coastguard Worker       "    *new_tag = temp;\n"
655*795d594fSAndroid Build Coastguard Worker       "  }\n"
656*795d594fSAndroid Build Coastguard Worker       "\n"
657*795d594fSAndroid Build Coastguard Worker       "Note that this event does not support filtering based on thread. This event has the same"
658*795d594fSAndroid Build Coastguard Worker       " restrictions on JNI and JVMTI function calls as the ObjectFree event.\n"
659*795d594fSAndroid Build Coastguard Worker       "\n"
660*795d594fSAndroid Build Coastguard Worker       "Arguments:\n"
661*795d594fSAndroid Build Coastguard Worker       "  obsolete_tag: Pointer to the tag the old object (now obsolete) has. Setting the pointer"
662*795d594fSAndroid Build Coastguard Worker       " will update the tag value.\n"
663*795d594fSAndroid Build Coastguard Worker       "  new_tag: Pointer to the tag the new object (replacing the obsolete one) has. Setting the"
664*795d594fSAndroid Build Coastguard Worker       " pointer will update the tag value.",
665*795d594fSAndroid Build Coastguard Worker       {
666*795d594fSAndroid Build Coastguard Worker         { "obsolete_tag", JVMTI_KIND_IN_PTR, JVMTI_TYPE_JLONG, false },
667*795d594fSAndroid Build Coastguard Worker         { "new_tag", JVMTI_KIND_IN_PTR, JVMTI_TYPE_JLONG, false },
668*795d594fSAndroid Build Coastguard Worker       });
669*795d594fSAndroid Build Coastguard Worker   if (error != OK) {
670*795d594fSAndroid Build Coastguard Worker     return error;
671*795d594fSAndroid Build Coastguard Worker   }
672*795d594fSAndroid Build Coastguard Worker   art::Runtime* runtime = art::Runtime::Current();
673*795d594fSAndroid Build Coastguard Worker   if (runtime->GetJniIdType() == art::JniIdType::kIndices && IsFullJvmtiAvailable()) {
674*795d594fSAndroid Build Coastguard Worker     error = add_extension(
675*795d594fSAndroid Build Coastguard Worker         ArtJvmtiEvent::kStructuralDexFileLoadHook,
676*795d594fSAndroid Build Coastguard Worker         "com.android.art.class.structural_dex_file_load_hook",
677*795d594fSAndroid Build Coastguard Worker         "Called during class load, after a 'RetransformClasses' call, or after a 'RedefineClasses'"
678*795d594fSAndroid Build Coastguard Worker         " call in order to allow the agent to modify the class. This event is called after any"
679*795d594fSAndroid Build Coastguard Worker         " non-can_retransform_classes ClassFileLoadHookEvents and before any"
680*795d594fSAndroid Build Coastguard Worker         " can_retransform_classes ClassFileLoadHookEvents. The transformations applied are"
681*795d594fSAndroid Build Coastguard Worker         " restricted in the same way that transformations applied via the "
682*795d594fSAndroid Build Coastguard Worker         " 'com.android.art.class.structurally_redefine_classes' extension function. The arguments"
683*795d594fSAndroid Build Coastguard Worker         " to the event are identical to the ones in the ClassFileLoadHook and have the same"
684*795d594fSAndroid Build Coastguard Worker         " semantics.",
685*795d594fSAndroid Build Coastguard Worker         {
686*795d594fSAndroid Build Coastguard Worker           { "jni_env", JVMTI_KIND_IN, JVMTI_TYPE_JNIENV, false },
687*795d594fSAndroid Build Coastguard Worker           { "class_being_redefined", JVMTI_KIND_IN, JVMTI_TYPE_JCLASS, true },
688*795d594fSAndroid Build Coastguard Worker           { "loader", JVMTI_KIND_IN, JVMTI_TYPE_JOBJECT, false },
689*795d594fSAndroid Build Coastguard Worker           { "name", JVMTI_KIND_IN_PTR, JVMTI_TYPE_CCHAR, false },
690*795d594fSAndroid Build Coastguard Worker           { "protection_domain", JVMTI_KIND_IN, JVMTI_TYPE_JOBJECT, true },
691*795d594fSAndroid Build Coastguard Worker           { "dex_data_len", JVMTI_KIND_IN, JVMTI_TYPE_JINT, false },
692*795d594fSAndroid Build Coastguard Worker           { "dex_data", JVMTI_KIND_IN_BUF, JVMTI_TYPE_CCHAR, false },
693*795d594fSAndroid Build Coastguard Worker           { "new_dex_data_len", JVMTI_KIND_OUT, JVMTI_TYPE_JINT, false },
694*795d594fSAndroid Build Coastguard Worker           { "new_dex_data", JVMTI_KIND_ALLOC_BUF, JVMTI_TYPE_CCHAR, true },
695*795d594fSAndroid Build Coastguard Worker         });
696*795d594fSAndroid Build Coastguard Worker   } else {
697*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "debuggable & jni-type indices are required to implement structural "
698*795d594fSAndroid Build Coastguard Worker               << "class redefinition extensions.";
699*795d594fSAndroid Build Coastguard Worker   }
700*795d594fSAndroid Build Coastguard Worker   // Copy into output buffer.
701*795d594fSAndroid Build Coastguard Worker 
702*795d594fSAndroid Build Coastguard Worker   *extension_count_ptr = ext_vector.size();
703*795d594fSAndroid Build Coastguard Worker   JvmtiUniquePtr<jvmtiExtensionEventInfo[]> out_data =
704*795d594fSAndroid Build Coastguard Worker       AllocJvmtiUniquePtr<jvmtiExtensionEventInfo[]>(env, ext_vector.size(), &error);
705*795d594fSAndroid Build Coastguard Worker   if (out_data == nullptr) {
706*795d594fSAndroid Build Coastguard Worker     return error;
707*795d594fSAndroid Build Coastguard Worker   }
708*795d594fSAndroid Build Coastguard Worker   memcpy(out_data.get(),
709*795d594fSAndroid Build Coastguard Worker          ext_vector.data(),
710*795d594fSAndroid Build Coastguard Worker          ext_vector.size() * sizeof(jvmtiExtensionEventInfo));
711*795d594fSAndroid Build Coastguard Worker   *extensions = out_data.release();
712*795d594fSAndroid Build Coastguard Worker 
713*795d594fSAndroid Build Coastguard Worker   // Release all the buffer holders, we're OK now.
714*795d594fSAndroid Build Coastguard Worker   for (auto& holder : char_buffers) {
715*795d594fSAndroid Build Coastguard Worker     holder.release();
716*795d594fSAndroid Build Coastguard Worker   }
717*795d594fSAndroid Build Coastguard Worker   for (auto& holder : param_buffers) {
718*795d594fSAndroid Build Coastguard Worker     holder.release();
719*795d594fSAndroid Build Coastguard Worker   }
720*795d594fSAndroid Build Coastguard Worker 
721*795d594fSAndroid Build Coastguard Worker   return OK;
722*795d594fSAndroid Build Coastguard Worker }
723*795d594fSAndroid Build Coastguard Worker 
SetExtensionEventCallback(jvmtiEnv * env,jint extension_event_index,jvmtiExtensionEvent callback,EventHandler * event_handler)724*795d594fSAndroid Build Coastguard Worker jvmtiError ExtensionUtil::SetExtensionEventCallback(jvmtiEnv* env,
725*795d594fSAndroid Build Coastguard Worker                                                     jint extension_event_index,
726*795d594fSAndroid Build Coastguard Worker                                                     jvmtiExtensionEvent callback,
727*795d594fSAndroid Build Coastguard Worker                                                     EventHandler* event_handler) {
728*795d594fSAndroid Build Coastguard Worker   if (!IsExtensionEvent(extension_event_index)) {
729*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
730*795d594fSAndroid Build Coastguard Worker   }
731*795d594fSAndroid Build Coastguard Worker   ArtJvmTiEnv* art_env = ArtJvmTiEnv::AsArtJvmTiEnv(env);
732*795d594fSAndroid Build Coastguard Worker   jvmtiEventMode mode = callback == nullptr ? JVMTI_DISABLE : JVMTI_ENABLE;
733*795d594fSAndroid Build Coastguard Worker   // Lock the event_info_mutex_ while we set the event to make sure it isn't lost by a concurrent
734*795d594fSAndroid Build Coastguard Worker   // change to the normal callbacks.
735*795d594fSAndroid Build Coastguard Worker   {
736*795d594fSAndroid Build Coastguard Worker     art::WriterMutexLock lk(art::Thread::Current(), art_env->event_info_mutex_);
737*795d594fSAndroid Build Coastguard Worker     if (art_env->event_callbacks.get() == nullptr) {
738*795d594fSAndroid Build Coastguard Worker       art_env->event_callbacks.reset(new ArtJvmtiEventCallbacks());
739*795d594fSAndroid Build Coastguard Worker     }
740*795d594fSAndroid Build Coastguard Worker     jvmtiError err = art_env->event_callbacks->Set(extension_event_index, callback);
741*795d594fSAndroid Build Coastguard Worker     if (err != OK) {
742*795d594fSAndroid Build Coastguard Worker       return err;
743*795d594fSAndroid Build Coastguard Worker     }
744*795d594fSAndroid Build Coastguard Worker   }
745*795d594fSAndroid Build Coastguard Worker   return event_handler->SetEvent(art_env,
746*795d594fSAndroid Build Coastguard Worker                                  /*thread=*/nullptr,
747*795d594fSAndroid Build Coastguard Worker                                  static_cast<ArtJvmtiEvent>(extension_event_index),
748*795d594fSAndroid Build Coastguard Worker                                  mode);
749*795d594fSAndroid Build Coastguard Worker }
750*795d594fSAndroid Build Coastguard Worker 
751*795d594fSAndroid Build Coastguard Worker }  // namespace openjdkjvmti
752