• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ti_class_definition.h"
33 
34 #include "base/array_slice.h"
35 #include "class_linker-inl.h"
36 #include "dex_file.h"
37 #include "fixed_up_dex_file.h"
38 #include "handle_scope-inl.h"
39 #include "handle.h"
40 #include "mirror/class_ext.h"
41 #include "mirror/class-inl.h"
42 #include "mirror/object-inl.h"
43 #include "reflection.h"
44 #include "thread.h"
45 
46 namespace openjdkjvmti {
47 
IsModified() const48 bool ArtClassDefinition::IsModified() const {
49   // RedefineClasses calls always are 'modified' since they need to change the original_dex_file of
50   // the class.
51   if (redefined_) {
52     return true;
53   }
54   // Check if the dex file we want to set is the same as the current one.
55   // Unfortunately we need to do this check even if no modifications have been done since it could
56   // be that agents were removed in the mean-time so we still have a different dex file. The dex
57   // checksum means this is likely to be fairly fast.
58   return static_cast<jint>(original_dex_file_.size()) != dex_len_ ||
59       memcmp(original_dex_file_.data(), dex_data_.get(), dex_len_) != 0;
60 }
61 
InitCommon(ArtJvmTiEnv * env,jclass klass)62 jvmtiError ArtClassDefinition::InitCommon(ArtJvmTiEnv* env, jclass klass) {
63   JNIEnv* jni_env = GetJniEnv(env);
64   if (jni_env == nullptr) {
65     return ERR(INTERNAL);
66   }
67   art::ScopedObjectAccess soa(jni_env);
68   art::ObjPtr<art::mirror::Class> m_klass(soa.Decode<art::mirror::Class>(klass));
69   if (m_klass.IsNull()) {
70     return ERR(INVALID_CLASS);
71   }
72   klass_ = klass;
73   loader_ = soa.AddLocalReference<jobject>(m_klass->GetClassLoader());
74   std::string descriptor_store;
75   std::string descriptor(m_klass->GetDescriptor(&descriptor_store));
76   name_ = descriptor.substr(1, descriptor.size() - 2);
77   // Android doesn't really have protection domains.
78   protection_domain_ = nullptr;
79   return OK;
80 }
81 
82 // Gets the data surrounding the given class.
GetDexDataForRetransformation(ArtJvmTiEnv * env,art::Handle<art::mirror::Class> klass,jint * dex_data_len,unsigned char ** dex_data)83 static jvmtiError GetDexDataForRetransformation(ArtJvmTiEnv* env,
84                                                 art::Handle<art::mirror::Class> klass,
85                                                 /*out*/jint* dex_data_len,
86                                                 /*out*/unsigned char** dex_data)
87     REQUIRES_SHARED(art::Locks::mutator_lock_) {
88   art::StackHandleScope<3> hs(art::Thread::Current());
89   art::Handle<art::mirror::ClassExt> ext(hs.NewHandle(klass->GetExtData()));
90   const art::DexFile* dex_file = nullptr;
91   if (!ext.IsNull()) {
92     art::Handle<art::mirror::Object> orig_dex(hs.NewHandle(ext->GetOriginalDexFile()));
93     if (!orig_dex.IsNull()) {
94       if (orig_dex->IsArrayInstance()) {
95         DCHECK(orig_dex->GetClass()->GetComponentType()->IsPrimitiveByte());
96         art::Handle<art::mirror::ByteArray> orig_dex_bytes(
97             hs.NewHandle(art::down_cast<art::mirror::ByteArray*>(orig_dex->AsArray())));
98         *dex_data_len = static_cast<jint>(orig_dex_bytes->GetLength());
99         return CopyDataIntoJvmtiBuffer(
100             env,
101             reinterpret_cast<const unsigned char*>(orig_dex_bytes->GetData()),
102             *dex_data_len,
103             /*out*/dex_data);
104       } else if (orig_dex->IsDexCache()) {
105         dex_file = orig_dex->AsDexCache()->GetDexFile();
106       } else {
107         DCHECK(orig_dex->GetClass()->DescriptorEquals("Ljava/lang/Long;"))
108             << "Expected java/lang/Long but found object of type "
109             << orig_dex->GetClass()->PrettyClass();
110         art::ObjPtr<art::mirror::Class> prim_long_class(
111             art::Runtime::Current()->GetClassLinker()->GetClassRoot(
112                 art::ClassLinker::kPrimitiveLong));
113         art::JValue val;
114         if (!art::UnboxPrimitiveForResult(orig_dex.Get(), prim_long_class, &val)) {
115           // This should never happen.
116           return ERR(INTERNAL);
117         }
118         dex_file = reinterpret_cast<const art::DexFile*>(static_cast<uintptr_t>(val.GetJ()));
119       }
120     }
121   }
122   if (dex_file == nullptr) {
123     dex_file = &klass->GetDexFile();
124   }
125   std::unique_ptr<FixedUpDexFile> fixed_dex_file(FixedUpDexFile::Create(*dex_file));
126   *dex_data_len = static_cast<jint>(fixed_dex_file->Size());
127   return CopyDataIntoJvmtiBuffer(env,
128                                  fixed_dex_file->Begin(),
129                                  fixed_dex_file->Size(),
130                                  /*out*/dex_data);
131 }
132 
Init(ArtJvmTiEnv * env,jclass klass)133 jvmtiError ArtClassDefinition::Init(ArtJvmTiEnv* env, jclass klass) {
134   jvmtiError res = InitCommon(env, klass);
135   if (res != OK) {
136     return res;
137   }
138   unsigned char* new_data = nullptr;
139   art::Thread* self = art::Thread::Current();
140   art::ScopedObjectAccess soa(self);
141   art::StackHandleScope<1> hs(self);
142   art::Handle<art::mirror::Class> m_klass(hs.NewHandle(self->DecodeJObject(klass)->AsClass()));
143   res = GetDexDataForRetransformation(env, m_klass, &dex_len_, &new_data);
144   if (res != OK) {
145     return res;
146   }
147   dex_data_ = MakeJvmtiUniquePtr(env, new_data);
148   if (m_klass->GetExtData() == nullptr || m_klass->GetExtData()->GetOriginalDexFile() == nullptr) {
149     // We have never redefined class this yet. Keep track of what the (de-quickened) dex file looks
150     // like so we can tell if anything has changed. Really we would like to just always do the
151     // 'else' block but the fact that we de-quickened stuff screws us over.
152     unsigned char* original_data_memory = nullptr;
153     res = CopyDataIntoJvmtiBuffer(env, dex_data_.get(), dex_len_, &original_data_memory);
154     original_dex_file_memory_ = MakeJvmtiUniquePtr(env, original_data_memory);
155     original_dex_file_ = art::ArrayRef<const unsigned char>(original_data_memory, dex_len_);
156   } else {
157     // We know that we have been redefined at least once (there is an original_dex_file set in
158     // the class) so we can just use the current dex file directly.
159     const art::DexFile& dex_file = m_klass->GetDexFile();
160     original_dex_file_ = art::ArrayRef<const unsigned char>(dex_file.Begin(), dex_file.Size());
161   }
162   return res;
163 }
164 
Init(ArtJvmTiEnv * env,const jvmtiClassDefinition & def)165 jvmtiError ArtClassDefinition::Init(ArtJvmTiEnv* env, const jvmtiClassDefinition& def) {
166   jvmtiError res = InitCommon(env, def.klass);
167   if (res != OK) {
168     return res;
169   }
170   unsigned char* new_data = nullptr;
171   original_dex_file_ = art::ArrayRef<const unsigned char>(def.class_bytes, def.class_byte_count);
172   redefined_ = true;
173   dex_len_ = def.class_byte_count;
174   res = CopyDataIntoJvmtiBuffer(env, def.class_bytes, def.class_byte_count, /*out*/ &new_data);
175   dex_data_ = MakeJvmtiUniquePtr(env, new_data);
176   return res;
177 }
178 
179 }  // namespace openjdkjvmti
180