Home | History | Annotate | Download | only in openjdkjvmti
      1 /* Copyright (C) 2017 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 <functional>
     33 
     34 #include "ti_breakpoint.h"
     35 
     36 #include "art_jvmti.h"
     37 #include "art_method-inl.h"
     38 #include "base/enums.h"
     39 #include "dex_file_annotations.h"
     40 #include "events-inl.h"
     41 #include "jni_internal.h"
     42 #include "mirror/class-inl.h"
     43 #include "mirror/object_array-inl.h"
     44 #include "modifiers.h"
     45 #include "nativehelper/ScopedLocalRef.h"
     46 #include "runtime_callbacks.h"
     47 #include "scoped_thread_state_change-inl.h"
     48 #include "thread-current-inl.h"
     49 #include "thread_list.h"
     50 #include "ti_phase.h"
     51 
     52 namespace openjdkjvmti {
     53 
     54 size_t Breakpoint::hash() const {
     55   return std::hash<uintptr_t> {}(reinterpret_cast<uintptr_t>(method_))
     56       ^ std::hash<jlocation> {}(location_);
     57 }
     58 
     59 Breakpoint::Breakpoint(art::ArtMethod* m, jlocation loc) : method_(m), location_(loc) {
     60   DCHECK(!m->IsDefault() || !m->IsCopied() || !m->IsInvokable())
     61       << "Flags are: 0x" << std::hex << m->GetAccessFlags();
     62 }
     63 
     64 void BreakpointUtil::RemoveBreakpointsInClass(ArtJvmTiEnv* env, art::mirror::Class* klass) {
     65   std::vector<Breakpoint> to_remove;
     66   for (const Breakpoint& b : env->breakpoints) {
     67     if (b.GetMethod()->GetDeclaringClass() == klass) {
     68       to_remove.push_back(b);
     69     }
     70   }
     71   for (const Breakpoint& b : to_remove) {
     72     auto it = env->breakpoints.find(b);
     73     DCHECK(it != env->breakpoints.end());
     74     env->breakpoints.erase(it);
     75   }
     76 }
     77 
     78 jvmtiError BreakpointUtil::SetBreakpoint(jvmtiEnv* jenv, jmethodID method, jlocation location) {
     79   ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
     80   if (method == nullptr) {
     81     return ERR(INVALID_METHODID);
     82   }
     83   // Need to get mutator_lock_ so we can find the interface version of any default methods.
     84   art::ScopedObjectAccess soa(art::Thread::Current());
     85   art::ArtMethod* art_method = art::jni::DecodeArtMethod(method)->GetCanonicalMethod();
     86   if (location < 0 || static_cast<uint32_t>(location) >=
     87       art_method->GetCodeItem()->insns_size_in_code_units_) {
     88     return ERR(INVALID_LOCATION);
     89   }
     90   auto res_pair = env->breakpoints.insert(/* Breakpoint */ {art_method, location});
     91   if (!res_pair.second) {
     92     // Didn't get inserted because it's already present!
     93     return ERR(DUPLICATE);
     94   }
     95   return OK;
     96 }
     97 
     98 jvmtiError BreakpointUtil::ClearBreakpoint(jvmtiEnv* jenv, jmethodID method, jlocation location) {
     99   ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
    100   if (method == nullptr) {
    101     return ERR(INVALID_METHODID);
    102   }
    103   // Need to get mutator_lock_ so we can find the interface version of any default methods.
    104   art::ScopedObjectAccess soa(art::Thread::Current());
    105   auto pos = env->breakpoints.find(
    106       /* Breakpoint */ {art::jni::DecodeArtMethod(method)->GetCanonicalMethod(), location});
    107   if (pos == env->breakpoints.end()) {
    108     return ERR(NOT_FOUND);
    109   }
    110   env->breakpoints.erase(pos);
    111   return OK;
    112 }
    113 
    114 }  // namespace openjdkjvmti
    115