1 /* Copyright (C) 2016 The Android Open Source Project
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This file implements interfaces from the file jvmti.h. This implementation
5  * is licensed under the same terms as the file jvmti.h.  The
6  * copyright and license information for the file jvmti.h follows.
7  *
8  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
9  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10  *
11  * This code is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License version 2 only, as
13  * published by the Free Software Foundation.  Oracle designates this
14  * particular file as subject to the "Classpath" exception as provided
15  * by Oracle in the LICENSE file that accompanied this code.
16  *
17  * This code is distributed in the hope that it will be useful, but WITHOUT
18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20  * version 2 for more details (a copy is included in the LICENSE file that
21  * accompanied this code).
22  *
23  * You should have received a copy of the GNU General Public License version
24  * 2 along with this work; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26  *
27  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28  * or visit www.oracle.com if you need additional information or have any
29  * questions.
30  */
31 
32 #include "events-inl.h"
33 
34 #include "art_jvmti.h"
35 #include "base/logging.h"
36 #include "gc/allocation_listener.h"
37 #include "gc/gc_pause_listener.h"
38 #include "gc/heap.h"
39 #include "handle_scope-inl.h"
40 #include "instrumentation.h"
41 #include "jni_env_ext-inl.h"
42 #include "mirror/class.h"
43 #include "mirror/object-inl.h"
44 #include "runtime.h"
45 #include "ScopedLocalRef.h"
46 #include "scoped_thread_state_change-inl.h"
47 #include "thread-inl.h"
48 
49 namespace openjdkjvmti {
50 
IsEnabledAnywhere(ArtJvmtiEvent event)51 bool EventMasks::IsEnabledAnywhere(ArtJvmtiEvent event) {
52   return global_event_mask.Test(event) || unioned_thread_event_mask.Test(event);
53 }
54 
GetEventMask(art::Thread * thread)55 EventMask& EventMasks::GetEventMask(art::Thread* thread) {
56   if (thread == nullptr) {
57     return global_event_mask;
58   }
59 
60   for (auto& pair : thread_event_masks) {
61     const UniqueThread& unique_thread = pair.first;
62     if (unique_thread.first == thread &&
63         unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
64       return pair.second;
65     }
66   }
67 
68   // TODO: Remove old UniqueThread with the same pointer, if exists.
69 
70   thread_event_masks.emplace_back(UniqueThread(thread, thread->GetTid()), EventMask());
71   return thread_event_masks.back().second;
72 }
73 
GetEventMaskOrNull(art::Thread * thread)74 EventMask* EventMasks::GetEventMaskOrNull(art::Thread* thread) {
75   if (thread == nullptr) {
76     return &global_event_mask;
77   }
78 
79   for (auto& pair : thread_event_masks) {
80     const UniqueThread& unique_thread = pair.first;
81     if (unique_thread.first == thread &&
82         unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
83       return &pair.second;
84     }
85   }
86 
87   return nullptr;
88 }
89 
90 
EnableEvent(art::Thread * thread,ArtJvmtiEvent event)91 void EventMasks::EnableEvent(art::Thread* thread, ArtJvmtiEvent event) {
92   DCHECK(EventMask::EventIsInRange(event));
93   GetEventMask(thread).Set(event);
94   if (thread != nullptr) {
95     unioned_thread_event_mask.Set(event, true);
96   }
97 }
98 
DisableEvent(art::Thread * thread,ArtJvmtiEvent event)99 void EventMasks::DisableEvent(art::Thread* thread, ArtJvmtiEvent event) {
100   DCHECK(EventMask::EventIsInRange(event));
101   GetEventMask(thread).Set(event, false);
102   if (thread != nullptr) {
103     // Regenerate union for the event.
104     bool union_value = false;
105     for (auto& pair : thread_event_masks) {
106       union_value |= pair.second.Test(event);
107       if (union_value) {
108         break;
109       }
110     }
111     unioned_thread_event_mask.Set(event, union_value);
112   }
113 }
114 
HandleChangedCapabilities(const jvmtiCapabilities & caps,bool caps_added)115 void EventMasks::HandleChangedCapabilities(const jvmtiCapabilities& caps, bool caps_added) {
116   if (UNLIKELY(caps.can_retransform_classes == 1)) {
117     // If we are giving this env the retransform classes cap we need to switch all events of
118     // NonTransformable to Transformable and vice versa.
119     ArtJvmtiEvent to_remove = caps_added ? ArtJvmtiEvent::kClassFileLoadHookNonRetransformable
120                                          : ArtJvmtiEvent::kClassFileLoadHookRetransformable;
121     ArtJvmtiEvent to_add = caps_added ? ArtJvmtiEvent::kClassFileLoadHookRetransformable
122                                       : ArtJvmtiEvent::kClassFileLoadHookNonRetransformable;
123     if (global_event_mask.Test(to_remove)) {
124       CHECK(!global_event_mask.Test(to_add));
125       global_event_mask.Set(to_remove, false);
126       global_event_mask.Set(to_add, true);
127     }
128 
129     if (unioned_thread_event_mask.Test(to_remove)) {
130       CHECK(!unioned_thread_event_mask.Test(to_add));
131       unioned_thread_event_mask.Set(to_remove, false);
132       unioned_thread_event_mask.Set(to_add, true);
133     }
134     for (auto thread_mask : thread_event_masks) {
135       if (thread_mask.second.Test(to_remove)) {
136         CHECK(!thread_mask.second.Test(to_add));
137         thread_mask.second.Set(to_remove, false);
138         thread_mask.second.Set(to_add, true);
139       }
140     }
141   }
142 }
143 
RegisterArtJvmTiEnv(ArtJvmTiEnv * env)144 void EventHandler::RegisterArtJvmTiEnv(ArtJvmTiEnv* env) {
145   // Since we never shrink this array we might as well try to fill gaps.
146   auto it = std::find(envs.begin(), envs.end(), nullptr);
147   if (it != envs.end()) {
148     *it = env;
149   } else {
150     envs.push_back(env);
151   }
152 }
153 
RemoveArtJvmTiEnv(ArtJvmTiEnv * env)154 void EventHandler::RemoveArtJvmTiEnv(ArtJvmTiEnv* env) {
155   // Since we might be currently iterating over the envs list we cannot actually erase elements.
156   // Instead we will simply replace them with 'nullptr' and skip them manually.
157   auto it = std::find(envs.begin(), envs.end(), env);
158   if (it != envs.end()) {
159     *it = nullptr;
160     for (size_t i = static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal);
161          i <= static_cast<size_t>(ArtJvmtiEvent::kMaxEventTypeVal);
162          ++i) {
163       RecalculateGlobalEventMask(static_cast<ArtJvmtiEvent>(i));
164     }
165   }
166 }
167 
IsThreadControllable(ArtJvmtiEvent event)168 static bool IsThreadControllable(ArtJvmtiEvent event) {
169   switch (event) {
170     case ArtJvmtiEvent::kVmInit:
171     case ArtJvmtiEvent::kVmStart:
172     case ArtJvmtiEvent::kVmDeath:
173     case ArtJvmtiEvent::kThreadStart:
174     case ArtJvmtiEvent::kCompiledMethodLoad:
175     case ArtJvmtiEvent::kCompiledMethodUnload:
176     case ArtJvmtiEvent::kDynamicCodeGenerated:
177     case ArtJvmtiEvent::kDataDumpRequest:
178       return false;
179 
180     default:
181       return true;
182   }
183 }
184 
185 class JvmtiAllocationListener : public art::gc::AllocationListener {
186  public:
JvmtiAllocationListener(EventHandler * handler)187   explicit JvmtiAllocationListener(EventHandler* handler) : handler_(handler) {}
188 
ObjectAllocated(art::Thread * self,art::ObjPtr<art::mirror::Object> * obj,size_t byte_count)189   void ObjectAllocated(art::Thread* self, art::ObjPtr<art::mirror::Object>* obj, size_t byte_count)
190       OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
191     DCHECK_EQ(self, art::Thread::Current());
192 
193     if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kVmObjectAlloc)) {
194       art::StackHandleScope<1> hs(self);
195       auto h = hs.NewHandleWrapper(obj);
196       // jvmtiEventVMObjectAlloc parameters:
197       //      jvmtiEnv *jvmti_env,
198       //      JNIEnv* jni_env,
199       //      jthread thread,
200       //      jobject object,
201       //      jclass object_klass,
202       //      jlong size
203       art::JNIEnvExt* jni_env = self->GetJniEnv();
204 
205       jthread thread_peer;
206       if (self->IsStillStarting()) {
207         thread_peer = nullptr;
208       } else {
209         thread_peer = jni_env->AddLocalReference<jthread>(self->GetPeer());
210       }
211 
212       ScopedLocalRef<jthread> thread(jni_env, thread_peer);
213       ScopedLocalRef<jobject> object(
214           jni_env, jni_env->AddLocalReference<jobject>(*obj));
215       ScopedLocalRef<jclass> klass(
216           jni_env, jni_env->AddLocalReference<jclass>(obj->Ptr()->GetClass()));
217 
218       handler_->DispatchEvent<ArtJvmtiEvent::kVmObjectAlloc>(self,
219                                                              reinterpret_cast<JNIEnv*>(jni_env),
220                                                              thread.get(),
221                                                              object.get(),
222                                                              klass.get(),
223                                                              static_cast<jlong>(byte_count));
224     }
225   }
226 
227  private:
228   EventHandler* handler_;
229 };
230 
SetupObjectAllocationTracking(art::gc::AllocationListener * listener,bool enable)231 static void SetupObjectAllocationTracking(art::gc::AllocationListener* listener, bool enable) {
232   // We must not hold the mutator lock here, but if we're in FastJNI, for example, we might. For
233   // now, do a workaround: (possibly) acquire and release.
234   art::ScopedObjectAccess soa(art::Thread::Current());
235   art::ScopedThreadSuspension sts(soa.Self(), art::ThreadState::kSuspended);
236   if (enable) {
237     art::Runtime::Current()->GetHeap()->SetAllocationListener(listener);
238   } else {
239     art::Runtime::Current()->GetHeap()->RemoveAllocationListener();
240   }
241 }
242 
243 // Report GC pauses (see spec) as GARBAGE_COLLECTION_START and GARBAGE_COLLECTION_END.
244 class JvmtiGcPauseListener : public art::gc::GcPauseListener {
245  public:
JvmtiGcPauseListener(EventHandler * handler)246   explicit JvmtiGcPauseListener(EventHandler* handler)
247       : handler_(handler),
248         start_enabled_(false),
249         finish_enabled_(false) {}
250 
StartPause()251   void StartPause() OVERRIDE {
252     handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionStart>(nullptr);
253   }
254 
EndPause()255   void EndPause() OVERRIDE {
256     handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionFinish>(nullptr);
257   }
258 
IsEnabled()259   bool IsEnabled() {
260     return start_enabled_ || finish_enabled_;
261   }
262 
SetStartEnabled(bool e)263   void SetStartEnabled(bool e) {
264     start_enabled_ = e;
265   }
266 
SetFinishEnabled(bool e)267   void SetFinishEnabled(bool e) {
268     finish_enabled_ = e;
269   }
270 
271  private:
272   EventHandler* handler_;
273   bool start_enabled_;
274   bool finish_enabled_;
275 };
276 
SetupGcPauseTracking(JvmtiGcPauseListener * listener,ArtJvmtiEvent event,bool enable)277 static void SetupGcPauseTracking(JvmtiGcPauseListener* listener, ArtJvmtiEvent event, bool enable) {
278   bool old_state = listener->IsEnabled();
279 
280   if (event == ArtJvmtiEvent::kGarbageCollectionStart) {
281     listener->SetStartEnabled(enable);
282   } else {
283     listener->SetFinishEnabled(enable);
284   }
285 
286   bool new_state = listener->IsEnabled();
287 
288   if (old_state != new_state) {
289     if (new_state) {
290       art::Runtime::Current()->GetHeap()->SetGcPauseListener(listener);
291     } else {
292       art::Runtime::Current()->GetHeap()->RemoveGcPauseListener();
293     }
294   }
295 }
296 
297 // Handle special work for the given event type, if necessary.
HandleEventType(ArtJvmtiEvent event,bool enable)298 void EventHandler::HandleEventType(ArtJvmtiEvent event, bool enable) {
299   switch (event) {
300     case ArtJvmtiEvent::kVmObjectAlloc:
301       SetupObjectAllocationTracking(alloc_listener_.get(), enable);
302       return;
303 
304     case ArtJvmtiEvent::kGarbageCollectionStart:
305     case ArtJvmtiEvent::kGarbageCollectionFinish:
306       SetupGcPauseTracking(gc_pause_listener_.get(), event, enable);
307       return;
308 
309     default:
310       break;
311   }
312 }
313 
314 // Checks to see if the env has the capabilities associated with the given event.
HasAssociatedCapability(ArtJvmTiEnv * env,ArtJvmtiEvent event)315 static bool HasAssociatedCapability(ArtJvmTiEnv* env,
316                                     ArtJvmtiEvent event) {
317   jvmtiCapabilities caps = env->capabilities;
318   switch (event) {
319     case ArtJvmtiEvent::kBreakpoint:
320       return caps.can_generate_breakpoint_events == 1;
321 
322     case ArtJvmtiEvent::kCompiledMethodLoad:
323     case ArtJvmtiEvent::kCompiledMethodUnload:
324       return caps.can_generate_compiled_method_load_events == 1;
325 
326     case ArtJvmtiEvent::kException:
327     case ArtJvmtiEvent::kExceptionCatch:
328       return caps.can_generate_exception_events == 1;
329 
330     case ArtJvmtiEvent::kFieldAccess:
331       return caps.can_generate_field_access_events == 1;
332 
333     case ArtJvmtiEvent::kFieldModification:
334       return caps.can_generate_field_modification_events == 1;
335 
336     case ArtJvmtiEvent::kFramePop:
337       return caps.can_generate_frame_pop_events == 1;
338 
339     case ArtJvmtiEvent::kGarbageCollectionStart:
340     case ArtJvmtiEvent::kGarbageCollectionFinish:
341       return caps.can_generate_garbage_collection_events == 1;
342 
343     case ArtJvmtiEvent::kMethodEntry:
344       return caps.can_generate_method_entry_events == 1;
345 
346     case ArtJvmtiEvent::kMethodExit:
347       return caps.can_generate_method_exit_events == 1;
348 
349     case ArtJvmtiEvent::kMonitorContendedEnter:
350     case ArtJvmtiEvent::kMonitorContendedEntered:
351     case ArtJvmtiEvent::kMonitorWait:
352     case ArtJvmtiEvent::kMonitorWaited:
353       return caps.can_generate_monitor_events == 1;
354 
355     case ArtJvmtiEvent::kNativeMethodBind:
356       return caps.can_generate_native_method_bind_events == 1;
357 
358     case ArtJvmtiEvent::kObjectFree:
359       return caps.can_generate_object_free_events == 1;
360 
361     case ArtJvmtiEvent::kSingleStep:
362       return caps.can_generate_single_step_events == 1;
363 
364     case ArtJvmtiEvent::kVmObjectAlloc:
365       return caps.can_generate_vm_object_alloc_events == 1;
366 
367     default:
368       return true;
369   }
370 }
371 
SetEvent(ArtJvmTiEnv * env,art::Thread * thread,ArtJvmtiEvent event,jvmtiEventMode mode)372 jvmtiError EventHandler::SetEvent(ArtJvmTiEnv* env,
373                                   art::Thread* thread,
374                                   ArtJvmtiEvent event,
375                                   jvmtiEventMode mode) {
376   if (thread != nullptr) {
377     art::ThreadState state = thread->GetState();
378     if (state == art::ThreadState::kStarting ||
379         state == art::ThreadState::kTerminated ||
380         thread->IsStillStarting()) {
381       return ERR(THREAD_NOT_ALIVE);
382     }
383     if (!IsThreadControllable(event)) {
384       return ERR(ILLEGAL_ARGUMENT);
385     }
386   }
387 
388   if (mode != JVMTI_ENABLE && mode != JVMTI_DISABLE) {
389     return ERR(ILLEGAL_ARGUMENT);
390   }
391 
392   if (!EventMask::EventIsInRange(event)) {
393     return ERR(INVALID_EVENT_TYPE);
394   }
395 
396   if (!HasAssociatedCapability(env, event)) {
397     return ERR(MUST_POSSESS_CAPABILITY);
398   }
399 
400   bool old_state = global_mask.Test(event);
401 
402   if (mode == JVMTI_ENABLE) {
403     env->event_masks.EnableEvent(thread, event);
404     global_mask.Set(event);
405   } else {
406     DCHECK_EQ(mode, JVMTI_DISABLE);
407 
408     env->event_masks.DisableEvent(thread, event);
409     RecalculateGlobalEventMask(event);
410   }
411 
412   bool new_state = global_mask.Test(event);
413 
414   // Handle any special work required for the event type.
415   if (new_state != old_state) {
416     HandleEventType(event, mode == JVMTI_ENABLE);
417   }
418 
419   return ERR(NONE);
420 }
421 
EventHandler()422 EventHandler::EventHandler() {
423   alloc_listener_.reset(new JvmtiAllocationListener(this));
424   gc_pause_listener_.reset(new JvmtiGcPauseListener(this));
425 }
426 
~EventHandler()427 EventHandler::~EventHandler() {
428 }
429 
430 }  // namespace openjdkjvmti
431