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 #ifndef ART_OPENJDKJVMTI_TI_CLASS_DEFINITION_H_
     33 #define ART_OPENJDKJVMTI_TI_CLASS_DEFINITION_H_
     34 
     35 #include <stddef.h>
     36 #include <sys/mman.h>
     37 #include <sys/types.h>
     38 
     39 #include "art_jvmti.h"
     40 
     41 #include "base/array_ref.h"
     42 #include "base/mem_map.h"
     43 
     44 namespace openjdkjvmti {
     45 
     46 // A struct that stores data needed for redefining/transforming classes. This structure should only
     47 // even be accessed from a single thread and must not survive past the completion of the
     48 // redefinition/retransformation function that created it.
     49 class ArtClassDefinition {
     50  public:
     51   // If we support doing a on-demand dex-dequickening using signal handlers.
     52   static constexpr bool kEnableOnDemandDexDequicken = true;
     53 
     54   ArtClassDefinition()
     55       : klass_(nullptr),
     56         loader_(nullptr),
     57         name_(),
     58         protection_domain_(nullptr),
     59         dex_data_mmap_(),
     60         temp_mmap_(),
     61         dex_data_memory_(),
     62         initial_dex_file_unquickened_(nullptr),
     63         dex_data_(),
     64         current_dex_memory_(),
     65         current_dex_file_(),
     66         redefined_(false),
     67         from_class_ext_(false),
     68         initialized_(false) {}
     69 
     70   void InitFirstLoad(const char* descriptor,
     71                      art::Handle<art::mirror::ClassLoader> klass_loader,
     72                      const art::DexFile& dex_file);
     73   jvmtiError Init(art::Thread* self, jclass klass);
     74   jvmtiError Init(art::Thread* self, const jvmtiClassDefinition& def);
     75 
     76   ArtClassDefinition(ArtClassDefinition&& o) = default;
     77   ArtClassDefinition& operator=(ArtClassDefinition&& o) = default;
     78 
     79   void SetNewDexData(jint new_dex_len, unsigned char* new_dex_data) {
     80     DCHECK(IsInitialized());
     81     if (new_dex_data == nullptr) {
     82       return;
     83     } else {
     84       art::ArrayRef<const unsigned char> new_data(new_dex_data, new_dex_len);
     85       if (new_data != dex_data_) {
     86         dex_data_memory_.resize(new_dex_len);
     87         memcpy(dex_data_memory_.data(), new_dex_data, new_dex_len);
     88         dex_data_ = art::ArrayRef<const unsigned char>(dex_data_memory_);
     89       }
     90     }
     91   }
     92 
     93   art::ArrayRef<const unsigned char> GetNewOriginalDexFile() const {
     94     DCHECK(IsInitialized());
     95     if (redefined_) {
     96       return current_dex_file_;
     97     } else {
     98       return art::ArrayRef<const unsigned char>();
     99     }
    100   }
    101 
    102   bool ContainsAddress(uintptr_t ptr) const {
    103     return dex_data_mmap_.IsValid() &&
    104         reinterpret_cast<uintptr_t>(dex_data_mmap_.Begin()) <= ptr &&
    105         reinterpret_cast<uintptr_t>(dex_data_mmap_.End()) > ptr;
    106   }
    107 
    108   bool IsModified() const REQUIRES_SHARED(art::Locks::mutator_lock_);
    109 
    110   bool IsInitialized() const {
    111     return initialized_;
    112   }
    113 
    114   jclass GetClass() const {
    115     DCHECK(IsInitialized());
    116     return klass_;
    117   }
    118 
    119   jobject GetLoader() const {
    120     DCHECK(IsInitialized());
    121     return loader_;
    122   }
    123 
    124   const std::string& GetName() const {
    125     DCHECK(IsInitialized());
    126     return name_;
    127   }
    128 
    129   bool IsLazyDefinition() const {
    130     DCHECK(IsInitialized());
    131     return dex_data_mmap_.IsValid() &&
    132         dex_data_.data() == dex_data_mmap_.Begin() &&
    133         dex_data_mmap_.GetProtect() == PROT_NONE;
    134   }
    135 
    136   jobject GetProtectionDomain() const {
    137     DCHECK(IsInitialized());
    138     return protection_domain_;
    139   }
    140 
    141   art::ArrayRef<const unsigned char> GetDexData() const {
    142     DCHECK(IsInitialized());
    143     return dex_data_;
    144   }
    145 
    146   void InitializeMemory() const;
    147 
    148  private:
    149   jvmtiError InitCommon(art::Thread* self, jclass klass);
    150 
    151   template<typename GetOriginalDexFile>
    152   void InitWithDex(GetOriginalDexFile get_original, const art::DexFile* quick_dex)
    153       REQUIRES_SHARED(art::Locks::mutator_lock_);
    154 
    155   jclass klass_;
    156   jobject loader_;
    157   std::string name_;
    158   jobject protection_domain_;
    159 
    160   // Mmap that will be filled with the original-dex-file lazily if it needs to be de-quickened or
    161   // de-compact-dex'd
    162   mutable art::MemMap dex_data_mmap_;
    163   // This is a temporary mmap we will use to be able to fill the dex file data atomically.
    164   mutable art::MemMap temp_mmap_;
    165 
    166   // A unique_ptr to the current dex_data if it needs to be cleaned up.
    167   std::vector<unsigned char> dex_data_memory_;
    168 
    169   const art::DexFile* initial_dex_file_unquickened_;
    170 
    171   // A ref to the current dex data. This is either dex_data_memory_, or current_dex_file_. This is
    172   // what the dex file will be turned into.
    173   art::ArrayRef<const unsigned char> dex_data_;
    174 
    175   // This is only used if we failed to create a mmap to store the dequickened data
    176   std::vector<unsigned char> current_dex_memory_;
    177 
    178   // This is a dequickened version of what is loaded right now. It is either current_dex_memory_ (if
    179   // no other redefinition has ever happened to this) or the current dex_file_ directly (if this
    180   // class has been redefined, thus it cannot have any quickened stuff).
    181   art::ArrayRef<const unsigned char> current_dex_file_;
    182 
    183   bool redefined_;
    184 
    185   // If we got the initial dex_data_ from a class_ext
    186   bool from_class_ext_;
    187 
    188   bool initialized_;
    189 
    190   DISALLOW_COPY_AND_ASSIGN(ArtClassDefinition);
    191 };
    192 
    193 }  // namespace openjdkjvmti
    194 
    195 #endif  // ART_OPENJDKJVMTI_TI_CLASS_DEFINITION_H_
    196