1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "runtime_callbacks.h"
18 
19 #include <algorithm>
20 
21 #include "art_method.h"
22 #include "base/macros.h"
23 #include "base/mutex-inl.h"
24 #include "class_linker.h"
25 #include "monitor.h"
26 #include "thread-current-inl.h"
27 
28 namespace art {
29 
RuntimeCallbacks()30 RuntimeCallbacks::RuntimeCallbacks()
31     : callback_lock_(new ReaderWriterMutex("Runtime callbacks lock",
32                                            LockLevel::kGenericBottomLock)) {}
33 
34 // We don't want to be holding any locks when the actual event is called so we use this to define a
35 // helper that gets a copy of the current event list and returns it.
36 #define COPY(T)                                                   \
37   ([this]() -> decltype(this->T) {                                \
38     ReaderMutexLock mu(Thread::Current(), *this->callback_lock_); \
39     return std::vector<decltype(this->T)::value_type>(this->T);   \
40   })()
41 
42 template <typename T>
43 ALWAYS_INLINE
Remove(T * cb,std::vector<T * > * data)44 static inline void Remove(T* cb, std::vector<T*>* data) {
45   auto it = std::find(data->begin(), data->end(), cb);
46   if (it != data->end()) {
47     data->erase(it);
48   }
49 }
50 
AddDdmCallback(DdmCallback * cb)51 void RuntimeCallbacks::AddDdmCallback(DdmCallback* cb) {
52   WriterMutexLock mu(Thread::Current(), *callback_lock_);
53   ddm_callbacks_.push_back(cb);
54 }
55 
RemoveDdmCallback(DdmCallback * cb)56 void RuntimeCallbacks::RemoveDdmCallback(DdmCallback* cb) {
57   WriterMutexLock mu(Thread::Current(), *callback_lock_);
58   Remove(cb, &ddm_callbacks_);
59 }
60 
DdmPublishChunk(uint32_t type,const ArrayRef<const uint8_t> & data)61 void RuntimeCallbacks::DdmPublishChunk(uint32_t type, const ArrayRef<const uint8_t>& data) {
62   for (DdmCallback* cb : COPY(ddm_callbacks_)) {
63     cb->DdmPublishChunk(type, data);
64   }
65 }
66 
AddDebuggerControlCallback(DebuggerControlCallback * cb)67 void RuntimeCallbacks::AddDebuggerControlCallback(DebuggerControlCallback* cb) {
68   WriterMutexLock mu(Thread::Current(), *callback_lock_);
69   debugger_control_callbacks_.push_back(cb);
70 }
71 
RemoveDebuggerControlCallback(DebuggerControlCallback * cb)72 void RuntimeCallbacks::RemoveDebuggerControlCallback(DebuggerControlCallback* cb) {
73   WriterMutexLock mu(Thread::Current(), *callback_lock_);
74   Remove(cb, &debugger_control_callbacks_);
75 }
76 
IsDebuggerConfigured()77 bool RuntimeCallbacks::IsDebuggerConfigured() {
78   for (DebuggerControlCallback* cb : COPY(debugger_control_callbacks_)) {
79     if (cb->IsDebuggerConfigured()) {
80       return true;
81     }
82   }
83   return false;
84 }
85 
StartDebugger()86 void RuntimeCallbacks::StartDebugger() {
87   for (DebuggerControlCallback* cb : COPY(debugger_control_callbacks_)) {
88     cb->StartDebugger();
89   }
90 }
91 
StopDebugger()92 void RuntimeCallbacks::StopDebugger() {
93   for (DebuggerControlCallback* cb : COPY(debugger_control_callbacks_)) {
94     cb->StopDebugger();
95   }
96 }
97 
AddMethodInspectionCallback(MethodInspectionCallback * cb)98 void RuntimeCallbacks::AddMethodInspectionCallback(MethodInspectionCallback* cb) {
99   WriterMutexLock mu(Thread::Current(), *callback_lock_);
100   method_inspection_callbacks_.push_back(cb);
101 }
102 
RemoveMethodInspectionCallback(MethodInspectionCallback * cb)103 void RuntimeCallbacks::RemoveMethodInspectionCallback(MethodInspectionCallback* cb) {
104   WriterMutexLock mu(Thread::Current(), *callback_lock_);
105   Remove(cb, &method_inspection_callbacks_);
106 }
107 
IsMethodSafeToJit(ArtMethod * m)108 bool RuntimeCallbacks::IsMethodSafeToJit(ArtMethod* m) {
109   for (MethodInspectionCallback* cb : COPY(method_inspection_callbacks_)) {
110     if (!cb->IsMethodSafeToJit(m)) {
111       DCHECK(cb->IsMethodBeingInspected(m))
112           << "Contract requires that !IsMethodSafeToJit(m) -> IsMethodBeingInspected(m)";
113       return false;
114     }
115   }
116   return true;
117 }
118 
IsMethodBeingInspected(ArtMethod * m)119 bool RuntimeCallbacks::IsMethodBeingInspected(ArtMethod* m) {
120   for (MethodInspectionCallback* cb : COPY(method_inspection_callbacks_)) {
121     if (cb->IsMethodBeingInspected(m)) {
122       return true;
123     }
124   }
125   return false;
126 }
127 
MethodNeedsDebugVersion(ArtMethod * m)128 bool RuntimeCallbacks::MethodNeedsDebugVersion(ArtMethod* m) {
129   for (MethodInspectionCallback* cb : COPY(method_inspection_callbacks_)) {
130     if (cb->MethodNeedsDebugVersion(m)) {
131       return true;
132     }
133   }
134   return false;
135 }
136 
AddThreadLifecycleCallback(ThreadLifecycleCallback * cb)137 void RuntimeCallbacks::AddThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
138   WriterMutexLock mu(Thread::Current(), *callback_lock_);
139   thread_callbacks_.push_back(cb);
140 }
141 
MonitorContendedLocking(Monitor * m)142 void RuntimeCallbacks::MonitorContendedLocking(Monitor* m) {
143   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
144     cb->MonitorContendedLocking(m);
145   }
146 }
147 
MonitorContendedLocked(Monitor * m)148 void RuntimeCallbacks::MonitorContendedLocked(Monitor* m) {
149   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
150     cb->MonitorContendedLocked(m);
151   }
152 }
153 
ObjectWaitStart(Handle<mirror::Object> m,int64_t timeout)154 void RuntimeCallbacks::ObjectWaitStart(Handle<mirror::Object> m, int64_t timeout) {
155   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
156     cb->ObjectWaitStart(m, timeout);
157   }
158 }
159 
MonitorWaitFinished(Monitor * m,bool timeout)160 void RuntimeCallbacks::MonitorWaitFinished(Monitor* m, bool timeout) {
161   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
162     cb->MonitorWaitFinished(m, timeout);
163   }
164 }
165 
AddMonitorCallback(MonitorCallback * cb)166 void RuntimeCallbacks::AddMonitorCallback(MonitorCallback* cb) {
167   WriterMutexLock mu(Thread::Current(), *callback_lock_);
168   monitor_callbacks_.push_back(cb);
169 }
170 
RemoveMonitorCallback(MonitorCallback * cb)171 void RuntimeCallbacks::RemoveMonitorCallback(MonitorCallback* cb) {
172   WriterMutexLock mu(Thread::Current(), *callback_lock_);
173   Remove(cb, &monitor_callbacks_);
174 }
175 
ThreadParkStart(bool is_absolute,int64_t timeout)176 void RuntimeCallbacks::ThreadParkStart(bool is_absolute, int64_t timeout) {
177   for (ParkCallback * cb : COPY(park_callbacks_)) {
178     cb->ThreadParkStart(is_absolute, timeout);
179   }
180 }
181 
ThreadParkFinished(bool timeout)182 void RuntimeCallbacks::ThreadParkFinished(bool timeout) {
183   for (ParkCallback * cb : COPY(park_callbacks_)) {
184     cb->ThreadParkFinished(timeout);
185   }
186 }
187 
AddParkCallback(ParkCallback * cb)188 void RuntimeCallbacks::AddParkCallback(ParkCallback* cb) {
189   WriterMutexLock mu(Thread::Current(), *callback_lock_);
190   park_callbacks_.push_back(cb);
191 }
192 
RemoveParkCallback(ParkCallback * cb)193 void RuntimeCallbacks::RemoveParkCallback(ParkCallback* cb) {
194   WriterMutexLock mu(Thread::Current(), *callback_lock_);
195   Remove(cb, &park_callbacks_);
196 }
197 
RemoveThreadLifecycleCallback(ThreadLifecycleCallback * cb)198 void RuntimeCallbacks::RemoveThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
199   WriterMutexLock mu(Thread::Current(), *callback_lock_);
200   Remove(cb, &thread_callbacks_);
201 }
202 
ThreadStart(Thread * self)203 void RuntimeCallbacks::ThreadStart(Thread* self) {
204   for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) {
205     cb->ThreadStart(self);
206   }
207 }
208 
ThreadDeath(Thread * self)209 void RuntimeCallbacks::ThreadDeath(Thread* self) {
210   for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) {
211     cb->ThreadDeath(self);
212   }
213 }
214 
AddClassLoadCallback(ClassLoadCallback * cb)215 void RuntimeCallbacks::AddClassLoadCallback(ClassLoadCallback* cb) {
216   WriterMutexLock mu(Thread::Current(), *callback_lock_);
217   class_callbacks_.push_back(cb);
218 }
219 
RemoveClassLoadCallback(ClassLoadCallback * cb)220 void RuntimeCallbacks::RemoveClassLoadCallback(ClassLoadCallback* cb) {
221   WriterMutexLock mu(Thread::Current(), *callback_lock_);
222   Remove(cb, &class_callbacks_);
223 }
224 
ClassLoad(Handle<mirror::Class> klass)225 void RuntimeCallbacks::ClassLoad(Handle<mirror::Class> klass) {
226   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
227     cb->ClassLoad(klass);
228   }
229 }
230 
ClassPreDefine(const char * descriptor,Handle<mirror::Class> temp_class,Handle<mirror::ClassLoader> loader,const DexFile & initial_dex_file,const dex::ClassDef & initial_class_def,DexFile const ** final_dex_file,dex::ClassDef const ** final_class_def)231 void RuntimeCallbacks::ClassPreDefine(const char* descriptor,
232                                       Handle<mirror::Class> temp_class,
233                                       Handle<mirror::ClassLoader> loader,
234                                       const DexFile& initial_dex_file,
235                                       const dex::ClassDef& initial_class_def,
236                                       /*out*/DexFile const** final_dex_file,
237                                       /*out*/dex::ClassDef const** final_class_def) {
238   DexFile const* current_dex_file = &initial_dex_file;
239   dex::ClassDef const* current_class_def = &initial_class_def;
240   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
241     DexFile const* new_dex_file = nullptr;
242     dex::ClassDef const* new_class_def = nullptr;
243     cb->ClassPreDefine(descriptor,
244                        temp_class,
245                        loader,
246                        *current_dex_file,
247                        *current_class_def,
248                        &new_dex_file,
249                        &new_class_def);
250     if ((new_dex_file != nullptr && new_dex_file != current_dex_file) ||
251         (new_class_def != nullptr && new_class_def != current_class_def)) {
252       DCHECK(new_dex_file != nullptr && new_class_def != nullptr);
253       current_dex_file = new_dex_file;
254       current_class_def = new_class_def;
255     }
256   }
257   *final_dex_file = current_dex_file;
258   *final_class_def = current_class_def;
259 }
260 
ClassPrepare(Handle<mirror::Class> temp_klass,Handle<mirror::Class> klass)261 void RuntimeCallbacks::ClassPrepare(Handle<mirror::Class> temp_klass, Handle<mirror::Class> klass) {
262   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
263     cb->ClassPrepare(temp_klass, klass);
264   }
265 }
266 
AddRuntimeSigQuitCallback(RuntimeSigQuitCallback * cb)267 void RuntimeCallbacks::AddRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
268   WriterMutexLock mu(Thread::Current(), *callback_lock_);
269   sigquit_callbacks_.push_back(cb);
270 }
271 
RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback * cb)272 void RuntimeCallbacks::RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
273   WriterMutexLock mu(Thread::Current(), *callback_lock_);
274   Remove(cb, &sigquit_callbacks_);
275 }
276 
SigQuit()277 void RuntimeCallbacks::SigQuit() {
278   for (RuntimeSigQuitCallback* cb : COPY(sigquit_callbacks_)) {
279     cb->SigQuit();
280   }
281 }
282 
AddRuntimePhaseCallback(RuntimePhaseCallback * cb)283 void RuntimeCallbacks::AddRuntimePhaseCallback(RuntimePhaseCallback* cb) {
284   WriterMutexLock mu(Thread::Current(), *callback_lock_);
285   phase_callbacks_.push_back(cb);
286 }
287 
RemoveRuntimePhaseCallback(RuntimePhaseCallback * cb)288 void RuntimeCallbacks::RemoveRuntimePhaseCallback(RuntimePhaseCallback* cb) {
289   WriterMutexLock mu(Thread::Current(), *callback_lock_);
290   Remove(cb, &phase_callbacks_);
291 }
292 
NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase)293 void RuntimeCallbacks::NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase) {
294   for (RuntimePhaseCallback* cb : COPY(phase_callbacks_)) {
295     cb->NextRuntimePhase(phase);
296   }
297 }
298 
AddMethodCallback(MethodCallback * cb)299 void RuntimeCallbacks::AddMethodCallback(MethodCallback* cb) {
300   WriterMutexLock mu(Thread::Current(), *callback_lock_);
301   method_callbacks_.push_back(cb);
302 }
303 
RemoveMethodCallback(MethodCallback * cb)304 void RuntimeCallbacks::RemoveMethodCallback(MethodCallback* cb) {
305   WriterMutexLock mu(Thread::Current(), *callback_lock_);
306   Remove(cb, &method_callbacks_);
307 }
308 
RegisterNativeMethod(ArtMethod * method,const void * in_cur_method,void ** new_method)309 void RuntimeCallbacks::RegisterNativeMethod(ArtMethod* method,
310                                             const void* in_cur_method,
311                                             /*out*/void** new_method) {
312   void* cur_method = const_cast<void*>(in_cur_method);
313   *new_method = cur_method;
314   for (MethodCallback* cb : COPY(method_callbacks_)) {
315     cb->RegisterNativeMethod(method, cur_method, new_method);
316     if (*new_method != nullptr) {
317       cur_method = *new_method;
318     }
319   }
320 }
321 
322 }  // namespace art
323