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 #include "events.h" 44 45 namespace openjdkjvmti { 46 47 // A struct that stores data needed for redefining/transforming classes. This structure should only 48 // even be accessed from a single thread and must not survive past the completion of the 49 // redefinition/retransformation function that created it. 50 class ArtClassDefinition { 51 public: ArtClassDefinition()52 ArtClassDefinition() 53 : klass_(nullptr), 54 loader_(nullptr), 55 name_(), 56 protection_domain_(nullptr), 57 dex_data_memory_(), 58 dex_data_(), 59 current_dex_memory_(), 60 current_dex_file_(), 61 redefined_(false), 62 initialized_(false), 63 structural_transform_update_(false) {} 64 65 jvmtiError InitFirstLoad(const char* descriptor, 66 art::Handle<art::mirror::ClassLoader> klass_loader, 67 const art::DexFile& dex_file); 68 jvmtiError Init(art::Thread* self, jclass klass); 69 jvmtiError Init(art::Thread* self, const jvmtiClassDefinition& def); 70 71 ArtClassDefinition(ArtClassDefinition&& o) = default; 72 ArtClassDefinition& operator=(ArtClassDefinition&& o) = default; 73 SetNewDexData(jint new_dex_len,unsigned char * new_dex_data,ArtJvmtiEvent event)74 void SetNewDexData(jint new_dex_len, unsigned char* new_dex_data, ArtJvmtiEvent event) { 75 DCHECK(IsInitialized()); 76 if (new_dex_data == nullptr) { 77 return; 78 } else { 79 art::ArrayRef<const unsigned char> new_data(new_dex_data, new_dex_len); 80 if (new_data != dex_data_) { 81 dex_data_memory_.resize(new_dex_len); 82 memcpy(dex_data_memory_.data(), new_dex_data, new_dex_len); 83 dex_data_ = art::ArrayRef<const unsigned char>(dex_data_memory_); 84 if (event == ArtJvmtiEvent::kStructuralDexFileLoadHook) { 85 structural_transform_update_ = true; 86 } 87 } 88 } 89 } 90 HasStructuralChanges()91 bool HasStructuralChanges() const { 92 return structural_transform_update_; 93 } 94 GetNewOriginalDexFile()95 art::ArrayRef<const unsigned char> GetNewOriginalDexFile() const { 96 DCHECK(IsInitialized()); 97 if (redefined_) { 98 return current_dex_file_; 99 } else { 100 return art::ArrayRef<const unsigned char>(); 101 } 102 } 103 104 bool IsModified() const REQUIRES_SHARED(art::Locks::mutator_lock_); 105 IsInitialized()106 bool IsInitialized() const { 107 return initialized_; 108 } 109 GetClass()110 jclass GetClass() const { 111 DCHECK(IsInitialized()); 112 return klass_; 113 } 114 GetLoader()115 jobject GetLoader() const { 116 DCHECK(IsInitialized()); 117 return loader_; 118 } 119 GetName()120 const std::string& GetName() const { 121 DCHECK(IsInitialized()); 122 return name_; 123 } 124 GetProtectionDomain()125 jobject GetProtectionDomain() const { 126 DCHECK(IsInitialized()); 127 return protection_domain_; 128 } 129 GetDexData()130 art::ArrayRef<const unsigned char> GetDexData() const { 131 DCHECK(IsInitialized()); 132 return dex_data_; 133 } 134 135 private: 136 jvmtiError InitCommon(art::Thread* self, jclass klass); 137 jvmtiError Init(const art::DexFile& dex_file); 138 139 jclass klass_; 140 jobject loader_; 141 std::string name_; 142 jobject protection_domain_; 143 144 // A unique_ptr to the current dex_data if it needs to be cleaned up. 145 std::vector<unsigned char> dex_data_memory_; 146 147 // A ref to the current dex data. This is either dex_data_memory_, or current_dex_file_. This is 148 // what the dex file will be turned into. 149 art::ArrayRef<const unsigned char> dex_data_; 150 151 // This is only used if we failed to create a mmap to store the dequickened data 152 std::vector<unsigned char> current_dex_memory_; 153 154 // This is a dequickened version of what is loaded right now. It is either current_dex_memory_ (if 155 // no other redefinition has ever happened to this) or the current dex_file_ directly (if this 156 // class has been redefined, thus it cannot have any quickened stuff). 157 art::ArrayRef<const unsigned char> current_dex_file_; 158 159 bool redefined_; 160 161 bool initialized_; 162 163 // Set if we had a new dex from the given transform type. 164 bool structural_transform_update_; 165 166 DISALLOW_COPY_AND_ASSIGN(ArtClassDefinition); 167 }; 168 169 } // namespace openjdkjvmti 170 171 #endif // ART_OPENJDKJVMTI_TI_CLASS_DEFINITION_H_ 172