blob: 3d24c831a4c9001f0943538cdd4e55f659ae3b90 [file] [log] [blame]
Alex Lighta01de592016-11-15 10:43:06 -08001/* 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_redefine.h"
33
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000034#include <algorithm>
35#include <atomic>
Alex Lighte7a33542019-04-10 14:22:49 -070036#include <iterator>
Alex Lighta01de592016-11-15 10:43:06 -080037#include <limits>
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000038#include <sstream>
Vladimir Markoeb37ba52019-02-05 14:10:38 +000039#include <string_view>
Alex Lighte7a33542019-04-10 14:22:49 -070040#include <unordered_map>
Alex Lighta01de592016-11-15 10:43:06 -080041
Andreas Gampe57943812017-12-06 21:39:13 -080042#include <android-base/logging.h>
43#include <android-base/stringprintf.h>
Andreas Gampe46ee31b2016-12-14 10:11:49 -080044
Alex Light986914b2019-11-19 01:12:25 +000045#include "alloc_manager.h"
46#include "android-base/macros.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000047#include "android-base/thread_annotations.h"
Andreas Gampea1d2f952017-04-20 22:53:58 -070048#include "art_field-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000049#include "art_field.h"
Alex Lighta01de592016-11-15 10:43:06 -080050#include "art_jvmti.h"
Steven Morelande431e272017-07-18 16:53:49 -070051#include "art_method-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000052#include "art_method.h"
Vladimir Markoe1993c72017-06-14 17:01:38 +010053#include "base/array_ref.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000054#include "base/casts.h"
55#include "base/enums.h"
56#include "base/globals.h"
57#include "base/length_prefixed_array.h"
58#include "base/utils.h"
Andreas Gampec6ea7d02017-02-01 16:46:28 -080059#include "class_linker-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000060#include "class_linker.h"
Vladimir Markob4eb1b12018-05-24 11:09:38 +010061#include "class_root.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000062#include "class_status.h"
Alex Light5643caf2017-02-08 11:39:07 -080063#include "debugger.h"
David Sehr013fd802018-01-11 22:55:24 -080064#include "dex/art_dex_file_loader.h"
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -070065#include "dex/class_accessor-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000066#include "dex/class_accessor.h"
David Sehr9e734c72018-01-04 17:56:19 -080067#include "dex/dex_file.h"
68#include "dex/dex_file_loader.h"
69#include "dex/dex_file_types.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000070#include "dex/primitive.h"
Andreas Gampead1aa632019-01-02 10:30:54 -080071#include "dex/signature-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000072#include "dex/signature.h"
Alex Lighta01de592016-11-15 10:43:06 -080073#include "events-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000074#include "events.h"
Alex Lighta01de592016-11-15 10:43:06 -080075#include "gc/allocation_listener.h"
Alex Light6abd5392017-01-05 17:53:00 -080076#include "gc/heap.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000077#include "gc/heap-inl.h"
78#include "gc/heap-visit-objects-inl.h"
79#include "handle.h"
80#include "handle_scope.h"
Alex Lighta01de592016-11-15 10:43:06 -080081#include "instrumentation.h"
Alex Light07f06212017-06-01 14:01:43 -070082#include "intern_table.h"
Alex Light5643caf2017-02-08 11:39:07 -080083#include "jdwp/jdwp.h"
84#include "jdwp/jdwp_constants.h"
85#include "jdwp/jdwp_event.h"
86#include "jdwp/object_registry.h"
Alex Lightdba61482016-12-21 08:20:29 -080087#include "jit/jit.h"
88#include "jit/jit_code_cache.h"
Vladimir Markoa3ad0cd2018-05-04 10:06:38 +010089#include "jni/jni_env_ext-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000090#include "jni/jni_id_manager.h"
91#include "jvmti.h"
Alex Lighta01de592016-11-15 10:43:06 -080092#include "jvmti_allocator.h"
Vladimir Marko5924a4a2018-05-29 17:40:41 +010093#include "linear_alloc.h"
Andreas Gampe8e0f0432018-10-24 13:38:03 -070094#include "mirror/array-alloc-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000095#include "mirror/array.h"
Andreas Gampe70f5fd02018-10-24 19:58:37 -070096#include "mirror/class-alloc-inl.h"
Alex Light6161f132017-01-25 10:30:20 -080097#include "mirror/class-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000098#include "mirror/class-refvisitor-inl.h"
99#include "mirror/class.h"
Vladimir Markobb206de2019-03-28 10:30:32 +0000100#include "mirror/class_ext-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000101#include "mirror/dex_cache-inl.h"
102#include "mirror/dex_cache.h"
103#include "mirror/executable-inl.h"
104#include "mirror/field-inl.h"
105#include "mirror/method.h"
106#include "mirror/method_handle_impl-inl.h"
Alex Lighta01de592016-11-15 10:43:06 -0800107#include "mirror/object.h"
Andreas Gampe52ecb652018-10-24 15:18:21 -0700108#include "mirror/object_array-alloc-inl.h"
109#include "mirror/object_array-inl.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000110#include "mirror/object_array.h"
111#include "mirror/string.h"
Alex Lightc18eba32019-09-24 14:36:27 -0700112#include "mirror/var_handle.h"
Andreas Gampe373a9b52017-10-18 09:01:57 -0700113#include "nativehelper/scoped_local_ref.h"
Alex Lighte77b48b2017-02-22 11:08:06 -0800114#include "non_debuggable_classes.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000115#include "obj_ptr.h"
Alex Lighta01de592016-11-15 10:43:06 -0800116#include "object_lock.h"
Alex Light24627892019-11-06 10:28:21 -0800117#include "reflective_value_visitor.h"
Alex Lighta01de592016-11-15 10:43:06 -0800118#include "runtime.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000119#include "runtime_globals.h"
Alex Light986914b2019-11-19 01:12:25 +0000120#include "scoped_thread_state_change.h"
Vladimir Marko5924a4a2018-05-29 17:40:41 +0100121#include "stack.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000122#include "thread.h"
Vladimir Marko5924a4a2018-05-29 17:40:41 +0100123#include "thread_list.h"
Alex Lighta26e3492017-06-27 17:55:37 -0700124#include "ti_breakpoint.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000125#include "ti_class_definition.h"
Alex Lighteb98b082017-01-25 13:02:32 -0800126#include "ti_class_loader.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000127#include "ti_heap.h"
128#include "ti_logging.h"
129#include "ti_thread.h"
Alex Light0e692732017-01-10 15:00:05 -0800130#include "transform.h"
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700131#include "verifier/class_verifier.h"
Andreas Gampe6d7abbd2017-04-24 13:19:09 -0700132#include "verifier/verifier_enums.h"
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000133#include "well_known_classes.h"
134#include "write_barrier.h"
Alex Lighta01de592016-11-15 10:43:06 -0800135
136namespace openjdkjvmti {
137
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000138// Debug check to force us to directly check we saw all methods and fields exactly once directly.
139// Normally we don't need to do this since if any are missing the count will be different
140constexpr bool kCheckAllMethodsSeenOnce = art::kIsDebugBuild;
141
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800142using android::base::StringPrintf;
143
Alex Lighteee0bd42017-02-14 15:31:45 +0000144// A helper that fills in a classes obsolete_methods_ and obsolete_dex_caches_ classExt fields as
145// they are created. This ensures that we can always call any method of an obsolete ArtMethod object
146// almost as soon as they are created since the GetObsoleteDexCache method will succeed.
147class ObsoleteMap {
148 public:
Alex Lighte7a33542019-04-10 14:22:49 -0700149 art::ArtMethod* FindObsoleteVersion(art::ArtMethod* original) const
Alex Lighteee0bd42017-02-14 15:31:45 +0000150 REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
151 auto method_pair = id_map_.find(original);
152 if (method_pair != id_map_.end()) {
153 art::ArtMethod* res = obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
154 method_pair->second, art::kRuntimePointerSize);
155 DCHECK(res != nullptr);
Alex Lighteee0bd42017-02-14 15:31:45 +0000156 return res;
157 } else {
158 return nullptr;
159 }
160 }
161
162 void RecordObsolete(art::ArtMethod* original, art::ArtMethod* obsolete)
163 REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
164 DCHECK(original != nullptr);
165 DCHECK(obsolete != nullptr);
166 int32_t slot = next_free_slot_++;
167 DCHECK_LT(slot, obsolete_methods_->GetLength());
168 DCHECK(nullptr ==
169 obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(slot, art::kRuntimePointerSize));
170 DCHECK(nullptr == obsolete_dex_caches_->Get(slot));
171 obsolete_methods_->SetElementPtrSize(slot, obsolete, art::kRuntimePointerSize);
172 obsolete_dex_caches_->Set(slot, original_dex_cache_);
173 id_map_.insert({original, slot});
174 }
175
176 ObsoleteMap(art::ObjPtr<art::mirror::PointerArray> obsolete_methods,
177 art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> obsolete_dex_caches,
178 art::ObjPtr<art::mirror::DexCache> original_dex_cache)
179 : next_free_slot_(0),
180 obsolete_methods_(obsolete_methods),
181 obsolete_dex_caches_(obsolete_dex_caches),
182 original_dex_cache_(original_dex_cache) {
183 // Figure out where the first unused slot in the obsolete_methods_ array is.
184 while (obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
185 next_free_slot_, art::kRuntimePointerSize) != nullptr) {
186 DCHECK(obsolete_dex_caches_->Get(next_free_slot_) != nullptr);
187 next_free_slot_++;
188 }
189 // Sanity check that the same slot in obsolete_dex_caches_ is free.
190 DCHECK(obsolete_dex_caches_->Get(next_free_slot_) == nullptr);
191 }
192
Alex Lighte7a33542019-04-10 14:22:49 -0700193 struct ObsoleteMethodPair {
194 art::ArtMethod* old_method;
195 art::ArtMethod* obsolete_method;
196 };
197
Vladimir Markoeab02482019-05-09 10:28:17 +0100198 class ObsoleteMapIter {
Alex Lighte7a33542019-04-10 14:22:49 -0700199 public:
Vladimir Markoeab02482019-05-09 10:28:17 +0100200 using iterator_category = std::forward_iterator_tag;
201 using value_type = ObsoleteMethodPair;
202 using difference_type = ptrdiff_t;
203 using pointer = void; // Unsupported.
204 using reference = void; // Unsupported.
205
Alex Lighte7a33542019-04-10 14:22:49 -0700206 ObsoleteMethodPair operator*() const
207 REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
Vladimir Markoeab02482019-05-09 10:28:17 +0100208 art::ArtMethod* obsolete = map_->obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
209 iter_->second, art::kRuntimePointerSize);
Alex Lighte7a33542019-04-10 14:22:49 -0700210 DCHECK(obsolete != nullptr);
211 return { iter_->first, obsolete };
212 }
213
214 bool operator==(ObsoleteMapIter other) const {
215 return map_ == other.map_ && iter_ == other.iter_;
216 }
217
218 bool operator!=(ObsoleteMapIter other) const {
219 return !(*this == other);
220 }
221
Vladimir Markoeab02482019-05-09 10:28:17 +0100222 ObsoleteMapIter operator++(int) {
Alex Lighte7a33542019-04-10 14:22:49 -0700223 ObsoleteMapIter retval = *this;
224 ++(*this);
225 return retval;
226 }
227
Vladimir Markoeab02482019-05-09 10:28:17 +0100228 ObsoleteMapIter operator++() {
Alex Lighte7a33542019-04-10 14:22:49 -0700229 ++iter_;
230 return *this;
231 }
232
233 private:
234 ObsoleteMapIter(const ObsoleteMap* map,
235 std::unordered_map<art::ArtMethod*, int32_t>::const_iterator iter)
236 : map_(map), iter_(iter) {}
237
238 const ObsoleteMap* map_;
Vladimir Markoeab02482019-05-09 10:28:17 +0100239 std::unordered_map<art::ArtMethod*, int32_t>::const_iterator iter_;
Alex Lighte7a33542019-04-10 14:22:49 -0700240
241 friend class ObsoleteMap;
242 };
243
244 ObsoleteMapIter end() const {
245 return ObsoleteMapIter(this, id_map_.cend());
246 }
247
248 ObsoleteMapIter begin() const {
249 return ObsoleteMapIter(this, id_map_.cbegin());
250 }
251
Alex Lighteee0bd42017-02-14 15:31:45 +0000252 private:
253 int32_t next_free_slot_;
254 std::unordered_map<art::ArtMethod*, int32_t> id_map_;
255 // Pointers to the fields in mirror::ClassExt. These can be held as ObjPtr since this is only used
256 // when we have an exclusive mutator_lock_ (i.e. all threads are suspended).
257 art::ObjPtr<art::mirror::PointerArray> obsolete_methods_;
258 art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> obsolete_dex_caches_;
259 art::ObjPtr<art::mirror::DexCache> original_dex_cache_;
260};
261
Alex Lightdba61482016-12-21 08:20:29 -0800262// This visitor walks thread stacks and allocates and sets up the obsolete methods. It also does
263// some basic sanity checks that the obsolete method is sane.
264class ObsoleteMethodStackVisitor : public art::StackVisitor {
265 protected:
266 ObsoleteMethodStackVisitor(
267 art::Thread* thread,
268 art::LinearAlloc* allocator,
269 const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
Alex Lighteee0bd42017-02-14 15:31:45 +0000270 ObsoleteMap* obsolete_maps)
Alex Lightdba61482016-12-21 08:20:29 -0800271 : StackVisitor(thread,
Andreas Gampe6e897762018-10-16 13:09:32 -0700272 /*context=*/nullptr,
Alex Lightdba61482016-12-21 08:20:29 -0800273 StackVisitor::StackWalkKind::kIncludeInlinedFrames),
274 allocator_(allocator),
275 obsoleted_methods_(obsoleted_methods),
Alex Light4ba388a2017-01-27 10:26:49 -0800276 obsolete_maps_(obsolete_maps) { }
Alex Lightdba61482016-12-21 08:20:29 -0800277
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100278 ~ObsoleteMethodStackVisitor() override {}
Alex Lightdba61482016-12-21 08:20:29 -0800279
280 public:
281 // Returns true if we successfully installed obsolete methods on this thread, filling
282 // obsolete_maps_ with the translations if needed. Returns false and fills error_msg if we fail.
283 // The stack is cleaned up when we fail.
Alex Light007ada22017-01-10 13:33:56 -0800284 static void UpdateObsoleteFrames(
Alex Lightdba61482016-12-21 08:20:29 -0800285 art::Thread* thread,
286 art::LinearAlloc* allocator,
287 const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
Alex Lighteee0bd42017-02-14 15:31:45 +0000288 ObsoleteMap* obsolete_maps)
Alex Light007ada22017-01-10 13:33:56 -0800289 REQUIRES(art::Locks::mutator_lock_) {
Alex Lightdba61482016-12-21 08:20:29 -0800290 ObsoleteMethodStackVisitor visitor(thread,
291 allocator,
292 obsoleted_methods,
Alex Light007ada22017-01-10 13:33:56 -0800293 obsolete_maps);
Alex Lightdba61482016-12-21 08:20:29 -0800294 visitor.WalkStack();
Alex Lightdba61482016-12-21 08:20:29 -0800295 }
296
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100297 bool VisitFrame() override REQUIRES(art::Locks::mutator_lock_) {
Alex Lighteee0bd42017-02-14 15:31:45 +0000298 art::ScopedAssertNoThreadSuspension snts("Fixing up the stack for obsolete methods.");
Alex Lightdba61482016-12-21 08:20:29 -0800299 art::ArtMethod* old_method = GetMethod();
Alex Lightdba61482016-12-21 08:20:29 -0800300 if (obsoleted_methods_.find(old_method) != obsoleted_methods_.end()) {
Alex Lightdba61482016-12-21 08:20:29 -0800301 // We cannot ensure that the right dex file is used in inlined frames so we don't support
302 // redefining them.
Nicolas Geoffray226805d2018-12-14 10:59:02 +0000303 DCHECK(!IsInInlinedFrame()) << "Inlined frames are not supported when using redefinition: "
304 << old_method->PrettyMethod() << " is inlined into "
305 << GetOuterMethod()->PrettyMethod();
Alex Lighteee0bd42017-02-14 15:31:45 +0000306 art::ArtMethod* new_obsolete_method = obsolete_maps_->FindObsoleteVersion(old_method);
307 if (new_obsolete_method == nullptr) {
Alex Lightdba61482016-12-21 08:20:29 -0800308 // Create a new Obsolete Method and put it in the list.
309 art::Runtime* runtime = art::Runtime::Current();
310 art::ClassLinker* cl = runtime->GetClassLinker();
311 auto ptr_size = cl->GetImagePointerSize();
312 const size_t method_size = art::ArtMethod::Size(ptr_size);
Alex Light5c11a792017-03-10 14:29:22 -0800313 auto* method_storage = allocator_->Alloc(art::Thread::Current(), method_size);
Alex Light007ada22017-01-10 13:33:56 -0800314 CHECK(method_storage != nullptr) << "Unable to allocate storage for obsolete version of '"
315 << old_method->PrettyMethod() << "'";
Alex Lightdba61482016-12-21 08:20:29 -0800316 new_obsolete_method = new (method_storage) art::ArtMethod();
317 new_obsolete_method->CopyFrom(old_method, ptr_size);
318 DCHECK_EQ(new_obsolete_method->GetDeclaringClass(), old_method->GetDeclaringClass());
319 new_obsolete_method->SetIsObsolete();
Alex Lightfcbafb32017-02-02 15:09:54 -0800320 new_obsolete_method->SetDontCompile();
Alex Lightdb01a092017-04-03 15:39:55 -0700321 cl->SetEntryPointsForObsoleteMethod(new_obsolete_method);
Alex Lighteee0bd42017-02-14 15:31:45 +0000322 obsolete_maps_->RecordObsolete(old_method, new_obsolete_method);
Alex Lightdba61482016-12-21 08:20:29 -0800323 }
324 DCHECK(new_obsolete_method != nullptr);
325 SetMethod(new_obsolete_method);
326 }
327 return true;
328 }
329
330 private:
331 // The linear allocator we should use to make new methods.
332 art::LinearAlloc* allocator_;
333 // The set of all methods which could be obsoleted.
334 const std::unordered_set<art::ArtMethod*>& obsoleted_methods_;
335 // A map from the original to the newly allocated obsolete method for frames on this thread. The
Alex Lighteee0bd42017-02-14 15:31:45 +0000336 // values in this map are added to the obsolete_methods_ (and obsolete_dex_caches_) fields of
337 // the redefined classes ClassExt as it is filled.
338 ObsoleteMap* obsolete_maps_;
Alex Lightdba61482016-12-21 08:20:29 -0800339};
340
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000341template <RedefinitionType kType>
342jvmtiError
343Redefiner::IsModifiableClassGeneric(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
344 if (env == nullptr) {
345 return ERR(INVALID_ENVIRONMENT);
346 }
Alex Lighte4a88632017-01-10 07:41:24 -0800347 art::Thread* self = art::Thread::Current();
348 art::ScopedObjectAccess soa(self);
349 art::StackHandleScope<1> hs(self);
350 art::ObjPtr<art::mirror::Object> obj(self->DecodeJObject(klass));
Alex Light413a8ad2019-02-14 10:19:44 -0800351 if (obj.IsNull() || !obj->IsClass()) {
Alex Lighte4a88632017-01-10 07:41:24 -0800352 return ERR(INVALID_CLASS);
353 }
354 art::Handle<art::mirror::Class> h_klass(hs.NewHandle(obj->AsClass()));
355 std::string err_unused;
356 *is_redefinable =
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000357 Redefiner::GetClassRedefinitionError<kType>(h_klass, &err_unused) != ERR(UNMODIFIABLE_CLASS)
358 ? JNI_TRUE
359 : JNI_FALSE;
Alex Lighte4a88632017-01-10 07:41:24 -0800360 return OK;
361}
362
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000363jvmtiError
364Redefiner::IsStructurallyModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
365 return Redefiner::IsModifiableClassGeneric<RedefinitionType::kStructural>(
366 env, klass, is_redefinable);
367}
368
369jvmtiError Redefiner::IsModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
370 return Redefiner::IsModifiableClassGeneric<RedefinitionType::kNormal>(env, klass, is_redefinable);
371}
372
373template <RedefinitionType kType>
374jvmtiError Redefiner::GetClassRedefinitionError(jclass klass, /*out*/ std::string* error_msg) {
Alex Light9e7859c2018-04-05 13:49:43 -0700375 art::Thread* self = art::Thread::Current();
376 art::ScopedObjectAccess soa(self);
377 art::StackHandleScope<1> hs(self);
378 art::ObjPtr<art::mirror::Object> obj(self->DecodeJObject(klass));
Alex Light413a8ad2019-02-14 10:19:44 -0800379 if (obj.IsNull() || !obj->IsClass()) {
Alex Light9e7859c2018-04-05 13:49:43 -0700380 return ERR(INVALID_CLASS);
381 }
382 art::Handle<art::mirror::Class> h_klass(hs.NewHandle(obj->AsClass()));
Alex Lightd55b8442019-10-15 15:46:07 -0700383 return Redefiner::GetClassRedefinitionError<kType>(h_klass, error_msg);
Alex Light9e7859c2018-04-05 13:49:43 -0700384}
385
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000386template <RedefinitionType kType>
Alex Lighte4a88632017-01-10 07:41:24 -0800387jvmtiError Redefiner::GetClassRedefinitionError(art::Handle<art::mirror::Class> klass,
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000388 /*out*/ std::string* error_msg) {
389 art::Thread* self = art::Thread::Current();
Alex Light9e7859c2018-04-05 13:49:43 -0700390 if (!klass->IsResolved()) {
391 // It's only a problem to try to retransform/redefine a unprepared class if it's happening on
392 // the same thread as the class-linking process. If it's on another thread we will be able to
393 // wait for the preparation to finish and continue from there.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000394 if (klass->GetLockOwnerThreadId() == self->GetThreadId()) {
Alex Light9e7859c2018-04-05 13:49:43 -0700395 *error_msg = "Modification of class " + klass->PrettyClass() +
396 " from within the classes ClassLoad callback is not supported to prevent deadlocks." +
397 " Please use ClassFileLoadHook directly instead.";
398 return ERR(INTERNAL);
399 } else {
400 LOG(WARNING) << klass->PrettyClass() << " is not yet resolved. Attempting to transform "
401 << "it could cause arbitrary length waits as the class is being resolved.";
402 }
403 }
Alex Lighte4a88632017-01-10 07:41:24 -0800404 if (klass->IsPrimitive()) {
405 *error_msg = "Modification of primitive classes is not supported";
406 return ERR(UNMODIFIABLE_CLASS);
407 } else if (klass->IsInterface()) {
408 *error_msg = "Modification of Interface classes is currently not supported";
409 return ERR(UNMODIFIABLE_CLASS);
Alex Light09f274f2017-02-21 15:00:48 -0800410 } else if (klass->IsStringClass()) {
411 *error_msg = "Modification of String class is not supported";
412 return ERR(UNMODIFIABLE_CLASS);
Alex Lighte4a88632017-01-10 07:41:24 -0800413 } else if (klass->IsArrayClass()) {
414 *error_msg = "Modification of Array classes is not supported";
415 return ERR(UNMODIFIABLE_CLASS);
416 } else if (klass->IsProxyClass()) {
417 *error_msg = "Modification of proxy classes is not supported";
418 return ERR(UNMODIFIABLE_CLASS);
419 }
420
Alex Lighte77b48b2017-02-22 11:08:06 -0800421 for (jclass c : art::NonDebuggableClasses::GetNonDebuggableClasses()) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000422 if (klass.Get() == self->DecodeJObject(c)->AsClass()) {
Alex Lighte77b48b2017-02-22 11:08:06 -0800423 *error_msg = "Class might have stack frames that cannot be made obsolete";
424 return ERR(UNMODIFIABLE_CLASS);
425 }
426 }
427
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000428 if (kType == RedefinitionType::kStructural) {
Alex Lightfb119572019-09-18 15:04:53 -0700429 // Class initialization interacts really badly with structural redefinition since we need to
430 // make the old class obsolete. We currently just blanket don't allow it.
431 // TODO It might be nice to allow this at some point.
432 if (klass->IsInitializing() &&
433 !klass->IsInitialized() &&
434 klass->GetClinitThreadId() == self->GetTid()) {
435 // We are in the class-init running on this thread.
436 *error_msg = "Modification of class " + klass->PrettyClass() + " during class" +
437 " initialization is not allowed.";
438 return ERR(INTERNAL);
439 }
440 if (!art::Runtime::Current()->GetClassLinker()->EnsureInitialized(
441 self, klass, /*can_init_fields=*/true, /*can_init_parents=*/true)) {
442 self->AssertPendingException();
443 *error_msg = "Class " + klass->PrettyClass() + " failed initialization. Structural" +
444 " redefinition of erroneous classes is not allowed. Failure was: " +
445 self->GetException()->Dump();
446 self->ClearException();
447 return ERR(INVALID_CLASS);
448 }
Alex Lightf1b18fa2019-11-11 14:22:00 -0800449 if (klass->IsMirrored()) {
450 std::string pc(klass->PrettyClass());
451 *error_msg = StringPrintf("Class %s is a mirror class and cannot be structurally redefined.",
452 pc.c_str());
453 return ERR(UNMODIFIABLE_CLASS);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000454 }
455 // Check Thread specifically since it's not a root but too many things reach into it with Unsafe
456 // too allow structural redefinition.
457 if (klass->IsAssignableFrom(
458 self->DecodeJObject(art::WellKnownClasses::java_lang_Thread)->AsClass())) {
459 *error_msg =
460 "java.lang.Thread has fields accessed using sun.misc.unsafe directly. It is not "
461 "safe to structurally redefine it.";
462 return ERR(UNMODIFIABLE_CLASS);
463 }
Nicolas Geoffray664999a2019-12-03 08:47:26 +0000464 // Check for already existing non-static fields/methods.
465 // TODO Remove this once we support generic method/field addition.
466 if (!klass->IsFinal()) {
467 bool non_static_method = false;
468 klass->VisitMethods([&](art::ArtMethod* m) REQUIRES_SHARED(art::Locks::mutator_lock_) {
469 // Since direct-methods (ie privates + <init> are not in any vtable/iftable we can update
470 // them).
471 if (!m->IsDirect()) {
472 non_static_method = true;
473 *error_msg = StringPrintf("%s has a non-direct function %s",
474 klass->PrettyClass().c_str(),
475 m->PrettyMethod().c_str());
476 }
477 }, art::kRuntimePointerSize);
478 if (non_static_method) {
479 return ERR(UNMODIFIABLE_CLASS);
480 }
481 bool non_static_field = false;
482 klass->VisitFields([&](art::ArtField* f) REQUIRES_SHARED(art::Locks::mutator_lock_) {
483 if (!f->IsStatic()) {
484 non_static_field = true;
485 *error_msg = StringPrintf("%s has a non-static field %s",
486 klass->PrettyClass().c_str(),
487 f->PrettyField().c_str());
488 }
489 });
490 if (non_static_field) {
491 return ERR(UNMODIFIABLE_CLASS);
492 }
493 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000494 // Check for fields/methods which were returned before moving to index jni id type.
495 // TODO We might want to rework how this is done. Once full redefinition is implemented we will
496 // need to check any subtypes too.
497 art::ObjPtr<art::mirror::ClassExt> ext(klass->GetExtData());
498 if (!ext.IsNull()) {
Alex Lightbc19b752019-12-02 18:54:13 +0000499 if (ext->HasInstanceFieldPointerIdMarker() ||
500 ext->HasMethodPointerIdMarker() ||
501 ext->HasStaticFieldPointerIdMarker()) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000502 return ERR(UNMODIFIABLE_CLASS);
503 }
504 }
505 }
Alex Lighte4a88632017-01-10 07:41:24 -0800506 return OK;
507}
508
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000509template jvmtiError Redefiner::GetClassRedefinitionError<RedefinitionType::kNormal>(
510 art::Handle<art::mirror::Class> klass, /*out*/ std::string* error_msg);
511template jvmtiError Redefiner::GetClassRedefinitionError<RedefinitionType::kStructural>(
512 art::Handle<art::mirror::Class> klass, /*out*/ std::string* error_msg);
513
Alex Lighta01de592016-11-15 10:43:06 -0800514// Moves dex data to an anonymous, read-only mmap'd region.
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100515art::MemMap Redefiner::MoveDataToMemMap(const std::string& original_location,
516 art::ArrayRef<const unsigned char> data,
517 std::string* error_msg) {
518 art::MemMap map = art::MemMap::MapAnonymous(
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800519 StringPrintf("%s-transformed", original_location.c_str()).c_str(),
Alex Lightb7354d52017-03-30 15:17:01 -0700520 data.size(),
Alex Lighta01de592016-11-15 10:43:06 -0800521 PROT_READ|PROT_WRITE,
Andreas Gampe6e897762018-10-16 13:09:32 -0700522 /*low_4gb=*/ false,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100523 error_msg);
524 if (LIKELY(map.IsValid())) {
525 memcpy(map.Begin(), data.data(), data.size());
526 // Make the dex files mmap read only. This matches how other DexFiles are mmaped and prevents
527 // programs from corrupting it.
528 map.Protect(PROT_READ);
Alex Lighta01de592016-11-15 10:43:06 -0800529 }
Alex Lighta01de592016-11-15 10:43:06 -0800530 return map;
531}
532
Alex Lighta7e38d82017-01-19 14:57:28 -0800533Redefiner::ClassRedefinition::ClassRedefinition(
534 Redefiner* driver,
535 jclass klass,
536 const art::DexFile* redefined_dex_file,
537 const char* class_sig,
Vladimir Markoe1993c72017-06-14 17:01:38 +0100538 art::ArrayRef<const unsigned char> orig_dex_file) :
Alex Lighta7e38d82017-01-19 14:57:28 -0800539 driver_(driver),
540 klass_(klass),
541 dex_file_(redefined_dex_file),
542 class_sig_(class_sig),
543 original_dex_file_(orig_dex_file) {
Alex Light0e692732017-01-10 15:00:05 -0800544 GetMirrorClass()->MonitorEnter(driver_->self_);
545}
546
547Redefiner::ClassRedefinition::~ClassRedefinition() {
548 if (driver_ != nullptr) {
549 GetMirrorClass()->MonitorExit(driver_->self_);
550 }
551}
552
Alex Lightd55b8442019-10-15 15:46:07 -0700553template<RedefinitionType kType>
554jvmtiError Redefiner::RedefineClassesGeneric(jvmtiEnv* jenv,
555 jint class_count,
556 const jvmtiClassDefinition* definitions) {
Alex Light3732beb2019-10-04 13:35:34 -0700557 art::Runtime* runtime = art::Runtime::Current();
558 art::Thread* self = art::Thread::Current();
559 ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
Alex Light0e692732017-01-10 15:00:05 -0800560 if (env == nullptr) {
Alex Light3732beb2019-10-04 13:35:34 -0700561 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE env was null!";
Alex Light0e692732017-01-10 15:00:05 -0800562 return ERR(INVALID_ENVIRONMENT);
563 } else if (class_count < 0) {
Alex Light3732beb2019-10-04 13:35:34 -0700564 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE class_count was less then 0";
Alex Light0e692732017-01-10 15:00:05 -0800565 return ERR(ILLEGAL_ARGUMENT);
566 } else if (class_count == 0) {
567 // We don't actually need to do anything. Just return OK.
568 return OK;
569 } else if (definitions == nullptr) {
Alex Light3732beb2019-10-04 13:35:34 -0700570 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE null definitions!";
Alex Light0e692732017-01-10 15:00:05 -0800571 return ERR(NULL_POINTER);
572 }
Alex Light3732beb2019-10-04 13:35:34 -0700573 std::string error_msg;
Alex Light6ac57502017-01-19 15:05:06 -0800574 std::vector<ArtClassDefinition> def_vector;
575 def_vector.reserve(class_count);
576 for (jint i = 0; i < class_count; i++) {
Alex Lightd55b8442019-10-15 15:46:07 -0700577 jvmtiError res = Redefiner::GetClassRedefinitionError<RedefinitionType::kNormal>(
578 definitions[i].klass, &error_msg);
Alex Lightce6ee702017-03-06 15:46:43 -0800579 if (res != OK) {
Alex Light3732beb2019-10-04 13:35:34 -0700580 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE " << error_msg;
Alex Lightce6ee702017-03-06 15:46:43 -0800581 return res;
Alex Lightce6ee702017-03-06 15:46:43 -0800582 }
Alex Light6ac57502017-01-19 15:05:06 -0800583 ArtClassDefinition def;
Alex Light64e4c142018-01-30 13:46:37 -0800584 res = def.Init(self, definitions[i]);
Alex Light6ac57502017-01-19 15:05:06 -0800585 if (res != OK) {
Alex Light3732beb2019-10-04 13:35:34 -0700586 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE bad definition " << i;
Alex Light6ac57502017-01-19 15:05:06 -0800587 return res;
588 }
589 def_vector.push_back(std::move(def));
590 }
591 // Call all the transformation events.
Alex Lightd55b8442019-10-15 15:46:07 -0700592 Transformer::RetransformClassesDirect<kType>(self, &def_vector);
593 if (kType == RedefinitionType::kStructural) {
594 Transformer::RetransformClassesDirect<RedefinitionType::kNormal>(self, &def_vector);
595 }
596 jvmtiError res = RedefineClassesDirect(env, runtime, self, def_vector, kType, &error_msg);
Alex Light3732beb2019-10-04 13:35:34 -0700597 if (res != OK) {
598 JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE " << error_msg;
599 }
600 return res;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000601}
602
Alex Lightd55b8442019-10-15 15:46:07 -0700603jvmtiError Redefiner::StructurallyRedefineClasses(jvmtiEnv* jenv,
604 jint class_count,
605 const jvmtiClassDefinition* definitions) {
606 ArtJvmTiEnv* art_env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
607 if (art_env == nullptr) {
608 return ERR(INVALID_ENVIRONMENT);
609 } else if (art_env->capabilities.can_redefine_classes != 1) {
610 return ERR(MUST_POSSESS_CAPABILITY);
611 }
612 return RedefineClassesGeneric<RedefinitionType::kStructural>(jenv, class_count, definitions);
613}
614
615jvmtiError Redefiner::RedefineClasses(jvmtiEnv* jenv,
616 jint class_count,
617 const jvmtiClassDefinition* definitions) {
618 return RedefineClassesGeneric<RedefinitionType::kNormal>(jenv, class_count, definitions);
619}
620
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000621jvmtiError Redefiner::StructurallyRedefineClassDirect(jvmtiEnv* env,
622 jclass klass,
623 const unsigned char* data,
624 jint data_size) {
625 if (env == nullptr) {
626 return ERR(INVALID_ENVIRONMENT);
627 } else if (ArtJvmTiEnv::AsArtJvmTiEnv(env)->capabilities.can_redefine_classes != 1) {
628 JVMTI_LOG(INFO, env) << "Does not have can_redefine_classes cap!";
629 return ERR(MUST_POSSESS_CAPABILITY);
630 }
631 std::vector<ArtClassDefinition> acds;
632 ArtClassDefinition acd;
633 jvmtiError err = acd.Init(
634 art::Thread::Current(),
635 jvmtiClassDefinition{ .klass = klass, .class_byte_count = data_size, .class_bytes = data });
636 if (err != OK) {
637 return err;
638 }
639 acds.push_back(std::move(acd));
640 std::string err_msg;
641 err = RedefineClassesDirect(ArtJvmTiEnv::AsArtJvmTiEnv(env),
642 art::Runtime::Current(),
643 art::Thread::Current(),
644 acds,
645 RedefinitionType::kStructural,
646 &err_msg);
647 if (err != OK) {
648 JVMTI_LOG(WARNING, env) << "Failed structural redefinition: " << err_msg;
649 }
650 return err;
Alex Light6ac57502017-01-19 15:05:06 -0800651}
652
653jvmtiError Redefiner::RedefineClassesDirect(ArtJvmTiEnv* env,
654 art::Runtime* runtime,
655 art::Thread* self,
656 const std::vector<ArtClassDefinition>& definitions,
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000657 RedefinitionType type,
Alex Light6ac57502017-01-19 15:05:06 -0800658 std::string* error_msg) {
659 DCHECK(env != nullptr);
660 if (definitions.size() == 0) {
661 // We don't actually need to do anything. Just return OK.
662 return OK;
663 }
Alex Lightc2d0c962019-10-23 14:14:25 -0700664 // We need to fiddle with the verification class flags. To do this we need to make sure there are
665 // no concurrent redefinitions of the same class at the same time. For simplicity and because
666 // this is not expected to be a common occurrence we will just wrap the whole thing in a TOP-level
667 // lock.
668
Alex Light0e692732017-01-10 15:00:05 -0800669 // Stop JIT for the duration of this redefine since the JIT might concurrently compile a method we
670 // are going to redefine.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000671 // TODO We should prevent user-code suspensions to make sure this isn't held for too long.
Alex Light0e692732017-01-10 15:00:05 -0800672 art::jit::ScopedJitSuspend suspend_jit;
673 // Get shared mutator lock so we can lock all the classes.
674 art::ScopedObjectAccess soa(self);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000675 Redefiner r(env, runtime, self, type, error_msg);
Alex Light6ac57502017-01-19 15:05:06 -0800676 for (const ArtClassDefinition& def : definitions) {
677 // Only try to transform classes that have been modified.
Alex Light40528472017-03-28 09:07:36 -0700678 if (def.IsModified()) {
Alex Light6ac57502017-01-19 15:05:06 -0800679 jvmtiError res = r.AddRedefinition(env, def);
680 if (res != OK) {
681 return res;
682 }
Alex Light0e692732017-01-10 15:00:05 -0800683 }
684 }
685 return r.Run();
686}
687
Alex Light6ac57502017-01-19 15:05:06 -0800688jvmtiError Redefiner::AddRedefinition(ArtJvmTiEnv* env, const ArtClassDefinition& def) {
Alex Light0e692732017-01-10 15:00:05 -0800689 std::string original_dex_location;
690 jvmtiError ret = OK;
Alex Lightb7354d52017-03-30 15:17:01 -0700691 if ((ret = GetClassLocation(env, def.GetClass(), &original_dex_location))) {
Alex Light0e692732017-01-10 15:00:05 -0800692 *error_msg_ = "Unable to get original dex file location!";
693 return ret;
694 }
Alex Light52a2db52017-01-19 23:00:21 +0000695 char* generic_ptr_unused = nullptr;
696 char* signature_ptr = nullptr;
Alex Lightb7354d52017-03-30 15:17:01 -0700697 if ((ret = env->GetClassSignature(def.GetClass(), &signature_ptr, &generic_ptr_unused)) != OK) {
Alex Light6ac57502017-01-19 15:05:06 -0800698 *error_msg_ = "Unable to get class signature!";
699 return ret;
Alex Light52a2db52017-01-19 23:00:21 +0000700 }
Andreas Gampe54711412017-02-21 12:41:43 -0800701 JvmtiUniquePtr<char> generic_unique_ptr(MakeJvmtiUniquePtr(env, generic_ptr_unused));
702 JvmtiUniquePtr<char> signature_unique_ptr(MakeJvmtiUniquePtr(env, signature_ptr));
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100703 art::MemMap map = MoveDataToMemMap(original_dex_location, def.GetDexData(), error_msg_);
Alex Light6ac57502017-01-19 15:05:06 -0800704 std::ostringstream os;
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100705 if (!map.IsValid()) {
Alex Lightb7354d52017-03-30 15:17:01 -0700706 os << "Failed to create anonymous mmap for modified dex file of class " << def.GetName()
Alex Light0e692732017-01-10 15:00:05 -0800707 << "in dex file " << original_dex_location << " because: " << *error_msg_;
708 *error_msg_ = os.str();
Alex Lighta01de592016-11-15 10:43:06 -0800709 return ERR(OUT_OF_MEMORY);
710 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100711 if (map.Size() < sizeof(art::DexFile::Header)) {
Alex Light0e692732017-01-10 15:00:05 -0800712 *error_msg_ = "Could not read dex file header because dex_data was too short";
Alex Lighta01de592016-11-15 10:43:06 -0800713 return ERR(INVALID_CLASS_FORMAT);
714 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100715 std::string name = map.GetName();
716 uint32_t checksum = reinterpret_cast<const art::DexFile::Header*>(map.Begin())->checksum_;
David Sehr013fd802018-01-11 22:55:24 -0800717 const art::ArtDexFileLoader dex_file_loader;
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100718 std::unique_ptr<const art::DexFile> dex_file(dex_file_loader.Open(name,
David Sehr013fd802018-01-11 22:55:24 -0800719 checksum,
720 std::move(map),
Andreas Gampe6e897762018-10-16 13:09:32 -0700721 /*verify=*/true,
722 /*verify_checksum=*/true,
David Sehr013fd802018-01-11 22:55:24 -0800723 error_msg_));
Alex Lighta01de592016-11-15 10:43:06 -0800724 if (dex_file.get() == nullptr) {
Alex Lightb7354d52017-03-30 15:17:01 -0700725 os << "Unable to load modified dex file for " << def.GetName() << ": " << *error_msg_;
Alex Light0e692732017-01-10 15:00:05 -0800726 *error_msg_ = os.str();
Alex Lighta01de592016-11-15 10:43:06 -0800727 return ERR(INVALID_CLASS_FORMAT);
728 }
Alex Light0e692732017-01-10 15:00:05 -0800729 redefinitions_.push_back(
Alex Lighta7e38d82017-01-19 14:57:28 -0800730 Redefiner::ClassRedefinition(this,
Alex Lightb7354d52017-03-30 15:17:01 -0700731 def.GetClass(),
Alex Lighta7e38d82017-01-19 14:57:28 -0800732 dex_file.release(),
733 signature_ptr,
Alex Light40528472017-03-28 09:07:36 -0700734 def.GetNewOriginalDexFile()));
Alex Light0e692732017-01-10 15:00:05 -0800735 return OK;
Alex Lighta01de592016-11-15 10:43:06 -0800736}
737
Vladimir Marko4617d582019-03-28 13:48:31 +0000738art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::GetMirrorClass() {
Alex Light0e692732017-01-10 15:00:05 -0800739 return driver_->self_->DecodeJObject(klass_)->AsClass();
Alex Lighta01de592016-11-15 10:43:06 -0800740}
741
Vladimir Markoc524e9e2019-03-26 10:54:50 +0000742art::ObjPtr<art::mirror::ClassLoader> Redefiner::ClassRedefinition::GetClassLoader() {
Alex Lighta01de592016-11-15 10:43:06 -0800743 return GetMirrorClass()->GetClassLoader();
744}
745
Alex Light0e692732017-01-10 15:00:05 -0800746art::mirror::DexCache* Redefiner::ClassRedefinition::CreateNewDexCache(
747 art::Handle<art::mirror::ClassLoader> loader) {
Alex Light07f06212017-06-01 14:01:43 -0700748 art::StackHandleScope<2> hs(driver_->self_);
749 art::ClassLinker* cl = driver_->runtime_->GetClassLinker();
750 art::Handle<art::mirror::DexCache> cache(hs.NewHandle(
751 art::ObjPtr<art::mirror::DexCache>::DownCast(
Vladimir Markob4eb1b12018-05-24 11:09:38 +0100752 art::GetClassRoot<art::mirror::DexCache>(cl)->AllocObject(driver_->self_))));
Alex Light07f06212017-06-01 14:01:43 -0700753 if (cache.IsNull()) {
754 driver_->self_->AssertPendingOOMException();
755 return nullptr;
756 }
757 art::Handle<art::mirror::String> location(hs.NewHandle(
758 cl->GetInternTable()->InternStrong(dex_file_->GetLocation().c_str())));
759 if (location.IsNull()) {
760 driver_->self_->AssertPendingOOMException();
761 return nullptr;
762 }
763 art::WriterMutexLock mu(driver_->self_, *art::Locks::dex_lock_);
764 art::mirror::DexCache::InitializeDexCache(driver_->self_,
765 cache.Get(),
766 location.Get(),
767 dex_file_.get(),
768 loader.IsNull() ? driver_->runtime_->GetLinearAlloc()
769 : loader->GetAllocator(),
770 art::kRuntimePointerSize);
771 return cache.Get();
Alex Lighta01de592016-11-15 10:43:06 -0800772}
773
Alex Light0e692732017-01-10 15:00:05 -0800774void Redefiner::RecordFailure(jvmtiError result,
775 const std::string& class_sig,
776 const std::string& error_msg) {
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800777 *error_msg_ = StringPrintf("Unable to perform redefinition of '%s': %s",
Alex Light0e692732017-01-10 15:00:05 -0800778 class_sig.c_str(),
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800779 error_msg.c_str());
Alex Lighta01de592016-11-15 10:43:06 -0800780 result_ = result;
781}
782
Alex Light2f814aa2017-03-24 15:21:34 +0000783art::mirror::Object* Redefiner::ClassRedefinition::AllocateOrGetOriginalDexFile() {
Alex Lighta7e38d82017-01-19 14:57:28 -0800784 // If we have been specifically given a new set of bytes use that
785 if (original_dex_file_.size() != 0) {
Alex Light440b5d92017-01-24 15:32:25 -0800786 return art::mirror::ByteArray::AllocateAndFill(
787 driver_->self_,
Vladimir Markoe1993c72017-06-14 17:01:38 +0100788 reinterpret_cast<const signed char*>(original_dex_file_.data()),
Vladimir Markobcf17522018-06-01 13:14:32 +0100789 original_dex_file_.size()).Ptr();
Alex Lighta01de592016-11-15 10:43:06 -0800790 }
Alex Lighta7e38d82017-01-19 14:57:28 -0800791
792 // See if we already have one set.
793 art::ObjPtr<art::mirror::ClassExt> ext(GetMirrorClass()->GetExtData());
794 if (!ext.IsNull()) {
Alex Light2f814aa2017-03-24 15:21:34 +0000795 art::ObjPtr<art::mirror::Object> old_original_dex_file(ext->GetOriginalDexFile());
796 if (!old_original_dex_file.IsNull()) {
Alex Lighta7e38d82017-01-19 14:57:28 -0800797 // We do. Use it.
Alex Light2f814aa2017-03-24 15:21:34 +0000798 return old_original_dex_file.Ptr();
Alex Lighta7e38d82017-01-19 14:57:28 -0800799 }
Alex Lighta01de592016-11-15 10:43:06 -0800800 }
Alex Lighta7e38d82017-01-19 14:57:28 -0800801
Alex Light2f814aa2017-03-24 15:21:34 +0000802 // return the current dex_cache which has the dex file in it.
803 art::ObjPtr<art::mirror::DexCache> current_dex_cache(GetMirrorClass()->GetDexCache());
Alex Lighta7e38d82017-01-19 14:57:28 -0800804 // TODO Handle this or make it so it cannot happen.
Alex Light2f814aa2017-03-24 15:21:34 +0000805 if (current_dex_cache->GetDexFile()->NumClassDefs() != 1) {
Alex Lighta7e38d82017-01-19 14:57:28 -0800806 LOG(WARNING) << "Current dex file has more than one class in it. Calling RetransformClasses "
807 << "on this class might fail if no transformations are applied to it!";
Alex Lighta01de592016-11-15 10:43:06 -0800808 }
Alex Light2f814aa2017-03-24 15:21:34 +0000809 return current_dex_cache.Ptr();
Alex Lighta01de592016-11-15 10:43:06 -0800810}
811
Alex Lightdba61482016-12-21 08:20:29 -0800812struct CallbackCtx {
Alex Lighteee0bd42017-02-14 15:31:45 +0000813 ObsoleteMap* obsolete_map;
Alex Lightdba61482016-12-21 08:20:29 -0800814 art::LinearAlloc* allocator;
Alex Lightdba61482016-12-21 08:20:29 -0800815 std::unordered_set<art::ArtMethod*> obsolete_methods;
Alex Lightdba61482016-12-21 08:20:29 -0800816
Alex Lighteee0bd42017-02-14 15:31:45 +0000817 explicit CallbackCtx(ObsoleteMap* map, art::LinearAlloc* alloc)
818 : obsolete_map(map), allocator(alloc) {}
Alex Lightdba61482016-12-21 08:20:29 -0800819};
820
Alex Lightdba61482016-12-21 08:20:29 -0800821void DoAllocateObsoleteMethodsCallback(art::Thread* t, void* vdata) NO_THREAD_SAFETY_ANALYSIS {
822 CallbackCtx* data = reinterpret_cast<CallbackCtx*>(vdata);
Alex Light007ada22017-01-10 13:33:56 -0800823 ObsoleteMethodStackVisitor::UpdateObsoleteFrames(t,
824 data->allocator,
825 data->obsolete_methods,
Alex Lighteee0bd42017-02-14 15:31:45 +0000826 data->obsolete_map);
Alex Lightdba61482016-12-21 08:20:29 -0800827}
828
829// This creates any ArtMethod* structures needed for obsolete methods and ensures that the stack is
830// updated so they will be run.
Alex Light0e692732017-01-10 15:00:05 -0800831// TODO Rewrite so we can do this only once regardless of how many redefinitions there are.
Vladimir Markod93e3742018-07-18 10:58:13 +0100832void Redefiner::ClassRedefinition::FindAndAllocateObsoleteMethods(
833 art::ObjPtr<art::mirror::Class> art_klass) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000834 DCHECK(!IsStructuralRedefinition());
Alex Lightdba61482016-12-21 08:20:29 -0800835 art::ScopedAssertNoThreadSuspension ns("No thread suspension during thread stack walking");
Vladimir Markod93e3742018-07-18 10:58:13 +0100836 art::ObjPtr<art::mirror::ClassExt> ext = art_klass->GetExtData();
Alex Lightdba61482016-12-21 08:20:29 -0800837 CHECK(ext->GetObsoleteMethods() != nullptr);
Alex Light7916f202017-01-27 09:00:15 -0800838 art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
Alex Lighteee0bd42017-02-14 15:31:45 +0000839 // This holds pointers to the obsolete methods map fields which are updated as needed.
840 ObsoleteMap map(ext->GetObsoleteMethods(), ext->GetObsoleteDexCaches(), art_klass->GetDexCache());
841 CallbackCtx ctx(&map, linker->GetAllocatorForClassLoader(art_klass->GetClassLoader()));
Alex Lightdba61482016-12-21 08:20:29 -0800842 // Add all the declared methods to the map
843 for (auto& m : art_klass->GetDeclaredMethods(art::kRuntimePointerSize)) {
Alex Light7532d582017-02-13 16:36:06 -0800844 if (m.IsIntrinsic()) {
845 LOG(WARNING) << "Redefining intrinsic method " << m.PrettyMethod() << ". This may cause the "
846 << "unexpected use of the original definition of " << m.PrettyMethod() << "in "
847 << "methods that have already been compiled.";
848 }
Alex Lighteee0bd42017-02-14 15:31:45 +0000849 // It is possible to simply filter out some methods where they cannot really become obsolete,
850 // such as native methods and keep their original (possibly optimized) implementations. We don't
851 // do this, however, since we would need to mark these functions (still in the classes
852 // declared_methods array) as obsolete so we will find the correct dex file to get meta-data
853 // from (for example about stack-frame size). Furthermore we would be unable to get some useful
854 // error checking from the interpreter which ensure we don't try to start executing obsolete
855 // methods.
Nicolas Geoffray7558d272017-02-10 10:01:47 +0000856 ctx.obsolete_methods.insert(&m);
Alex Lightdba61482016-12-21 08:20:29 -0800857 }
858 {
Alex Light0e692732017-01-10 15:00:05 -0800859 art::MutexLock mu(driver_->self_, *art::Locks::thread_list_lock_);
Alex Lightdba61482016-12-21 08:20:29 -0800860 art::ThreadList* list = art::Runtime::Current()->GetThreadList();
861 list->ForEach(DoAllocateObsoleteMethodsCallback, static_cast<void*>(&ctx));
Vladimir Markoeab02482019-05-09 10:28:17 +0100862 // After we've done walking all threads' stacks and updating method pointers on them,
863 // update JIT data structures (used by the stack walk above) to point to the new methods.
Alex Lighte7a33542019-04-10 14:22:49 -0700864 art::jit::Jit* jit = art::Runtime::Current()->GetJit();
865 if (jit != nullptr) {
866 for (const ObsoleteMap::ObsoleteMethodPair& it : *ctx.obsolete_map) {
867 // Notify the JIT we are making this obsolete method. It will update the jit's internal
868 // structures to keep track of the new obsolete method.
869 jit->GetCodeCache()->MoveObsoleteMethod(it.old_method, it.obsolete_method);
870 }
871 }
Alex Lightdba61482016-12-21 08:20:29 -0800872 }
Alex Lightdba61482016-12-21 08:20:29 -0800873}
874
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000875namespace {
876template <typename T> struct SignatureType {};
877template <> struct SignatureType<art::ArtField> { using type = std::string_view; };
878template <> struct SignatureType<art::ArtMethod> { using type = art::Signature; };
879
880template <typename T> struct NameAndSignature {
881 public:
882 using SigType = typename SignatureType<T>::type;
883
884 NameAndSignature(const art::DexFile* dex_file, uint32_t id);
885
886 NameAndSignature(const std::string_view& name, const SigType& sig) : name_(name), sig_(sig) {}
887
888 bool operator==(const NameAndSignature<T>& o) {
889 return name_ == o.name_ && sig_ == o.sig_;
Alex Light6161f132017-01-25 10:30:20 -0800890 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000891
892 std::ostream& dump(std::ostream& os) const {
893 return os << "'" << name_ << "' (sig: " << sig_ << ")";
894 }
895
896 std::string ToString() const {
897 std::ostringstream os;
898 os << *this;
899 return os.str();
900 }
901
902 std::string_view name_;
903 SigType sig_;
904};
905
906template <typename T>
907std::ostream& operator<<(std::ostream& os, const NameAndSignature<T>& nas) {
908 return nas.dump(os);
Alex Light6161f132017-01-25 10:30:20 -0800909}
910
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000911using FieldNameAndSignature = NameAndSignature<art::ArtField>;
912template <>
913FieldNameAndSignature::NameAndSignature(const art::DexFile* dex_file, uint32_t id)
914 : FieldNameAndSignature(dex_file->GetFieldName(dex_file->GetFieldId(id)),
915 dex_file->GetFieldTypeDescriptor(dex_file->GetFieldId(id))) {}
916
917using MethodNameAndSignature = NameAndSignature<art::ArtMethod>;
918template <>
919MethodNameAndSignature::NameAndSignature(const art::DexFile* dex_file, uint32_t id)
920 : MethodNameAndSignature(dex_file->GetMethodName(dex_file->GetMethodId(id)),
921 dex_file->GetMethodSignature(dex_file->GetMethodId(id))) {}
922
923} // namespace
924
925void Redefiner::ClassRedefinition::RecordNewMethodAdded() {
926 DCHECK(driver_->IsStructuralRedefinition());
927 added_methods_ = true;
928}
929void Redefiner::ClassRedefinition::RecordNewFieldAdded() {
930 DCHECK(driver_->IsStructuralRedefinition());
931 added_fields_ = true;
932}
933
934bool Redefiner::ClassRedefinition::CheckMethods() {
Alex Light6161f132017-01-25 10:30:20 -0800935 art::StackHandleScope<1> hs(driver_->self_);
936 art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
937 DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
938
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000939 // Make sure we have the same number of methods (or the same or greater if we're structural).
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -0700940 art::ClassAccessor accessor(*dex_file_, dex_file_->GetClassDef(0));
941 uint32_t num_new_method = accessor.NumMethods();
Alex Light6161f132017-01-25 10:30:20 -0800942 uint32_t num_old_method = h_klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size();
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000943 const bool is_structural = driver_->IsStructuralRedefinition();
944 if (!is_structural && num_new_method != num_old_method) {
Alex Light6161f132017-01-25 10:30:20 -0800945 bool bigger = num_new_method > num_old_method;
946 RecordFailure(bigger ? ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED)
947 : ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED),
948 StringPrintf("Total number of declared methods changed from %d to %d",
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000949 num_old_method,
950 num_new_method));
Alex Light6161f132017-01-25 10:30:20 -0800951 return false;
952 }
953
954 // Skip all of the fields. We should have already checked this.
Alex Light6161f132017-01-25 10:30:20 -0800955 // Check each of the methods. NB we don't need to specifically check for removals since the 2 dex
956 // files have the same number of methods, which means there must be an equal amount of additions
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -0700957 // and removals. We should have already checked the fields.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000958 const art::DexFile& old_dex_file = h_klass->GetDexFile();
959 art::ClassAccessor old_accessor(old_dex_file, *h_klass->GetClassDef());
960 // We need this to check for methods going missing in structural cases.
961 std::vector<bool> seen_old_methods(
962 (kCheckAllMethodsSeenOnce || is_structural) ? old_accessor.NumMethods() : 0, false);
963 const auto old_methods = old_accessor.GetMethods();
964 for (const art::ClassAccessor::Method& new_method : accessor.GetMethods()) {
Alex Light6161f132017-01-25 10:30:20 -0800965 // Get the data on the method we are searching for
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000966 MethodNameAndSignature new_method_id(dex_file_.get(), new_method.GetIndex());
967 const auto old_iter =
968 std::find_if(old_methods.cbegin(), old_methods.cend(), [&](const auto& current_old_method) {
969 MethodNameAndSignature old_method_id(&old_dex_file, current_old_method.GetIndex());
970 return old_method_id == new_method_id;
971 });
972
Alex Light986914b2019-11-19 01:12:25 +0000973 if (!new_method.IsStaticOrDirect()) {
974 RecordHasVirtualMembers();
975 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000976 if (old_iter == old_methods.cend()) {
Nicolas Geoffray664999a2019-12-03 08:47:26 +0000977 // TODO Support adding non-static methods.
978 if (is_structural && (new_method.IsStaticOrDirect() || h_klass->IsFinal())) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000979 RecordNewMethodAdded();
980 } else {
981 RecordFailure(
982 ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED),
983 StringPrintf("Unknown virtual method %s was added!", new_method_id.ToString().c_str()));
984 return false;
985 }
986 } else if (new_method.GetAccessFlags() != old_iter->GetAccessFlags()) {
987 RecordFailure(
988 ERR(UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED),
989 StringPrintf("method %s had different access flags", new_method_id.ToString().c_str()));
Alex Light6161f132017-01-25 10:30:20 -0800990 return false;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000991 } else if (kCheckAllMethodsSeenOnce || is_structural) {
992 // We only need this if we are structural.
993 size_t off = std::distance(old_methods.cbegin(), old_iter);
994 DCHECK(!seen_old_methods[off])
995 << "field at " << off << "("
996 << MethodNameAndSignature(&old_dex_file, old_iter->GetIndex()) << ") already seen?";
997 seen_old_methods[off] = true;
Alex Light6161f132017-01-25 10:30:20 -0800998 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +0000999 }
1000 if ((kCheckAllMethodsSeenOnce || is_structural) &&
1001 !std::all_of(seen_old_methods.cbegin(), seen_old_methods.cend(), [](auto x) { return x; })) {
1002 DCHECK(is_structural) << "We should have hit an earlier failure before getting here!";
1003 auto first_fail =
1004 std::find_if(seen_old_methods.cbegin(), seen_old_methods.cend(), [](auto x) { return !x; });
1005 auto off = std::distance(seen_old_methods.cbegin(), first_fail);
1006 auto fail = old_methods.cbegin();
1007 std::advance(fail, off);
1008 RecordFailure(
1009 ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED),
1010 StringPrintf("Method %s missing!",
1011 FieldNameAndSignature(&old_dex_file, fail->GetIndex()).ToString().c_str()));
1012 return false;
Alex Light6161f132017-01-25 10:30:20 -08001013 }
1014 return true;
1015}
1016
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001017bool Redefiner::ClassRedefinition::CheckFields() {
Alex Light6161f132017-01-25 10:30:20 -08001018 art::StackHandleScope<1> hs(driver_->self_);
1019 art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
1020 DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -07001021 art::ClassAccessor new_accessor(*dex_file_, dex_file_->GetClassDef(0));
1022
Alex Light6161f132017-01-25 10:30:20 -08001023 const art::DexFile& old_dex_file = h_klass->GetDexFile();
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -07001024 art::ClassAccessor old_accessor(old_dex_file, *h_klass->GetClassDef());
Alex Light6161f132017-01-25 10:30:20 -08001025 // Instance and static fields can be differentiated by their flags so no need to check them
1026 // separately.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001027 std::vector<bool> seen_old_fields(old_accessor.NumFields(), false);
1028 const auto old_fields = old_accessor.GetFields();
Mathieu Chartier4ac9ade2018-07-24 10:27:21 -07001029 for (const art::ClassAccessor::Field& new_field : new_accessor.GetFields()) {
Alex Light6161f132017-01-25 10:30:20 -08001030 // Get the data on the method we are searching for
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001031 FieldNameAndSignature new_field_id(dex_file_.get(), new_field.GetIndex());
1032 const auto old_iter =
1033 std::find_if(old_fields.cbegin(), old_fields.cend(), [&](const auto& old_iter) {
1034 FieldNameAndSignature old_field_id(&old_dex_file, old_iter.GetIndex());
1035 return old_field_id == new_field_id;
1036 });
Alex Light986914b2019-11-19 01:12:25 +00001037 if (!new_field.IsStatic()) {
1038 RecordHasVirtualMembers();
1039 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001040 if (old_iter == old_fields.cend()) {
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001041 // TODO Support adding non-static fields.
1042 if (driver_->IsStructuralRedefinition() && (new_field.IsStatic() || h_klass->IsFinal())) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001043 RecordNewFieldAdded();
1044 } else {
1045 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
1046 StringPrintf("Unknown field %s added!", new_field_id.ToString().c_str()));
1047 return false;
1048 }
1049 } else if (new_field.GetAccessFlags() != old_iter->GetAccessFlags()) {
1050 RecordFailure(
1051 ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
1052 StringPrintf("Field %s had different access flags", new_field_id.ToString().c_str()));
Alex Light6161f132017-01-25 10:30:20 -08001053 return false;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001054 } else {
1055 size_t off = std::distance(old_fields.cbegin(), old_iter);
1056 DCHECK(!seen_old_fields[off])
1057 << "field at " << off << "(" << FieldNameAndSignature(&old_dex_file, old_iter->GetIndex())
1058 << ") already seen?";
1059 seen_old_fields[off] = true;
Alex Light6161f132017-01-25 10:30:20 -08001060 }
Alex Light6161f132017-01-25 10:30:20 -08001061 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001062 if (!std::all_of(seen_old_fields.cbegin(), seen_old_fields.cend(), [](auto x) { return x; })) {
1063 auto first_fail =
1064 std::find_if(seen_old_fields.cbegin(), seen_old_fields.cend(), [](auto x) { return !x; });
1065 auto off = std::distance(seen_old_fields.cbegin(), first_fail);
1066 auto fail = old_fields.cbegin();
1067 std::advance(fail, off);
1068 RecordFailure(
1069 ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
1070 StringPrintf("Field %s is missing!",
1071 FieldNameAndSignature(&old_dex_file, fail->GetIndex()).ToString().c_str()));
Alex Light6161f132017-01-25 10:30:20 -08001072 return false;
1073 }
1074 return true;
1075}
1076
Alex Light0e692732017-01-10 15:00:05 -08001077bool Redefiner::ClassRedefinition::CheckClass() {
Alex Light0e692732017-01-10 15:00:05 -08001078 art::StackHandleScope<1> hs(driver_->self_);
Alex Light460d1b42017-01-10 15:37:17 +00001079 // Easy check that only 1 class def is present.
1080 if (dex_file_->NumClassDefs() != 1) {
1081 RecordFailure(ERR(ILLEGAL_ARGUMENT),
1082 StringPrintf("Expected 1 class def in dex file but found %d",
1083 dex_file_->NumClassDefs()));
1084 return false;
1085 }
1086 // Get the ClassDef from the new DexFile.
1087 // Since the dex file has only a single class def the index is always 0.
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08001088 const art::dex::ClassDef& def = dex_file_->GetClassDef(0);
Alex Light460d1b42017-01-10 15:37:17 +00001089 // Get the class as it is now.
1090 art::Handle<art::mirror::Class> current_class(hs.NewHandle(GetMirrorClass()));
1091
1092 // Check the access flags didn't change.
1093 if (def.GetJavaAccessFlags() != (current_class->GetAccessFlags() & art::kAccValidClassFlags)) {
1094 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED),
1095 "Cannot change modifiers of class by redefinition");
1096 return false;
1097 }
1098
1099 // Check class name.
1100 // These should have been checked by the dexfile verifier on load.
1101 DCHECK_NE(def.class_idx_, art::dex::TypeIndex::Invalid()) << "Invalid type index";
1102 const char* descriptor = dex_file_->StringByTypeIdx(def.class_idx_);
1103 DCHECK(descriptor != nullptr) << "Invalid dex file structure!";
1104 if (!current_class->DescriptorEquals(descriptor)) {
1105 std::string storage;
1106 RecordFailure(ERR(NAMES_DONT_MATCH),
1107 StringPrintf("expected file to contain class called '%s' but found '%s'!",
1108 current_class->GetDescriptor(&storage),
1109 descriptor));
1110 return false;
1111 }
1112 if (current_class->IsObjectClass()) {
1113 if (def.superclass_idx_ != art::dex::TypeIndex::Invalid()) {
1114 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass added!");
1115 return false;
1116 }
1117 } else {
1118 const char* super_descriptor = dex_file_->StringByTypeIdx(def.superclass_idx_);
1119 DCHECK(descriptor != nullptr) << "Invalid dex file structure!";
1120 if (!current_class->GetSuperClass()->DescriptorEquals(super_descriptor)) {
1121 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass changed");
1122 return false;
1123 }
1124 }
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08001125 const art::dex::TypeList* interfaces = dex_file_->GetInterfacesList(def);
Alex Light460d1b42017-01-10 15:37:17 +00001126 if (interfaces == nullptr) {
1127 if (current_class->NumDirectInterfaces() != 0) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001128 // TODO Support this for kStructural.
Alex Light460d1b42017-01-10 15:37:17 +00001129 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added");
1130 return false;
1131 }
1132 } else {
1133 DCHECK(!current_class->IsProxyClass());
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08001134 const art::dex::TypeList* current_interfaces = current_class->GetInterfaceTypeList();
Alex Light460d1b42017-01-10 15:37:17 +00001135 if (current_interfaces == nullptr || current_interfaces->Size() != interfaces->Size()) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001136 // TODO Support this for kStructural.
Alex Light460d1b42017-01-10 15:37:17 +00001137 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added or removed");
1138 return false;
1139 }
1140 // The order of interfaces is (barely) meaningful so we error if it changes.
1141 const art::DexFile& orig_dex_file = current_class->GetDexFile();
1142 for (uint32_t i = 0; i < interfaces->Size(); i++) {
1143 if (strcmp(
1144 dex_file_->StringByTypeIdx(interfaces->GetTypeItem(i).type_idx_),
1145 orig_dex_file.StringByTypeIdx(current_interfaces->GetTypeItem(i).type_idx_)) != 0) {
1146 RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED),
1147 "Interfaces changed or re-ordered");
1148 return false;
1149 }
1150 }
1151 }
Alex Light460d1b42017-01-10 15:37:17 +00001152 return true;
1153}
1154
Alex Light0e692732017-01-10 15:00:05 -08001155bool Redefiner::ClassRedefinition::CheckRedefinable() {
Alex Lighte4a88632017-01-10 07:41:24 -08001156 std::string err;
Alex Light0e692732017-01-10 15:00:05 -08001157 art::StackHandleScope<1> hs(driver_->self_);
Alex Light460d1b42017-01-10 15:37:17 +00001158
Alex Lighte4a88632017-01-10 07:41:24 -08001159 art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001160 jvmtiError res;
Alex Lightd55b8442019-10-15 15:46:07 -07001161 if (driver_->type_ == RedefinitionType::kStructural && this->IsStructuralRedefinition()) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001162 res = Redefiner::GetClassRedefinitionError<RedefinitionType::kStructural>(h_klass, &err);
Alex Light986914b2019-11-19 01:12:25 +00001163 if (res == OK && HasVirtualMembers() && h_klass->IsFinalizable()) {
1164 res = ERR(INTERNAL);
1165 err = "Cannot redefine finalizable objects at this time.";
1166 }
Alex Lightd55b8442019-10-15 15:46:07 -07001167 } else {
1168 res = Redefiner::GetClassRedefinitionError<RedefinitionType::kNormal>(h_klass, &err);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001169 }
Alex Lighte4a88632017-01-10 07:41:24 -08001170 if (res != OK) {
1171 RecordFailure(res, err);
1172 return false;
1173 } else {
1174 return true;
1175 }
Alex Light460d1b42017-01-10 15:37:17 +00001176}
1177
Alex Light0e692732017-01-10 15:00:05 -08001178bool Redefiner::ClassRedefinition::CheckRedefinitionIsValid() {
Alex Lightd55b8442019-10-15 15:46:07 -07001179 return CheckClass() && CheckFields() && CheckMethods() && CheckRedefinable();
Alex Light460d1b42017-01-10 15:37:17 +00001180}
1181
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001182class RedefinitionDataIter;
1183
Alex Light0e692732017-01-10 15:00:05 -08001184// A wrapper that lets us hold onto the arbitrary sized data needed for redefinitions in a
1185// reasonably sane way. This adds no fields to the normal ObjectArray. By doing this we can avoid
1186// having to deal with the fact that we need to hold an arbitrary number of references live.
1187class RedefinitionDataHolder {
1188 public:
1189 enum DataSlot : int32_t {
1190 kSlotSourceClassLoader = 0,
1191 kSlotJavaDexFile = 1,
1192 kSlotNewDexFileCookie = 2,
1193 kSlotNewDexCache = 3,
1194 kSlotMirrorClass = 4,
Alex Lighta7e38d82017-01-19 14:57:28 -08001195 kSlotOrigDexFile = 5,
Alex Light1e3926a2017-04-07 10:38:06 -07001196 kSlotOldObsoleteMethods = 6,
1197 kSlotOldDexCaches = 7,
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001198 kSlotNewClassObject = 8,
Alex Light986914b2019-11-19 01:12:25 +00001199 kSlotOldInstanceObjects = 9,
1200 kSlotNewInstanceObjects = 10,
Alex Light0e692732017-01-10 15:00:05 -08001201
1202 // Must be last one.
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001203 kNumSlots = 11,
Alex Light0e692732017-01-10 15:00:05 -08001204 };
1205
1206 // This needs to have a HandleScope passed in that is capable of creating a new Handle without
1207 // overflowing. Only one handle will be created. This object has a lifetime identical to that of
1208 // the passed in handle-scope.
1209 RedefinitionDataHolder(art::StackHandleScope<1>* hs,
1210 art::Runtime* runtime,
1211 art::Thread* self,
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001212 std::vector<Redefiner::ClassRedefinition>* redefinitions)
1213 REQUIRES_SHARED(art::Locks::mutator_lock_) :
Vladimir Markob4eb1b12018-05-24 11:09:38 +01001214 arr_(hs->NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
1215 self,
1216 art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Object>>(runtime->GetClassLinker()),
1217 redefinitions->size() * kNumSlots))),
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001218 redefinitions_(redefinitions) {}
Alex Light0e692732017-01-10 15:00:05 -08001219
1220 bool IsNull() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1221 return arr_.IsNull();
1222 }
1223
Vladimir Markod93e3742018-07-18 10:58:13 +01001224 art::ObjPtr<art::mirror::ClassLoader> GetSourceClassLoader(jint klass_index) const
Alex Light0e692732017-01-10 15:00:05 -08001225 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001226 return art::ObjPtr<art::mirror::ClassLoader>::DownCast(
1227 GetSlot(klass_index, kSlotSourceClassLoader));
Alex Light0e692732017-01-10 15:00:05 -08001228 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001229 art::ObjPtr<art::mirror::Object> GetJavaDexFile(jint klass_index) const
Alex Light8c889d22017-02-06 13:58:27 -08001230 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light0e692732017-01-10 15:00:05 -08001231 return GetSlot(klass_index, kSlotJavaDexFile);
1232 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001233 art::ObjPtr<art::mirror::LongArray> GetNewDexFileCookie(jint klass_index) const
Alex Light0e692732017-01-10 15:00:05 -08001234 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001235 return art::ObjPtr<art::mirror::LongArray>::DownCast(
1236 GetSlot(klass_index, kSlotNewDexFileCookie));
Alex Light0e692732017-01-10 15:00:05 -08001237 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001238 art::ObjPtr<art::mirror::DexCache> GetNewDexCache(jint klass_index) const
Alex Light0e692732017-01-10 15:00:05 -08001239 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001240 return art::ObjPtr<art::mirror::DexCache>::DownCast(GetSlot(klass_index, kSlotNewDexCache));
Alex Light0e692732017-01-10 15:00:05 -08001241 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001242 art::ObjPtr<art::mirror::Class> GetMirrorClass(jint klass_index) const
Alex Light8c889d22017-02-06 13:58:27 -08001243 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001244 return art::ObjPtr<art::mirror::Class>::DownCast(GetSlot(klass_index, kSlotMirrorClass));
Alex Light0e692732017-01-10 15:00:05 -08001245 }
1246
Vladimir Markod93e3742018-07-18 10:58:13 +01001247 art::ObjPtr<art::mirror::Object> GetOriginalDexFile(jint klass_index) const
Alex Lighta7e38d82017-01-19 14:57:28 -08001248 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001249 return art::ObjPtr<art::mirror::Object>::DownCast(GetSlot(klass_index, kSlotOrigDexFile));
Alex Lighta7e38d82017-01-19 14:57:28 -08001250 }
1251
Vladimir Markod93e3742018-07-18 10:58:13 +01001252 art::ObjPtr<art::mirror::PointerArray> GetOldObsoleteMethods(jint klass_index) const
Alex Light1e3926a2017-04-07 10:38:06 -07001253 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Vladimir Markod93e3742018-07-18 10:58:13 +01001254 return art::ObjPtr<art::mirror::PointerArray>::DownCast(
Alex Light1e3926a2017-04-07 10:38:06 -07001255 GetSlot(klass_index, kSlotOldObsoleteMethods));
1256 }
1257
Vladimir Markod93e3742018-07-18 10:58:13 +01001258 art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> GetOldDexCaches(
1259 jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1260 return art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>>::DownCast(
Alex Light1e3926a2017-04-07 10:38:06 -07001261 GetSlot(klass_index, kSlotOldDexCaches));
1262 }
1263
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001264 art::ObjPtr<art::mirror::Class> GetNewClassObject(jint klass_index) const
1265 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1266 return art::ObjPtr<art::mirror::Class>::DownCast(GetSlot(klass_index, kSlotNewClassObject));
1267 }
1268
Alex Light986914b2019-11-19 01:12:25 +00001269 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetOldInstanceObjects(
1270 jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1271 return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>>::DownCast(
1272 GetSlot(klass_index, kSlotOldInstanceObjects));
1273 }
1274
1275 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetNewInstanceObjects(
1276 jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1277 return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>>::DownCast(
1278 GetSlot(klass_index, kSlotNewInstanceObjects));
1279 }
1280
Vladimir Markod93e3742018-07-18 10:58:13 +01001281 void SetSourceClassLoader(jint klass_index, art::ObjPtr<art::mirror::ClassLoader> loader)
Alex Light0e692732017-01-10 15:00:05 -08001282 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1283 SetSlot(klass_index, kSlotSourceClassLoader, loader);
1284 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001285 void SetJavaDexFile(jint klass_index, art::ObjPtr<art::mirror::Object> dexfile)
Alex Light0e692732017-01-10 15:00:05 -08001286 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1287 SetSlot(klass_index, kSlotJavaDexFile, dexfile);
1288 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001289 void SetNewDexFileCookie(jint klass_index, art::ObjPtr<art::mirror::LongArray> cookie)
Alex Light0e692732017-01-10 15:00:05 -08001290 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1291 SetSlot(klass_index, kSlotNewDexFileCookie, cookie);
1292 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001293 void SetNewDexCache(jint klass_index, art::ObjPtr<art::mirror::DexCache> cache)
Alex Light0e692732017-01-10 15:00:05 -08001294 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1295 SetSlot(klass_index, kSlotNewDexCache, cache);
1296 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001297 void SetMirrorClass(jint klass_index, art::ObjPtr<art::mirror::Class> klass)
Alex Light0e692732017-01-10 15:00:05 -08001298 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1299 SetSlot(klass_index, kSlotMirrorClass, klass);
1300 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001301 void SetOriginalDexFile(jint klass_index, art::ObjPtr<art::mirror::Object> bytes)
Alex Lighta7e38d82017-01-19 14:57:28 -08001302 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1303 SetSlot(klass_index, kSlotOrigDexFile, bytes);
1304 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001305 void SetOldObsoleteMethods(jint klass_index, art::ObjPtr<art::mirror::PointerArray> methods)
Alex Light1e3926a2017-04-07 10:38:06 -07001306 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1307 SetSlot(klass_index, kSlotOldObsoleteMethods, methods);
1308 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001309 void SetOldDexCaches(jint klass_index,
1310 art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> caches)
Alex Light1e3926a2017-04-07 10:38:06 -07001311 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1312 SetSlot(klass_index, kSlotOldDexCaches, caches);
1313 }
Alex Light0e692732017-01-10 15:00:05 -08001314
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001315 void SetNewClassObject(jint klass_index, art::ObjPtr<art::mirror::Class> klass)
1316 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1317 SetSlot(klass_index, kSlotNewClassObject, klass);
1318 }
1319
Alex Light986914b2019-11-19 01:12:25 +00001320 void SetOldInstanceObjects(jint klass_index,
1321 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1322 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1323 SetSlot(klass_index, kSlotOldInstanceObjects, objs);
1324 }
1325 void SetNewInstanceObjects(jint klass_index,
1326 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1327 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1328 SetSlot(klass_index, kSlotNewInstanceObjects, objs);
1329 }
Alex Light8c889d22017-02-06 13:58:27 -08001330 int32_t Length() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light0e692732017-01-10 15:00:05 -08001331 return arr_->GetLength() / kNumSlots;
1332 }
1333
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001334 std::vector<Redefiner::ClassRedefinition>* GetRedefinitions()
1335 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1336 return redefinitions_;
1337 }
1338
1339 bool operator==(const RedefinitionDataHolder& other) const
1340 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1341 return arr_.Get() == other.arr_.Get();
1342 }
1343
1344 bool operator!=(const RedefinitionDataHolder& other) const
1345 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1346 return !(*this == other);
1347 }
1348
1349 RedefinitionDataIter begin() REQUIRES_SHARED(art::Locks::mutator_lock_);
1350 RedefinitionDataIter end() REQUIRES_SHARED(art::Locks::mutator_lock_);
1351
Alex Light0e692732017-01-10 15:00:05 -08001352 private:
Alex Light8c889d22017-02-06 13:58:27 -08001353 mutable art::Handle<art::mirror::ObjectArray<art::mirror::Object>> arr_;
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001354 std::vector<Redefiner::ClassRedefinition>* redefinitions_;
Alex Light0e692732017-01-10 15:00:05 -08001355
Vladimir Markod93e3742018-07-18 10:58:13 +01001356 art::ObjPtr<art::mirror::Object> GetSlot(jint klass_index, DataSlot slot) const
1357 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light0e692732017-01-10 15:00:05 -08001358 DCHECK_LT(klass_index, Length());
1359 return arr_->Get((kNumSlots * klass_index) + slot);
1360 }
1361
1362 void SetSlot(jint klass_index,
1363 DataSlot slot,
1364 art::ObjPtr<art::mirror::Object> obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1365 DCHECK(!art::Runtime::Current()->IsActiveTransaction());
1366 DCHECK_LT(klass_index, Length());
1367 arr_->Set<false>((kNumSlots * klass_index) + slot, obj);
1368 }
1369
1370 DISALLOW_COPY_AND_ASSIGN(RedefinitionDataHolder);
1371};
1372
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001373class RedefinitionDataIter {
1374 public:
1375 RedefinitionDataIter(int32_t idx, RedefinitionDataHolder& holder) : idx_(idx), holder_(holder) {}
1376
1377 RedefinitionDataIter(const RedefinitionDataIter&) = default;
1378 RedefinitionDataIter(RedefinitionDataIter&&) = default;
1379 RedefinitionDataIter& operator=(const RedefinitionDataIter&) = default;
1380 RedefinitionDataIter& operator=(RedefinitionDataIter&&) = default;
1381
1382 bool operator==(const RedefinitionDataIter& other) const
1383 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1384 return idx_ == other.idx_ && holder_ == other.holder_;
1385 }
1386
1387 bool operator!=(const RedefinitionDataIter& other) const
1388 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1389 return !(*this == other);
1390 }
1391
1392 RedefinitionDataIter operator++() { // Value after modification.
1393 idx_++;
1394 return *this;
1395 }
1396
1397 RedefinitionDataIter operator++(int) {
1398 RedefinitionDataIter temp = *this;
1399 idx_++;
1400 return temp;
1401 }
1402
1403 RedefinitionDataIter operator+(ssize_t delta) const {
1404 RedefinitionDataIter temp = *this;
1405 temp += delta;
1406 return temp;
1407 }
1408
1409 RedefinitionDataIter& operator+=(ssize_t delta) {
1410 idx_ += delta;
1411 return *this;
1412 }
1413
Alex Light986914b2019-11-19 01:12:25 +00001414 // Compat for STL iterators.
1415 RedefinitionDataIter& operator*() {
1416 return *this;
1417 }
1418
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001419 Redefiner::ClassRedefinition& GetRedefinition() REQUIRES_SHARED(art::Locks::mutator_lock_) {
1420 return (*holder_.GetRedefinitions())[idx_];
1421 }
1422
1423 RedefinitionDataHolder& GetHolder() {
1424 return holder_;
1425 }
1426
Vladimir Markod93e3742018-07-18 10:58:13 +01001427 art::ObjPtr<art::mirror::ClassLoader> GetSourceClassLoader() const
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001428 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1429 return holder_.GetSourceClassLoader(idx_);
1430 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001431 art::ObjPtr<art::mirror::Object> GetJavaDexFile() const
1432 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001433 return holder_.GetJavaDexFile(idx_);
1434 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001435 art::ObjPtr<art::mirror::LongArray> GetNewDexFileCookie() const
1436 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001437 return holder_.GetNewDexFileCookie(idx_);
1438 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001439 art::ObjPtr<art::mirror::DexCache> GetNewDexCache() const
1440 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001441 return holder_.GetNewDexCache(idx_);
1442 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001443 art::ObjPtr<art::mirror::Class> GetMirrorClass() const
1444 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001445 return holder_.GetMirrorClass(idx_);
1446 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001447 art::ObjPtr<art::mirror::Object> GetOriginalDexFile() const
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001448 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light2f814aa2017-03-24 15:21:34 +00001449 return holder_.GetOriginalDexFile(idx_);
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001450 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001451 art::ObjPtr<art::mirror::PointerArray> GetOldObsoleteMethods() const
Alex Light1e3926a2017-04-07 10:38:06 -07001452 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1453 return holder_.GetOldObsoleteMethods(idx_);
1454 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001455 art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> GetOldDexCaches() const
Alex Light1e3926a2017-04-07 10:38:06 -07001456 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1457 return holder_.GetOldDexCaches(idx_);
1458 }
1459
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001460 art::ObjPtr<art::mirror::Class> GetNewClassObject() const
1461 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1462 return holder_.GetNewClassObject(idx_);
1463 }
1464
Alex Light986914b2019-11-19 01:12:25 +00001465 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetOldInstanceObjects() const
1466 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1467 return holder_.GetOldInstanceObjects(idx_);
1468 }
1469 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetNewInstanceObjects() const
1470 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1471 return holder_.GetNewInstanceObjects(idx_);
1472 }
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001473 int32_t GetIndex() const {
1474 return idx_;
1475 }
1476
1477 void SetSourceClassLoader(art::mirror::ClassLoader* loader)
1478 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1479 holder_.SetSourceClassLoader(idx_, loader);
1480 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001481 void SetJavaDexFile(art::ObjPtr<art::mirror::Object> dexfile)
1482 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001483 holder_.SetJavaDexFile(idx_, dexfile);
1484 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001485 void SetNewDexFileCookie(art::ObjPtr<art::mirror::LongArray> cookie)
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001486 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1487 holder_.SetNewDexFileCookie(idx_, cookie);
1488 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001489 void SetNewDexCache(art::ObjPtr<art::mirror::DexCache> cache)
1490 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001491 holder_.SetNewDexCache(idx_, cache);
1492 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001493 void SetMirrorClass(art::ObjPtr<art::mirror::Class> klass)
1494 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001495 holder_.SetMirrorClass(idx_, klass);
1496 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001497 void SetOriginalDexFile(art::ObjPtr<art::mirror::Object> bytes)
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001498 REQUIRES_SHARED(art::Locks::mutator_lock_) {
Alex Light2f814aa2017-03-24 15:21:34 +00001499 holder_.SetOriginalDexFile(idx_, bytes);
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001500 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001501 void SetOldObsoleteMethods(art::ObjPtr<art::mirror::PointerArray> methods)
Alex Light1e3926a2017-04-07 10:38:06 -07001502 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1503 holder_.SetOldObsoleteMethods(idx_, methods);
1504 }
Vladimir Markod93e3742018-07-18 10:58:13 +01001505 void SetOldDexCaches(art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> caches)
Alex Light1e3926a2017-04-07 10:38:06 -07001506 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1507 holder_.SetOldDexCaches(idx_, caches);
1508 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001509 void SetNewClassObject(art::ObjPtr<art::mirror::Class> klass)
1510 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1511 holder_.SetNewClassObject(idx_, klass);
1512 }
Alex Light986914b2019-11-19 01:12:25 +00001513 void SetOldInstanceObjects(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1514 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1515 holder_.SetOldInstanceObjects(idx_, objs);
1516 }
1517 void SetNewInstanceObjects(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1518 REQUIRES_SHARED(art::Locks::mutator_lock_) {
1519 holder_.SetNewInstanceObjects(idx_, objs);
1520 }
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001521
1522 private:
1523 int32_t idx_;
1524 RedefinitionDataHolder& holder_;
1525};
1526
1527RedefinitionDataIter RedefinitionDataHolder::begin() {
1528 return RedefinitionDataIter(0, *this);
1529}
1530
1531RedefinitionDataIter RedefinitionDataHolder::end() {
1532 return RedefinitionDataIter(Length(), *this);
1533}
1534
1535bool Redefiner::ClassRedefinition::CheckVerification(const RedefinitionDataIter& iter) {
Alex Light8c889d22017-02-06 13:58:27 -08001536 DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
1537 art::StackHandleScope<2> hs(driver_->self_);
1538 std::string error;
1539 // TODO Make verification log level lower
Andreas Gampe6d7abbd2017-04-24 13:19:09 -07001540 art::verifier::FailureKind failure =
Andreas Gampea43ba3d2019-03-13 15:49:20 -07001541 art::verifier::ClassVerifier::VerifyClass(driver_->self_,
1542 dex_file_.get(),
1543 hs.NewHandle(iter.GetNewDexCache()),
1544 hs.NewHandle(GetClassLoader()),
1545 /*class_def=*/ dex_file_->GetClassDef(0),
1546 /*callbacks=*/ nullptr,
1547 /*allow_soft_failures=*/ true,
1548 /*log_level=*/
1549 art::verifier::HardFailLogMode::kLogWarning,
1550 art::Runtime::Current()->GetTargetSdkVersion(),
1551 &error);
Alex Light53330612017-10-04 15:29:53 -07001552 switch (failure) {
1553 case art::verifier::FailureKind::kNoFailure:
Alex Lightb1eebde2019-10-22 16:30:47 +00001554 // TODO It is possible that by doing redefinition previous NO_COMPILE verification failures
1555 // were fixed. It would be nice to reflect this in the new implementations.
1556 return true;
Alex Light53330612017-10-04 15:29:53 -07001557 case art::verifier::FailureKind::kSoftFailure:
Alex Lightb1eebde2019-10-22 16:30:47 +00001558 // Soft failures might require interpreter on some methods. It won't prevent redefinition but
1559 // it does mean we need to run the verifier again and potentially update method flags after
1560 // performing the swap.
1561 needs_reverify_ = true;
Alex Light53330612017-10-04 15:29:53 -07001562 return true;
1563 case art::verifier::FailureKind::kHardFailure: {
1564 RecordFailure(ERR(FAILS_VERIFICATION), "Failed to verify class. Error was: " + error);
1565 return false;
1566 }
Alex Light8c889d22017-02-06 13:58:27 -08001567 }
Alex Light8c889d22017-02-06 13:58:27 -08001568}
1569
Alex Light1babae02017-02-01 15:35:34 -08001570// Looks through the previously allocated cookies to see if we need to update them with another new
1571// dexfile. This is so that even if multiple classes with the same classloader are redefined at
1572// once they are all added to the classloader.
1573bool Redefiner::ClassRedefinition::AllocateAndRememberNewDexFileCookie(
Alex Light1babae02017-02-01 15:35:34 -08001574 art::Handle<art::mirror::ClassLoader> source_class_loader,
1575 art::Handle<art::mirror::Object> dex_file_obj,
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001576 /*out*/RedefinitionDataIter* cur_data) {
Alex Light1babae02017-02-01 15:35:34 -08001577 art::StackHandleScope<2> hs(driver_->self_);
1578 art::MutableHandle<art::mirror::LongArray> old_cookie(
1579 hs.NewHandle<art::mirror::LongArray>(nullptr));
1580 bool has_older_cookie = false;
1581 // See if we already have a cookie that a previous redefinition got from the same classloader.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001582 for (auto old_data = cur_data->GetHolder().begin(); old_data != *cur_data; ++old_data) {
1583 if (old_data.GetSourceClassLoader() == source_class_loader.Get()) {
Alex Light1babae02017-02-01 15:35:34 -08001584 // Since every instance of this classloader should have the same cookie associated with it we
1585 // can stop looking here.
1586 has_older_cookie = true;
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001587 old_cookie.Assign(old_data.GetNewDexFileCookie());
Alex Light1babae02017-02-01 15:35:34 -08001588 break;
1589 }
1590 }
1591 if (old_cookie.IsNull()) {
1592 // No older cookie. Get it directly from the dex_file_obj
1593 // We should not have seen this classloader elsewhere.
1594 CHECK(!has_older_cookie);
1595 old_cookie.Assign(ClassLoaderHelper::GetDexFileCookie(dex_file_obj));
1596 }
1597 // Use the old cookie to generate the new one with the new DexFile* added in.
1598 art::Handle<art::mirror::LongArray>
1599 new_cookie(hs.NewHandle(ClassLoaderHelper::AllocateNewDexFileCookie(driver_->self_,
1600 old_cookie,
1601 dex_file_.get())));
1602 // Make sure the allocation worked.
1603 if (new_cookie.IsNull()) {
1604 return false;
1605 }
1606
1607 // Save the cookie.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001608 cur_data->SetNewDexFileCookie(new_cookie.Get());
Alex Light1babae02017-02-01 15:35:34 -08001609 // If there are other copies of this same classloader we need to make sure that we all have the
1610 // same cookie.
1611 if (has_older_cookie) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001612 for (auto old_data = cur_data->GetHolder().begin(); old_data != *cur_data; ++old_data) {
Alex Light1babae02017-02-01 15:35:34 -08001613 // We will let the GC take care of the cookie we allocated for this one.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001614 if (old_data.GetSourceClassLoader() == source_class_loader.Get()) {
1615 old_data.SetNewDexFileCookie(new_cookie.Get());
Alex Light1babae02017-02-01 15:35:34 -08001616 }
1617 }
1618 }
1619
1620 return true;
1621}
1622
Alex Light986914b2019-11-19 01:12:25 +00001623bool Redefiner::ClassRedefinition::CollectAndCreateNewInstances(
1624 /*out*/ RedefinitionDataIter* cur_data) {
1625 if (!IsStructuralRedefinition()) {
1626 return true;
1627 }
1628 art::VariableSizedHandleScope hs(driver_->self_);
1629 art::Handle<art::mirror::Class> old_klass(hs.NewHandle(cur_data->GetMirrorClass()));
1630 std::vector<art::Handle<art::mirror::Object>> old_instances;
1631 art::gc::Heap* heap = driver_->runtime_->GetHeap();
1632 auto is_instance = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001633 if (HasVirtualMembers()) {
1634 return old_klass->IsAssignableFrom(obj->GetClass());
1635 } else {
1636 // We don't need to deal with objects of subtypes when we don't modify virtuals since the
1637 // vtable + field layout will remain the same.
1638 return old_klass.Get() == obj->GetClass();
1639 }
Alex Light986914b2019-11-19 01:12:25 +00001640 };
1641 heap->VisitObjects([&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1642 if (is_instance(obj)) {
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001643 CHECK(old_klass.Get() == obj->GetClass()) << "No support for subtypes yet!";
Alex Light986914b2019-11-19 01:12:25 +00001644 old_instances.push_back(hs.NewHandle(obj));
1645 }
1646 });
1647 VLOG(plugin) << "Collected " << old_instances.size() << " instances to recreate!";
1648
1649 art::Handle<art::mirror::Class> obj_array_class(
1650 hs.NewHandle(art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Object>>(
1651 driver_->runtime_->GetClassLinker())));
1652 art::Handle<art::mirror::ObjectArray<art::mirror::Object>> old_instances_arr(
1653 hs.NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
1654 driver_->self_, obj_array_class.Get(), old_instances.size())));
1655 if (old_instances_arr.IsNull()) {
1656 driver_->self_->AssertPendingOOMException();
1657 driver_->self_->ClearException();
1658 RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate old_instance arrays!");
1659 return false;
1660 }
1661 for (uint32_t i = 0; i < old_instances.size(); ++i) {
1662 old_instances_arr->Set(i, old_instances[i].Get());
1663 }
1664 cur_data->SetOldInstanceObjects(old_instances_arr.Get());
1665
1666 art::Handle<art::mirror::ObjectArray<art::mirror::Object>> new_instances_arr(
1667 hs.NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
1668 driver_->self_, obj_array_class.Get(), old_instances.size())));
1669 if (new_instances_arr.IsNull()) {
1670 driver_->self_->AssertPendingOOMException();
1671 driver_->self_->ClearException();
1672 RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate new_instance arrays!");
1673 return false;
1674 }
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001675 art::Handle<art::mirror::Class> new_klass(hs.NewHandle(cur_data->GetNewClassObject()));
1676 for (uint32_t i = 0; i < old_instances.size(); ++i) {
1677 art::ObjPtr<art::mirror::Object> new_instance(new_klass->AllocObject(driver_->self_));
Alex Light986914b2019-11-19 01:12:25 +00001678 if (new_instance.IsNull()) {
1679 driver_->self_->AssertPendingOOMException();
1680 driver_->self_->ClearException();
1681 std::string msg(
1682 StringPrintf("Could not allocate instance %d of %zu", i, old_instances.size()));
1683 RecordFailure(ERR(OUT_OF_MEMORY), msg);
1684 return false;
1685 }
1686 new_instances_arr->Set(i, new_instance);
1687 }
1688 cur_data->SetNewInstanceObjects(new_instances_arr.Get());
1689 return true;
1690}
1691
Alex Lighta7e38d82017-01-19 14:57:28 -08001692bool Redefiner::ClassRedefinition::FinishRemainingAllocations(
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001693 /*out*/RedefinitionDataIter* cur_data) {
Alex Light7916f202017-01-27 09:00:15 -08001694 art::ScopedObjectAccessUnchecked soa(driver_->self_);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001695 art::StackHandleScope<4> hs(driver_->self_);
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001696 cur_data->SetMirrorClass(GetMirrorClass());
Alex Lighta7e38d82017-01-19 14:57:28 -08001697 // This shouldn't allocate
1698 art::Handle<art::mirror::ClassLoader> loader(hs.NewHandle(GetClassLoader()));
Alex Light7916f202017-01-27 09:00:15 -08001699 // The bootclasspath is handled specially so it doesn't have a j.l.DexFile.
1700 if (!art::ClassLinker::IsBootClassLoader(soa, loader.Get())) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001701 cur_data->SetSourceClassLoader(loader.Get());
Alex Light7916f202017-01-27 09:00:15 -08001702 art::Handle<art::mirror::Object> dex_file_obj(hs.NewHandle(
1703 ClassLoaderHelper::FindSourceDexFileObject(driver_->self_, loader)));
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001704 cur_data->SetJavaDexFile(dex_file_obj.Get());
Andreas Gampefa4333d2017-02-14 11:10:34 -08001705 if (dex_file_obj == nullptr) {
Alex Light7916f202017-01-27 09:00:15 -08001706 RecordFailure(ERR(INTERNAL), "Unable to find dex file!");
1707 return false;
1708 }
Alex Light1babae02017-02-01 15:35:34 -08001709 // Allocate the new dex file cookie.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001710 if (!AllocateAndRememberNewDexFileCookie(loader, dex_file_obj, cur_data)) {
Alex Light7916f202017-01-27 09:00:15 -08001711 driver_->self_->AssertPendingOOMException();
1712 driver_->self_->ClearException();
1713 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate dex file array for class loader");
1714 return false;
1715 }
Alex Lighta7e38d82017-01-19 14:57:28 -08001716 }
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001717 cur_data->SetNewDexCache(CreateNewDexCache(loader));
1718 if (cur_data->GetNewDexCache() == nullptr) {
Vladimir Markocd556b02017-02-03 11:47:34 +00001719 driver_->self_->AssertPendingException();
Alex Lighta7e38d82017-01-19 14:57:28 -08001720 driver_->self_->ClearException();
1721 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate DexCache");
1722 return false;
1723 }
1724
1725 // We won't always need to set this field.
Alex Light2f814aa2017-03-24 15:21:34 +00001726 cur_data->SetOriginalDexFile(AllocateOrGetOriginalDexFile());
1727 if (cur_data->GetOriginalDexFile() == nullptr) {
Alex Lighta7e38d82017-01-19 14:57:28 -08001728 driver_->self_->AssertPendingOOMException();
1729 driver_->self_->ClearException();
1730 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate array for original dex file");
1731 return false;
1732 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001733 if (added_fields_ || added_methods_) {
1734 art::Handle<art::mirror::Class> nc(hs.NewHandle(
1735 AllocateNewClassObject(hs.NewHandle(cur_data->GetNewDexCache()))));
1736 if (nc.IsNull()) {
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001737 driver_->self_->ClearException();
1738 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate new class object");
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001739 return false;
1740 }
1741
1742 cur_data->SetNewClassObject(nc.Get());
Alex Light24627892019-11-06 10:28:21 -08001743 // We really want to be able to resolve to the new class-object using this dex-cache for
1744 // verification work. Since we haven't put it in the class-table yet we wll just manually add it
1745 // to the dex-cache.
1746 // TODO: We should maybe do this in a better spot.
1747 cur_data->GetNewDexCache()->SetResolvedType(nc->GetDexTypeIndex(), nc.Get());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001748 }
Alex Lighta7e38d82017-01-19 14:57:28 -08001749 return true;
1750}
1751
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001752uint32_t Redefiner::ClassRedefinition::GetNewClassSize(bool with_embedded_tables,
1753 art::Handle<art::mirror::Class> old_klass) {
1754 // TODO Once we can add methods this won't work any more.
1755 uint32_t num_vtable_entries = old_klass->GetVTableLength();
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001756 uint32_t num_8bit_static_fields = 0;
1757 uint32_t num_16bit_static_fields = 0;
1758 uint32_t num_32bit_static_fields = 0;
1759 uint32_t num_64bit_static_fields = 0;
1760 uint32_t num_ref_static_fields = 0;
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001761 art::ClassAccessor accessor(*dex_file_, dex_file_->GetClassDef(0));
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001762 for (const art::ClassAccessor::Field& f : accessor.GetStaticFields()) {
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001763 std::string_view desc(dex_file_->GetFieldTypeDescriptor(dex_file_->GetFieldId(f.GetIndex())));
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001764 if (desc[0] == 'L' || desc[0] == '[') {
1765 num_ref_static_fields++;
1766 } else if (desc == "Z" || desc == "B") {
1767 num_8bit_static_fields++;
1768 } else if (desc == "C" || desc == "S") {
1769 num_16bit_static_fields++;
1770 } else if (desc == "I" || desc == "F") {
1771 num_32bit_static_fields++;
1772 } else if (desc == "J" || desc == "D") {
1773 num_64bit_static_fields++;
1774 } else {
1775 LOG(FATAL) << "Unknown type descriptor! " << desc;
1776 }
1777 }
1778
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001779 return art::mirror::Class::ComputeClassSize(with_embedded_tables,
1780 with_embedded_tables ? num_vtable_entries : 0,
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001781 num_8bit_static_fields,
1782 num_16bit_static_fields,
1783 num_32bit_static_fields,
1784 num_64bit_static_fields,
1785 num_ref_static_fields,
1786 art::kRuntimePointerSize);
1787}
1788
1789art::ObjPtr<art::mirror::Class>
1790Redefiner::ClassRedefinition::AllocateNewClassObject(art::Handle<art::mirror::DexCache> cache) {
1791 // This is a stripped down DefineClass. We don't want to use DefineClass directly because it needs
1792 // to perform a lot of extra steps to tell the ClassTable and the jit and everything about a new
1793 // class. For now we will need to rely on our tests catching any issues caused by changes in how
1794 // class_linker sets up classes.
1795 // TODO Unify/move this into ClassLinker maybe.
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001796 art::StackHandleScope<5> hs(driver_->self_);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001797 art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001798 art::Handle<art::mirror::Class> old_class(hs.NewHandle(GetMirrorClass()));
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001799 art::Handle<art::mirror::Class> new_class(hs.NewHandle(linker->AllocClass(
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001800 driver_->self_, GetNewClassSize(/*with_embedded_tables=*/false, old_class))));
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001801 if (new_class.IsNull()) {
1802 driver_->self_->AssertPendingOOMException();
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001803 JVMTI_LOG(ERROR, driver_->env_) << "Unable to allocate new class object!";
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001804 return nullptr;
1805 }
1806 new_class->SetDexCache(cache.Get());
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001807 linker->SetupClass(*dex_file_, dex_file_->GetClassDef(0), new_class, old_class->GetClassLoader());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001808
1809 // Make sure we are ready for linking. The lock isn't really needed since this isn't visible to
1810 // other threads but the linker expects it.
1811 art::ObjectLock<art::mirror::Class> lock(driver_->self_, new_class);
1812 new_class->SetClinitThreadId(driver_->self_->GetTid());
1813 // Make sure we have a valid empty iftable even if there are errors.
1814 new_class->SetIfTable(art::GetClassRoot<art::mirror::Object>(linker)->GetIfTable());
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001815 linker->LoadClass(driver_->self_, *dex_file_, dex_file_->GetClassDef(0), new_class);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001816 // NB. We know the interfaces and supers didn't change! :)
1817 art::MutableHandle<art::mirror::Class> linked_class(hs.NewHandle<art::mirror::Class>(nullptr));
1818 art::Handle<art::mirror::ObjectArray<art::mirror::Class>> proxy_ifaces(
1819 hs.NewHandle<art::mirror::ObjectArray<art::mirror::Class>>(nullptr));
1820 // No changing hierarchy so everything is loaded.
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001821 new_class->SetSuperClass(old_class->GetSuperClass());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001822 art::mirror::Class::SetStatus(new_class, art::ClassStatus::kLoaded, nullptr);
1823 if (!linker->LinkClass(driver_->self_, nullptr, new_class, proxy_ifaces, &linked_class)) {
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001824 JVMTI_LOG(ERROR, driver_->env_)
1825 << "failed to link class due to "
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001826 << (driver_->self_->IsExceptionPending() ? driver_->self_->GetException()->Dump()
1827 : " unknown");
1828 driver_->self_->ClearException();
1829 return nullptr;
1830 }
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001831 // We will initialize it manually.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001832 art::ObjectLock<art::mirror::Class> objlock(driver_->self_, linked_class);
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001833 // We already verified the class earlier. No need to do it again.
1834 linked_class->SetVerificationAttempted();
Alex Lightfb119572019-09-18 15:04:53 -07001835 // Mark the class as initialized.
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001836 CHECK(old_class->IsInitialized())
1837 << "Attempting to redefine an uninitalized class " << old_class->PrettyClass()
Alex Lightfb119572019-09-18 15:04:53 -07001838 << " status=" << old_class->GetStatus();
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001839 linker->ForceClassInitialized(driver_->self_, linked_class);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001840 // Make sure we have ext-data space for method & field ids. We won't know if we need them until
1841 // it's too late to create them.
1842 // TODO We might want to remove these arrays if they're not needed.
Alex Lightbc19b752019-12-02 18:54:13 +00001843 if (!art::mirror::Class::EnsureInstanceFieldIds(linked_class) ||
1844 !art::mirror::Class::EnsureStaticFieldIds(linked_class) ||
1845 !art::mirror::Class::EnsureMethodIds(linked_class)) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001846 driver_->self_->AssertPendingOOMException();
1847 driver_->self_->ClearException();
Nicolas Geoffray664999a2019-12-03 08:47:26 +00001848 JVMTI_LOG(ERROR, driver_->env_) << "Unable to allocate jni-id arrays!";
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00001849 return nullptr;
1850 }
1851 // Finish setting up methods.
1852 linked_class->VisitMethods([&](art::ArtMethod* m) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1853 linker->SetEntryPointsToInterpreter(m);
1854 m->SetNotIntrinsic();
1855 DCHECK(m->IsCopied() || m->GetDeclaringClass() == linked_class.Get())
1856 << m->PrettyMethod()
1857 << " m->GetDeclaringClass(): " << m->GetDeclaringClass()->PrettyClass()
1858 << " != linked_class.Get(): " << linked_class->PrettyClass();
1859 }, art::kRuntimePointerSize);
1860 if (art::kIsDebugBuild) {
1861 linked_class->VisitFields([&](art::ArtField* f) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1862 DCHECK_EQ(f->GetDeclaringClass(), linked_class.Get());
1863 });
1864 }
1865 return linked_class.Get();
1866}
1867
Alex Lighta26e3492017-06-27 17:55:37 -07001868void Redefiner::ClassRedefinition::UnregisterJvmtiBreakpoints() {
Vladimir Marko4617d582019-03-28 13:48:31 +00001869 BreakpointUtil::RemoveBreakpointsInClass(driver_->env_, GetMirrorClass().Ptr());
Alex Lighta26e3492017-06-27 17:55:37 -07001870}
1871
Alex Light5643caf2017-02-08 11:39:07 -08001872void Redefiner::ClassRedefinition::UnregisterBreakpoints() {
Alex Lighte34fe442018-02-21 17:35:55 -08001873 if (LIKELY(!art::Dbg::IsDebuggerActive())) {
1874 return;
1875 }
Alex Light5643caf2017-02-08 11:39:07 -08001876 art::JDWP::JdwpState* state = art::Dbg::GetJdwpState();
1877 if (state != nullptr) {
1878 state->UnregisterLocationEventsOnClass(GetMirrorClass());
1879 }
1880}
1881
1882void Redefiner::UnregisterAllBreakpoints() {
Alex Light5643caf2017-02-08 11:39:07 -08001883 for (Redefiner::ClassRedefinition& redef : redefinitions_) {
1884 redef.UnregisterBreakpoints();
Alex Lighte34fe442018-02-21 17:35:55 -08001885 redef.UnregisterJvmtiBreakpoints();
Alex Light5643caf2017-02-08 11:39:07 -08001886 }
1887}
1888
Alex Light0e692732017-01-10 15:00:05 -08001889bool Redefiner::CheckAllRedefinitionAreValid() {
1890 for (Redefiner::ClassRedefinition& redef : redefinitions_) {
1891 if (!redef.CheckRedefinitionIsValid()) {
1892 return false;
1893 }
1894 }
1895 return true;
1896}
1897
Alex Light1e3926a2017-04-07 10:38:06 -07001898void Redefiner::RestoreObsoleteMethodMapsIfUnneeded(RedefinitionDataHolder& holder) {
1899 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
1900 data.GetRedefinition().RestoreObsoleteMethodMapsIfUnneeded(&data);
1901 }
1902}
1903
1904bool Redefiner::EnsureAllClassAllocationsFinished(RedefinitionDataHolder& holder) {
1905 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
1906 if (!data.GetRedefinition().EnsureClassAllocationsFinished(&data)) {
Alex Light0e692732017-01-10 15:00:05 -08001907 return false;
1908 }
1909 }
1910 return true;
1911}
1912
Alex Light986914b2019-11-19 01:12:25 +00001913bool Redefiner::CollectAndCreateNewInstances(RedefinitionDataHolder& holder) {
1914 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
1915 // Allocate the data this redefinition requires.
1916 if (!data.GetRedefinition().CollectAndCreateNewInstances(&data)) {
1917 return false;
1918 }
1919 }
1920 return true;
1921}
1922
Alex Light0e692732017-01-10 15:00:05 -08001923bool Redefiner::FinishAllRemainingAllocations(RedefinitionDataHolder& holder) {
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001924 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
Alex Light0e692732017-01-10 15:00:05 -08001925 // Allocate the data this redefinition requires.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001926 if (!data.GetRedefinition().FinishRemainingAllocations(&data)) {
Alex Light0e692732017-01-10 15:00:05 -08001927 return false;
1928 }
Alex Light0e692732017-01-10 15:00:05 -08001929 }
1930 return true;
1931}
1932
1933void Redefiner::ClassRedefinition::ReleaseDexFile() {
Andreas Gampeafaf7f82018-10-16 11:32:38 -07001934 dex_file_.release(); // NOLINT b/117926937
Alex Light0e692732017-01-10 15:00:05 -08001935}
1936
1937void Redefiner::ReleaseAllDexFiles() {
1938 for (Redefiner::ClassRedefinition& redef : redefinitions_) {
1939 redef.ReleaseDexFile();
1940 }
1941}
1942
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001943bool Redefiner::CheckAllClassesAreVerified(RedefinitionDataHolder& holder) {
1944 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
1945 if (!data.GetRedefinition().CheckVerification(data)) {
Alex Light8c889d22017-02-06 13:58:27 -08001946 return false;
1947 }
Alex Light8c889d22017-02-06 13:58:27 -08001948 }
1949 return true;
1950}
1951
Alex Lightc5f5a6e2017-03-01 16:57:08 -08001952class ScopedDisableConcurrentAndMovingGc {
1953 public:
1954 ScopedDisableConcurrentAndMovingGc(art::gc::Heap* heap, art::Thread* self)
1955 : heap_(heap), self_(self) {
1956 if (heap_->IsGcConcurrentAndMoving()) {
1957 heap_->IncrementDisableMovingGC(self_);
1958 }
1959 }
1960
1961 ~ScopedDisableConcurrentAndMovingGc() {
1962 if (heap_->IsGcConcurrentAndMoving()) {
1963 heap_->DecrementDisableMovingGC(self_);
1964 }
1965 }
1966 private:
1967 art::gc::Heap* heap_;
1968 art::Thread* self_;
1969};
1970
Alex Light986914b2019-11-19 01:12:25 +00001971class ScopedSuspendAllocations {
1972 public:
1973 ScopedSuspendAllocations(art::Runtime* runtime, RedefinitionDataHolder& h)
1974 REQUIRES_SHARED(art::Locks::mutator_lock_)
1975 : paused_(false) {
1976 if (std::any_of(h.begin(),
1977 h.end(),
1978 [](auto r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1979 return r.GetRedefinition().IsStructuralRedefinition();
1980 })) {
1981 VLOG(plugin) << "Pausing allocations for structural redefinition.";
1982 paused_ = true;
1983 AllocationManager::Get()->PauseAllocations(art::Thread::Current());
1984 // Collect garbage so we don't need to recreate as much.
1985 runtime->GetHeap()->CollectGarbage(/*clear_soft_references=*/false);
1986 }
1987 }
1988
1989 ~ScopedSuspendAllocations() REQUIRES_SHARED(art::Locks::mutator_lock_) {
1990 if (paused_) {
1991 AllocationManager::Get()->ResumeAllocations(art::Thread::Current());
1992 }
1993 }
1994
1995 private:
1996 bool paused_;
1997
1998 DISALLOW_COPY_AND_ASSIGN(ScopedSuspendAllocations);
1999};
2000
Alex Lighta01de592016-11-15 10:43:06 -08002001jvmtiError Redefiner::Run() {
Alex Light0e692732017-01-10 15:00:05 -08002002 art::StackHandleScope<1> hs(self_);
2003 // Allocate an array to hold onto all java temporary objects associated with this redefinition.
2004 // We will let this be collected after the end of this function.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002005 RedefinitionDataHolder holder(&hs, runtime_, self_, &redefinitions_);
Alex Light0e692732017-01-10 15:00:05 -08002006 if (holder.IsNull()) {
2007 self_->AssertPendingOOMException();
2008 self_->ClearException();
2009 RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate storage for temporaries");
2010 return result_;
2011 }
2012
Alex Lighta01de592016-11-15 10:43:06 -08002013 // First we just allocate the ClassExt and its fields that we need. These can be updated
2014 // atomically without any issues (since we allocate the map arrays as empty) so we don't bother
2015 // doing a try loop. The other allocations we need to ensure that nothing has changed in the time
2016 // between allocating them and pausing all threads before we can update them so we need to do a
2017 // try loop.
Alex Light0e692732017-01-10 15:00:05 -08002018 if (!CheckAllRedefinitionAreValid() ||
Alex Light1e3926a2017-04-07 10:38:06 -07002019 !EnsureAllClassAllocationsFinished(holder) ||
Alex Light8c889d22017-02-06 13:58:27 -08002020 !FinishAllRemainingAllocations(holder) ||
2021 !CheckAllClassesAreVerified(holder)) {
Alex Lighta01de592016-11-15 10:43:06 -08002022 return result_;
2023 }
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002024
Alex Light986914b2019-11-19 01:12:25 +00002025 ScopedSuspendAllocations suspend_alloc(runtime_, holder);
2026 if (!CollectAndCreateNewInstances(holder)) {
2027 return result_;
2028 }
2029
Alex Light5643caf2017-02-08 11:39:07 -08002030 // At this point we can no longer fail without corrupting the runtime state.
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002031 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
Alex Light07f06212017-06-01 14:01:43 -07002032 art::ClassLinker* cl = runtime_->GetClassLinker();
2033 cl->RegisterExistingDexCache(data.GetNewDexCache(), data.GetSourceClassLoader());
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002034 if (data.GetSourceClassLoader() == nullptr) {
Mathieu Chartier0a19e212019-11-27 14:35:24 -08002035 cl->AppendToBootClassPath(self_, &data.GetRedefinition().GetDexFile());
Alex Light7916f202017-01-27 09:00:15 -08002036 }
Alex Light7916f202017-01-27 09:00:15 -08002037 }
Alex Light5643caf2017-02-08 11:39:07 -08002038 UnregisterAllBreakpoints();
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002039
Alex Lightc2d0c962019-10-23 14:14:25 -07002040 {
2041 // Disable GC and wait for it to be done if we are a moving GC. This is fine since we are done
2042 // allocating so no deadlocks.
2043 ScopedDisableConcurrentAndMovingGc sdcamgc(runtime_->GetHeap(), self_);
Alex Lightc5f5a6e2017-03-01 16:57:08 -08002044
Alex Lightc2d0c962019-10-23 14:14:25 -07002045 // Do transition to final suspension
2046 // TODO We might want to give this its own suspended state!
2047 // TODO This isn't right. We need to change state without any chance of suspend ideally!
2048 art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative);
2049 art::ScopedSuspendAll ssa("Final installation of redefined Classes!", /*long_suspend=*/true);
2050 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2051 art::ScopedAssertNoThreadSuspension nts("Updating runtime objects for redefinition");
2052 ClassRedefinition& redef = data.GetRedefinition();
2053 if (data.GetSourceClassLoader() != nullptr) {
2054 ClassLoaderHelper::UpdateJavaDexFile(data.GetJavaDexFile(), data.GetNewDexFileCookie());
2055 }
2056 redef.UpdateClass(data);
Alex Light7916f202017-01-27 09:00:15 -08002057 }
Alex Lightc2d0c962019-10-23 14:14:25 -07002058 RestoreObsoleteMethodMapsIfUnneeded(holder);
2059 // TODO We should check for if any of the redefined methods are intrinsic methods here and, if
2060 // any are, force a full-world deoptimization before finishing redefinition. If we don't do this
2061 // then methods that have been jitted prior to the current redefinition being applied might
2062 // continue to use the old versions of the intrinsics!
2063 // TODO Do the dex_file release at a more reasonable place. This works but it muddles who really
2064 // owns the DexFile and when ownership is transferred.
2065 ReleaseAllDexFiles();
Alex Light0e692732017-01-10 15:00:05 -08002066 }
Alex Lightb1eebde2019-10-22 16:30:47 +00002067 // By now the class-linker knows about all the classes so we can safetly retry verification and
2068 // update method flags.
2069 ReverifyClasses(holder);
Alex Lighta01de592016-11-15 10:43:06 -08002070 return OK;
2071}
2072
Alex Lightb1eebde2019-10-22 16:30:47 +00002073void Redefiner::ReverifyClasses(RedefinitionDataHolder& holder) {
Alex Lightb1eebde2019-10-22 16:30:47 +00002074 for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2075 data.GetRedefinition().ReverifyClass(data);
2076 }
2077}
2078
2079void Redefiner::ClassRedefinition::ReverifyClass(const RedefinitionDataIter &cur_data) {
2080 if (!needs_reverify_) {
2081 return;
2082 }
2083 VLOG(plugin) << "Reverifying " << class_sig_ << " due to soft failures";
2084 std::string error;
2085 // TODO Make verification log level lower
2086 art::verifier::FailureKind failure =
2087 art::verifier::ClassVerifier::ReverifyClass(driver_->self_,
2088 cur_data.GetMirrorClass(),
2089 /*log_level=*/
2090 art::verifier::HardFailLogMode::kLogWarning,
2091 /*api_level=*/
2092 art::Runtime::Current()->GetTargetSdkVersion(),
2093 &error);
2094 CHECK_NE(failure, art::verifier::FailureKind::kHardFailure);
2095}
2096
Alex Light0e692732017-01-10 15:00:05 -08002097void Redefiner::ClassRedefinition::UpdateMethods(art::ObjPtr<art::mirror::Class> mclass,
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002098 const art::dex::ClassDef& class_def) {
Alex Light0e692732017-01-10 15:00:05 -08002099 art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
Alex Lighta01de592016-11-15 10:43:06 -08002100 art::PointerSize image_pointer_size = linker->GetImagePointerSize();
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002101 const art::dex::TypeId& declaring_class_id = dex_file_->GetTypeId(class_def.class_idx_);
Alex Lighta01de592016-11-15 10:43:06 -08002102 const art::DexFile& old_dex_file = mclass->GetDexFile();
Alex Light200b9d72016-12-15 11:34:13 -08002103 // Update methods.
Alex Light00e475c2017-07-19 16:36:23 -07002104 for (art::ArtMethod& method : mclass->GetDeclaredMethods(image_pointer_size)) {
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002105 const art::dex::StringId* new_name_id = dex_file_->FindStringId(method.GetName());
Alex Lighta01de592016-11-15 10:43:06 -08002106 art::dex::TypeIndex method_return_idx =
2107 dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(method.GetReturnTypeDescriptor()));
2108 const auto* old_type_list = method.GetParameterTypeList();
2109 std::vector<art::dex::TypeIndex> new_type_list;
2110 for (uint32_t i = 0; old_type_list != nullptr && i < old_type_list->Size(); i++) {
2111 new_type_list.push_back(
2112 dex_file_->GetIndexForTypeId(
2113 *dex_file_->FindTypeId(
2114 old_dex_file.GetTypeDescriptor(
2115 old_dex_file.GetTypeId(
2116 old_type_list->GetTypeItem(i).type_idx_)))));
2117 }
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002118 const art::dex::ProtoId* proto_id = dex_file_->FindProtoId(method_return_idx, new_type_list);
Alex Lightdba61482016-12-21 08:20:29 -08002119 CHECK(proto_id != nullptr || old_type_list == nullptr);
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002120 const art::dex::MethodId* method_id = dex_file_->FindMethodId(declaring_class_id,
2121 *new_name_id,
2122 *proto_id);
Alex Lightdba61482016-12-21 08:20:29 -08002123 CHECK(method_id != nullptr);
Alex Lighta01de592016-11-15 10:43:06 -08002124 uint32_t dex_method_idx = dex_file_->GetIndexForMethodId(*method_id);
2125 method.SetDexMethodIndex(dex_method_idx);
2126 linker->SetEntryPointsToInterpreter(&method);
Alex Light200b9d72016-12-15 11:34:13 -08002127 method.SetCodeItemOffset(dex_file_->FindCodeItemOffset(class_def, dex_method_idx));
Alex Light7532d582017-02-13 16:36:06 -08002128 // Clear all the intrinsics related flags.
Orion Hodsoncfcc9cf2017-09-29 15:07:27 +01002129 method.SetNotIntrinsic();
Alex Lighta01de592016-11-15 10:43:06 -08002130 }
Alex Light200b9d72016-12-15 11:34:13 -08002131}
2132
Alex Light0e692732017-01-10 15:00:05 -08002133void Redefiner::ClassRedefinition::UpdateFields(art::ObjPtr<art::mirror::Class> mclass) {
Alex Light200b9d72016-12-15 11:34:13 -08002134 // TODO The IFields & SFields pointers should be combined like the methods_ arrays were.
2135 for (auto fields_iter : {mclass->GetIFields(), mclass->GetSFields()}) {
2136 for (art::ArtField& field : fields_iter) {
2137 std::string declaring_class_name;
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002138 const art::dex::TypeId* new_declaring_id =
Alex Light200b9d72016-12-15 11:34:13 -08002139 dex_file_->FindTypeId(field.GetDeclaringClass()->GetDescriptor(&declaring_class_name));
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002140 const art::dex::StringId* new_name_id = dex_file_->FindStringId(field.GetName());
2141 const art::dex::TypeId* new_type_id = dex_file_->FindTypeId(field.GetTypeDescriptor());
Alex Light200b9d72016-12-15 11:34:13 -08002142 CHECK(new_name_id != nullptr && new_type_id != nullptr && new_declaring_id != nullptr);
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002143 const art::dex::FieldId* new_field_id =
Alex Light200b9d72016-12-15 11:34:13 -08002144 dex_file_->FindFieldId(*new_declaring_id, *new_name_id, *new_type_id);
2145 CHECK(new_field_id != nullptr);
2146 // We only need to update the index since the other data in the ArtField cannot be updated.
2147 field.SetDexFieldIndex(dex_file_->GetIndexForFieldId(*new_field_id));
2148 }
2149 }
Alex Light200b9d72016-12-15 11:34:13 -08002150}
2151
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002152void Redefiner::ClassRedefinition::CollectNewFieldAndMethodMappings(
2153 const RedefinitionDataIter& data,
2154 std::map<art::ArtMethod*, art::ArtMethod*>* method_map,
2155 std::map<art::ArtField*, art::ArtField*>* field_map) {
Nicolas Geoffray664999a2019-12-03 08:47:26 +00002156 art::ObjPtr<art::mirror::Class> old_cls(data.GetMirrorClass());
2157 art::ObjPtr<art::mirror::Class> new_cls(data.GetNewClassObject());
2158 for (art::ArtField& f : old_cls->GetSFields()) {
2159 (*field_map)[&f] = new_cls->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor());
2160 }
2161 for (art::ArtField& f : old_cls->GetIFields()) {
2162 (*field_map)[&f] = new_cls->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor());
2163 }
2164 auto new_methods = new_cls->GetMethods(art::kRuntimePointerSize);
2165 for (art::ArtMethod& m : old_cls->GetMethods(art::kRuntimePointerSize)) {
2166 // No support for finding methods in this way since it's generally not needed. Just do it the
2167 // easy way.
2168 auto nm_iter = std::find_if(
2169 new_methods.begin(),
2170 new_methods.end(),
2171 [&](art::ArtMethod& cand) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2172 return cand.GetNameView() == m.GetNameView() && cand.GetSignature() == m.GetSignature();
2173 });
2174 CHECK(nm_iter != new_methods.end())
2175 << "Could not find redefined version of " << m.PrettyMethod();
2176 (*method_map)[&m] = &(*nm_iter);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002177 }
2178}
2179
Alex Light986914b2019-11-19 01:12:25 +00002180static void CopyField(art::ObjPtr<art::mirror::Object> target,
2181 art::ArtField* new_field,
2182 art::ObjPtr<art::mirror::Object> source,
2183 art::ArtField& old_field) REQUIRES(art::Locks::mutator_lock_) {
2184 art::Primitive::Type ftype = old_field.GetTypeAsPrimitiveType();
2185 CHECK_EQ(ftype, new_field->GetTypeAsPrimitiveType())
2186 << old_field.PrettyField() << " vs " << new_field->PrettyField();
2187 if (ftype == art::Primitive::kPrimNot) {
2188 new_field->SetObject<false>(target, old_field.GetObject(source));
2189 } else {
2190 switch (ftype) {
2191#define UPDATE_FIELD(TYPE) \
2192 case art::Primitive::kPrim##TYPE: \
2193 new_field->Set##TYPE<false>(target, old_field.Get##TYPE(source)); \
2194 break
2195 UPDATE_FIELD(Int);
2196 UPDATE_FIELD(Float);
2197 UPDATE_FIELD(Long);
2198 UPDATE_FIELD(Double);
2199 UPDATE_FIELD(Short);
2200 UPDATE_FIELD(Char);
2201 UPDATE_FIELD(Byte);
2202 UPDATE_FIELD(Boolean);
2203 case art::Primitive::kPrimNot:
2204 case art::Primitive::kPrimVoid:
2205 LOG(FATAL) << "Unexpected field with type " << ftype << " found!";
2206 UNREACHABLE();
2207#undef UPDATE_FIELD
2208 }
2209 }
2210}
2211
2212static void CopyFields(bool is_static,
2213 art::ObjPtr<art::mirror::Object> target,
2214 art::ObjPtr<art::mirror::Class> target_class,
2215 art::ObjPtr<art::mirror::Object> source,
2216 art::ObjPtr<art::mirror::Class> source_class)
2217 REQUIRES(art::Locks::mutator_lock_) {
2218 DCHECK(!source_class->IsObjectClass() && !target_class->IsObjectClass())
2219 << "Should not be overriding object class fields. Target: " << target_class->PrettyClass()
2220 << " Source: " << source_class->PrettyClass();
2221 for (art::ArtField& f : (is_static ? source_class->GetSFields() : source_class->GetIFields())) {
2222 art::ArtField* new_field =
2223 (is_static ? target_class->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor())
2224 : target_class->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor()));
2225 CHECK(new_field != nullptr) << "could not find new version of " << f.PrettyField();
2226 CopyField(target, new_field, source, f);
2227 }
2228 if (!is_static && !target_class->GetSuperClass()->IsObjectClass()) {
2229 CopyFields(
2230 is_static, target, target_class->GetSuperClass(), source, source_class->GetSuperClass());
2231 }
2232}
2233
2234static void ClearField(art::ObjPtr<art::mirror::Object> target, art::ArtField& field)
2235 REQUIRES(art::Locks::mutator_lock_) {
2236 art::Primitive::Type ftype = field.GetTypeAsPrimitiveType();
2237 if (ftype == art::Primitive::kPrimNot) {
2238 field.SetObject<false>(target, nullptr);
2239 } else {
2240 switch (ftype) {
2241#define UPDATE_FIELD(TYPE) \
2242 case art::Primitive::kPrim##TYPE: \
2243 field.Set##TYPE<false>(target, 0); \
2244 break
2245 UPDATE_FIELD(Int);
2246 UPDATE_FIELD(Float);
2247 UPDATE_FIELD(Long);
2248 UPDATE_FIELD(Double);
2249 UPDATE_FIELD(Short);
2250 UPDATE_FIELD(Char);
2251 UPDATE_FIELD(Byte);
2252 UPDATE_FIELD(Boolean);
2253 case art::Primitive::kPrimNot:
2254 case art::Primitive::kPrimVoid:
2255 LOG(FATAL) << "Unexpected field with type " << ftype << " found!";
2256 UNREACHABLE();
2257#undef UPDATE_FIELD
2258 }
2259 }
2260}
2261
2262static void ClearFields(bool is_static,
2263 art::ObjPtr<art::mirror::Object> target,
2264 art::ObjPtr<art::mirror::Class> target_class)
2265 REQUIRES(art::Locks::mutator_lock_) {
2266 DCHECK(!target_class->IsObjectClass());
2267 for (art::ArtField& f : (is_static ? target_class->GetSFields() : target_class->GetIFields())) {
2268 ClearField(target, f);
2269 }
2270 if (!is_static && !target_class->GetSuperClass()->IsObjectClass()) {
2271 ClearFields(is_static, target, target_class->GetSuperClass());
2272 }
2273}
2274
2275static void CopyAndClearFields(bool is_static,
2276 art::ObjPtr<art::mirror::Object> target,
2277 art::ObjPtr<art::mirror::Class> target_class,
2278 art::ObjPtr<art::mirror::Object> source,
2279 art::ObjPtr<art::mirror::Class> source_class)
2280 REQUIRES(art::Locks::mutator_lock_) {
2281 // Copy all non-j.l.Object fields
2282 CopyFields(is_static, target, target_class, source, source_class);
2283 // Copy the lock-word.
2284 target->SetLockWord(source->GetLockWord(false), false);
2285 // Clear (reset) the old one.
2286 source->SetLockWord(art::LockWord::Default(), false);
2287 art::WriteBarrier::ForEveryFieldWrite(target);
2288
2289 // Clear the fields from the old class. We don't need it anymore.
2290 ClearFields(is_static, source, source_class);
2291 art::WriteBarrier::ForEveryFieldWrite(source);
2292}
2293
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002294void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDataIter& holder) {
2295 DCHECK(IsStructuralRedefinition());
2296 // LETS GO. We've got all new class structures so no need to do all the updating of the stacks.
2297 // Instead we need to update everything else.
2298 // Just replace the class and be done with it.
2299 art::Locks::mutator_lock_->AssertExclusiveHeld(driver_->self_);
2300 art::ScopedAssertNoThreadSuspension sants(__FUNCTION__);
2301 art::ObjPtr<art::mirror::Class> orig(holder.GetMirrorClass());
2302 art::ObjPtr<art::mirror::Class> replacement(holder.GetNewClassObject());
2303 // Collect mappings from old to new fields/methods
2304 std::map<art::ArtMethod*, art::ArtMethod*> method_map;
2305 std::map<art::ArtField*, art::ArtField*> field_map;
2306 CollectNewFieldAndMethodMappings(holder, &method_map, &field_map);
Alex Light986914b2019-11-19 01:12:25 +00002307 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> new_instances(
2308 holder.GetNewInstanceObjects());
2309 art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> old_instances(
2310 holder.GetOldInstanceObjects());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002311 CHECK(!orig.IsNull());
2312 CHECK(!replacement.IsNull());
Alex Light986914b2019-11-19 01:12:25 +00002313 // Copy over the static fields of the class and all the instance fields.
Nicolas Geoffray664999a2019-12-03 08:47:26 +00002314 CopyAndClearFields(/*is_static=*/true, replacement, replacement, orig, orig);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002315
Alex Light986914b2019-11-19 01:12:25 +00002316 // Copy and clear the fields of the old-instances.
Nicolas Geoffray664999a2019-12-03 08:47:26 +00002317 for (int32_t i = 0; i < old_instances->GetLength(); i++) {
2318 art::ObjPtr<art::mirror::Object> old_instance(old_instances->Get(i));
2319 art::ObjPtr<art::mirror::Object> new_instance(new_instances->Get(i));
Alex Light986914b2019-11-19 01:12:25 +00002320 CopyAndClearFields(/*is_static=*/false,
2321 new_instance,
2322 new_instance->GetClass(),
2323 old_instance,
2324 old_instance->GetClass());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002325 }
2326 // Mark old class obsolete.
Nicolas Geoffray664999a2019-12-03 08:47:26 +00002327 orig->SetObsoleteObject();
2328 // Mark methods obsolete. We need to wait until later to actually clear the jit data.
2329 for (art::ArtMethod& m : orig->GetMethods(art::kRuntimePointerSize)) {
2330 m.SetIsObsolete();
2331 m.SetDontCompile();
2332 DCHECK_EQ(orig, m.GetDeclaringClass());
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002333 }
Alex Lightc18eba32019-09-24 14:36:27 -07002334 // Update live pointers in ART code.
Alex Light24627892019-11-06 10:28:21 -08002335 auto could_change_resolution_of = [&](auto* field_or_method,
2336 const auto& info) REQUIRES(art::Locks::mutator_lock_) {
2337 constexpr bool is_method = std::is_same_v<art::ArtMethod*, decltype(field_or_method)>;
2338 static_assert(is_method || std::is_same_v<art::ArtField*, decltype(field_or_method)>,
2339 "Input is not field or method!");
2340 // Only dex-cache is used for resolution
2341 if (LIKELY(info.GetType() != art::ReflectionSourceType::kSourceDexCacheResolvedField &&
2342 info.GetType() != art::ReflectionSourceType::kSourceDexCacheResolvedMethod)) {
2343 return false;
2344 }
2345 if constexpr (is_method) {
2346 // Only direct methods are used without further indirection through a vtable/IFTable.
2347 // Constructors cannot be shadowed.
2348 if (LIKELY(!field_or_method->IsDirect() || field_or_method->IsConstructor())) {
2349 return false;
2350 }
2351 } else {
2352 // Only non-private fields can be shadowed in a manner that's visible.
2353 if (LIKELY(field_or_method->IsPrivate())) {
2354 return false;
2355 }
2356 }
2357 // We can only shadow things from our superclasses
2358 if (LIKELY(!field_or_method->GetDeclaringClass()->IsAssignableFrom(orig))) {
2359 return false;
2360 }
2361 if constexpr (is_method) {
2362 auto direct_methods = replacement->GetDirectMethods(art::kRuntimePointerSize);
2363 return std::find_if(direct_methods.begin(),
2364 direct_methods.end(),
2365 [&](art::ArtMethod& m) REQUIRES(art::Locks::mutator_lock_) {
2366 return UNLIKELY(m.HasSameNameAndSignature(field_or_method));
2367 }) != direct_methods.end();
2368 } else {
2369 auto pred = [&](art::ArtField& f) REQUIRES(art::Locks::mutator_lock_) {
2370 return std::string_view(f.GetName()) == std::string_view(field_or_method->GetName()) &&
2371 std::string_view(f.GetTypeDescriptor()) ==
2372 std::string_view(field_or_method->GetTypeDescriptor());
2373 };
2374 if (field_or_method->IsStatic()) {
2375 auto sfields = replacement->GetSFields();
2376 return std::find_if(sfields.begin(), sfields.end(), pred) != sfields.end();
2377 } else {
2378 auto ifields = replacement->GetIFields();
2379 return std::find_if(ifields.begin(), ifields.end(), pred) != ifields.end();
2380 }
2381 }
2382 };
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002383 // TODO Performing 2 stack-walks back to back isn't the greatest. We might want to try to combine
2384 // it with the one ReplaceReferences does. Doing so would be rather complicated though.
Alex Lightc18eba32019-09-24 14:36:27 -07002385 driver_->runtime_->VisitReflectiveTargets(
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002386 [&](art::ArtField* f, const auto& info) REQUIRES(art::Locks::mutator_lock_) {
Alex Light28b6efe2019-11-06 12:49:41 -08002387 DCHECK(f != nullptr) << info;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002388 auto it = field_map.find(f);
Alex Light24627892019-11-06 10:28:21 -08002389 if (it != field_map.end()) {
2390 VLOG(plugin) << "Updating " << info << " object for (field) "
2391 << it->second->PrettyField();
2392 return it->second;
2393 } else if (UNLIKELY(could_change_resolution_of(f, info))) {
2394 // Resolution might change. Just clear the resolved value.
2395 VLOG(plugin) << "Clearing resolution " << info << " for (field) " << f->PrettyField();
2396 return static_cast<art::ArtField*>(nullptr);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002397 }
Alex Light24627892019-11-06 10:28:21 -08002398 return f;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002399 },
2400 [&](art::ArtMethod* m, const auto& info) REQUIRES(art::Locks::mutator_lock_) {
Alex Light28b6efe2019-11-06 12:49:41 -08002401 DCHECK(m != nullptr) << info;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002402 auto it = method_map.find(m);
Alex Light24627892019-11-06 10:28:21 -08002403 if (it != method_map.end()) {
2404 VLOG(plugin) << "Updating " << info << " object for (method) "
2405 << it->second->PrettyMethod();
2406 return it->second;
2407 } else if (UNLIKELY(could_change_resolution_of(m, info))) {
2408 // Resolution might change. Just clear the resolved value.
2409 VLOG(plugin) << "Clearing resolution " << info << " for (method) " << m->PrettyMethod();
2410 return static_cast<art::ArtMethod*>(nullptr);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002411 }
Alex Light24627892019-11-06 10:28:21 -08002412 return m;
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002413 });
2414
2415 // Force every frame of every thread to deoptimize (any frame might have eg offsets compiled in).
2416 driver_->runtime_->GetInstrumentation()->DeoptimizeAllThreadFrames();
2417
Alex Light986914b2019-11-19 01:12:25 +00002418 std::unordered_map<art::ObjPtr<art::mirror::Object>,
2419 art::ObjPtr<art::mirror::Object>,
2420 art::HashObjPtr> map;
Nicolas Geoffray664999a2019-12-03 08:47:26 +00002421 map.emplace(orig, replacement);
2422 for (int32_t i = 0; i < old_instances->GetLength(); i++) {
2423 map.emplace(old_instances->Get(i), new_instances->Get(i));
Alex Light986914b2019-11-19 01:12:25 +00002424 }
2425
2426 // Actually perform the general replacement. This doesn't affect ArtMethod/ArtFields. It does
2427 // affect the declaring_class field of all the obsolete objects, which is unfortunate and needs to
2428 // be undone. This replaces the mirror::Class in 'holder' as well. It's magic!
2429 HeapExtensions::ReplaceReferences(driver_->self_, map);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002430
2431 // Save the old class so that the JIT gc doesn't get confused by it being collected before the
2432 // jit code. This is also needed to keep the dex-caches of any obsolete methods live.
Nicolas Geoffray664999a2019-12-03 08:47:26 +00002433 replacement->GetExtData()->SetObsoleteClass(orig);
2434
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002435
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002436 art::jit::Jit* jit = driver_->runtime_->GetJit();
2437 if (jit != nullptr) {
2438 // Clear jit.
2439 // TODO We might want to have some way to tell the JIT not to wait the kJitSamplesBatchSize
2440 // invokes to start compiling things again.
2441 jit->GetCodeCache()->InvalidateAllCompiledCode();
2442 }
2443
2444 // Clear thread caches
2445 {
2446 // TODO We might be able to avoid doing this but given the rather unstructured nature of the
2447 // interpreter cache it's probably not worth the effort.
2448 art::MutexLock mu(driver_->self_, *art::Locks::thread_list_lock_);
2449 driver_->runtime_->GetThreadList()->ForEach(
2450 [](art::Thread* t) { t->GetInterpreterCache()->Clear(t); });
2451 }
2452
2453 if (art::kIsDebugBuild) {
2454 // Just make sure we didn't screw up any of the now obsolete methods or fields. We need their
2455 // declaring-class to still be the obolete class
2456 orig->VisitMethods([&](art::ArtMethod* method) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2457 DCHECK_EQ(method->GetDeclaringClass(), orig) << method->GetDeclaringClass()->PrettyClass()
2458 << " vs " << orig->PrettyClass();
2459 }, art::kRuntimePointerSize);
2460 orig->VisitFields([&](art::ArtField* field) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2461 DCHECK_EQ(field->GetDeclaringClass(), orig) << field->GetDeclaringClass()->PrettyClass()
2462 << " vs " << orig->PrettyClass();
2463 });
2464 }
2465}
2466
2467// Redefines the class in place
2468void Redefiner::ClassRedefinition::UpdateClassInPlace(const RedefinitionDataIter& holder) {
2469 art::ObjPtr<art::mirror::Class> mclass(holder.GetMirrorClass());
2470 // TODO Rewrite so we don't do a stack walk for each and every class.
2471 FindAndAllocateObsoleteMethods(mclass);
2472 art::ObjPtr<art::mirror::DexCache> new_dex_cache(holder.GetNewDexCache());
2473 art::ObjPtr<art::mirror::Object> original_dex_file(holder.GetOriginalDexFile());
Alex Light6ac57502017-01-19 15:05:06 -08002474 DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002475 const art::dex::ClassDef& class_def = dex_file_->GetClassDef(0);
Vladimir Marko5122e6b2017-08-17 16:10:09 +01002476 UpdateMethods(mclass, class_def);
Alex Light007ada22017-01-10 13:33:56 -08002477 UpdateFields(mclass);
Alex Light200b9d72016-12-15 11:34:13 -08002478
David Brazdil1a658632018-12-01 17:54:26 +00002479 art::ObjPtr<art::mirror::ClassExt> ext(mclass->GetExtData());
2480 CHECK(!ext.IsNull());
2481 ext->SetOriginalDexFile(original_dex_file);
2482
2483 // If this is the first time the class is being redefined, store
2484 // the native DexFile pointer and initial ClassDef index in ClassExt.
2485 // This preserves the pointer for hiddenapi access checks which need
2486 // to read access flags from the initial DexFile.
2487 if (ext->GetPreRedefineDexFile() == nullptr) {
2488 ext->SetPreRedefineDexFile(&mclass->GetDexFile());
2489 ext->SetPreRedefineClassDefIndex(mclass->GetDexClassDefIndex());
2490 }
2491
Alex Lighta01de592016-11-15 10:43:06 -08002492 // Update the class fields.
2493 // Need to update class last since the ArtMethod gets its DexFile from the class (which is needed
2494 // to call GetReturnTypeDescriptor and GetParameterTypeList above).
2495 mclass->SetDexCache(new_dex_cache.Ptr());
Alex Light6ac57502017-01-19 15:05:06 -08002496 mclass->SetDexClassDefIndex(dex_file_->GetIndexForClassDef(class_def));
Alex Light0e692732017-01-10 15:00:05 -08002497 mclass->SetDexTypeIndex(dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(class_sig_.c_str())));
Alex Light035105f2018-03-05 17:48:48 -08002498
2499 // Notify the jit that all the methods in this class were redefined. Need to do this last since
2500 // the jit relies on the dex_file_ being correct (for native methods at least) to find the method
2501 // meta-data.
2502 art::jit::Jit* jit = driver_->runtime_->GetJit();
2503 if (jit != nullptr) {
2504 art::PointerSize image_pointer_size =
2505 driver_->runtime_->GetClassLinker()->GetImagePointerSize();
2506 auto code_cache = jit->GetCodeCache();
2507 // Non-invokable methods don't have any JIT data associated with them so we don't need to tell
2508 // the jit about them.
2509 for (art::ArtMethod& method : mclass->GetDeclaredMethods(image_pointer_size)) {
2510 if (method.IsInvokable()) {
2511 code_cache->NotifyMethodRedefined(&method);
2512 }
2513 }
2514 }
Alex Lighta01de592016-11-15 10:43:06 -08002515}
2516
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002517// Performs final updates to class for redefinition.
2518void Redefiner::ClassRedefinition::UpdateClass(const RedefinitionDataIter& holder) {
2519 if (IsStructuralRedefinition()) {
2520 UpdateClassStructurally(holder);
2521 } else {
2522 UpdateClassInPlace(holder);
2523 }
Alex Lightc2d0c962019-10-23 14:14:25 -07002524 UpdateClassCommon(holder);
2525}
2526
2527void Redefiner::ClassRedefinition::UpdateClassCommon(const RedefinitionDataIter &cur_data) {
2528 // NB This is after we've already replaced all old-refs with new-refs in the structural case.
2529 art::ObjPtr<art::mirror::Class> klass(cur_data.GetMirrorClass());
2530 DCHECK(!IsStructuralRedefinition() || klass == cur_data.GetNewClassObject());
2531 if (!needs_reverify_) {
2532 return;
2533 }
2534 // Force the most restrictive interpreter environment. We don't know what the final verification
2535 // will allow. We will clear these after retrying verification once we drop the mutator-lock.
2536 klass->VisitMethods([](art::ArtMethod* m) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2537 if (!m->IsNative() && m->IsInvokable() && !m->IsObsolete()) {
2538 m->ClearSkipAccessChecks();
2539 m->SetDontCompile();
2540 m->SetMustCountLocks();
2541 }
2542 }, art::kRuntimePointerSize);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002543}
2544
Alex Light1e3926a2017-04-07 10:38:06 -07002545// Restores the old obsolete methods maps if it turns out they weren't needed (ie there were no new
2546// obsolete methods).
2547void Redefiner::ClassRedefinition::RestoreObsoleteMethodMapsIfUnneeded(
2548 const RedefinitionDataIter* cur_data) {
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002549 if (IsStructuralRedefinition()) {
2550 // We didn't touch these in this case.
2551 return;
2552 }
Vladimir Markod93e3742018-07-18 10:58:13 +01002553 art::ObjPtr<art::mirror::Class> klass = GetMirrorClass();
2554 art::ObjPtr<art::mirror::ClassExt> ext = klass->GetExtData();
2555 art::ObjPtr<art::mirror::PointerArray> methods = ext->GetObsoleteMethods();
2556 art::ObjPtr<art::mirror::PointerArray> old_methods = cur_data->GetOldObsoleteMethods();
Alex Light70713df2017-04-18 13:03:31 -07002557 int32_t old_length = old_methods == nullptr ? 0 : old_methods->GetLength();
Alex Light1e3926a2017-04-07 10:38:06 -07002558 int32_t expected_length =
2559 old_length + klass->NumDirectMethods() + klass->NumDeclaredVirtualMethods();
2560 // Check to make sure we are only undoing this one.
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002561 if (methods.IsNull()) {
2562 // No new obsolete methods! We can get rid of the maps.
2563 ext->SetObsoleteArrays(cur_data->GetOldObsoleteMethods(), cur_data->GetOldDexCaches());
2564 } else if (expected_length == methods->GetLength()) {
Alex Light70713df2017-04-18 13:03:31 -07002565 for (int32_t i = 0; i < expected_length; i++) {
2566 art::ArtMethod* expected = nullptr;
2567 if (i < old_length) {
2568 expected = old_methods->GetElementPtrSize<art::ArtMethod*>(i, art::kRuntimePointerSize);
2569 }
2570 if (methods->GetElementPtrSize<art::ArtMethod*>(i, art::kRuntimePointerSize) != expected) {
Alex Light1e3926a2017-04-07 10:38:06 -07002571 // We actually have some new obsolete methods. Just abort since we cannot safely shrink the
2572 // obsolete methods array.
2573 return;
2574 }
2575 }
2576 // No new obsolete methods! We can get rid of the maps.
2577 ext->SetObsoleteArrays(cur_data->GetOldObsoleteMethods(), cur_data->GetOldDexCaches());
2578 }
2579}
2580
Alex Lighta01de592016-11-15 10:43:06 -08002581// This function does all (java) allocations we need to do for the Class being redefined.
2582// TODO Change this name maybe?
Alex Light1e3926a2017-04-07 10:38:06 -07002583bool Redefiner::ClassRedefinition::EnsureClassAllocationsFinished(
2584 /*out*/RedefinitionDataIter* cur_data) {
Alex Light0e692732017-01-10 15:00:05 -08002585 art::StackHandleScope<2> hs(driver_->self_);
2586 art::Handle<art::mirror::Class> klass(hs.NewHandle(
2587 driver_->self_->DecodeJObject(klass_)->AsClass()));
Andreas Gampefa4333d2017-02-14 11:10:34 -08002588 if (klass == nullptr) {
Alex Lighta01de592016-11-15 10:43:06 -08002589 RecordFailure(ERR(INVALID_CLASS), "Unable to decode class argument!");
2590 return false;
2591 }
2592 // Allocate the classExt
Vladimir Marko3068d582019-05-28 16:39:29 +01002593 art::Handle<art::mirror::ClassExt> ext =
2594 hs.NewHandle(art::mirror::Class::EnsureExtDataPresent(klass, driver_->self_));
Andreas Gampefa4333d2017-02-14 11:10:34 -08002595 if (ext == nullptr) {
Alex Lighta01de592016-11-15 10:43:06 -08002596 // No memory. Clear exception (it's not useful) and return error.
Alex Light0e692732017-01-10 15:00:05 -08002597 driver_->self_->AssertPendingOOMException();
2598 driver_->self_->ClearException();
Alex Lighta01de592016-11-15 10:43:06 -08002599 RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate ClassExt");
2600 return false;
2601 }
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +00002602 if (!IsStructuralRedefinition()) {
2603 // First save the old values of the 2 arrays that make up the obsolete methods maps. Then
2604 // allocate the 2 arrays that make up the obsolete methods map. Since the contents of the arrays
2605 // are only modified when all threads (other than the modifying one) are suspended we don't need
2606 // to worry about missing the unsyncronized writes to the array. We do synchronize when setting
2607 // it however, since that can happen at any time.
2608 cur_data->SetOldObsoleteMethods(ext->GetObsoleteMethods());
2609 cur_data->SetOldDexCaches(ext->GetObsoleteDexCaches());
2610 if (!art::mirror::ClassExt::ExtendObsoleteArrays(
2611 ext, driver_->self_, klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size())) {
2612 // OOM. Clear exception and return error.
2613 driver_->self_->AssertPendingOOMException();
2614 driver_->self_->ClearException();
2615 RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate/extend obsolete methods map");
2616 return false;
2617 }
Alex Lighta01de592016-11-15 10:43:06 -08002618 }
2619 return true;
2620}
2621
2622} // namespace openjdkjvmti