xref: /aosp_15_r20/art/test/ti-stress/stress.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright 2017 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include <cstdio>
18*795d594fSAndroid Build Coastguard Worker #include <fstream>
19*795d594fSAndroid Build Coastguard Worker #include <iomanip>
20*795d594fSAndroid Build Coastguard Worker #include <iostream>
21*795d594fSAndroid Build Coastguard Worker #include <memory>
22*795d594fSAndroid Build Coastguard Worker #include <sstream>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include <jni.h>
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
27*795d594fSAndroid Build Coastguard Worker #include "jvmti.h"
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic push
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker // Slicer's headers have code that triggers these warnings. b/65298177
32*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wunused-parameter"
33*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wsign-compare"
34*795d594fSAndroid Build Coastguard Worker 
35*795d594fSAndroid Build Coastguard Worker #include "slicer/code_ir.h"
36*795d594fSAndroid Build Coastguard Worker #include "slicer/control_flow_graph.h"
37*795d594fSAndroid Build Coastguard Worker #include "slicer/dex_ir.h"
38*795d594fSAndroid Build Coastguard Worker #include "slicer/dex_ir_builder.h"
39*795d594fSAndroid Build Coastguard Worker #include "slicer/instrumentation.h"
40*795d594fSAndroid Build Coastguard Worker #include "slicer/reader.h"
41*795d594fSAndroid Build Coastguard Worker #include "slicer/writer.h"
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic pop
44*795d594fSAndroid Build Coastguard Worker 
45*795d594fSAndroid Build Coastguard Worker namespace art {
46*795d594fSAndroid Build Coastguard Worker 
47*795d594fSAndroid Build Coastguard Worker // Should we do a 'full_rewrite' with this test?
48*795d594fSAndroid Build Coastguard Worker static constexpr bool kDoFullRewrite = true;
49*795d594fSAndroid Build Coastguard Worker 
50*795d594fSAndroid Build Coastguard Worker struct StressData {
51*795d594fSAndroid Build Coastguard Worker   bool vm_class_loader_initialized;
52*795d594fSAndroid Build Coastguard Worker   bool trace_stress;
53*795d594fSAndroid Build Coastguard Worker   bool redefine_stress;
54*795d594fSAndroid Build Coastguard Worker   bool field_stress;
55*795d594fSAndroid Build Coastguard Worker   bool step_stress;
56*795d594fSAndroid Build Coastguard Worker };
57*795d594fSAndroid Build Coastguard Worker 
DeleteLocalRef(JNIEnv * env,jobject obj)58*795d594fSAndroid Build Coastguard Worker static void DeleteLocalRef(JNIEnv* env, jobject obj) {
59*795d594fSAndroid Build Coastguard Worker   if (obj != nullptr) {
60*795d594fSAndroid Build Coastguard Worker     env->DeleteLocalRef(obj);
61*795d594fSAndroid Build Coastguard Worker   }
62*795d594fSAndroid Build Coastguard Worker }
63*795d594fSAndroid Build Coastguard Worker 
DoExtractClassFromData(jvmtiEnv * env,const std::string & descriptor,jint in_len,const unsigned char * in_data,jint * out_len,unsigned char ** out_data)64*795d594fSAndroid Build Coastguard Worker static bool DoExtractClassFromData(jvmtiEnv* env,
65*795d594fSAndroid Build Coastguard Worker                                    const std::string& descriptor,
66*795d594fSAndroid Build Coastguard Worker                                    jint in_len,
67*795d594fSAndroid Build Coastguard Worker                                    const unsigned char* in_data,
68*795d594fSAndroid Build Coastguard Worker                                    /*out*/jint* out_len,
69*795d594fSAndroid Build Coastguard Worker                                    /*out*/unsigned char** out_data) {
70*795d594fSAndroid Build Coastguard Worker   dex::Reader reader(in_data, in_len);
71*795d594fSAndroid Build Coastguard Worker   dex::u4 class_idx = reader.FindClassIndex(descriptor.c_str());
72*795d594fSAndroid Build Coastguard Worker   if (class_idx != dex::kNoIndex) {
73*795d594fSAndroid Build Coastguard Worker     reader.CreateClassIr(class_idx);
74*795d594fSAndroid Build Coastguard Worker   } else {
75*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "ERROR: Can't find class " << descriptor;
76*795d594fSAndroid Build Coastguard Worker     return false;
77*795d594fSAndroid Build Coastguard Worker   }
78*795d594fSAndroid Build Coastguard Worker   auto dex_ir = reader.GetIr();
79*795d594fSAndroid Build Coastguard Worker 
80*795d594fSAndroid Build Coastguard Worker   if (kDoFullRewrite) {
81*795d594fSAndroid Build Coastguard Worker     for (auto& ir_method : dex_ir->encoded_methods) {
82*795d594fSAndroid Build Coastguard Worker       if (ir_method->code != nullptr) {
83*795d594fSAndroid Build Coastguard Worker         lir::CodeIr code_ir(ir_method.get(), dex_ir);
84*795d594fSAndroid Build Coastguard Worker         lir::ControlFlowGraph cfg_compact(&code_ir, false);
85*795d594fSAndroid Build Coastguard Worker         lir::ControlFlowGraph cfg_verbose(&code_ir, true);
86*795d594fSAndroid Build Coastguard Worker         code_ir.Assemble();
87*795d594fSAndroid Build Coastguard Worker       }
88*795d594fSAndroid Build Coastguard Worker     }
89*795d594fSAndroid Build Coastguard Worker   }
90*795d594fSAndroid Build Coastguard Worker   dex::Writer writer(dex_ir);
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker   struct Allocator : public dex::Writer::Allocator {
93*795d594fSAndroid Build Coastguard Worker     explicit Allocator(jvmtiEnv* jvmti_env) : jvmti_env_(jvmti_env) {}
94*795d594fSAndroid Build Coastguard Worker     void* Allocate(size_t size) override {
95*795d594fSAndroid Build Coastguard Worker       unsigned char* out = nullptr;
96*795d594fSAndroid Build Coastguard Worker       if (JVMTI_ERROR_NONE != jvmti_env_->Allocate(size, &out)) {
97*795d594fSAndroid Build Coastguard Worker         return nullptr;
98*795d594fSAndroid Build Coastguard Worker       } else {
99*795d594fSAndroid Build Coastguard Worker         return out;
100*795d594fSAndroid Build Coastguard Worker       }
101*795d594fSAndroid Build Coastguard Worker     }
102*795d594fSAndroid Build Coastguard Worker     void Free(void* ptr) override {
103*795d594fSAndroid Build Coastguard Worker       jvmti_env_->Deallocate(reinterpret_cast<unsigned char*>(ptr));
104*795d594fSAndroid Build Coastguard Worker     }
105*795d594fSAndroid Build Coastguard Worker    private:
106*795d594fSAndroid Build Coastguard Worker     jvmtiEnv* jvmti_env_;
107*795d594fSAndroid Build Coastguard Worker   };
108*795d594fSAndroid Build Coastguard Worker   Allocator alloc(env);
109*795d594fSAndroid Build Coastguard Worker   size_t res_len;
110*795d594fSAndroid Build Coastguard Worker   unsigned char* res = writer.CreateImage(&alloc, &res_len);
111*795d594fSAndroid Build Coastguard Worker   if (res != nullptr) {
112*795d594fSAndroid Build Coastguard Worker     *out_data = res;
113*795d594fSAndroid Build Coastguard Worker     *out_len = res_len;
114*795d594fSAndroid Build Coastguard Worker     return true;
115*795d594fSAndroid Build Coastguard Worker   } else {
116*795d594fSAndroid Build Coastguard Worker     return false;
117*795d594fSAndroid Build Coastguard Worker   }
118*795d594fSAndroid Build Coastguard Worker }
119*795d594fSAndroid Build Coastguard Worker 
120*795d594fSAndroid Build Coastguard Worker class ScopedThreadInfo {
121*795d594fSAndroid Build Coastguard Worker  public:
ScopedThreadInfo(jvmtiEnv * jvmtienv,JNIEnv * env,jthread thread)122*795d594fSAndroid Build Coastguard Worker   ScopedThreadInfo(jvmtiEnv* jvmtienv, JNIEnv* env, jthread thread)
123*795d594fSAndroid Build Coastguard Worker       : jvmtienv_(jvmtienv), env_(env), free_name_(false) {
124*795d594fSAndroid Build Coastguard Worker     memset(&info_, 0, sizeof(info_));
125*795d594fSAndroid Build Coastguard Worker     if (thread == nullptr) {
126*795d594fSAndroid Build Coastguard Worker       info_.name = const_cast<char*>("<NULLPTR>");
127*795d594fSAndroid Build Coastguard Worker     } else if (jvmtienv->GetThreadInfo(thread, &info_) != JVMTI_ERROR_NONE) {
128*795d594fSAndroid Build Coastguard Worker       info_.name = const_cast<char*>("<UNKNOWN THREAD>");
129*795d594fSAndroid Build Coastguard Worker     } else {
130*795d594fSAndroid Build Coastguard Worker       free_name_ = true;
131*795d594fSAndroid Build Coastguard Worker     }
132*795d594fSAndroid Build Coastguard Worker   }
133*795d594fSAndroid Build Coastguard Worker 
~ScopedThreadInfo()134*795d594fSAndroid Build Coastguard Worker   ~ScopedThreadInfo() {
135*795d594fSAndroid Build Coastguard Worker     if (free_name_) {
136*795d594fSAndroid Build Coastguard Worker       jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(info_.name));
137*795d594fSAndroid Build Coastguard Worker     }
138*795d594fSAndroid Build Coastguard Worker     DeleteLocalRef(env_, info_.thread_group);
139*795d594fSAndroid Build Coastguard Worker     DeleteLocalRef(env_, info_.context_class_loader);
140*795d594fSAndroid Build Coastguard Worker   }
141*795d594fSAndroid Build Coastguard Worker 
GetName() const142*795d594fSAndroid Build Coastguard Worker   const char* GetName() const {
143*795d594fSAndroid Build Coastguard Worker     return info_.name;
144*795d594fSAndroid Build Coastguard Worker   }
145*795d594fSAndroid Build Coastguard Worker 
146*795d594fSAndroid Build Coastguard Worker  private:
147*795d594fSAndroid Build Coastguard Worker   jvmtiEnv* jvmtienv_;
148*795d594fSAndroid Build Coastguard Worker   JNIEnv* env_;
149*795d594fSAndroid Build Coastguard Worker   bool free_name_;
150*795d594fSAndroid Build Coastguard Worker   jvmtiThreadInfo info_;
151*795d594fSAndroid Build Coastguard Worker };
152*795d594fSAndroid Build Coastguard Worker 
153*795d594fSAndroid Build Coastguard Worker class ScopedClassInfo {
154*795d594fSAndroid Build Coastguard Worker  public:
ScopedClassInfo(jvmtiEnv * jvmtienv,jclass c)155*795d594fSAndroid Build Coastguard Worker   ScopedClassInfo(jvmtiEnv* jvmtienv, jclass c)
156*795d594fSAndroid Build Coastguard Worker       : jvmtienv_(jvmtienv),
157*795d594fSAndroid Build Coastguard Worker         class_(c),
158*795d594fSAndroid Build Coastguard Worker         name_(nullptr),
159*795d594fSAndroid Build Coastguard Worker         file_(nullptr),
160*795d594fSAndroid Build Coastguard Worker         debug_ext_(nullptr) {}
161*795d594fSAndroid Build Coastguard Worker 
~ScopedClassInfo()162*795d594fSAndroid Build Coastguard Worker   ~ScopedClassInfo() {
163*795d594fSAndroid Build Coastguard Worker     if (class_ != nullptr) {
164*795d594fSAndroid Build Coastguard Worker       jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(name_));
165*795d594fSAndroid Build Coastguard Worker       jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(file_));
166*795d594fSAndroid Build Coastguard Worker       jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(debug_ext_));
167*795d594fSAndroid Build Coastguard Worker     }
168*795d594fSAndroid Build Coastguard Worker   }
169*795d594fSAndroid Build Coastguard Worker 
Init()170*795d594fSAndroid Build Coastguard Worker   bool Init() {
171*795d594fSAndroid Build Coastguard Worker     if (class_ == nullptr) {
172*795d594fSAndroid Build Coastguard Worker       name_ = const_cast<char*>("<NONE>");
173*795d594fSAndroid Build Coastguard Worker       return true;
174*795d594fSAndroid Build Coastguard Worker     } else {
175*795d594fSAndroid Build Coastguard Worker       jvmtiError ret1 = jvmtienv_->GetSourceFileName(class_, &file_);
176*795d594fSAndroid Build Coastguard Worker       jvmtiError ret2 = jvmtienv_->GetSourceDebugExtension(class_, &debug_ext_);
177*795d594fSAndroid Build Coastguard Worker       return jvmtienv_->GetClassSignature(class_, &name_, nullptr) == JVMTI_ERROR_NONE &&
178*795d594fSAndroid Build Coastguard Worker           ret1 != JVMTI_ERROR_MUST_POSSESS_CAPABILITY &&
179*795d594fSAndroid Build Coastguard Worker           ret1 != JVMTI_ERROR_INVALID_CLASS &&
180*795d594fSAndroid Build Coastguard Worker           ret2 != JVMTI_ERROR_MUST_POSSESS_CAPABILITY &&
181*795d594fSAndroid Build Coastguard Worker           ret2 != JVMTI_ERROR_INVALID_CLASS;
182*795d594fSAndroid Build Coastguard Worker     }
183*795d594fSAndroid Build Coastguard Worker   }
184*795d594fSAndroid Build Coastguard Worker 
GetClass() const185*795d594fSAndroid Build Coastguard Worker   jclass GetClass() const {
186*795d594fSAndroid Build Coastguard Worker     return class_;
187*795d594fSAndroid Build Coastguard Worker   }
GetName() const188*795d594fSAndroid Build Coastguard Worker   const char* GetName() const {
189*795d594fSAndroid Build Coastguard Worker     return name_;
190*795d594fSAndroid Build Coastguard Worker   }
GetSourceDebugExtension() const191*795d594fSAndroid Build Coastguard Worker   const char* GetSourceDebugExtension() const {
192*795d594fSAndroid Build Coastguard Worker     if (debug_ext_ == nullptr) {
193*795d594fSAndroid Build Coastguard Worker       return "<UNKNOWN_SOURCE_DEBUG_EXTENSION>";
194*795d594fSAndroid Build Coastguard Worker     } else {
195*795d594fSAndroid Build Coastguard Worker       return debug_ext_;
196*795d594fSAndroid Build Coastguard Worker     }
197*795d594fSAndroid Build Coastguard Worker   }
GetSourceFileName() const198*795d594fSAndroid Build Coastguard Worker   const char* GetSourceFileName() const {
199*795d594fSAndroid Build Coastguard Worker     if (file_ == nullptr) {
200*795d594fSAndroid Build Coastguard Worker       return "<UNKNOWN_FILE>";
201*795d594fSAndroid Build Coastguard Worker     } else {
202*795d594fSAndroid Build Coastguard Worker       return file_;
203*795d594fSAndroid Build Coastguard Worker     }
204*795d594fSAndroid Build Coastguard Worker   }
205*795d594fSAndroid Build Coastguard Worker 
206*795d594fSAndroid Build Coastguard Worker  private:
207*795d594fSAndroid Build Coastguard Worker   jvmtiEnv* jvmtienv_;
208*795d594fSAndroid Build Coastguard Worker   jclass class_;
209*795d594fSAndroid Build Coastguard Worker   char* name_;
210*795d594fSAndroid Build Coastguard Worker   char* file_;
211*795d594fSAndroid Build Coastguard Worker   char* debug_ext_;
212*795d594fSAndroid Build Coastguard Worker };
213*795d594fSAndroid Build Coastguard Worker 
214*795d594fSAndroid Build Coastguard Worker class ScopedMethodInfo {
215*795d594fSAndroid Build Coastguard Worker  public:
ScopedMethodInfo(jvmtiEnv * jvmtienv,JNIEnv * env,jmethodID m)216*795d594fSAndroid Build Coastguard Worker   ScopedMethodInfo(jvmtiEnv* jvmtienv, JNIEnv* env, jmethodID m)
217*795d594fSAndroid Build Coastguard Worker       : jvmtienv_(jvmtienv),
218*795d594fSAndroid Build Coastguard Worker         env_(env),
219*795d594fSAndroid Build Coastguard Worker         method_(m),
220*795d594fSAndroid Build Coastguard Worker         declaring_class_(nullptr),
221*795d594fSAndroid Build Coastguard Worker         class_info_(nullptr),
222*795d594fSAndroid Build Coastguard Worker         name_(nullptr),
223*795d594fSAndroid Build Coastguard Worker         signature_(nullptr),
224*795d594fSAndroid Build Coastguard Worker         first_line_(-1) {}
225*795d594fSAndroid Build Coastguard Worker 
~ScopedMethodInfo()226*795d594fSAndroid Build Coastguard Worker   ~ScopedMethodInfo() {
227*795d594fSAndroid Build Coastguard Worker     DeleteLocalRef(env_, declaring_class_);
228*795d594fSAndroid Build Coastguard Worker     jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(name_));
229*795d594fSAndroid Build Coastguard Worker     jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(signature_));
230*795d594fSAndroid Build Coastguard Worker   }
231*795d594fSAndroid Build Coastguard Worker 
Init()232*795d594fSAndroid Build Coastguard Worker   bool Init() {
233*795d594fSAndroid Build Coastguard Worker     if (jvmtienv_->GetMethodDeclaringClass(method_, &declaring_class_) != JVMTI_ERROR_NONE) {
234*795d594fSAndroid Build Coastguard Worker       return false;
235*795d594fSAndroid Build Coastguard Worker     }
236*795d594fSAndroid Build Coastguard Worker     class_info_.reset(new ScopedClassInfo(jvmtienv_, declaring_class_));
237*795d594fSAndroid Build Coastguard Worker     jint nlines;
238*795d594fSAndroid Build Coastguard Worker     jvmtiLineNumberEntry* lines;
239*795d594fSAndroid Build Coastguard Worker     jvmtiError err = jvmtienv_->GetLineNumberTable(method_, &nlines, &lines);
240*795d594fSAndroid Build Coastguard Worker     if (err == JVMTI_ERROR_NONE) {
241*795d594fSAndroid Build Coastguard Worker       if (nlines > 0) {
242*795d594fSAndroid Build Coastguard Worker         first_line_ = lines[0].line_number;
243*795d594fSAndroid Build Coastguard Worker       }
244*795d594fSAndroid Build Coastguard Worker       jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(lines));
245*795d594fSAndroid Build Coastguard Worker     } else if (err != JVMTI_ERROR_ABSENT_INFORMATION &&
246*795d594fSAndroid Build Coastguard Worker                err != JVMTI_ERROR_NATIVE_METHOD) {
247*795d594fSAndroid Build Coastguard Worker       return false;
248*795d594fSAndroid Build Coastguard Worker     }
249*795d594fSAndroid Build Coastguard Worker     return class_info_->Init() &&
250*795d594fSAndroid Build Coastguard Worker         (jvmtienv_->GetMethodName(method_, &name_, &signature_, nullptr) == JVMTI_ERROR_NONE);
251*795d594fSAndroid Build Coastguard Worker   }
252*795d594fSAndroid Build Coastguard Worker 
GetDeclaringClassInfo() const253*795d594fSAndroid Build Coastguard Worker   const ScopedClassInfo& GetDeclaringClassInfo() const {
254*795d594fSAndroid Build Coastguard Worker     return *class_info_;
255*795d594fSAndroid Build Coastguard Worker   }
256*795d594fSAndroid Build Coastguard Worker 
GetDeclaringClass() const257*795d594fSAndroid Build Coastguard Worker   jclass GetDeclaringClass() const {
258*795d594fSAndroid Build Coastguard Worker     return declaring_class_;
259*795d594fSAndroid Build Coastguard Worker   }
260*795d594fSAndroid Build Coastguard Worker 
GetName() const261*795d594fSAndroid Build Coastguard Worker   const char* GetName() const {
262*795d594fSAndroid Build Coastguard Worker     return name_;
263*795d594fSAndroid Build Coastguard Worker   }
264*795d594fSAndroid Build Coastguard Worker 
GetSignature() const265*795d594fSAndroid Build Coastguard Worker   const char* GetSignature() const {
266*795d594fSAndroid Build Coastguard Worker     return signature_;
267*795d594fSAndroid Build Coastguard Worker   }
268*795d594fSAndroid Build Coastguard Worker 
GetFirstLine() const269*795d594fSAndroid Build Coastguard Worker   jint GetFirstLine() const {
270*795d594fSAndroid Build Coastguard Worker     return first_line_;
271*795d594fSAndroid Build Coastguard Worker   }
272*795d594fSAndroid Build Coastguard Worker 
273*795d594fSAndroid Build Coastguard Worker  private:
274*795d594fSAndroid Build Coastguard Worker   jvmtiEnv* jvmtienv_;
275*795d594fSAndroid Build Coastguard Worker   JNIEnv* env_;
276*795d594fSAndroid Build Coastguard Worker   jmethodID method_;
277*795d594fSAndroid Build Coastguard Worker   jclass declaring_class_;
278*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ScopedClassInfo> class_info_;
279*795d594fSAndroid Build Coastguard Worker   char* name_;
280*795d594fSAndroid Build Coastguard Worker   char* signature_;
281*795d594fSAndroid Build Coastguard Worker   jint first_line_;
282*795d594fSAndroid Build Coastguard Worker 
283*795d594fSAndroid Build Coastguard Worker   friend std::ostream& operator<<(std::ostream &os, ScopedMethodInfo const& m);
284*795d594fSAndroid Build Coastguard Worker };
285*795d594fSAndroid Build Coastguard Worker 
286*795d594fSAndroid Build Coastguard Worker class ScopedFieldInfo {
287*795d594fSAndroid Build Coastguard Worker  public:
ScopedFieldInfo(jvmtiEnv * jvmtienv,jclass field_klass,jfieldID field)288*795d594fSAndroid Build Coastguard Worker   ScopedFieldInfo(jvmtiEnv* jvmtienv, jclass field_klass, jfieldID field)
289*795d594fSAndroid Build Coastguard Worker       : jvmtienv_(jvmtienv),
290*795d594fSAndroid Build Coastguard Worker         declaring_class_(field_klass),
291*795d594fSAndroid Build Coastguard Worker         field_(field),
292*795d594fSAndroid Build Coastguard Worker         class_info_(nullptr),
293*795d594fSAndroid Build Coastguard Worker         name_(nullptr),
294*795d594fSAndroid Build Coastguard Worker         type_(nullptr) {}
295*795d594fSAndroid Build Coastguard Worker 
~ScopedFieldInfo()296*795d594fSAndroid Build Coastguard Worker   ~ScopedFieldInfo() {
297*795d594fSAndroid Build Coastguard Worker     jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(name_));
298*795d594fSAndroid Build Coastguard Worker     jvmtienv_->Deallocate(reinterpret_cast<unsigned char*>(type_));
299*795d594fSAndroid Build Coastguard Worker   }
300*795d594fSAndroid Build Coastguard Worker 
Init()301*795d594fSAndroid Build Coastguard Worker   bool Init() {
302*795d594fSAndroid Build Coastguard Worker     class_info_.reset(new ScopedClassInfo(jvmtienv_, declaring_class_));
303*795d594fSAndroid Build Coastguard Worker     return class_info_->Init() &&
304*795d594fSAndroid Build Coastguard Worker         (jvmtienv_->GetFieldName(
305*795d594fSAndroid Build Coastguard Worker             declaring_class_, field_, &name_, &type_, nullptr) == JVMTI_ERROR_NONE);
306*795d594fSAndroid Build Coastguard Worker   }
307*795d594fSAndroid Build Coastguard Worker 
GetDeclaringClassInfo() const308*795d594fSAndroid Build Coastguard Worker   const ScopedClassInfo& GetDeclaringClassInfo() const {
309*795d594fSAndroid Build Coastguard Worker     return *class_info_;
310*795d594fSAndroid Build Coastguard Worker   }
311*795d594fSAndroid Build Coastguard Worker 
GetDeclaringClass() const312*795d594fSAndroid Build Coastguard Worker   jclass GetDeclaringClass() const {
313*795d594fSAndroid Build Coastguard Worker     return declaring_class_;
314*795d594fSAndroid Build Coastguard Worker   }
315*795d594fSAndroid Build Coastguard Worker 
GetName() const316*795d594fSAndroid Build Coastguard Worker   const char* GetName() const {
317*795d594fSAndroid Build Coastguard Worker     return name_;
318*795d594fSAndroid Build Coastguard Worker   }
319*795d594fSAndroid Build Coastguard Worker 
GetType() const320*795d594fSAndroid Build Coastguard Worker   const char* GetType() const {
321*795d594fSAndroid Build Coastguard Worker     return type_;
322*795d594fSAndroid Build Coastguard Worker   }
323*795d594fSAndroid Build Coastguard Worker 
324*795d594fSAndroid Build Coastguard Worker  private:
325*795d594fSAndroid Build Coastguard Worker   jvmtiEnv* jvmtienv_;
326*795d594fSAndroid Build Coastguard Worker   jclass declaring_class_;
327*795d594fSAndroid Build Coastguard Worker   jfieldID field_;
328*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ScopedClassInfo> class_info_;
329*795d594fSAndroid Build Coastguard Worker   char* name_;
330*795d594fSAndroid Build Coastguard Worker   char* type_;
331*795d594fSAndroid Build Coastguard Worker 
332*795d594fSAndroid Build Coastguard Worker   friend std::ostream& operator<<(std::ostream &os, ScopedFieldInfo const& m);
333*795d594fSAndroid Build Coastguard Worker };
334*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const ScopedFieldInfo * m)335*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream &os, const ScopedFieldInfo* m) {
336*795d594fSAndroid Build Coastguard Worker   return os << *m;
337*795d594fSAndroid Build Coastguard Worker }
338*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,ScopedFieldInfo const & m)339*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream &os, ScopedFieldInfo const& m) {
340*795d594fSAndroid Build Coastguard Worker   return os << m.GetDeclaringClassInfo().GetName() << "->" << m.GetName()
341*795d594fSAndroid Build Coastguard Worker             << ":" << m.GetType();
342*795d594fSAndroid Build Coastguard Worker }
343*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const ScopedMethodInfo * m)344*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream &os, const ScopedMethodInfo* m) {
345*795d594fSAndroid Build Coastguard Worker   return os << *m;
346*795d594fSAndroid Build Coastguard Worker }
347*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,ScopedMethodInfo const & m)348*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream &os, ScopedMethodInfo const& m) {
349*795d594fSAndroid Build Coastguard Worker   return os << m.GetDeclaringClassInfo().GetName() << "->" << m.GetName() << m.GetSignature()
350*795d594fSAndroid Build Coastguard Worker             << " (source: " << m.GetDeclaringClassInfo().GetSourceFileName() << ":"
351*795d594fSAndroid Build Coastguard Worker             << m.GetFirstLine() << ")";
352*795d594fSAndroid Build Coastguard Worker }
353*795d594fSAndroid Build Coastguard Worker 
doJvmtiMethodBind(jvmtiEnv * jvmtienv,JNIEnv * env,jthread thread,jmethodID m,void * address,void ** out_address)354*795d594fSAndroid Build Coastguard Worker static void doJvmtiMethodBind(jvmtiEnv* jvmtienv,
355*795d594fSAndroid Build Coastguard Worker                               JNIEnv* env,
356*795d594fSAndroid Build Coastguard Worker                               jthread thread,
357*795d594fSAndroid Build Coastguard Worker                               jmethodID m,
358*795d594fSAndroid Build Coastguard Worker                               void* address,
359*795d594fSAndroid Build Coastguard Worker                               /*out*/void** out_address) {
360*795d594fSAndroid Build Coastguard Worker   *out_address = address;
361*795d594fSAndroid Build Coastguard Worker   ScopedThreadInfo thread_info(jvmtienv, env, thread);
362*795d594fSAndroid Build Coastguard Worker   ScopedMethodInfo method_info(jvmtienv, env, m);
363*795d594fSAndroid Build Coastguard Worker   if (!method_info.Init()) {
364*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to get method info!";
365*795d594fSAndroid Build Coastguard Worker     return;
366*795d594fSAndroid Build Coastguard Worker   }
367*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "Loading native method \"" << method_info << "\". Thread is "
368*795d594fSAndroid Build Coastguard Worker             << thread_info.GetName();
369*795d594fSAndroid Build Coastguard Worker }
370*795d594fSAndroid Build Coastguard Worker 
GetName(jvmtiEnv * jvmtienv,JNIEnv * jnienv,jobject obj)371*795d594fSAndroid Build Coastguard Worker static std::string GetName(jvmtiEnv* jvmtienv, JNIEnv* jnienv, jobject obj) {
372*795d594fSAndroid Build Coastguard Worker   jclass klass = jnienv->GetObjectClass(obj);
373*795d594fSAndroid Build Coastguard Worker   char *cname, *cgen;
374*795d594fSAndroid Build Coastguard Worker   if (jvmtienv->GetClassSignature(klass, &cname, &cgen) != JVMTI_ERROR_NONE) {
375*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to get class name!";
376*795d594fSAndroid Build Coastguard Worker     DeleteLocalRef(jnienv, klass);
377*795d594fSAndroid Build Coastguard Worker     return "<UNKNOWN>";
378*795d594fSAndroid Build Coastguard Worker   }
379*795d594fSAndroid Build Coastguard Worker   std::string name(cname);
380*795d594fSAndroid Build Coastguard Worker   if (name == "Ljava/lang/String;") {
381*795d594fSAndroid Build Coastguard Worker     jstring str = reinterpret_cast<jstring>(obj);
382*795d594fSAndroid Build Coastguard Worker     const char* val = jnienv->GetStringUTFChars(str, nullptr);
383*795d594fSAndroid Build Coastguard Worker     if (val == nullptr) {
384*795d594fSAndroid Build Coastguard Worker       name += " (unable to get value)";
385*795d594fSAndroid Build Coastguard Worker     } else {
386*795d594fSAndroid Build Coastguard Worker       std::ostringstream oss;
387*795d594fSAndroid Build Coastguard Worker       oss << name << " (value: \"" << val << "\")";
388*795d594fSAndroid Build Coastguard Worker       name = oss.str();
389*795d594fSAndroid Build Coastguard Worker       jnienv->ReleaseStringUTFChars(str, val);
390*795d594fSAndroid Build Coastguard Worker     }
391*795d594fSAndroid Build Coastguard Worker   }
392*795d594fSAndroid Build Coastguard Worker   jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(cname));
393*795d594fSAndroid Build Coastguard Worker   jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(cgen));
394*795d594fSAndroid Build Coastguard Worker   DeleteLocalRef(jnienv, klass);
395*795d594fSAndroid Build Coastguard Worker   return name;
396*795d594fSAndroid Build Coastguard Worker }
397*795d594fSAndroid Build Coastguard Worker 
GetValOf(jvmtiEnv * env,JNIEnv * jnienv,std::string type,jvalue val)398*795d594fSAndroid Build Coastguard Worker static std::string GetValOf(jvmtiEnv* env, JNIEnv* jnienv, std::string type, jvalue val) {
399*795d594fSAndroid Build Coastguard Worker   std::ostringstream oss;
400*795d594fSAndroid Build Coastguard Worker   switch (type[0]) {
401*795d594fSAndroid Build Coastguard Worker     case '[':
402*795d594fSAndroid Build Coastguard Worker     case 'L':
403*795d594fSAndroid Build Coastguard Worker       return val.l != nullptr ? GetName(env, jnienv, val.l) : "null";
404*795d594fSAndroid Build Coastguard Worker     case 'Z':
405*795d594fSAndroid Build Coastguard Worker       return val.z == JNI_TRUE ? "true" : "false";
406*795d594fSAndroid Build Coastguard Worker     case 'B':
407*795d594fSAndroid Build Coastguard Worker       oss << val.b;
408*795d594fSAndroid Build Coastguard Worker       return oss.str();
409*795d594fSAndroid Build Coastguard Worker     case 'C':
410*795d594fSAndroid Build Coastguard Worker       oss << val.c;
411*795d594fSAndroid Build Coastguard Worker       return oss.str();
412*795d594fSAndroid Build Coastguard Worker     case 'S':
413*795d594fSAndroid Build Coastguard Worker       oss << val.s;
414*795d594fSAndroid Build Coastguard Worker       return oss.str();
415*795d594fSAndroid Build Coastguard Worker     case 'I':
416*795d594fSAndroid Build Coastguard Worker       oss << val.i;
417*795d594fSAndroid Build Coastguard Worker       return oss.str();
418*795d594fSAndroid Build Coastguard Worker     case 'J':
419*795d594fSAndroid Build Coastguard Worker       oss << val.j;
420*795d594fSAndroid Build Coastguard Worker       return oss.str();
421*795d594fSAndroid Build Coastguard Worker     case 'F':
422*795d594fSAndroid Build Coastguard Worker       oss << val.f;
423*795d594fSAndroid Build Coastguard Worker       return oss.str();
424*795d594fSAndroid Build Coastguard Worker     case 'D':
425*795d594fSAndroid Build Coastguard Worker       oss << val.d;
426*795d594fSAndroid Build Coastguard Worker       return oss.str();
427*795d594fSAndroid Build Coastguard Worker     case 'V':
428*795d594fSAndroid Build Coastguard Worker       return "<void>";
429*795d594fSAndroid Build Coastguard Worker     default:
430*795d594fSAndroid Build Coastguard Worker       return "<ERROR Found type " + type + ">";
431*795d594fSAndroid Build Coastguard Worker   }
432*795d594fSAndroid Build Coastguard Worker }
433*795d594fSAndroid Build Coastguard Worker 
FieldAccessHook(jvmtiEnv * jvmtienv,JNIEnv * env,jthread thread,jmethodID m,jlocation location,jclass field_klass,jobject object,jfieldID field)434*795d594fSAndroid Build Coastguard Worker void JNICALL FieldAccessHook(jvmtiEnv* jvmtienv,
435*795d594fSAndroid Build Coastguard Worker                              JNIEnv* env,
436*795d594fSAndroid Build Coastguard Worker                              jthread thread,
437*795d594fSAndroid Build Coastguard Worker                              jmethodID m,
438*795d594fSAndroid Build Coastguard Worker                              jlocation location,
439*795d594fSAndroid Build Coastguard Worker                              jclass field_klass,
440*795d594fSAndroid Build Coastguard Worker                              jobject object,
441*795d594fSAndroid Build Coastguard Worker                              jfieldID field) {
442*795d594fSAndroid Build Coastguard Worker   ScopedThreadInfo info(jvmtienv, env, thread);
443*795d594fSAndroid Build Coastguard Worker   ScopedMethodInfo method_info(jvmtienv, env, m);
444*795d594fSAndroid Build Coastguard Worker   ScopedFieldInfo field_info(jvmtienv, field_klass, field);
445*795d594fSAndroid Build Coastguard Worker   jclass oklass = (object != nullptr) ? env->GetObjectClass(object) : nullptr;
446*795d594fSAndroid Build Coastguard Worker   ScopedClassInfo obj_class_info(jvmtienv, oklass);
447*795d594fSAndroid Build Coastguard Worker   if (!method_info.Init() || !field_info.Init() || !obj_class_info.Init()) {
448*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to get callback info!";
449*795d594fSAndroid Build Coastguard Worker     return;
450*795d594fSAndroid Build Coastguard Worker   }
451*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "ACCESS field \"" << field_info << "\" on object of "
452*795d594fSAndroid Build Coastguard Worker             << "type \"" << obj_class_info.GetName() << "\" in method \"" << method_info
453*795d594fSAndroid Build Coastguard Worker             << "\" at location 0x" << std::hex << location << ". Thread is \""
454*795d594fSAndroid Build Coastguard Worker             << info.GetName() << "\".";
455*795d594fSAndroid Build Coastguard Worker   DeleteLocalRef(env, oklass);
456*795d594fSAndroid Build Coastguard Worker }
457*795d594fSAndroid Build Coastguard Worker 
PrintJValue(jvmtiEnv * jvmtienv,JNIEnv * env,char type,jvalue new_value)458*795d594fSAndroid Build Coastguard Worker static std::string PrintJValue(jvmtiEnv* jvmtienv, JNIEnv* env, char type, jvalue new_value) {
459*795d594fSAndroid Build Coastguard Worker   std::ostringstream oss;
460*795d594fSAndroid Build Coastguard Worker   switch (type) {
461*795d594fSAndroid Build Coastguard Worker     case 'L': {
462*795d594fSAndroid Build Coastguard Worker       jobject nv = new_value.l;
463*795d594fSAndroid Build Coastguard Worker       if (nv == nullptr) {
464*795d594fSAndroid Build Coastguard Worker         oss << "\"null\"";
465*795d594fSAndroid Build Coastguard Worker       } else {
466*795d594fSAndroid Build Coastguard Worker         jclass nv_klass = env->GetObjectClass(nv);
467*795d594fSAndroid Build Coastguard Worker         ScopedClassInfo nv_class_info(jvmtienv, nv_klass);
468*795d594fSAndroid Build Coastguard Worker         if (!nv_class_info.Init()) {
469*795d594fSAndroid Build Coastguard Worker           oss << "with unknown type";
470*795d594fSAndroid Build Coastguard Worker         } else {
471*795d594fSAndroid Build Coastguard Worker           oss << "of type \"" << nv_class_info.GetName() << "\"";
472*795d594fSAndroid Build Coastguard Worker         }
473*795d594fSAndroid Build Coastguard Worker         DeleteLocalRef(env, nv_klass);
474*795d594fSAndroid Build Coastguard Worker       }
475*795d594fSAndroid Build Coastguard Worker       break;
476*795d594fSAndroid Build Coastguard Worker     }
477*795d594fSAndroid Build Coastguard Worker     case 'Z': {
478*795d594fSAndroid Build Coastguard Worker       if (new_value.z) {
479*795d594fSAndroid Build Coastguard Worker         oss << "true";
480*795d594fSAndroid Build Coastguard Worker       } else {
481*795d594fSAndroid Build Coastguard Worker         oss << "false";
482*795d594fSAndroid Build Coastguard Worker       }
483*795d594fSAndroid Build Coastguard Worker       break;
484*795d594fSAndroid Build Coastguard Worker     }
485*795d594fSAndroid Build Coastguard Worker #define SEND_VALUE(chr, sym, type) \
486*795d594fSAndroid Build Coastguard Worker     case chr: { \
487*795d594fSAndroid Build Coastguard Worker       oss << static_cast<type>(new_value.sym); \
488*795d594fSAndroid Build Coastguard Worker       break; \
489*795d594fSAndroid Build Coastguard Worker     }
490*795d594fSAndroid Build Coastguard Worker     SEND_VALUE('B', b, int8_t);
491*795d594fSAndroid Build Coastguard Worker     SEND_VALUE('C', c, uint16_t);
492*795d594fSAndroid Build Coastguard Worker     SEND_VALUE('S', s, int16_t);
493*795d594fSAndroid Build Coastguard Worker     SEND_VALUE('I', i, int32_t);
494*795d594fSAndroid Build Coastguard Worker     SEND_VALUE('J', j, int64_t);
495*795d594fSAndroid Build Coastguard Worker     SEND_VALUE('F', f, float);
496*795d594fSAndroid Build Coastguard Worker     SEND_VALUE('D', d, double);
497*795d594fSAndroid Build Coastguard Worker #undef SEND_VALUE
498*795d594fSAndroid Build Coastguard Worker   }
499*795d594fSAndroid Build Coastguard Worker   return oss.str();
500*795d594fSAndroid Build Coastguard Worker }
501*795d594fSAndroid Build Coastguard Worker 
FieldModificationHook(jvmtiEnv * jvmtienv,JNIEnv * env,jthread thread,jmethodID m,jlocation location,jclass field_klass,jobject object,jfieldID field,char type,jvalue new_value)502*795d594fSAndroid Build Coastguard Worker void JNICALL FieldModificationHook(jvmtiEnv* jvmtienv,
503*795d594fSAndroid Build Coastguard Worker                                    JNIEnv* env,
504*795d594fSAndroid Build Coastguard Worker                                    jthread thread,
505*795d594fSAndroid Build Coastguard Worker                                    jmethodID m,
506*795d594fSAndroid Build Coastguard Worker                                    jlocation location,
507*795d594fSAndroid Build Coastguard Worker                                    jclass field_klass,
508*795d594fSAndroid Build Coastguard Worker                                    jobject object,
509*795d594fSAndroid Build Coastguard Worker                                    jfieldID field,
510*795d594fSAndroid Build Coastguard Worker                                    char type,
511*795d594fSAndroid Build Coastguard Worker                                    jvalue new_value) {
512*795d594fSAndroid Build Coastguard Worker   ScopedThreadInfo info(jvmtienv, env, thread);
513*795d594fSAndroid Build Coastguard Worker   ScopedMethodInfo method_info(jvmtienv, env, m);
514*795d594fSAndroid Build Coastguard Worker   ScopedFieldInfo field_info(jvmtienv, field_klass, field);
515*795d594fSAndroid Build Coastguard Worker   jclass oklass = (object != nullptr) ? env->GetObjectClass(object) : nullptr;
516*795d594fSAndroid Build Coastguard Worker   ScopedClassInfo obj_class_info(jvmtienv, oklass);
517*795d594fSAndroid Build Coastguard Worker   if (!method_info.Init() || !field_info.Init() || !obj_class_info.Init()) {
518*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to get callback info!";
519*795d594fSAndroid Build Coastguard Worker     return;
520*795d594fSAndroid Build Coastguard Worker   }
521*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "MODIFY field \"" << field_info << "\" on object of "
522*795d594fSAndroid Build Coastguard Worker             << "type \"" << obj_class_info.GetName() << "\" in method \"" << method_info
523*795d594fSAndroid Build Coastguard Worker             << "\" at location 0x" << std::hex << location << std::dec << ". New value is "
524*795d594fSAndroid Build Coastguard Worker             << PrintJValue(jvmtienv, env, type, new_value) << ". Thread is \""
525*795d594fSAndroid Build Coastguard Worker             << info.GetName() << "\".";
526*795d594fSAndroid Build Coastguard Worker   DeleteLocalRef(env, oklass);
527*795d594fSAndroid Build Coastguard Worker }
MethodExitHook(jvmtiEnv * jvmtienv,JNIEnv * env,jthread thread,jmethodID m,jboolean was_popped_by_exception,jvalue val)528*795d594fSAndroid Build Coastguard Worker void JNICALL MethodExitHook(jvmtiEnv* jvmtienv,
529*795d594fSAndroid Build Coastguard Worker                             JNIEnv* env,
530*795d594fSAndroid Build Coastguard Worker                             jthread thread,
531*795d594fSAndroid Build Coastguard Worker                             jmethodID m,
532*795d594fSAndroid Build Coastguard Worker                             jboolean was_popped_by_exception,
533*795d594fSAndroid Build Coastguard Worker                             jvalue val) {
534*795d594fSAndroid Build Coastguard Worker   ScopedThreadInfo info(jvmtienv, env, thread);
535*795d594fSAndroid Build Coastguard Worker   ScopedMethodInfo method_info(jvmtienv, env, m);
536*795d594fSAndroid Build Coastguard Worker   if (!method_info.Init()) {
537*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to get method info!";
538*795d594fSAndroid Build Coastguard Worker     return;
539*795d594fSAndroid Build Coastguard Worker   }
540*795d594fSAndroid Build Coastguard Worker   std::string type(method_info.GetSignature());
541*795d594fSAndroid Build Coastguard Worker   type = type.substr(type.find(')') + 1);
542*795d594fSAndroid Build Coastguard Worker   std::string out_val(was_popped_by_exception ? "" : GetValOf(jvmtienv, env, type, val));
543*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "Leaving method \"" << method_info << "\". Thread is \"" << info.GetName() << "\"."
544*795d594fSAndroid Build Coastguard Worker             << std::endl
545*795d594fSAndroid Build Coastguard Worker             << "    Cause: " << (was_popped_by_exception ? "exception" : "return ")
546*795d594fSAndroid Build Coastguard Worker             << out_val << ".";
547*795d594fSAndroid Build Coastguard Worker }
548*795d594fSAndroid Build Coastguard Worker 
MethodEntryHook(jvmtiEnv * jvmtienv,JNIEnv * env,jthread thread,jmethodID m)549*795d594fSAndroid Build Coastguard Worker void JNICALL MethodEntryHook(jvmtiEnv* jvmtienv,
550*795d594fSAndroid Build Coastguard Worker                              JNIEnv* env,
551*795d594fSAndroid Build Coastguard Worker                              jthread thread,
552*795d594fSAndroid Build Coastguard Worker                              jmethodID m) {
553*795d594fSAndroid Build Coastguard Worker   ScopedThreadInfo info(jvmtienv, env, thread);
554*795d594fSAndroid Build Coastguard Worker   ScopedMethodInfo method_info(jvmtienv, env, m);
555*795d594fSAndroid Build Coastguard Worker   if (!method_info.Init()) {
556*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to get method info!";
557*795d594fSAndroid Build Coastguard Worker     return;
558*795d594fSAndroid Build Coastguard Worker   }
559*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "Entering method \"" << method_info << "\". Thread is \"" << info.GetName() << "\"";
560*795d594fSAndroid Build Coastguard Worker }
561*795d594fSAndroid Build Coastguard Worker 
ClassPrepareHook(jvmtiEnv * jvmtienv,JNIEnv * env,jthread thread,jclass klass)562*795d594fSAndroid Build Coastguard Worker void JNICALL ClassPrepareHook(jvmtiEnv* jvmtienv,
563*795d594fSAndroid Build Coastguard Worker                               JNIEnv* env,
564*795d594fSAndroid Build Coastguard Worker                               jthread thread,
565*795d594fSAndroid Build Coastguard Worker                               jclass klass) {
566*795d594fSAndroid Build Coastguard Worker   StressData* data = nullptr;
567*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(jvmtienv->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)),
568*795d594fSAndroid Build Coastguard Worker            JVMTI_ERROR_NONE);
569*795d594fSAndroid Build Coastguard Worker   if (data->field_stress) {
570*795d594fSAndroid Build Coastguard Worker     jint nfields;
571*795d594fSAndroid Build Coastguard Worker     jfieldID* fields;
572*795d594fSAndroid Build Coastguard Worker     if (jvmtienv->GetClassFields(klass, &nfields, &fields) != JVMTI_ERROR_NONE) {
573*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unable to get a classes fields!";
574*795d594fSAndroid Build Coastguard Worker       return;
575*795d594fSAndroid Build Coastguard Worker     }
576*795d594fSAndroid Build Coastguard Worker     for (jint i = 0; i < nfields; i++) {
577*795d594fSAndroid Build Coastguard Worker       jfieldID f = fields[i];
578*795d594fSAndroid Build Coastguard Worker       // Ignore errors
579*795d594fSAndroid Build Coastguard Worker       jvmtienv->SetFieldAccessWatch(klass, f);
580*795d594fSAndroid Build Coastguard Worker       jvmtienv->SetFieldModificationWatch(klass, f);
581*795d594fSAndroid Build Coastguard Worker     }
582*795d594fSAndroid Build Coastguard Worker     jvmtienv->Deallocate(reinterpret_cast<unsigned char*>(fields));
583*795d594fSAndroid Build Coastguard Worker   }
584*795d594fSAndroid Build Coastguard Worker   if (data->trace_stress) {
585*795d594fSAndroid Build Coastguard Worker     ScopedThreadInfo info(jvmtienv, env, thread);
586*795d594fSAndroid Build Coastguard Worker     ScopedClassInfo class_info(jvmtienv, klass);
587*795d594fSAndroid Build Coastguard Worker     if (!class_info.Init()) {
588*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unable to get class info!";
589*795d594fSAndroid Build Coastguard Worker       return;
590*795d594fSAndroid Build Coastguard Worker     }
591*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "Prepared class \"" << class_info.GetName() << "\". Thread is \""
592*795d594fSAndroid Build Coastguard Worker               << info.GetName() << "\"";
593*795d594fSAndroid Build Coastguard Worker   }
594*795d594fSAndroid Build Coastguard Worker }
595*795d594fSAndroid Build Coastguard Worker 
SingleStepHook(jvmtiEnv * jvmtienv,JNIEnv * env,jthread thread,jmethodID method,jlocation location)596*795d594fSAndroid Build Coastguard Worker void JNICALL SingleStepHook(jvmtiEnv* jvmtienv,
597*795d594fSAndroid Build Coastguard Worker                             JNIEnv* env,
598*795d594fSAndroid Build Coastguard Worker                             jthread thread,
599*795d594fSAndroid Build Coastguard Worker                             jmethodID method,
600*795d594fSAndroid Build Coastguard Worker                             jlocation location) {
601*795d594fSAndroid Build Coastguard Worker   ScopedThreadInfo info(jvmtienv, env, thread);
602*795d594fSAndroid Build Coastguard Worker   ScopedMethodInfo method_info(jvmtienv, env, method);
603*795d594fSAndroid Build Coastguard Worker   if (!method_info.Init()) {
604*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to get method info!";
605*795d594fSAndroid Build Coastguard Worker     return;
606*795d594fSAndroid Build Coastguard Worker   }
607*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "Single step at location: 0x" << std::setw(8) << std::setfill('0') << std::hex
608*795d594fSAndroid Build Coastguard Worker             << location << " in method " << method_info << " thread: " << info.GetName();
609*795d594fSAndroid Build Coastguard Worker }
610*795d594fSAndroid Build Coastguard Worker 
611*795d594fSAndroid Build Coastguard Worker // The hook we are using.
ClassFileLoadHookSecretNoOp(jvmtiEnv * jvmti,JNIEnv * jni_env,jclass class_being_redefined,jobject loader,const char * name,jobject protection_domain,jint class_data_len,const unsigned char * class_data,jint * new_class_data_len,unsigned char ** new_class_data)612*795d594fSAndroid Build Coastguard Worker void JNICALL ClassFileLoadHookSecretNoOp(jvmtiEnv* jvmti,
613*795d594fSAndroid Build Coastguard Worker                                          [[maybe_unused]] JNIEnv* jni_env,
614*795d594fSAndroid Build Coastguard Worker                                          [[maybe_unused]] jclass class_being_redefined,
615*795d594fSAndroid Build Coastguard Worker                                          [[maybe_unused]] jobject loader,
616*795d594fSAndroid Build Coastguard Worker                                          const char* name,
617*795d594fSAndroid Build Coastguard Worker                                          [[maybe_unused]] jobject protection_domain,
618*795d594fSAndroid Build Coastguard Worker                                          jint class_data_len,
619*795d594fSAndroid Build Coastguard Worker                                          const unsigned char* class_data,
620*795d594fSAndroid Build Coastguard Worker                                          jint* new_class_data_len,
621*795d594fSAndroid Build Coastguard Worker                                          unsigned char** new_class_data) {
622*795d594fSAndroid Build Coastguard Worker   std::vector<unsigned char> out;
623*795d594fSAndroid Build Coastguard Worker   // Make the jvmti semi-descriptor into the full descriptor.
624*795d594fSAndroid Build Coastguard Worker   std::string name_str("L");
625*795d594fSAndroid Build Coastguard Worker   name_str += name;
626*795d594fSAndroid Build Coastguard Worker   name_str += ";";
627*795d594fSAndroid Build Coastguard Worker   StressData* data = nullptr;
628*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)),
629*795d594fSAndroid Build Coastguard Worker            JVMTI_ERROR_NONE);
630*795d594fSAndroid Build Coastguard Worker   if (!data->vm_class_loader_initialized) {
631*795d594fSAndroid Build Coastguard Worker     LOG(WARNING) << "Ignoring load of class " << name << " because VMClassLoader is not yet "
632*795d594fSAndroid Build Coastguard Worker                  << "initialized. Transforming this class could cause spurious test failures.";
633*795d594fSAndroid Build Coastguard Worker     return;
634*795d594fSAndroid Build Coastguard Worker   } else if (DoExtractClassFromData(jvmti, name_str, class_data_len, class_data,
635*795d594fSAndroid Build Coastguard Worker                                     /*out*/ new_class_data_len, /*out*/ new_class_data)) {
636*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "Extracted class: " << name;
637*795d594fSAndroid Build Coastguard Worker   } else {
638*795d594fSAndroid Build Coastguard Worker     std::cerr << "Unable to extract class " << name << std::endl;
639*795d594fSAndroid Build Coastguard Worker     *new_class_data_len = 0;
640*795d594fSAndroid Build Coastguard Worker     *new_class_data = nullptr;
641*795d594fSAndroid Build Coastguard Worker   }
642*795d594fSAndroid Build Coastguard Worker }
643*795d594fSAndroid Build Coastguard Worker 
AdvanceOption(const std::string & ops)644*795d594fSAndroid Build Coastguard Worker static std::string AdvanceOption(const std::string& ops) {
645*795d594fSAndroid Build Coastguard Worker   return ops.substr(ops.find(',') + 1);
646*795d594fSAndroid Build Coastguard Worker }
647*795d594fSAndroid Build Coastguard Worker 
HasNextOption(const std::string & ops)648*795d594fSAndroid Build Coastguard Worker static bool HasNextOption(const std::string& ops) {
649*795d594fSAndroid Build Coastguard Worker   return ops.find(',') != std::string::npos;
650*795d594fSAndroid Build Coastguard Worker }
651*795d594fSAndroid Build Coastguard Worker 
GetOption(const std::string & in)652*795d594fSAndroid Build Coastguard Worker static std::string GetOption(const std::string& in) {
653*795d594fSAndroid Build Coastguard Worker   return in.substr(0, in.find(','));
654*795d594fSAndroid Build Coastguard Worker }
655*795d594fSAndroid Build Coastguard Worker 
656*795d594fSAndroid Build Coastguard Worker // Options are
657*795d594fSAndroid Build Coastguard Worker // jvmti-stress,[redefine,][trace,][field]
ReadOptions(StressData * data,char * options)658*795d594fSAndroid Build Coastguard Worker static void ReadOptions(StressData* data, char* options) {
659*795d594fSAndroid Build Coastguard Worker   std::string ops(options);
660*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(GetOption(ops), "jvmti-stress") << "Options should start with jvmti-stress";
661*795d594fSAndroid Build Coastguard Worker   do {
662*795d594fSAndroid Build Coastguard Worker     ops = AdvanceOption(ops);
663*795d594fSAndroid Build Coastguard Worker     std::string cur = GetOption(ops);
664*795d594fSAndroid Build Coastguard Worker     if (cur == "trace") {
665*795d594fSAndroid Build Coastguard Worker       data->trace_stress = true;
666*795d594fSAndroid Build Coastguard Worker     } else if (cur == "step") {
667*795d594fSAndroid Build Coastguard Worker       data->step_stress = true;
668*795d594fSAndroid Build Coastguard Worker     } else if (cur == "field") {
669*795d594fSAndroid Build Coastguard Worker       data->field_stress = true;
670*795d594fSAndroid Build Coastguard Worker     } else if (cur == "redefine") {
671*795d594fSAndroid Build Coastguard Worker       data->redefine_stress = true;
672*795d594fSAndroid Build Coastguard Worker     } else {
673*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unknown option: " << GetOption(ops);
674*795d594fSAndroid Build Coastguard Worker     }
675*795d594fSAndroid Build Coastguard Worker   } while (HasNextOption(ops));
676*795d594fSAndroid Build Coastguard Worker }
677*795d594fSAndroid Build Coastguard Worker 
678*795d594fSAndroid Build Coastguard Worker // Do final setup during the VMInit callback. By this time most things are all setup.
PerformFinalSetupVMInit(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)679*795d594fSAndroid Build Coastguard Worker static void JNICALL PerformFinalSetupVMInit(jvmtiEnv *jvmti_env,
680*795d594fSAndroid Build Coastguard Worker                                             JNIEnv* jni_env,
681*795d594fSAndroid Build Coastguard Worker                                             [[maybe_unused]] jthread thread) {
682*795d594fSAndroid Build Coastguard Worker   // Load the VMClassLoader class. We will get a ClassNotFound exception because we don't have
683*795d594fSAndroid Build Coastguard Worker   // visibility but the class will be loaded behind the scenes.
684*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "manual load & initialization of class java/lang/VMClassLoader!";
685*795d594fSAndroid Build Coastguard Worker   jclass klass = jni_env->FindClass("java/lang/VMClassLoader");
686*795d594fSAndroid Build Coastguard Worker   StressData* data = nullptr;
687*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(jvmti_env->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)),
688*795d594fSAndroid Build Coastguard Worker            JVMTI_ERROR_NONE);
689*795d594fSAndroid Build Coastguard Worker   // We need to make sure that VMClassLoader is initialized before we start redefining anything
690*795d594fSAndroid Build Coastguard Worker   // since it can give (non-fatal) error messages if it's initialized after we've redefined BCP
691*795d594fSAndroid Build Coastguard Worker   // classes. These error messages are expected and no problem but they will mess up our testing
692*795d594fSAndroid Build Coastguard Worker   // infrastructure.
693*795d594fSAndroid Build Coastguard Worker   if (klass == nullptr) {
694*795d594fSAndroid Build Coastguard Worker     // Probably on RI. Clear the exception so we can continue but don't mark vmclassloader as
695*795d594fSAndroid Build Coastguard Worker     // initialized.
696*795d594fSAndroid Build Coastguard Worker     LOG(WARNING) << "Unable to find VMClassLoader class!";
697*795d594fSAndroid Build Coastguard Worker     jni_env->ExceptionClear();
698*795d594fSAndroid Build Coastguard Worker   } else {
699*795d594fSAndroid Build Coastguard Worker     // GetMethodID is spec'd to cause the class to be initialized.
700*795d594fSAndroid Build Coastguard Worker     jni_env->GetMethodID(klass, "hashCode", "()I");
701*795d594fSAndroid Build Coastguard Worker     DeleteLocalRef(jni_env, klass);
702*795d594fSAndroid Build Coastguard Worker     data->vm_class_loader_initialized = true;
703*795d594fSAndroid Build Coastguard Worker   }
704*795d594fSAndroid Build Coastguard Worker }
705*795d594fSAndroid Build Coastguard Worker 
WatchAllFields(JavaVM * vm,jvmtiEnv * jvmti)706*795d594fSAndroid Build Coastguard Worker static bool WatchAllFields(JavaVM* vm, jvmtiEnv* jvmti) {
707*795d594fSAndroid Build Coastguard Worker   if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
708*795d594fSAndroid Build Coastguard Worker                                       JVMTI_EVENT_CLASS_PREPARE,
709*795d594fSAndroid Build Coastguard Worker                                       nullptr) != JVMTI_ERROR_NONE) {
710*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Couldn't set prepare event!";
711*795d594fSAndroid Build Coastguard Worker     return false;
712*795d594fSAndroid Build Coastguard Worker   }
713*795d594fSAndroid Build Coastguard Worker   // TODO We really shouldn't need to do this step here.
714*795d594fSAndroid Build Coastguard Worker   jint nklass;
715*795d594fSAndroid Build Coastguard Worker   jclass* klasses;
716*795d594fSAndroid Build Coastguard Worker   if (jvmti->GetLoadedClasses(&nklass, &klasses) != JVMTI_ERROR_NONE) {
717*795d594fSAndroid Build Coastguard Worker     LOG(WARNING) << "Couldn't get loaded classes! Ignoring.";
718*795d594fSAndroid Build Coastguard Worker     return true;
719*795d594fSAndroid Build Coastguard Worker   }
720*795d594fSAndroid Build Coastguard Worker   JNIEnv* jni = nullptr;
721*795d594fSAndroid Build Coastguard Worker   if (vm->GetEnv(reinterpret_cast<void**>(&jni), JNI_VERSION_1_6)) {
722*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to get jni env. Ignoring and potentially leaking jobjects.";
723*795d594fSAndroid Build Coastguard Worker     return false;
724*795d594fSAndroid Build Coastguard Worker   }
725*795d594fSAndroid Build Coastguard Worker   for (jint i = 0; i < nklass; i++) {
726*795d594fSAndroid Build Coastguard Worker     jclass k = klasses[i];
727*795d594fSAndroid Build Coastguard Worker     ScopedClassInfo sci(jvmti, k);
728*795d594fSAndroid Build Coastguard Worker     if (sci.Init()) {
729*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << "NOTE: class " << sci.GetName() << " already loaded.";
730*795d594fSAndroid Build Coastguard Worker     }
731*795d594fSAndroid Build Coastguard Worker     jint nfields;
732*795d594fSAndroid Build Coastguard Worker     jfieldID* fields;
733*795d594fSAndroid Build Coastguard Worker     jvmtiError err = jvmti->GetClassFields(k, &nfields, &fields);
734*795d594fSAndroid Build Coastguard Worker     if (err == JVMTI_ERROR_NONE) {
735*795d594fSAndroid Build Coastguard Worker       for (jint j = 0; j < nfields; j++) {
736*795d594fSAndroid Build Coastguard Worker         jfieldID f = fields[j];
737*795d594fSAndroid Build Coastguard Worker         if (jvmti->SetFieldModificationWatch(k, f) != JVMTI_ERROR_NONE ||
738*795d594fSAndroid Build Coastguard Worker             jvmti->SetFieldAccessWatch(k, f) != JVMTI_ERROR_NONE) {
739*795d594fSAndroid Build Coastguard Worker           LOG(ERROR) << "Unable to set watches on a field.";
740*795d594fSAndroid Build Coastguard Worker           return false;
741*795d594fSAndroid Build Coastguard Worker         }
742*795d594fSAndroid Build Coastguard Worker       }
743*795d594fSAndroid Build Coastguard Worker     } else if (err != JVMTI_ERROR_CLASS_NOT_PREPARED) {
744*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unexpected error getting class fields!";
745*795d594fSAndroid Build Coastguard Worker       return false;
746*795d594fSAndroid Build Coastguard Worker     }
747*795d594fSAndroid Build Coastguard Worker     jvmti->Deallocate(reinterpret_cast<unsigned char*>(fields));
748*795d594fSAndroid Build Coastguard Worker     DeleteLocalRef(jni, k);
749*795d594fSAndroid Build Coastguard Worker   }
750*795d594fSAndroid Build Coastguard Worker   jvmti->Deallocate(reinterpret_cast<unsigned char*>(klasses));
751*795d594fSAndroid Build Coastguard Worker   return true;
752*795d594fSAndroid Build Coastguard Worker }
753*795d594fSAndroid Build Coastguard Worker 
Agent_OnLoad(JavaVM * vm,char * options,void * reserved)754*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm,
755*795d594fSAndroid Build Coastguard Worker                                                char* options,
756*795d594fSAndroid Build Coastguard Worker                                                [[maybe_unused]] void* reserved) {
757*795d594fSAndroid Build Coastguard Worker   jvmtiEnv* jvmti = nullptr;
758*795d594fSAndroid Build Coastguard Worker   if (vm->GetEnv(reinterpret_cast<void**>(&jvmti), JVMTI_VERSION_1_0)) {
759*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to get jvmti env.";
760*795d594fSAndroid Build Coastguard Worker     return 1;
761*795d594fSAndroid Build Coastguard Worker   }
762*795d594fSAndroid Build Coastguard Worker   StressData* data = nullptr;
763*795d594fSAndroid Build Coastguard Worker   if (JVMTI_ERROR_NONE != jvmti->Allocate(sizeof(StressData),
764*795d594fSAndroid Build Coastguard Worker                                           reinterpret_cast<unsigned char**>(&data))) {
765*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to allocate data for stress test.";
766*795d594fSAndroid Build Coastguard Worker     return 1;
767*795d594fSAndroid Build Coastguard Worker   }
768*795d594fSAndroid Build Coastguard Worker   memset(data, 0, sizeof(StressData));
769*795d594fSAndroid Build Coastguard Worker   // Read the options into the static variables that hold them.
770*795d594fSAndroid Build Coastguard Worker   ReadOptions(data, options);
771*795d594fSAndroid Build Coastguard Worker   // Save the data
772*795d594fSAndroid Build Coastguard Worker   if (JVMTI_ERROR_NONE != jvmti->SetEnvironmentLocalStorage(data)) {
773*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to save stress test data.";
774*795d594fSAndroid Build Coastguard Worker     return 1;
775*795d594fSAndroid Build Coastguard Worker   }
776*795d594fSAndroid Build Coastguard Worker 
777*795d594fSAndroid Build Coastguard Worker   // Just get all capabilities.
778*795d594fSAndroid Build Coastguard Worker   jvmtiCapabilities caps = {
779*795d594fSAndroid Build Coastguard Worker     .can_tag_objects                                 = 0,
780*795d594fSAndroid Build Coastguard Worker     .can_generate_field_modification_events          = 1,
781*795d594fSAndroid Build Coastguard Worker     .can_generate_field_access_events                = 1,
782*795d594fSAndroid Build Coastguard Worker     .can_get_bytecodes                               = 0,
783*795d594fSAndroid Build Coastguard Worker     .can_get_synthetic_attribute                     = 0,
784*795d594fSAndroid Build Coastguard Worker     .can_get_owned_monitor_info                      = 0,
785*795d594fSAndroid Build Coastguard Worker     .can_get_current_contended_monitor               = 0,
786*795d594fSAndroid Build Coastguard Worker     .can_get_monitor_info                            = 0,
787*795d594fSAndroid Build Coastguard Worker     .can_pop_frame                                   = 0,
788*795d594fSAndroid Build Coastguard Worker     .can_redefine_classes                            = 1,
789*795d594fSAndroid Build Coastguard Worker     .can_signal_thread                               = 0,
790*795d594fSAndroid Build Coastguard Worker     .can_get_source_file_name                        = 1,
791*795d594fSAndroid Build Coastguard Worker     .can_get_line_numbers                            = 1,
792*795d594fSAndroid Build Coastguard Worker     .can_get_source_debug_extension                  = 1,
793*795d594fSAndroid Build Coastguard Worker     .can_access_local_variables                      = 0,
794*795d594fSAndroid Build Coastguard Worker     .can_maintain_original_method_order              = 0,
795*795d594fSAndroid Build Coastguard Worker     .can_generate_single_step_events                 = 1,
796*795d594fSAndroid Build Coastguard Worker     .can_generate_exception_events                   = 0,
797*795d594fSAndroid Build Coastguard Worker     .can_generate_frame_pop_events                   = 0,
798*795d594fSAndroid Build Coastguard Worker     .can_generate_breakpoint_events                  = 0,
799*795d594fSAndroid Build Coastguard Worker     .can_suspend                                     = 0,
800*795d594fSAndroid Build Coastguard Worker     .can_redefine_any_class                          = 0,
801*795d594fSAndroid Build Coastguard Worker     .can_get_current_thread_cpu_time                 = 0,
802*795d594fSAndroid Build Coastguard Worker     .can_get_thread_cpu_time                         = 0,
803*795d594fSAndroid Build Coastguard Worker     .can_generate_method_entry_events                = 1,
804*795d594fSAndroid Build Coastguard Worker     .can_generate_method_exit_events                 = 1,
805*795d594fSAndroid Build Coastguard Worker     .can_generate_all_class_hook_events              = 0,
806*795d594fSAndroid Build Coastguard Worker     .can_generate_compiled_method_load_events        = 0,
807*795d594fSAndroid Build Coastguard Worker     .can_generate_monitor_events                     = 0,
808*795d594fSAndroid Build Coastguard Worker     .can_generate_vm_object_alloc_events             = 0,
809*795d594fSAndroid Build Coastguard Worker     .can_generate_native_method_bind_events          = 1,
810*795d594fSAndroid Build Coastguard Worker     .can_generate_garbage_collection_events          = 0,
811*795d594fSAndroid Build Coastguard Worker     .can_generate_object_free_events                 = 0,
812*795d594fSAndroid Build Coastguard Worker     .can_force_early_return                          = 0,
813*795d594fSAndroid Build Coastguard Worker     .can_get_owned_monitor_stack_depth_info          = 0,
814*795d594fSAndroid Build Coastguard Worker     .can_get_constant_pool                           = 0,
815*795d594fSAndroid Build Coastguard Worker     .can_set_native_method_prefix                    = 0,
816*795d594fSAndroid Build Coastguard Worker     .can_retransform_classes                         = 1,
817*795d594fSAndroid Build Coastguard Worker     .can_retransform_any_class                       = 0,
818*795d594fSAndroid Build Coastguard Worker     .can_generate_resource_exhaustion_heap_events    = 0,
819*795d594fSAndroid Build Coastguard Worker     .can_generate_resource_exhaustion_threads_events = 0,
820*795d594fSAndroid Build Coastguard Worker   };
821*795d594fSAndroid Build Coastguard Worker   jvmti->AddCapabilities(&caps);
822*795d594fSAndroid Build Coastguard Worker 
823*795d594fSAndroid Build Coastguard Worker   // Set callbacks.
824*795d594fSAndroid Build Coastguard Worker   jvmtiEventCallbacks cb;
825*795d594fSAndroid Build Coastguard Worker   memset(&cb, 0, sizeof(cb));
826*795d594fSAndroid Build Coastguard Worker   cb.ClassFileLoadHook = ClassFileLoadHookSecretNoOp;
827*795d594fSAndroid Build Coastguard Worker   cb.NativeMethodBind = doJvmtiMethodBind;
828*795d594fSAndroid Build Coastguard Worker   cb.VMInit = PerformFinalSetupVMInit;
829*795d594fSAndroid Build Coastguard Worker   cb.MethodEntry = MethodEntryHook;
830*795d594fSAndroid Build Coastguard Worker   cb.MethodExit = MethodExitHook;
831*795d594fSAndroid Build Coastguard Worker   cb.FieldAccess = FieldAccessHook;
832*795d594fSAndroid Build Coastguard Worker   cb.FieldModification = FieldModificationHook;
833*795d594fSAndroid Build Coastguard Worker   cb.ClassPrepare = ClassPrepareHook;
834*795d594fSAndroid Build Coastguard Worker   cb.SingleStep = SingleStepHook;
835*795d594fSAndroid Build Coastguard Worker   if (jvmti->SetEventCallbacks(&cb, sizeof(cb)) != JVMTI_ERROR_NONE) {
836*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to set class file load hook cb!";
837*795d594fSAndroid Build Coastguard Worker     return 1;
838*795d594fSAndroid Build Coastguard Worker   }
839*795d594fSAndroid Build Coastguard Worker   if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
840*795d594fSAndroid Build Coastguard Worker                                       JVMTI_EVENT_VM_INIT,
841*795d594fSAndroid Build Coastguard Worker                                       nullptr) != JVMTI_ERROR_NONE) {
842*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to enable JVMTI_EVENT_VM_INIT event!";
843*795d594fSAndroid Build Coastguard Worker     return 1;
844*795d594fSAndroid Build Coastguard Worker   }
845*795d594fSAndroid Build Coastguard Worker   if (data->redefine_stress) {
846*795d594fSAndroid Build Coastguard Worker     if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
847*795d594fSAndroid Build Coastguard Worker                                         JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
848*795d594fSAndroid Build Coastguard Worker                                         nullptr) != JVMTI_ERROR_NONE) {
849*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unable to enable CLASS_FILE_LOAD_HOOK event!";
850*795d594fSAndroid Build Coastguard Worker       return 1;
851*795d594fSAndroid Build Coastguard Worker     }
852*795d594fSAndroid Build Coastguard Worker   }
853*795d594fSAndroid Build Coastguard Worker   if (data->trace_stress) {
854*795d594fSAndroid Build Coastguard Worker     if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
855*795d594fSAndroid Build Coastguard Worker                                         JVMTI_EVENT_CLASS_PREPARE,
856*795d594fSAndroid Build Coastguard Worker                                         nullptr) != JVMTI_ERROR_NONE) {
857*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unable to enable CLASS_PREPARE event!";
858*795d594fSAndroid Build Coastguard Worker       return 1;
859*795d594fSAndroid Build Coastguard Worker     }
860*795d594fSAndroid Build Coastguard Worker     if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
861*795d594fSAndroid Build Coastguard Worker                                         JVMTI_EVENT_NATIVE_METHOD_BIND,
862*795d594fSAndroid Build Coastguard Worker                                         nullptr) != JVMTI_ERROR_NONE) {
863*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unable to enable JVMTI_EVENT_NATIVE_METHOD_BIND event!";
864*795d594fSAndroid Build Coastguard Worker       return 1;
865*795d594fSAndroid Build Coastguard Worker     }
866*795d594fSAndroid Build Coastguard Worker     if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
867*795d594fSAndroid Build Coastguard Worker                                         JVMTI_EVENT_METHOD_ENTRY,
868*795d594fSAndroid Build Coastguard Worker                                         nullptr) != JVMTI_ERROR_NONE) {
869*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unable to enable JVMTI_EVENT_METHOD_ENTRY event!";
870*795d594fSAndroid Build Coastguard Worker       return 1;
871*795d594fSAndroid Build Coastguard Worker     }
872*795d594fSAndroid Build Coastguard Worker     if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
873*795d594fSAndroid Build Coastguard Worker                                         JVMTI_EVENT_METHOD_EXIT,
874*795d594fSAndroid Build Coastguard Worker                                         nullptr) != JVMTI_ERROR_NONE) {
875*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unable to enable JVMTI_EVENT_METHOD_EXIT event!";
876*795d594fSAndroid Build Coastguard Worker       return 1;
877*795d594fSAndroid Build Coastguard Worker     }
878*795d594fSAndroid Build Coastguard Worker   }
879*795d594fSAndroid Build Coastguard Worker   if (data->field_stress) {
880*795d594fSAndroid Build Coastguard Worker     if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
881*795d594fSAndroid Build Coastguard Worker                                         JVMTI_EVENT_FIELD_MODIFICATION,
882*795d594fSAndroid Build Coastguard Worker                                         nullptr) != JVMTI_ERROR_NONE) {
883*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unable to enable FIELD_MODIFICATION event!";
884*795d594fSAndroid Build Coastguard Worker       return 1;
885*795d594fSAndroid Build Coastguard Worker     }
886*795d594fSAndroid Build Coastguard Worker     if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
887*795d594fSAndroid Build Coastguard Worker                                         JVMTI_EVENT_FIELD_ACCESS,
888*795d594fSAndroid Build Coastguard Worker                                         nullptr) != JVMTI_ERROR_NONE) {
889*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unable to enable FIELD_ACCESS event!";
890*795d594fSAndroid Build Coastguard Worker       return 1;
891*795d594fSAndroid Build Coastguard Worker     }
892*795d594fSAndroid Build Coastguard Worker     if (!WatchAllFields(vm, jvmti)) {
893*795d594fSAndroid Build Coastguard Worker       return 1;
894*795d594fSAndroid Build Coastguard Worker     }
895*795d594fSAndroid Build Coastguard Worker   }
896*795d594fSAndroid Build Coastguard Worker   if (data->step_stress) {
897*795d594fSAndroid Build Coastguard Worker     if (jvmti->SetEventNotificationMode(JVMTI_ENABLE,
898*795d594fSAndroid Build Coastguard Worker                                         JVMTI_EVENT_SINGLE_STEP,
899*795d594fSAndroid Build Coastguard Worker                                         nullptr) != JVMTI_ERROR_NONE) {
900*795d594fSAndroid Build Coastguard Worker       return 1;
901*795d594fSAndroid Build Coastguard Worker     }
902*795d594fSAndroid Build Coastguard Worker   }
903*795d594fSAndroid Build Coastguard Worker   return 0;
904*795d594fSAndroid Build Coastguard Worker }
905*795d594fSAndroid Build Coastguard Worker 
Agent_OnAttach(JavaVM * vm,char * options,void * reserved)906*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm, char* options, void* reserved) {
907*795d594fSAndroid Build Coastguard Worker   return Agent_OnLoad(vm, options, reserved);
908*795d594fSAndroid Build Coastguard Worker }
909*795d594fSAndroid Build Coastguard Worker 
910*795d594fSAndroid Build Coastguard Worker }  // namespace art
911