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
IsMethodBeingInspected(ArtMethod * m)108 bool RuntimeCallbacks::IsMethodBeingInspected(ArtMethod* m) {
109 for (MethodInspectionCallback* cb : COPY(method_inspection_callbacks_)) {
110 if (cb->IsMethodBeingInspected(m)) {
111 return true;
112 }
113 }
114 return false;
115 }
116
AddThreadLifecycleCallback(ThreadLifecycleCallback * cb)117 void RuntimeCallbacks::AddThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
118 WriterMutexLock mu(Thread::Current(), *callback_lock_);
119 thread_callbacks_.push_back(cb);
120 }
121
MonitorContendedLocking(Monitor * m)122 void RuntimeCallbacks::MonitorContendedLocking(Monitor* m) {
123 for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
124 cb->MonitorContendedLocking(m);
125 }
126 }
127
MonitorContendedLocked(Monitor * m)128 void RuntimeCallbacks::MonitorContendedLocked(Monitor* m) {
129 for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
130 cb->MonitorContendedLocked(m);
131 }
132 }
133
ObjectWaitStart(Handle<mirror::Object> m,int64_t timeout)134 void RuntimeCallbacks::ObjectWaitStart(Handle<mirror::Object> m, int64_t timeout) {
135 for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
136 cb->ObjectWaitStart(m, timeout);
137 }
138 }
139
MonitorWaitFinished(Monitor * m,bool timeout)140 void RuntimeCallbacks::MonitorWaitFinished(Monitor* m, bool timeout) {
141 for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
142 cb->MonitorWaitFinished(m, timeout);
143 }
144 }
145
AddMonitorCallback(MonitorCallback * cb)146 void RuntimeCallbacks::AddMonitorCallback(MonitorCallback* cb) {
147 WriterMutexLock mu(Thread::Current(), *callback_lock_);
148 monitor_callbacks_.push_back(cb);
149 }
150
RemoveMonitorCallback(MonitorCallback * cb)151 void RuntimeCallbacks::RemoveMonitorCallback(MonitorCallback* cb) {
152 WriterMutexLock mu(Thread::Current(), *callback_lock_);
153 Remove(cb, &monitor_callbacks_);
154 }
155
ThreadParkStart(bool is_absolute,int64_t timeout)156 void RuntimeCallbacks::ThreadParkStart(bool is_absolute, int64_t timeout) {
157 for (ParkCallback * cb : COPY(park_callbacks_)) {
158 cb->ThreadParkStart(is_absolute, timeout);
159 }
160 }
161
ThreadParkFinished(bool timeout)162 void RuntimeCallbacks::ThreadParkFinished(bool timeout) {
163 for (ParkCallback * cb : COPY(park_callbacks_)) {
164 cb->ThreadParkFinished(timeout);
165 }
166 }
167
AddParkCallback(ParkCallback * cb)168 void RuntimeCallbacks::AddParkCallback(ParkCallback* cb) {
169 WriterMutexLock mu(Thread::Current(), *callback_lock_);
170 park_callbacks_.push_back(cb);
171 }
172
RemoveParkCallback(ParkCallback * cb)173 void RuntimeCallbacks::RemoveParkCallback(ParkCallback* cb) {
174 WriterMutexLock mu(Thread::Current(), *callback_lock_);
175 Remove(cb, &park_callbacks_);
176 }
177
RemoveThreadLifecycleCallback(ThreadLifecycleCallback * cb)178 void RuntimeCallbacks::RemoveThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
179 WriterMutexLock mu(Thread::Current(), *callback_lock_);
180 Remove(cb, &thread_callbacks_);
181 }
182
ThreadStart(Thread * self)183 void RuntimeCallbacks::ThreadStart(Thread* self) {
184 for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) {
185 cb->ThreadStart(self);
186 }
187 }
188
ThreadDeath(Thread * self)189 void RuntimeCallbacks::ThreadDeath(Thread* self) {
190 for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) {
191 cb->ThreadDeath(self);
192 }
193 }
194
AddClassLoadCallback(ClassLoadCallback * cb)195 void RuntimeCallbacks::AddClassLoadCallback(ClassLoadCallback* cb) {
196 WriterMutexLock mu(Thread::Current(), *callback_lock_);
197 class_callbacks_.push_back(cb);
198 }
199
RemoveClassLoadCallback(ClassLoadCallback * cb)200 void RuntimeCallbacks::RemoveClassLoadCallback(ClassLoadCallback* cb) {
201 WriterMutexLock mu(Thread::Current(), *callback_lock_);
202 Remove(cb, &class_callbacks_);
203 }
204
ClassLoad(Handle<mirror::Class> klass)205 void RuntimeCallbacks::ClassLoad(Handle<mirror::Class> klass) {
206 for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
207 cb->ClassLoad(klass);
208 }
209 }
210
EndDefineClass()211 void RuntimeCallbacks::EndDefineClass() {
212 for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
213 cb->EndDefineClass();
214 }
215 }
216
BeginDefineClass()217 void RuntimeCallbacks::BeginDefineClass() {
218 for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
219 cb->BeginDefineClass();
220 }
221 }
222
223
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)224 void RuntimeCallbacks::ClassPreDefine(const char* descriptor,
225 Handle<mirror::Class> temp_class,
226 Handle<mirror::ClassLoader> loader,
227 const DexFile& initial_dex_file,
228 const dex::ClassDef& initial_class_def,
229 /*out*/DexFile const** final_dex_file,
230 /*out*/dex::ClassDef const** final_class_def) {
231 DexFile const* current_dex_file = &initial_dex_file;
232 dex::ClassDef const* current_class_def = &initial_class_def;
233 for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
234 DexFile const* new_dex_file = nullptr;
235 dex::ClassDef const* new_class_def = nullptr;
236 cb->ClassPreDefine(descriptor,
237 temp_class,
238 loader,
239 *current_dex_file,
240 *current_class_def,
241 &new_dex_file,
242 &new_class_def);
243 if ((new_dex_file != nullptr && new_dex_file != current_dex_file) ||
244 (new_class_def != nullptr && new_class_def != current_class_def)) {
245 DCHECK(new_dex_file != nullptr && new_class_def != nullptr);
246 current_dex_file = new_dex_file;
247 current_class_def = new_class_def;
248 }
249 }
250 *final_dex_file = current_dex_file;
251 *final_class_def = current_class_def;
252 }
253
ClassPrepare(Handle<mirror::Class> temp_klass,Handle<mirror::Class> klass)254 void RuntimeCallbacks::ClassPrepare(Handle<mirror::Class> temp_klass, Handle<mirror::Class> klass) {
255 for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
256 cb->ClassPrepare(temp_klass, klass);
257 }
258 }
259
AddRuntimeSigQuitCallback(RuntimeSigQuitCallback * cb)260 void RuntimeCallbacks::AddRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
261 WriterMutexLock mu(Thread::Current(), *callback_lock_);
262 sigquit_callbacks_.push_back(cb);
263 }
264
RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback * cb)265 void RuntimeCallbacks::RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
266 WriterMutexLock mu(Thread::Current(), *callback_lock_);
267 Remove(cb, &sigquit_callbacks_);
268 }
269
SigQuit()270 void RuntimeCallbacks::SigQuit() {
271 for (RuntimeSigQuitCallback* cb : COPY(sigquit_callbacks_)) {
272 cb->SigQuit();
273 }
274 }
275
AddRuntimePhaseCallback(RuntimePhaseCallback * cb)276 void RuntimeCallbacks::AddRuntimePhaseCallback(RuntimePhaseCallback* cb) {
277 WriterMutexLock mu(Thread::Current(), *callback_lock_);
278 phase_callbacks_.push_back(cb);
279 }
280
RemoveRuntimePhaseCallback(RuntimePhaseCallback * cb)281 void RuntimeCallbacks::RemoveRuntimePhaseCallback(RuntimePhaseCallback* cb) {
282 WriterMutexLock mu(Thread::Current(), *callback_lock_);
283 Remove(cb, &phase_callbacks_);
284 }
285
NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase)286 void RuntimeCallbacks::NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase) {
287 for (RuntimePhaseCallback* cb : COPY(phase_callbacks_)) {
288 cb->NextRuntimePhase(phase);
289 }
290 }
291
AddMethodCallback(MethodCallback * cb)292 void RuntimeCallbacks::AddMethodCallback(MethodCallback* cb) {
293 WriterMutexLock mu(Thread::Current(), *callback_lock_);
294 method_callbacks_.push_back(cb);
295 }
296
RemoveMethodCallback(MethodCallback * cb)297 void RuntimeCallbacks::RemoveMethodCallback(MethodCallback* cb) {
298 WriterMutexLock mu(Thread::Current(), *callback_lock_);
299 Remove(cb, &method_callbacks_);
300 }
301
RegisterNativeMethod(ArtMethod * method,const void * in_cur_method,void ** new_method)302 void RuntimeCallbacks::RegisterNativeMethod(ArtMethod* method,
303 const void* in_cur_method,
304 /*out*/void** new_method) {
305 void* cur_method = const_cast<void*>(in_cur_method);
306 *new_method = cur_method;
307 for (MethodCallback* cb : COPY(method_callbacks_)) {
308 cb->RegisterNativeMethod(method, cur_method, new_method);
309 if (*new_method != nullptr) {
310 cur_method = *new_method;
311 }
312 }
313 }
314
AddReflectiveValueVisitCallback(ReflectiveValueVisitCallback * cb)315 void RuntimeCallbacks::AddReflectiveValueVisitCallback(ReflectiveValueVisitCallback *cb) {
316 WriterMutexLock mu(Thread::Current(), *callback_lock_);
317 reflective_value_visit_callbacks_.push_back(cb);
318 }
319
RemoveReflectiveValueVisitCallback(ReflectiveValueVisitCallback * cb)320 void RuntimeCallbacks::RemoveReflectiveValueVisitCallback(ReflectiveValueVisitCallback *cb) {
321 WriterMutexLock mu(Thread::Current(), *callback_lock_);
322 Remove(cb, &reflective_value_visit_callbacks_);
323 }
324
VisitReflectiveTargets(ReflectiveValueVisitor * visitor)325 void RuntimeCallbacks::VisitReflectiveTargets(ReflectiveValueVisitor *visitor) {
326 for (ReflectiveValueVisitCallback* cb : COPY(reflective_value_visit_callbacks_)) {
327 cb->VisitReflectiveTargets(visitor);
328 }
329 }
330
331 } // namespace art
332