xref: /aosp_15_r20/art/tools/jvmti-agents/ti-fast/tifast.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker // Copyright (C) 2018 The Android Open Source Project
2*795d594fSAndroid Build Coastguard Worker //
3*795d594fSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*795d594fSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*795d594fSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*795d594fSAndroid Build Coastguard Worker //
7*795d594fSAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
8*795d594fSAndroid Build Coastguard Worker //
9*795d594fSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*795d594fSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*795d594fSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*795d594fSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*795d594fSAndroid Build Coastguard Worker // limitations under the License.
14*795d594fSAndroid Build Coastguard Worker //
15*795d594fSAndroid Build Coastguard Worker 
16*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
17*795d594fSAndroid Build Coastguard Worker 
18*795d594fSAndroid Build Coastguard Worker #include <atomic>
19*795d594fSAndroid Build Coastguard Worker #include <iostream>
20*795d594fSAndroid Build Coastguard Worker #include <istream>
21*795d594fSAndroid Build Coastguard Worker #include <iomanip>
22*795d594fSAndroid Build Coastguard Worker #include <jni.h>
23*795d594fSAndroid Build Coastguard Worker #include <jvmti.h>
24*795d594fSAndroid Build Coastguard Worker #include <limits>
25*795d594fSAndroid Build Coastguard Worker #include <memory>
26*795d594fSAndroid Build Coastguard Worker #include <string>
27*795d594fSAndroid Build Coastguard Worker #include <sstream>
28*795d594fSAndroid Build Coastguard Worker #include <vector>
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker namespace tifast {
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker #define EVENT(x) JVMTI_EVENT_ ## x
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker namespace {
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker // Special art ti-version number. We will use this as a fallback if we cannot get a regular JVMTI
37*795d594fSAndroid Build Coastguard Worker // env.
38*795d594fSAndroid Build Coastguard Worker static constexpr jint kArtTiVersion = JVMTI_VERSION_1_2 | 0x40000000;
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker template <typename... Args>
Unused(Args...args)41*795d594fSAndroid Build Coastguard Worker static void Unused([[maybe_unused]] Args... args) {}
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker // jthread is a typedef of jobject so we use this to allow the templates to distinguish them.
44*795d594fSAndroid Build Coastguard Worker struct jthreadContainer { jthread thread; };
45*795d594fSAndroid Build Coastguard Worker // jlocation is a typedef of jlong so use this to distinguish the less common jlong.
46*795d594fSAndroid Build Coastguard Worker struct jlongContainer { jlong val; };
47*795d594fSAndroid Build Coastguard Worker 
AddCapsForEvent(jvmtiEvent event,jvmtiCapabilities * caps)48*795d594fSAndroid Build Coastguard Worker static void AddCapsForEvent(jvmtiEvent event, jvmtiCapabilities* caps) {
49*795d594fSAndroid Build Coastguard Worker   switch (event) {
50*795d594fSAndroid Build Coastguard Worker #define DO_CASE(name, cap_name) \
51*795d594fSAndroid Build Coastguard Worker     case EVENT(name):           \
52*795d594fSAndroid Build Coastguard Worker       caps->cap_name = 1;       \
53*795d594fSAndroid Build Coastguard Worker       break
54*795d594fSAndroid Build Coastguard Worker     DO_CASE(SINGLE_STEP, can_generate_single_step_events);
55*795d594fSAndroid Build Coastguard Worker     DO_CASE(METHOD_ENTRY, can_generate_method_entry_events);
56*795d594fSAndroid Build Coastguard Worker     DO_CASE(METHOD_EXIT, can_generate_method_exit_events);
57*795d594fSAndroid Build Coastguard Worker     DO_CASE(NATIVE_METHOD_BIND, can_generate_native_method_bind_events);
58*795d594fSAndroid Build Coastguard Worker     DO_CASE(EXCEPTION, can_generate_exception_events);
59*795d594fSAndroid Build Coastguard Worker     DO_CASE(EXCEPTION_CATCH, can_generate_exception_events);
60*795d594fSAndroid Build Coastguard Worker     DO_CASE(COMPILED_METHOD_LOAD, can_generate_compiled_method_load_events);
61*795d594fSAndroid Build Coastguard Worker     DO_CASE(COMPILED_METHOD_UNLOAD, can_generate_compiled_method_load_events);
62*795d594fSAndroid Build Coastguard Worker     DO_CASE(MONITOR_CONTENDED_ENTER, can_generate_monitor_events);
63*795d594fSAndroid Build Coastguard Worker     DO_CASE(MONITOR_CONTENDED_ENTERED, can_generate_monitor_events);
64*795d594fSAndroid Build Coastguard Worker     DO_CASE(MONITOR_WAIT, can_generate_monitor_events);
65*795d594fSAndroid Build Coastguard Worker     DO_CASE(MONITOR_WAITED, can_generate_monitor_events);
66*795d594fSAndroid Build Coastguard Worker     DO_CASE(VM_OBJECT_ALLOC, can_generate_vm_object_alloc_events);
67*795d594fSAndroid Build Coastguard Worker     DO_CASE(GARBAGE_COLLECTION_START, can_generate_garbage_collection_events);
68*795d594fSAndroid Build Coastguard Worker     DO_CASE(GARBAGE_COLLECTION_FINISH, can_generate_garbage_collection_events);
69*795d594fSAndroid Build Coastguard Worker #undef DO_CASE
70*795d594fSAndroid Build Coastguard Worker     default: break;
71*795d594fSAndroid Build Coastguard Worker   }
72*795d594fSAndroid Build Coastguard Worker }
73*795d594fSAndroid Build Coastguard Worker 
74*795d594fSAndroid Build Coastguard Worker // Setup for all supported events. Give a macro with {non_}jni_fun(name, event_num, args)
75*795d594fSAndroid Build Coastguard Worker #define FOR_ALL_SUPPORTED_EVENTS_DIFFERENT(jni_fun, non_jni_fun)          \
76*795d594fSAndroid Build Coastguard Worker     jni_fun(VMInit, EVENT(VM_INIT), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread), (jvmti, jni, jthreadContainer{.thread = thread})) \
77*795d594fSAndroid Build Coastguard Worker     jni_fun(VMDeath, EVENT(VM_DEATH), (jvmtiEnv* jvmti, JNIEnv* jni), (jvmti, jni)) \
78*795d594fSAndroid Build Coastguard Worker     jni_fun(ThreadStart, EVENT(THREAD_START), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread), (jvmti, jni, jthreadContainer{.thread = thread})) \
79*795d594fSAndroid Build Coastguard Worker     jni_fun(ThreadEnd, EVENT(THREAD_END), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread), (jvmti, jni, jthreadContainer{.thread = thread})) \
80*795d594fSAndroid Build Coastguard Worker     jni_fun(ClassFileLoadHook, EVENT(CLASS_FILE_LOAD_HOOK), (jvmtiEnv* jvmti, JNIEnv* jni, jclass klass, jobject obj1, const char* c1, jobject obj2, jint i1, const unsigned char* c2, jint* ip1, unsigned char** cp1), (jvmti, jni, klass, obj1, c1, obj2, i1, c2, ip1, cp1)) \
81*795d594fSAndroid Build Coastguard Worker     jni_fun(ClassLoad, EVENT(CLASS_LOAD), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jclass klass), (jvmti, jni, jthreadContainer{.thread = thread}, klass) ) \
82*795d594fSAndroid Build Coastguard Worker     jni_fun(ClassPrepare, EVENT(CLASS_PREPARE), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jclass klass), (jvmti, jni, jthreadContainer{.thread = thread}, klass)) \
83*795d594fSAndroid Build Coastguard Worker     jni_fun(VMStart, EVENT(VM_START), (jvmtiEnv* jvmti, JNIEnv* jni), (jvmti, jni)) \
84*795d594fSAndroid Build Coastguard Worker     jni_fun(Exception, EVENT(EXCEPTION), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jmethodID meth1, jlocation loc1, jobject obj, jmethodID meth2, jlocation loc2), (jvmti, jni, jthreadContainer{.thread = thread}, meth1, loc1, obj, meth2, loc2)) \
85*795d594fSAndroid Build Coastguard Worker     jni_fun(ExceptionCatch, EVENT(EXCEPTION_CATCH), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jmethodID meth, jlocation loc, jobject obj), (jvmti, jni, jthreadContainer{.thread = thread}, meth, loc, obj)) \
86*795d594fSAndroid Build Coastguard Worker     jni_fun(SingleStep, EVENT(SINGLE_STEP), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jmethodID meth, jlocation loc), (jvmti, jni, jthreadContainer{.thread = thread}, meth, loc)) \
87*795d594fSAndroid Build Coastguard Worker     jni_fun(MethodEntry, EVENT(METHOD_ENTRY), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jmethodID meth), (jvmti, jni, jthreadContainer{.thread = thread}, meth)) \
88*795d594fSAndroid Build Coastguard Worker     jni_fun(MethodExit, EVENT(METHOD_EXIT), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jmethodID meth, jboolean jb, jvalue jv), (jvmti, jni, jthreadContainer{.thread = thread}, meth, jb, jv)) \
89*795d594fSAndroid Build Coastguard Worker     jni_fun(NativeMethodBind, EVENT(NATIVE_METHOD_BIND), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jmethodID meth, void* v1, void** v2), (jvmti, jni, jthreadContainer{.thread = thread}, meth, v1, v2)) \
90*795d594fSAndroid Build Coastguard Worker     non_jni_fun(CompiledMethodLoad, EVENT(COMPILED_METHOD_LOAD), (jvmtiEnv* jvmti, jmethodID meth, jint i1, const void* cv1, jint i2, const jvmtiAddrLocationMap* alm, const void* cv2), (jvmti, meth, i1, cv1, i2, alm, cv2)) \
91*795d594fSAndroid Build Coastguard Worker     non_jni_fun(CompiledMethodUnload, EVENT(COMPILED_METHOD_UNLOAD), (jvmtiEnv* jvmti, jmethodID meth, const void* cv1), (jvmti, meth, cv1)) \
92*795d594fSAndroid Build Coastguard Worker     non_jni_fun(DynamicCodeGenerated, EVENT(DYNAMIC_CODE_GENERATED), (jvmtiEnv* jvmti, const char* cc, const void* cv, jint i1), (jvmti, cc, cv, i1)) \
93*795d594fSAndroid Build Coastguard Worker     non_jni_fun(DataDumpRequest, EVENT(DATA_DUMP_REQUEST), (jvmtiEnv* jvmti), (jvmti)) \
94*795d594fSAndroid Build Coastguard Worker     jni_fun(MonitorWait, EVENT(MONITOR_WAIT), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jobject obj, jlong l1), (jvmti, jni, jthreadContainer{.thread = thread}, obj, jlongContainer{.val = l1})) \
95*795d594fSAndroid Build Coastguard Worker     jni_fun(MonitorWaited, EVENT(MONITOR_WAITED), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jobject obj, jboolean b1), (jvmti, jni, jthreadContainer{.thread = thread}, obj, b1)) \
96*795d594fSAndroid Build Coastguard Worker     jni_fun(MonitorContendedEnter, EVENT(MONITOR_CONTENDED_ENTER), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jobject obj), (jvmti, jni, jthreadContainer{.thread = thread}, obj)) \
97*795d594fSAndroid Build Coastguard Worker     jni_fun(MonitorContendedEntered, EVENT(MONITOR_CONTENDED_ENTERED), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jobject obj), (jvmti, jni, jthreadContainer{.thread = thread}, obj)) \
98*795d594fSAndroid Build Coastguard Worker     jni_fun(ResourceExhausted, EVENT(RESOURCE_EXHAUSTED), (jvmtiEnv* jvmti, JNIEnv* jni, jint i1, const void* cv, const char* cc), (jvmti, jni, i1, cv, cc)) \
99*795d594fSAndroid Build Coastguard Worker     non_jni_fun(GarbageCollectionStart, EVENT(GARBAGE_COLLECTION_START), (jvmtiEnv* jvmti), (jvmti)) \
100*795d594fSAndroid Build Coastguard Worker     non_jni_fun(GarbageCollectionFinish, EVENT(GARBAGE_COLLECTION_FINISH), (jvmtiEnv* jvmti), (jvmti)) \
101*795d594fSAndroid Build Coastguard Worker     jni_fun(VMObjectAlloc, EVENT(VM_OBJECT_ALLOC), (jvmtiEnv* jvmti, JNIEnv* jni, jthread thread, jobject obj, jclass klass, jlong l1), (jvmti, jni, jthreadContainer{.thread = thread}, obj, klass, jlongContainer{.val = l1})) \
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker #define FOR_ALL_SUPPORTED_EVENTS(fun) \
104*795d594fSAndroid Build Coastguard Worker     FOR_ALL_SUPPORTED_EVENTS_DIFFERENT(fun, fun)
105*795d594fSAndroid Build Coastguard Worker 
106*795d594fSAndroid Build Coastguard Worker static const jvmtiEvent kAllEvents[] = {
107*795d594fSAndroid Build Coastguard Worker #define GET_EVENT(a, event, b, c) event,
108*795d594fSAndroid Build Coastguard Worker FOR_ALL_SUPPORTED_EVENTS(GET_EVENT)
109*795d594fSAndroid Build Coastguard Worker #undef GET_EVENT
110*795d594fSAndroid Build Coastguard Worker };
111*795d594fSAndroid Build Coastguard Worker 
112*795d594fSAndroid Build Coastguard Worker #define GENERATE_EMPTY_FUNCTION(name, number, args, argnames) \
113*795d594fSAndroid Build Coastguard Worker     static void JNICALL empty ## name  args { Unused argnames ; }
FOR_ALL_SUPPORTED_EVENTS(GENERATE_EMPTY_FUNCTION)114*795d594fSAndroid Build Coastguard Worker FOR_ALL_SUPPORTED_EVENTS(GENERATE_EMPTY_FUNCTION)
115*795d594fSAndroid Build Coastguard Worker #undef GENERATE_EMPTY_FUNCTION
116*795d594fSAndroid Build Coastguard Worker 
117*795d594fSAndroid Build Coastguard Worker static jvmtiEventCallbacks kEmptyCallbacks {
118*795d594fSAndroid Build Coastguard Worker #define CREATE_EMPTY_EVENT_CALLBACKS(name, num, args, argnames) \
119*795d594fSAndroid Build Coastguard Worker     .name = empty ## name,
120*795d594fSAndroid Build Coastguard Worker   FOR_ALL_SUPPORTED_EVENTS(CREATE_EMPTY_EVENT_CALLBACKS)
121*795d594fSAndroid Build Coastguard Worker #undef CREATE_EMPTY_EVENT_CALLBACKS
122*795d594fSAndroid Build Coastguard Worker };
123*795d594fSAndroid Build Coastguard Worker 
DeleteLocalRef(JNIEnv * env,jobject obj)124*795d594fSAndroid Build Coastguard Worker static void DeleteLocalRef(JNIEnv* env, jobject obj) {
125*795d594fSAndroid Build Coastguard Worker   if (obj != nullptr && env != nullptr) {
126*795d594fSAndroid Build Coastguard Worker     env->DeleteLocalRef(obj);
127*795d594fSAndroid Build Coastguard Worker   }
128*795d594fSAndroid Build Coastguard Worker }
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker class ScopedThreadInfo {
131*795d594fSAndroid Build Coastguard Worker  public:
ScopedThreadInfo(jvmtiEnv * jvmtienv,JNIEnv * env,jthread thread)132*795d594fSAndroid Build Coastguard Worker   ScopedThreadInfo(jvmtiEnv* jvmtienv, JNIEnv* env, jthread thread)
133*795d594fSAndroid Build Coastguard Worker       : jvmtienv_(jvmtienv), env_(env), free_name_(false) {
134*795d594fSAndroid Build Coastguard Worker     if (thread == nullptr) {
135*795d594fSAndroid Build Coastguard Worker       info_.name = const_cast<char*>("<NULLPTR>");
136*795d594fSAndroid Build Coastguard Worker     } else if (jvmtienv->GetThreadInfo(thread, &info_) != JVMTI_ERROR_NONE) {
137*795d594fSAndroid Build Coastguard Worker       info_.name = const_cast<char*>("<UNKNOWN THREAD>");
138*795d594fSAndroid Build Coastguard Worker     } else {
139*795d594fSAndroid Build Coastguard Worker       free_name_ = true;
140*795d594fSAndroid Build Coastguard Worker     }
141*795d594fSAndroid Build Coastguard Worker   }
142*795d594fSAndroid Build Coastguard Worker 
~ScopedThreadInfo()143*795d594fSAndroid Build Coastguard Worker   ~ScopedThreadInfo() {
144*795d594fSAndroid Build Coastguard Worker     if (free_name_) {
145*795d594fSAndroid Build Coastguard Worker       jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(info_.name));
146*795d594fSAndroid Build Coastguard Worker     }
147*795d594fSAndroid Build Coastguard Worker     DeleteLocalRef(env_, info_.thread_group);
148*795d594fSAndroid Build Coastguard Worker     DeleteLocalRef(env_, info_.context_class_loader);
149*795d594fSAndroid Build Coastguard Worker   }
150*795d594fSAndroid Build Coastguard Worker 
GetName() const151*795d594fSAndroid Build Coastguard Worker   const char* GetName() const {
152*795d594fSAndroid Build Coastguard Worker     return info_.name;
153*795d594fSAndroid Build Coastguard Worker   }
154*795d594fSAndroid Build Coastguard Worker 
155*795d594fSAndroid Build Coastguard Worker  private:
156*795d594fSAndroid Build Coastguard Worker   jvmtiEnv* jvmtienv_;
157*795d594fSAndroid Build Coastguard Worker   JNIEnv* env_;
158*795d594fSAndroid Build Coastguard Worker   bool free_name_;
159*795d594fSAndroid Build Coastguard Worker   jvmtiThreadInfo info_{};
160*795d594fSAndroid Build Coastguard Worker };
161*795d594fSAndroid Build Coastguard Worker 
162*795d594fSAndroid Build Coastguard Worker class ScopedClassInfo {
163*795d594fSAndroid Build Coastguard Worker  public:
ScopedClassInfo(jvmtiEnv * jvmtienv,jclass c)164*795d594fSAndroid Build Coastguard Worker   ScopedClassInfo(jvmtiEnv* jvmtienv, jclass c) : jvmtienv_(jvmtienv), class_(c) {}
165*795d594fSAndroid Build Coastguard Worker 
~ScopedClassInfo()166*795d594fSAndroid Build Coastguard Worker   ~ScopedClassInfo() {
167*795d594fSAndroid Build Coastguard Worker     if (class_ != nullptr) {
168*795d594fSAndroid Build Coastguard Worker       jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(name_));
169*795d594fSAndroid Build Coastguard Worker       jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(generic_));
170*795d594fSAndroid Build Coastguard Worker       jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(file_));
171*795d594fSAndroid Build Coastguard Worker       jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(debug_ext_));
172*795d594fSAndroid Build Coastguard Worker     }
173*795d594fSAndroid Build Coastguard Worker   }
174*795d594fSAndroid Build Coastguard Worker 
Init(bool get_generic=true)175*795d594fSAndroid Build Coastguard Worker   bool Init(bool get_generic = true) {
176*795d594fSAndroid Build Coastguard Worker     if (class_ == nullptr) {
177*795d594fSAndroid Build Coastguard Worker       name_ = const_cast<char*>("<NONE>");
178*795d594fSAndroid Build Coastguard Worker       generic_ = const_cast<char*>("<NONE>");
179*795d594fSAndroid Build Coastguard Worker       return true;
180*795d594fSAndroid Build Coastguard Worker     } else {
181*795d594fSAndroid Build Coastguard Worker       jvmtiError ret1 = jvmtienv_->GetSourceFileName(class_, &file_);
182*795d594fSAndroid Build Coastguard Worker       jvmtiError ret2 = jvmtienv_->GetSourceDebugExtension(class_, &debug_ext_);
183*795d594fSAndroid Build Coastguard Worker       char** gen_ptr = &generic_;
184*795d594fSAndroid Build Coastguard Worker       if (!get_generic) {
185*795d594fSAndroid Build Coastguard Worker         generic_ = nullptr;
186*795d594fSAndroid Build Coastguard Worker         gen_ptr = nullptr;
187*795d594fSAndroid Build Coastguard Worker       }
188*795d594fSAndroid Build Coastguard Worker       return jvmtienv_->GetClassSignature(class_, &name_, gen_ptr) == JVMTI_ERROR_NONE &&
189*795d594fSAndroid Build Coastguard Worker           ret1 != JVMTI_ERROR_MUST_POSSESS_CAPABILITY &&
190*795d594fSAndroid Build Coastguard Worker           ret1 != JVMTI_ERROR_INVALID_CLASS &&
191*795d594fSAndroid Build Coastguard Worker           ret2 != JVMTI_ERROR_MUST_POSSESS_CAPABILITY &&
192*795d594fSAndroid Build Coastguard Worker           ret2 != JVMTI_ERROR_INVALID_CLASS;
193*795d594fSAndroid Build Coastguard Worker     }
194*795d594fSAndroid Build Coastguard Worker   }
195*795d594fSAndroid Build Coastguard Worker 
GetClass() const196*795d594fSAndroid Build Coastguard Worker   jclass GetClass() const {
197*795d594fSAndroid Build Coastguard Worker     return class_;
198*795d594fSAndroid Build Coastguard Worker   }
199*795d594fSAndroid Build Coastguard Worker 
GetName() const200*795d594fSAndroid Build Coastguard Worker   const char* GetName() const {
201*795d594fSAndroid Build Coastguard Worker     return name_;
202*795d594fSAndroid Build Coastguard Worker   }
203*795d594fSAndroid Build Coastguard Worker 
GetGeneric() const204*795d594fSAndroid Build Coastguard Worker   const char* GetGeneric() const {
205*795d594fSAndroid Build Coastguard Worker     return generic_;
206*795d594fSAndroid Build Coastguard Worker   }
207*795d594fSAndroid Build Coastguard Worker 
GetSourceDebugExtension() const208*795d594fSAndroid Build Coastguard Worker   const char* GetSourceDebugExtension() const {
209*795d594fSAndroid Build Coastguard Worker     if (debug_ext_ == nullptr) {
210*795d594fSAndroid Build Coastguard Worker       return "<UNKNOWN_SOURCE_DEBUG_EXTENSION>";
211*795d594fSAndroid Build Coastguard Worker     } else {
212*795d594fSAndroid Build Coastguard Worker       return debug_ext_;
213*795d594fSAndroid Build Coastguard Worker     }
214*795d594fSAndroid Build Coastguard Worker   }
GetSourceFileName() const215*795d594fSAndroid Build Coastguard Worker   const char* GetSourceFileName() const {
216*795d594fSAndroid Build Coastguard Worker     if (file_ == nullptr) {
217*795d594fSAndroid Build Coastguard Worker       return "<UNKNOWN_FILE>";
218*795d594fSAndroid Build Coastguard Worker     } else {
219*795d594fSAndroid Build Coastguard Worker       return file_;
220*795d594fSAndroid Build Coastguard Worker     }
221*795d594fSAndroid Build Coastguard Worker   }
222*795d594fSAndroid Build Coastguard Worker 
223*795d594fSAndroid Build Coastguard Worker  private:
224*795d594fSAndroid Build Coastguard Worker   jvmtiEnv* jvmtienv_;
225*795d594fSAndroid Build Coastguard Worker   jclass class_;
226*795d594fSAndroid Build Coastguard Worker   char* name_ = nullptr;
227*795d594fSAndroid Build Coastguard Worker   char* generic_ = nullptr;
228*795d594fSAndroid Build Coastguard Worker   char* file_ = nullptr;
229*795d594fSAndroid Build Coastguard Worker   char* debug_ext_ = nullptr;
230*795d594fSAndroid Build Coastguard Worker 
231*795d594fSAndroid Build Coastguard Worker   friend std::ostream& operator<<(std::ostream &os, ScopedClassInfo const& m);
232*795d594fSAndroid Build Coastguard Worker };
233*795d594fSAndroid Build Coastguard Worker 
234*795d594fSAndroid Build Coastguard Worker class ScopedMethodInfo {
235*795d594fSAndroid Build Coastguard Worker  public:
ScopedMethodInfo(jvmtiEnv * jvmtienv,JNIEnv * env,jmethodID m)236*795d594fSAndroid Build Coastguard Worker   ScopedMethodInfo(jvmtiEnv* jvmtienv, JNIEnv* env, jmethodID m)
237*795d594fSAndroid Build Coastguard Worker       : jvmtienv_(jvmtienv), env_(env), method_(m) {}
238*795d594fSAndroid Build Coastguard Worker 
~ScopedMethodInfo()239*795d594fSAndroid Build Coastguard Worker   ~ScopedMethodInfo() {
240*795d594fSAndroid Build Coastguard Worker     DeleteLocalRef(env_, declaring_class_);
241*795d594fSAndroid Build Coastguard Worker     jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(name_));
242*795d594fSAndroid Build Coastguard Worker     jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(signature_));
243*795d594fSAndroid Build Coastguard Worker     jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(generic_));
244*795d594fSAndroid Build Coastguard Worker   }
245*795d594fSAndroid Build Coastguard Worker 
Init(bool get_generic=true)246*795d594fSAndroid Build Coastguard Worker   bool Init(bool get_generic = true) {
247*795d594fSAndroid Build Coastguard Worker     if (jvmtienv_->GetMethodDeclaringClass(method_, &declaring_class_) != JVMTI_ERROR_NONE) {
248*795d594fSAndroid Build Coastguard Worker       return false;
249*795d594fSAndroid Build Coastguard Worker     }
250*795d594fSAndroid Build Coastguard Worker     class_info_.reset(new ScopedClassInfo(jvmtienv_, declaring_class_));
251*795d594fSAndroid Build Coastguard Worker     jint nlines;
252*795d594fSAndroid Build Coastguard Worker     jvmtiLineNumberEntry* lines;
253*795d594fSAndroid Build Coastguard Worker     jvmtiError err = jvmtienv_->GetLineNumberTable(method_, &nlines, &lines);
254*795d594fSAndroid Build Coastguard Worker     if (err == JVMTI_ERROR_NONE) {
255*795d594fSAndroid Build Coastguard Worker       if (nlines > 0) {
256*795d594fSAndroid Build Coastguard Worker         first_line_ = lines[0].line_number;
257*795d594fSAndroid Build Coastguard Worker       }
258*795d594fSAndroid Build Coastguard Worker       jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(lines));
259*795d594fSAndroid Build Coastguard Worker     } else if (err != JVMTI_ERROR_ABSENT_INFORMATION &&
260*795d594fSAndroid Build Coastguard Worker                err != JVMTI_ERROR_NATIVE_METHOD) {
261*795d594fSAndroid Build Coastguard Worker       return false;
262*795d594fSAndroid Build Coastguard Worker     }
263*795d594fSAndroid Build Coastguard Worker     return class_info_->Init(get_generic) &&
264*795d594fSAndroid Build Coastguard Worker         (jvmtienv_->GetMethodName(method_, &name_, &signature_, &generic_) == JVMTI_ERROR_NONE);
265*795d594fSAndroid Build Coastguard Worker   }
266*795d594fSAndroid Build Coastguard Worker 
GetDeclaringClassInfo() const267*795d594fSAndroid Build Coastguard Worker   const ScopedClassInfo& GetDeclaringClassInfo() const {
268*795d594fSAndroid Build Coastguard Worker     return *class_info_;
269*795d594fSAndroid Build Coastguard Worker   }
270*795d594fSAndroid Build Coastguard Worker 
GetDeclaringClass() const271*795d594fSAndroid Build Coastguard Worker   jclass GetDeclaringClass() const {
272*795d594fSAndroid Build Coastguard Worker     return declaring_class_;
273*795d594fSAndroid Build Coastguard Worker   }
274*795d594fSAndroid Build Coastguard Worker 
GetName() const275*795d594fSAndroid Build Coastguard Worker   const char* GetName() const {
276*795d594fSAndroid Build Coastguard Worker     return name_;
277*795d594fSAndroid Build Coastguard Worker   }
278*795d594fSAndroid Build Coastguard Worker 
GetSignature() const279*795d594fSAndroid Build Coastguard Worker   const char* GetSignature() const {
280*795d594fSAndroid Build Coastguard Worker     return signature_;
281*795d594fSAndroid Build Coastguard Worker   }
282*795d594fSAndroid Build Coastguard Worker 
GetGeneric() const283*795d594fSAndroid Build Coastguard Worker   const char* GetGeneric() const {
284*795d594fSAndroid Build Coastguard Worker     return generic_;
285*795d594fSAndroid Build Coastguard Worker   }
286*795d594fSAndroid Build Coastguard Worker 
GetFirstLine() const287*795d594fSAndroid Build Coastguard Worker   jint GetFirstLine() const {
288*795d594fSAndroid Build Coastguard Worker     return first_line_;
289*795d594fSAndroid Build Coastguard Worker   }
290*795d594fSAndroid Build Coastguard Worker 
291*795d594fSAndroid Build Coastguard Worker  private:
292*795d594fSAndroid Build Coastguard Worker   jvmtiEnv* jvmtienv_;
293*795d594fSAndroid Build Coastguard Worker   JNIEnv* env_;
294*795d594fSAndroid Build Coastguard Worker   jmethodID method_;
295*795d594fSAndroid Build Coastguard Worker   jclass declaring_class_ = nullptr;
296*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ScopedClassInfo> class_info_;
297*795d594fSAndroid Build Coastguard Worker   char* name_ = nullptr;
298*795d594fSAndroid Build Coastguard Worker   char* signature_ = nullptr;
299*795d594fSAndroid Build Coastguard Worker   char* generic_ = nullptr;
300*795d594fSAndroid Build Coastguard Worker   jint first_line_ = -1;
301*795d594fSAndroid Build Coastguard Worker 
302*795d594fSAndroid Build Coastguard Worker   friend std::ostream& operator<<(std::ostream &os, ScopedMethodInfo const& m);
303*795d594fSAndroid Build Coastguard Worker };
304*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,ScopedClassInfo const & c)305*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream &os, ScopedClassInfo const& c) {
306*795d594fSAndroid Build Coastguard Worker   const char* generic = c.GetGeneric();
307*795d594fSAndroid Build Coastguard Worker   if (generic != nullptr) {
308*795d594fSAndroid Build Coastguard Worker     return os << c.GetName() << "<" << generic << ">" << " file: " << c.GetSourceFileName();
309*795d594fSAndroid Build Coastguard Worker   } else {
310*795d594fSAndroid Build Coastguard Worker     return os << c.GetName() << " file: " << c.GetSourceFileName();
311*795d594fSAndroid Build Coastguard Worker   }
312*795d594fSAndroid Build Coastguard Worker }
313*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,ScopedMethodInfo const & m)314*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream &os, ScopedMethodInfo const& m) {
315*795d594fSAndroid Build Coastguard Worker   return os << m.GetDeclaringClassInfo().GetName() << "->" << m.GetName() << m.GetSignature()
316*795d594fSAndroid Build Coastguard Worker             << " (source: " << m.GetDeclaringClassInfo().GetSourceFileName() << ":"
317*795d594fSAndroid Build Coastguard Worker             << m.GetFirstLine() << ")";
318*795d594fSAndroid Build Coastguard Worker }
319*795d594fSAndroid Build Coastguard Worker 
320*795d594fSAndroid Build Coastguard Worker 
321*795d594fSAndroid Build Coastguard Worker class LogPrinter {
322*795d594fSAndroid Build Coastguard Worker  public:
LogPrinter(jvmtiEvent event)323*795d594fSAndroid Build Coastguard Worker   explicit LogPrinter(jvmtiEvent event) : event_(event) {}
324*795d594fSAndroid Build Coastguard Worker 
PrintRestNoJNI(jvmtiEnv * jvmti,Args...args)325*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRestNoJNI(jvmtiEnv* jvmti, Args... args) {
326*795d594fSAndroid Build Coastguard Worker     PrintRest(jvmti, static_cast<JNIEnv*>(nullptr), args...);
327*795d594fSAndroid Build Coastguard Worker   }
328*795d594fSAndroid Build Coastguard Worker 
329*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti, JNIEnv* env, Args... args);
330*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
331*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
332*795d594fSAndroid Build Coastguard Worker                                              jlongContainer l,
333*795d594fSAndroid Build Coastguard Worker                                              Args... args);
334*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
335*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
336*795d594fSAndroid Build Coastguard Worker                                              jthreadContainer thr,
337*795d594fSAndroid Build Coastguard Worker                                              Args... args);
338*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
339*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
340*795d594fSAndroid Build Coastguard Worker                                              jboolean i,
341*795d594fSAndroid Build Coastguard Worker                                              Args... args);
342*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
343*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
344*795d594fSAndroid Build Coastguard Worker                                              jint i,
345*795d594fSAndroid Build Coastguard Worker                                              Args... args);
346*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
347*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
348*795d594fSAndroid Build Coastguard Worker                                              jclass klass,
349*795d594fSAndroid Build Coastguard Worker                                              Args... args);
350*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
351*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
352*795d594fSAndroid Build Coastguard Worker                                              jmethodID meth,
353*795d594fSAndroid Build Coastguard Worker                                              Args... args);
354*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
355*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
356*795d594fSAndroid Build Coastguard Worker                                              jlocation loc,
357*795d594fSAndroid Build Coastguard Worker                                              Args... args);
358*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
359*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
360*795d594fSAndroid Build Coastguard Worker                                              jint* ip,
361*795d594fSAndroid Build Coastguard Worker                                              Args... args);
362*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
363*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
364*795d594fSAndroid Build Coastguard Worker                                              const void* loc,
365*795d594fSAndroid Build Coastguard Worker                                              Args... args);
366*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
367*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
368*795d594fSAndroid Build Coastguard Worker                                              void* loc,
369*795d594fSAndroid Build Coastguard Worker                                              Args... args);
370*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
371*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
372*795d594fSAndroid Build Coastguard Worker                                              void** loc,
373*795d594fSAndroid Build Coastguard Worker                                              Args... args);
374*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
375*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
376*795d594fSAndroid Build Coastguard Worker                                              unsigned char** v,
377*795d594fSAndroid Build Coastguard Worker                                              Args... args);
378*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
379*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
380*795d594fSAndroid Build Coastguard Worker                                              const unsigned char* v,
381*795d594fSAndroid Build Coastguard Worker                                              Args... args);
382*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
383*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
384*795d594fSAndroid Build Coastguard Worker                                              const char* v,
385*795d594fSAndroid Build Coastguard Worker                                              Args... args);
386*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
387*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
388*795d594fSAndroid Build Coastguard Worker                                              const jvmtiAddrLocationMap* v,
389*795d594fSAndroid Build Coastguard Worker                                              Args... args);
390*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
391*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
392*795d594fSAndroid Build Coastguard Worker                                              jvalue v,
393*795d594fSAndroid Build Coastguard Worker                                              Args... args);
394*795d594fSAndroid Build Coastguard Worker   template <typename ...Args> void PrintRest(jvmtiEnv* jvmti,
395*795d594fSAndroid Build Coastguard Worker                                              JNIEnv* env,
396*795d594fSAndroid Build Coastguard Worker                                              jobject v,
397*795d594fSAndroid Build Coastguard Worker                                              Args... args);
398*795d594fSAndroid Build Coastguard Worker 
GetResult()399*795d594fSAndroid Build Coastguard Worker   std::string GetResult() {
400*795d594fSAndroid Build Coastguard Worker     std::string out_str = stream.str();
401*795d594fSAndroid Build Coastguard Worker     return start_args + out_str;
402*795d594fSAndroid Build Coastguard Worker   }
403*795d594fSAndroid Build Coastguard Worker 
404*795d594fSAndroid Build Coastguard Worker  private:
405*795d594fSAndroid Build Coastguard Worker   jvmtiEvent event_;
406*795d594fSAndroid Build Coastguard Worker   std::string start_args;
407*795d594fSAndroid Build Coastguard Worker   std::ostringstream stream;
408*795d594fSAndroid Build Coastguard Worker };
409*795d594fSAndroid Build Coastguard Worker 
410*795d594fSAndroid Build Coastguard Worker // Base case
411*795d594fSAndroid Build Coastguard Worker template <>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni)412*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest([[maybe_unused]] jvmtiEnv* jvmti, JNIEnv* jni) {
413*795d594fSAndroid Build Coastguard Worker   if (jni == nullptr) {
414*795d594fSAndroid Build Coastguard Worker     start_args = "jvmtiEnv*";
415*795d594fSAndroid Build Coastguard Worker   } else {
416*795d594fSAndroid Build Coastguard Worker     start_args = "jvmtiEnv*, JNIEnv*";
417*795d594fSAndroid Build Coastguard Worker   }
418*795d594fSAndroid Build Coastguard Worker }
419*795d594fSAndroid Build Coastguard Worker 
420*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,const jvmtiAddrLocationMap * v,Args...args)421*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti,
422*795d594fSAndroid Build Coastguard Worker                            JNIEnv* jni,
423*795d594fSAndroid Build Coastguard Worker                            const jvmtiAddrLocationMap* v,
424*795d594fSAndroid Build Coastguard Worker                            Args... args) {
425*795d594fSAndroid Build Coastguard Worker   if (v != nullptr) {
426*795d594fSAndroid Build Coastguard Worker     stream << ", const jvmtiAddrLocationMap*[start_address: "
427*795d594fSAndroid Build Coastguard Worker            << v->start_address << ", location: " << v->location << "]";
428*795d594fSAndroid Build Coastguard Worker   } else {
429*795d594fSAndroid Build Coastguard Worker     stream << ", const jvmtiAddrLocationMap*[nullptr]";
430*795d594fSAndroid Build Coastguard Worker   }
431*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
432*795d594fSAndroid Build Coastguard Worker }
433*795d594fSAndroid Build Coastguard Worker 
434*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,jint * v,Args...args)435*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jint* v, Args... args) {
436*795d594fSAndroid Build Coastguard Worker   stream << ", jint*[" << static_cast<const void*>(v) << "]";
437*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
438*795d594fSAndroid Build Coastguard Worker }
439*795d594fSAndroid Build Coastguard Worker 
440*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,const void * v,Args...args)441*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, const void* v, Args... args) {
442*795d594fSAndroid Build Coastguard Worker   stream << ", const void*[" << v << "]";
443*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
444*795d594fSAndroid Build Coastguard Worker }
445*795d594fSAndroid Build Coastguard Worker 
446*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,unsigned char ** v,Args...args)447*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, unsigned char** v, Args... args) {
448*795d594fSAndroid Build Coastguard Worker   stream << ", unsigned char**[" << static_cast<const void*>(v) << "]";
449*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
450*795d594fSAndroid Build Coastguard Worker }
451*795d594fSAndroid Build Coastguard Worker 
452*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,const unsigned char * v,Args...args)453*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, const unsigned char* v, Args... args) {
454*795d594fSAndroid Build Coastguard Worker   stream << ", const unsigned char*[" << static_cast<const void*>(v) << "]";
455*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
456*795d594fSAndroid Build Coastguard Worker }
457*795d594fSAndroid Build Coastguard Worker 
458*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,const char * v,Args...args)459*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, const char* v, Args... args) {
460*795d594fSAndroid Build Coastguard Worker   stream << ", const char*[" << v << "]";
461*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
462*795d594fSAndroid Build Coastguard Worker }
463*795d594fSAndroid Build Coastguard Worker 
464*795d594fSAndroid Build Coastguard Worker template<typename... Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,jvalue v,Args...args)465*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jvalue v, Args... args) {
466*795d594fSAndroid Build Coastguard Worker   std::ostringstream hex;
467*795d594fSAndroid Build Coastguard Worker   hex << std::hex << v.j;
468*795d594fSAndroid Build Coastguard Worker   std::ostringstream char_val;
469*795d594fSAndroid Build Coastguard Worker   if (std::isprint(v.c) && v.c < std::numeric_limits<unsigned char>::max()) {
470*795d594fSAndroid Build Coastguard Worker     char_val << "'" << static_cast<unsigned char>(v.c) << "'";
471*795d594fSAndroid Build Coastguard Worker   } else {
472*795d594fSAndroid Build Coastguard Worker     char_val << "0x" << std::hex << reinterpret_cast<uint16_t>(v.c);
473*795d594fSAndroid Build Coastguard Worker   }
474*795d594fSAndroid Build Coastguard Worker   stream << ", jvalue[{<hex: 0x" << hex.str() << ">"
475*795d594fSAndroid Build Coastguard Worker          << ", .z=" << (v.z ? "true" : "false")
476*795d594fSAndroid Build Coastguard Worker          << ", .b=" << static_cast<int32_t>(v.b)
477*795d594fSAndroid Build Coastguard Worker          << ", .c=" << char_val.str()
478*795d594fSAndroid Build Coastguard Worker          << ", .s=" << static_cast<int32_t>(v.s)
479*795d594fSAndroid Build Coastguard Worker          << ", .i=" << v.i
480*795d594fSAndroid Build Coastguard Worker          << ", .j=" << v.j
481*795d594fSAndroid Build Coastguard Worker          << ", .f=" << v.f
482*795d594fSAndroid Build Coastguard Worker          << ", .d=" << v.d
483*795d594fSAndroid Build Coastguard Worker          << ", .l=" << v.l << "}]";
484*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
485*795d594fSAndroid Build Coastguard Worker }
486*795d594fSAndroid Build Coastguard Worker 
487*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,void ** v,Args...args)488*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, void** v, Args... args) {
489*795d594fSAndroid Build Coastguard Worker   stream << ", void**[" << v << "]";
490*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
491*795d594fSAndroid Build Coastguard Worker }
492*795d594fSAndroid Build Coastguard Worker 
493*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,void * v,Args...args)494*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, void* v, Args... args) {
495*795d594fSAndroid Build Coastguard Worker   stream << ", void*[" << v << "]";
496*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
497*795d594fSAndroid Build Coastguard Worker }
498*795d594fSAndroid Build Coastguard Worker 
499*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,jlongContainer l,Args...args)500*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jlongContainer l, Args... args) {
501*795d594fSAndroid Build Coastguard Worker   stream << ", jlong[" << l.val << ", hex: 0x" << std::hex << l.val << "]";
502*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
503*795d594fSAndroid Build Coastguard Worker }
504*795d594fSAndroid Build Coastguard Worker 
505*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,jlocation l,Args...args)506*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jlocation l, Args... args) {
507*795d594fSAndroid Build Coastguard Worker   stream << ", jlocation[" << l << ", hex: 0x" << std::hex << l << "]";
508*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
509*795d594fSAndroid Build Coastguard Worker }
510*795d594fSAndroid Build Coastguard Worker 
511*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,jboolean b,Args...args)512*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jboolean b, Args... args) {
513*795d594fSAndroid Build Coastguard Worker   stream << ", jboolean[" << (b ? "true" : "false") << "]";
514*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
515*795d594fSAndroid Build Coastguard Worker }
516*795d594fSAndroid Build Coastguard Worker 
517*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,jint i,Args...args)518*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jint i, Args... args) {
519*795d594fSAndroid Build Coastguard Worker   stream << ", jint[" << i << ", hex: 0x" << std::hex << i << "]";
520*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
521*795d594fSAndroid Build Coastguard Worker }
522*795d594fSAndroid Build Coastguard Worker 
523*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,jobject obj,Args...args)524*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jobject obj, Args... args) {
525*795d594fSAndroid Build Coastguard Worker   if (obj == nullptr) {
526*795d594fSAndroid Build Coastguard Worker     stream << ", jobject[nullptr]";
527*795d594fSAndroid Build Coastguard Worker   } else {
528*795d594fSAndroid Build Coastguard Worker     jni->PushLocalFrame(1);
529*795d594fSAndroid Build Coastguard Worker     jclass klass = jni->GetObjectClass(obj);
530*795d594fSAndroid Build Coastguard Worker     ScopedClassInfo sci(jvmti, klass);
531*795d594fSAndroid Build Coastguard Worker     if (sci.Init(event_ != JVMTI_EVENT_VM_OBJECT_ALLOC)) {
532*795d594fSAndroid Build Coastguard Worker       stream << ", jobject[type: " << sci << "]";
533*795d594fSAndroid Build Coastguard Worker     } else {
534*795d594fSAndroid Build Coastguard Worker       stream << ", jobject[type: TYPE UNKNOWN]";
535*795d594fSAndroid Build Coastguard Worker     }
536*795d594fSAndroid Build Coastguard Worker     jni->PopLocalFrame(nullptr);
537*795d594fSAndroid Build Coastguard Worker   }
538*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
539*795d594fSAndroid Build Coastguard Worker }
540*795d594fSAndroid Build Coastguard Worker 
541*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,jthreadContainer thr,Args...args)542*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jthreadContainer thr, Args... args) {
543*795d594fSAndroid Build Coastguard Worker   ScopedThreadInfo sti(jvmti, jni, thr.thread);
544*795d594fSAndroid Build Coastguard Worker   stream << ", jthread[" << sti.GetName() << "]";
545*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
546*795d594fSAndroid Build Coastguard Worker }
547*795d594fSAndroid Build Coastguard Worker 
548*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,jclass klass,Args...args)549*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jclass klass, Args... args) {
550*795d594fSAndroid Build Coastguard Worker   ScopedClassInfo sci(jvmti, klass);
551*795d594fSAndroid Build Coastguard Worker   if (sci.Init(/*get_generic=*/event_ != JVMTI_EVENT_VM_OBJECT_ALLOC)) {
552*795d594fSAndroid Build Coastguard Worker     stream << ", jclass[" << sci << "]";
553*795d594fSAndroid Build Coastguard Worker   } else {
554*795d594fSAndroid Build Coastguard Worker     stream << ", jclass[TYPE UNKNOWN]";
555*795d594fSAndroid Build Coastguard Worker   }
556*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
557*795d594fSAndroid Build Coastguard Worker }
558*795d594fSAndroid Build Coastguard Worker 
559*795d594fSAndroid Build Coastguard Worker template<typename ...Args>
PrintRest(jvmtiEnv * jvmti,JNIEnv * jni,jmethodID meth,Args...args)560*795d594fSAndroid Build Coastguard Worker void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jmethodID meth, Args... args) {
561*795d594fSAndroid Build Coastguard Worker   ScopedMethodInfo smi(jvmti, jni, meth);
562*795d594fSAndroid Build Coastguard Worker   if (smi.Init()) {
563*795d594fSAndroid Build Coastguard Worker     stream << ", jmethodID[" << smi << "]";
564*795d594fSAndroid Build Coastguard Worker   } else {
565*795d594fSAndroid Build Coastguard Worker     stream << ", jmethodID[METHOD UNKNOWN]";
566*795d594fSAndroid Build Coastguard Worker   }
567*795d594fSAndroid Build Coastguard Worker   PrintRest(jvmti, jni, args...);
568*795d594fSAndroid Build Coastguard Worker }
569*795d594fSAndroid Build Coastguard Worker 
570*795d594fSAndroid Build Coastguard Worker #define GENERATE_LOG_FUNCTION_JNI(name, event, args, argnames) \
571*795d594fSAndroid Build Coastguard Worker     static void JNICALL log ## name  args { \
572*795d594fSAndroid Build Coastguard Worker       LogPrinter printer(event); \
573*795d594fSAndroid Build Coastguard Worker       printer.PrintRest argnames; \
574*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << "Got event " << #name << "(" << printer.GetResult() << ")"; \
575*795d594fSAndroid Build Coastguard Worker     } \
576*795d594fSAndroid Build Coastguard Worker 
577*795d594fSAndroid Build Coastguard Worker #define GENERATE_LOG_FUNCTION_NO_JNI(name, event, args, argnames) \
578*795d594fSAndroid Build Coastguard Worker     static void JNICALL log ## name  args { \
579*795d594fSAndroid Build Coastguard Worker       LogPrinter printer(event); \
580*795d594fSAndroid Build Coastguard Worker       printer.PrintRestNoJNI argnames; \
581*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << "Got event " << #name << "(" << printer.GetResult() << ")"; \
582*795d594fSAndroid Build Coastguard Worker     } \
583*795d594fSAndroid Build Coastguard Worker 
FOR_ALL_SUPPORTED_EVENTS_DIFFERENT(GENERATE_LOG_FUNCTION_JNI,GENERATE_LOG_FUNCTION_NO_JNI)584*795d594fSAndroid Build Coastguard Worker FOR_ALL_SUPPORTED_EVENTS_DIFFERENT(GENERATE_LOG_FUNCTION_JNI, GENERATE_LOG_FUNCTION_NO_JNI)
585*795d594fSAndroid Build Coastguard Worker #undef GENERATE_LOG_FUNCTION
586*795d594fSAndroid Build Coastguard Worker 
587*795d594fSAndroid Build Coastguard Worker static jvmtiEventCallbacks kLogCallbacks {
588*795d594fSAndroid Build Coastguard Worker #define CREATE_LOG_EVENT_CALLBACK(name, num, args, argnames) \
589*795d594fSAndroid Build Coastguard Worker     .name = log ## name,
590*795d594fSAndroid Build Coastguard Worker   FOR_ALL_SUPPORTED_EVENTS(CREATE_LOG_EVENT_CALLBACK)
591*795d594fSAndroid Build Coastguard Worker #undef CREATE_LOG_EVENT_CALLBACK
592*795d594fSAndroid Build Coastguard Worker };
593*795d594fSAndroid Build Coastguard Worker 
EventToName(jvmtiEvent desired_event)594*795d594fSAndroid Build Coastguard Worker static std::string EventToName(jvmtiEvent desired_event) {
595*795d594fSAndroid Build Coastguard Worker #define CHECK_NAME(name, event, args, argnames) \
596*795d594fSAndroid Build Coastguard Worker   if (desired_event == (event)) { \
597*795d594fSAndroid Build Coastguard Worker     return #name; \
598*795d594fSAndroid Build Coastguard Worker   }
599*795d594fSAndroid Build Coastguard Worker   FOR_ALL_SUPPORTED_EVENTS(CHECK_NAME);
600*795d594fSAndroid Build Coastguard Worker   LOG(FATAL) << "Unknown event " << desired_event;
601*795d594fSAndroid Build Coastguard Worker   __builtin_unreachable();
602*795d594fSAndroid Build Coastguard Worker #undef CHECK_NAME
603*795d594fSAndroid Build Coastguard Worker }
NameToEvent(const std::string & desired_name)604*795d594fSAndroid Build Coastguard Worker static jvmtiEvent NameToEvent(const std::string& desired_name) {
605*795d594fSAndroid Build Coastguard Worker #define CHECK_NAME(name, event, args, argnames) \
606*795d594fSAndroid Build Coastguard Worker   if (desired_name == #name) { \
607*795d594fSAndroid Build Coastguard Worker     return event; \
608*795d594fSAndroid Build Coastguard Worker   }
609*795d594fSAndroid Build Coastguard Worker   FOR_ALL_SUPPORTED_EVENTS(CHECK_NAME);
610*795d594fSAndroid Build Coastguard Worker   LOG(FATAL) << "Unknown event " << desired_name;
611*795d594fSAndroid Build Coastguard Worker   __builtin_unreachable();
612*795d594fSAndroid Build Coastguard Worker #undef CHECK_NAME
613*795d594fSAndroid Build Coastguard Worker }
614*795d594fSAndroid Build Coastguard Worker 
615*795d594fSAndroid Build Coastguard Worker #undef FOR_ALL_SUPPORTED_EVENTS
616*795d594fSAndroid Build Coastguard Worker #undef FOR_ALL_SUPPORTED_EVENTS_DIFFERENT
617*795d594fSAndroid Build Coastguard Worker 
GetAllAvailableEvents(jvmtiEnv * jvmti)618*795d594fSAndroid Build Coastguard Worker static std::vector<jvmtiEvent> GetAllAvailableEvents(jvmtiEnv* jvmti) {
619*795d594fSAndroid Build Coastguard Worker   std::vector<jvmtiEvent> out;
620*795d594fSAndroid Build Coastguard Worker   jvmtiCapabilities caps{};
621*795d594fSAndroid Build Coastguard Worker   jvmti->GetPotentialCapabilities(&caps);
622*795d594fSAndroid Build Coastguard Worker   uint8_t caps_bytes[sizeof(caps)];
623*795d594fSAndroid Build Coastguard Worker   memcpy(caps_bytes, &caps, sizeof(caps));
624*795d594fSAndroid Build Coastguard Worker   for (jvmtiEvent e : kAllEvents) {
625*795d594fSAndroid Build Coastguard Worker     jvmtiCapabilities req{};
626*795d594fSAndroid Build Coastguard Worker     AddCapsForEvent(e, &req);
627*795d594fSAndroid Build Coastguard Worker     uint8_t req_bytes[sizeof(req)];
628*795d594fSAndroid Build Coastguard Worker     memcpy(req_bytes, &req, sizeof(req));
629*795d594fSAndroid Build Coastguard Worker     bool good = true;
630*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < sizeof(caps); i++) {
631*795d594fSAndroid Build Coastguard Worker       if ((req_bytes[i] & caps_bytes[i]) != req_bytes[i]) {
632*795d594fSAndroid Build Coastguard Worker         good = false;
633*795d594fSAndroid Build Coastguard Worker         break;
634*795d594fSAndroid Build Coastguard Worker       }
635*795d594fSAndroid Build Coastguard Worker     }
636*795d594fSAndroid Build Coastguard Worker     if (good) {
637*795d594fSAndroid Build Coastguard Worker       out.push_back(e);
638*795d594fSAndroid Build Coastguard Worker     } else {
639*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "Unable to get capabilities for event " << EventToName(e);
640*795d594fSAndroid Build Coastguard Worker     }
641*795d594fSAndroid Build Coastguard Worker   }
642*795d594fSAndroid Build Coastguard Worker   return out;
643*795d594fSAndroid Build Coastguard Worker }
644*795d594fSAndroid Build Coastguard Worker 
GetRequestedEventList(jvmtiEnv * jvmti,const std::string & args)645*795d594fSAndroid Build Coastguard Worker static std::vector<jvmtiEvent> GetRequestedEventList(jvmtiEnv* jvmti, const std::string& args) {
646*795d594fSAndroid Build Coastguard Worker   std::vector<jvmtiEvent> res;
647*795d594fSAndroid Build Coastguard Worker   std::stringstream args_stream(args);
648*795d594fSAndroid Build Coastguard Worker   std::string item;
649*795d594fSAndroid Build Coastguard Worker   while (std::getline(args_stream, item, ',')) {
650*795d594fSAndroid Build Coastguard Worker     if (item == "") {
651*795d594fSAndroid Build Coastguard Worker       continue;
652*795d594fSAndroid Build Coastguard Worker     } else if (item == "all") {
653*795d594fSAndroid Build Coastguard Worker       return GetAllAvailableEvents(jvmti);
654*795d594fSAndroid Build Coastguard Worker     }
655*795d594fSAndroid Build Coastguard Worker     res.push_back(NameToEvent(item));
656*795d594fSAndroid Build Coastguard Worker   }
657*795d594fSAndroid Build Coastguard Worker   return res;
658*795d594fSAndroid Build Coastguard Worker }
659*795d594fSAndroid Build Coastguard Worker 
SetupJvmtiEnv(JavaVM * vm,jvmtiEnv ** jvmti)660*795d594fSAndroid Build Coastguard Worker static jint SetupJvmtiEnv(JavaVM* vm, jvmtiEnv** jvmti) {
661*795d594fSAndroid Build Coastguard Worker   jint res = 0;
662*795d594fSAndroid Build Coastguard Worker   res = vm->GetEnv(reinterpret_cast<void**>(jvmti), JVMTI_VERSION_1_1);
663*795d594fSAndroid Build Coastguard Worker 
664*795d594fSAndroid Build Coastguard Worker   if (res != JNI_OK || *jvmti == nullptr) {
665*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to access JVMTI, error code " << res;
666*795d594fSAndroid Build Coastguard Worker     return vm->GetEnv(reinterpret_cast<void**>(jvmti), kArtTiVersion);
667*795d594fSAndroid Build Coastguard Worker   }
668*795d594fSAndroid Build Coastguard Worker   return res;
669*795d594fSAndroid Build Coastguard Worker }
670*795d594fSAndroid Build Coastguard Worker 
671*795d594fSAndroid Build Coastguard Worker }  // namespace
672*795d594fSAndroid Build Coastguard Worker 
AgentStart(JavaVM * vm,char * options,void * reserved)673*795d594fSAndroid Build Coastguard Worker static jint AgentStart(JavaVM* vm, char* options, [[maybe_unused]] void* reserved) {
674*795d594fSAndroid Build Coastguard Worker   jvmtiEnv* jvmti = nullptr;
675*795d594fSAndroid Build Coastguard Worker   jvmtiError error = JVMTI_ERROR_NONE;
676*795d594fSAndroid Build Coastguard Worker   if (SetupJvmtiEnv(vm, &jvmti) != JNI_OK) {
677*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Could not get JVMTI env or ArtTiEnv!";
678*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
679*795d594fSAndroid Build Coastguard Worker   }
680*795d594fSAndroid Build Coastguard Worker   std::string args(options);
681*795d594fSAndroid Build Coastguard Worker   bool is_log = false;
682*795d594fSAndroid Build Coastguard Worker   if (args.compare(0, 3, "log") == 0) {
683*795d594fSAndroid Build Coastguard Worker     is_log = true;
684*795d594fSAndroid Build Coastguard Worker     args = args.substr(3);
685*795d594fSAndroid Build Coastguard Worker   }
686*795d594fSAndroid Build Coastguard Worker 
687*795d594fSAndroid Build Coastguard Worker   std::vector<jvmtiEvent> events = GetRequestedEventList(jvmti, args);
688*795d594fSAndroid Build Coastguard Worker 
689*795d594fSAndroid Build Coastguard Worker   jvmtiCapabilities caps{};
690*795d594fSAndroid Build Coastguard Worker   for (jvmtiEvent e : events) {
691*795d594fSAndroid Build Coastguard Worker     AddCapsForEvent(e, &caps);
692*795d594fSAndroid Build Coastguard Worker   }
693*795d594fSAndroid Build Coastguard Worker   if (is_log) {
694*795d594fSAndroid Build Coastguard Worker     caps.can_get_line_numbers = 1;
695*795d594fSAndroid Build Coastguard Worker     caps.can_get_source_file_name = 1;
696*795d594fSAndroid Build Coastguard Worker     caps.can_get_source_debug_extension = 1;
697*795d594fSAndroid Build Coastguard Worker   }
698*795d594fSAndroid Build Coastguard Worker   error = jvmti->AddCapabilities(&caps);
699*795d594fSAndroid Build Coastguard Worker   if (error != JVMTI_ERROR_NONE) {
700*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to set caps";
701*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
702*795d594fSAndroid Build Coastguard Worker   }
703*795d594fSAndroid Build Coastguard Worker 
704*795d594fSAndroid Build Coastguard Worker   if (is_log) {
705*795d594fSAndroid Build Coastguard Worker     error = jvmti->SetEventCallbacks(&kLogCallbacks, static_cast<jint>(sizeof(kLogCallbacks)));
706*795d594fSAndroid Build Coastguard Worker   } else {
707*795d594fSAndroid Build Coastguard Worker     error = jvmti->SetEventCallbacks(&kEmptyCallbacks, static_cast<jint>(sizeof(kEmptyCallbacks)));
708*795d594fSAndroid Build Coastguard Worker   }
709*795d594fSAndroid Build Coastguard Worker   if (error != JVMTI_ERROR_NONE) {
710*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to set event callbacks.";
711*795d594fSAndroid Build Coastguard Worker     return JNI_ERR;
712*795d594fSAndroid Build Coastguard Worker   }
713*795d594fSAndroid Build Coastguard Worker   for (jvmtiEvent e : events) {
714*795d594fSAndroid Build Coastguard Worker     error = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
715*795d594fSAndroid Build Coastguard Worker                                             e,
716*795d594fSAndroid Build Coastguard Worker                                             nullptr /* all threads */);
717*795d594fSAndroid Build Coastguard Worker     if (error != JVMTI_ERROR_NONE) {
718*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unable to enable event " << e;
719*795d594fSAndroid Build Coastguard Worker       return JNI_ERR;
720*795d594fSAndroid Build Coastguard Worker     }
721*795d594fSAndroid Build Coastguard Worker   }
722*795d594fSAndroid Build Coastguard Worker   return JNI_OK;
723*795d594fSAndroid Build Coastguard Worker }
724*795d594fSAndroid Build Coastguard Worker 
725*795d594fSAndroid Build Coastguard Worker // Late attachment (e.g. 'am attach-agent').
Agent_OnAttach(JavaVM * vm,char * options,void * reserved)726*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *vm, char* options, void* reserved) {
727*795d594fSAndroid Build Coastguard Worker   return AgentStart(vm, options, reserved);
728*795d594fSAndroid Build Coastguard Worker }
729*795d594fSAndroid Build Coastguard Worker 
730*795d594fSAndroid Build Coastguard Worker // Early attachment
Agent_OnLoad(JavaVM * jvm,char * options,void * reserved)731*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* jvm, char* options, void* reserved) {
732*795d594fSAndroid Build Coastguard Worker   return AgentStart(jvm, options, reserved);
733*795d594fSAndroid Build Coastguard Worker }
734*795d594fSAndroid Build Coastguard Worker 
735*795d594fSAndroid Build Coastguard Worker }  // namespace tifast
736*795d594fSAndroid Build Coastguard Worker 
737