blob: da066d11801abb62c520df7748beadc15ffedf1b [file] [log] [blame]
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_CLASS_LINKER_INL_H_
18#define ART_RUNTIME_CLASS_LINKER_INL_H_
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080019
Vladimir Marko09c5ca42018-05-31 15:15:31 +010020#include <atomic>
21
Alex Lightabd8f052019-12-06 10:49:17 -080022#include "android-base/thread_annotations.h"
Vladimir Marko09c5ca42018-05-31 15:15:31 +010023#include "art_field-inl.h"
24#include "art_method-inl.h"
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080025#include "base/mutex.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080026#include "class_linker.h"
Andreas Gampe3f1dcd32018-12-28 09:39:56 -080027#include "dex/dex_file.h"
28#include "dex/dex_file_structs.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070029#include "gc_root-inl.h"
30#include "handle_scope-inl.h"
Alex Lightabd8f052019-12-06 10:49:17 -080031#include "jni/jni_internal.h"
Mathieu Chartier590fee92013-09-13 13:46:47 -070032#include "mirror/class_loader.h"
Mathieu Chartierbc56fc32014-06-03 15:37:03 -070033#include "mirror/dex_cache-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080034#include "mirror/iftable.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070035#include "mirror/object_array-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070036#include "obj_ptr-inl.h"
Mathieu Chartierc4f39252016-10-05 18:32:08 -070037#include "scoped_thread_state_change-inl.h"
Alex Lightabd8f052019-12-06 10:49:17 -080038#include "well_known_classes.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080039
40namespace art {
41
Vladimir Markoa8bba7d2018-05-30 15:18:48 +010042inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self,
Vladimir Markobcf17522018-06-01 13:14:32 +010043 ObjPtr<mirror::Class> element_class) {
Ian Rogers98379392014-02-24 16:53:16 -080044 for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
Ian Rogersa55cf412014-02-27 00:31:26 -080045 // Read the cached array class once to avoid races with other threads setting it.
Mathieu Chartier28357fa2016-10-18 16:27:40 -070046 ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read();
Vladimir Markobcf17522018-06-01 13:14:32 +010047 if (array_class != nullptr && array_class->GetComponentType() == element_class) {
48 return array_class;
Ian Rogers98379392014-02-24 16:53:16 -080049 }
50 }
Ian Rogers1ff3c982014-08-12 02:30:58 -070051 std::string descriptor = "[";
52 std::string temp;
Vladimir Markobcf17522018-06-01 13:14:32 +010053 descriptor += element_class->GetDescriptor(&temp);
54 StackHandleScope<1> hs(Thread::Current());
55 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
Mathieu Chartier28357fa2016-10-18 16:27:40 -070056 ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader);
Nicolas Geoffray9638b642015-06-23 18:16:46 +010057 if (array_class != nullptr) {
58 // Benign races in storing array class and incrementing index.
59 size_t victim_index = find_array_class_cache_next_victim_;
60 find_array_class_cache_[victim_index] = GcRoot<mirror::Class>(array_class);
61 find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize;
62 } else {
63 // We should have a NoClassDefFoundError.
64 self->AssertPendingException();
65 }
Vladimir Markobcf17522018-06-01 13:14:32 +010066 return array_class;
Ian Rogers98379392014-02-24 16:53:16 -080067}
68
Vladimir Marko18090d12018-06-01 16:53:12 +010069inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
70 ArtField* referrer) {
71 Thread::PoisonObjectPointersIfDebug();
72 DCHECK(!Thread::Current()->IsExceptionPending());
David Srbecky9f98fc32021-09-21 10:47:59 +010073 ObjPtr<mirror::String> resolved = referrer->GetDexCache()->GetResolvedString(string_idx);
Vladimir Marko18090d12018-06-01 16:53:12 +010074 if (resolved == nullptr) {
75 resolved = DoResolveString(string_idx, referrer->GetDexCache());
76 }
77 return resolved;
78}
79
80inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
81 ArtMethod* referrer) {
82 Thread::PoisonObjectPointersIfDebug();
83 DCHECK(!Thread::Current()->IsExceptionPending());
David Srbecky9f98fc32021-09-21 10:47:59 +010084 ObjPtr<mirror::String> resolved = referrer->GetDexCache()->GetResolvedString(string_idx);
Vladimir Marko18090d12018-06-01 16:53:12 +010085 if (resolved == nullptr) {
86 resolved = DoResolveString(string_idx, referrer->GetDexCache());
87 }
88 return resolved;
89}
90
91inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
92 Handle<mirror::DexCache> dex_cache) {
93 Thread::PoisonObjectPointersIfDebug();
94 DCHECK(!Thread::Current()->IsExceptionPending());
95 ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
96 if (resolved == nullptr) {
97 resolved = DoResolveString(string_idx, dex_cache);
98 }
99 return resolved;
100}
101
102inline ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
103 ObjPtr<mirror::DexCache> dex_cache) {
104 ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
105 if (resolved == nullptr) {
106 resolved = DoLookupString(string_idx, dex_cache);
107 }
108 return resolved;
109}
110
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000111inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
112 ObjPtr<mirror::Class> referrer) {
113 if (kObjPtrPoisoning) {
114 StackHandleScope<1> hs(Thread::Current());
115 HandleWrapperObjPtr<mirror::Class> referrer_wrapper = hs.NewHandleWrapper(&referrer);
116 Thread::Current()->PoisonObjectPointers();
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000117 }
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100118 DCHECK(!Thread::Current()->IsExceptionPending());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000119 ObjPtr<mirror::Class> resolved_type =
David Srbecky9f98fc32021-09-21 10:47:59 +0100120 referrer->GetDexCache<kDefaultVerifyFlags>()->GetResolvedType(type_idx);
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000121 if (resolved_type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100122 resolved_type = DoResolveType(type_idx, referrer);
123 }
124 return resolved_type;
125}
126
127inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
128 ArtField* referrer) {
129 Thread::PoisonObjectPointersIfDebug();
130 DCHECK(!Thread::Current()->IsExceptionPending());
David Srbecky9f98fc32021-09-21 10:47:59 +0100131 ObjPtr<mirror::Class> resolved_type = referrer->GetDexCache()->GetResolvedType(type_idx);
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100132 if (UNLIKELY(resolved_type == nullptr)) {
Andreas Gampe4835d212018-11-21 14:55:10 -0800133 resolved_type = DoResolveType(type_idx, referrer);
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000134 }
135 return resolved_type;
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000136}
137
Vladimir Marko28e012a2017-12-07 11:22:59 +0000138inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
139 ArtMethod* referrer) {
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700140 Thread::PoisonObjectPointersIfDebug();
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100141 DCHECK(!Thread::Current()->IsExceptionPending());
David Srbecky9f98fc32021-09-21 10:47:59 +0100142 ObjPtr<mirror::Class> resolved_type = referrer->GetDexCache()->GetResolvedType(type_idx);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700143 if (UNLIKELY(resolved_type == nullptr)) {
Andreas Gampe4835d212018-11-21 14:55:10 -0800144 resolved_type = DoResolveType(type_idx, referrer);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800145 }
Vladimir Marko28e012a2017-12-07 11:22:59 +0000146 return resolved_type;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800147}
148
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000149inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
150 Handle<mirror::DexCache> dex_cache,
151 Handle<mirror::ClassLoader> class_loader) {
152 DCHECK(dex_cache != nullptr);
Nicolas Geoffrayab91eef2021-09-14 09:48:51 +0100153 DCHECK(dex_cache->GetClassLoader() == class_loader.Get());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000154 Thread::PoisonObjectPointersIfDebug();
155 ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx);
156 if (resolved == nullptr) {
157 resolved = DoResolveType(type_idx, dex_cache, class_loader);
158 }
159 return resolved;
160}
161
162inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
163 ObjPtr<mirror::Class> referrer) {
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000164 ObjPtr<mirror::Class> type =
David Srbecky9f98fc32021-09-21 10:47:59 +0100165 referrer->GetDexCache<kDefaultVerifyFlags>()->GetResolvedType(type_idx);
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000166 if (type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100167 type = DoLookupResolvedType(type_idx, referrer);
168 }
169 return type;
170}
171
172inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
173 ArtField* referrer) {
David Srbecky9f98fc32021-09-21 10:47:59 +0100174 ObjPtr<mirror::Class> type = referrer->GetDexCache()->GetResolvedType(type_idx);
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100175 if (type == nullptr) {
176 type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000177 }
178 return type;
179}
180
181inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
182 ArtMethod* referrer) {
David Srbecky9f98fc32021-09-21 10:47:59 +0100183 ObjPtr<mirror::Class> type = referrer->GetDexCache()->GetResolvedType(type_idx);
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000184 if (type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100185 type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000186 }
187 return type;
188}
189
190inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(
191 dex::TypeIndex type_idx,
192 ObjPtr<mirror::DexCache> dex_cache,
193 ObjPtr<mirror::ClassLoader> class_loader) {
Nicolas Geoffrayab91eef2021-09-14 09:48:51 +0100194 DCHECK(dex_cache->GetClassLoader() == class_loader);
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000195 ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx);
196 if (type == nullptr) {
197 type = DoLookupResolvedType(type_idx, dex_cache, class_loader);
198 }
199 return type;
200}
201
Vladimir Markoba118822017-06-12 15:41:56 +0100202template <bool kThrowOnError, typename ClassGetter>
203inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
204 InvokeType type,
205 ClassGetter class_getter) {
206 switch (type) {
207 case kStatic:
208 case kSuper:
Andra Danciua0130e82020-07-23 12:34:56 +0000209 case kPolymorphic:
Vladimir Markoba118822017-06-12 15:41:56 +0100210 break;
211 case kInterface: {
212 // We have to check whether the method id really belongs to an interface (dex static bytecode
213 // constraints A15, A16). Otherwise you must not invoke-interface on it.
214 ObjPtr<mirror::Class> klass = class_getter();
215 if (UNLIKELY(!klass->IsInterface())) {
216 if (kThrowOnError) {
217 ThrowIncompatibleClassChangeError(klass,
218 "Found class %s, but interface was expected",
219 klass->PrettyDescriptor().c_str());
220 }
221 return true;
222 }
223 break;
224 }
225 case kDirect:
Mathieu Chartierf6e31472017-12-28 13:32:08 -0800226 if (dex_cache->GetDexFile()->SupportsDefaultMethods()) {
Vladimir Markoba118822017-06-12 15:41:56 +0100227 break;
228 }
229 FALLTHROUGH_INTENDED;
230 case kVirtual: {
231 // Similarly, invoke-virtual (and invoke-direct without default methods) must reference
232 // a non-interface class (dex static bytecode constraint A24, A25).
233 ObjPtr<mirror::Class> klass = class_getter();
234 if (UNLIKELY(klass->IsInterface())) {
235 if (kThrowOnError) {
236 ThrowIncompatibleClassChangeError(klass,
237 "Found interface %s, but class was expected",
238 klass->PrettyDescriptor().c_str());
239 }
240 return true;
241 }
242 break;
243 }
244 default:
245 LOG(FATAL) << "Unreachable - invocation type: " << type;
246 UNREACHABLE();
247 }
248 return false;
249}
250
251template <bool kThrow>
252inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
253 InvokeType type,
254 uint32_t method_idx,
255 ObjPtr<mirror::ClassLoader> class_loader) {
Nicolas Geoffrayc07f4882021-09-13 09:20:33 +0100256 DCHECK(dex_cache->GetClassLoader().Ptr() == class_loader.Ptr());
Vladimir Markoba118822017-06-12 15:41:56 +0100257 return CheckInvokeClassMismatch<kThrow>(
258 dex_cache,
259 type,
260 [this, dex_cache, method_idx, class_loader]() REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800261 const dex::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx);
Vladimir Markoba118822017-06-12 15:41:56 +0100262 ObjPtr<mirror::Class> klass =
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000263 LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
Nicolas Geoffrayeaf3a922020-07-03 11:15:48 +0100264 DCHECK(klass != nullptr) << dex_cache->GetDexFile()->PrettyMethod(method_idx);
Vladimir Markoba118822017-06-12 15:41:56 +0100265 return klass;
266 });
267}
268
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100269inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx,
270 ObjPtr<mirror::DexCache> dex_cache,
271 ObjPtr<mirror::ClassLoader> class_loader) {
Nicolas Geoffrayab91eef2021-09-14 09:48:51 +0100272 DCHECK(dex_cache->GetClassLoader() == class_loader);
David Srbecky5de5efe2021-02-15 21:23:00 +0000273 ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100274 if (resolved == nullptr) {
275 const DexFile& dex_file = *dex_cache->GetDexFile();
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800276 const dex::MethodId& method_id = dex_file.GetMethodId(method_idx);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100277 ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
278 if (klass != nullptr) {
Nicolas Geoffrayea179f42018-02-08 22:30:18 +0000279 resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100280 }
281 }
282 return resolved;
283}
284
Vladimir Markoba118822017-06-12 15:41:56 +0100285template <InvokeType type, ClassLinker::ResolveMode kResolveMode>
Mathieu Chartiere401d142015-04-22 13:56:20 -0700286inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer) {
Vladimir Markoba118822017-06-12 15:41:56 +0100287 DCHECK(referrer != nullptr);
288 // Note: The referrer can be a Proxy constructor. In that case, we need to do the
289 // lookup in the context of the original method from where it steals the code.
290 // However, we delay the GetInterfaceMethodIfProxy() until needed.
291 DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
David Srbecky9f98fc32021-09-21 10:47:59 +0100292 ArtMethod* resolved_method = referrer->GetDexCache()->GetResolvedMethod(method_idx);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100293 if (resolved_method == nullptr) {
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700294 return nullptr;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800295 }
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100296 DCHECK(!resolved_method->IsRuntimeMethod());
Vladimir Markoba118822017-06-12 15:41:56 +0100297 if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
298 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
299 // Check if the invoke type matches the class type.
300 ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
301 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
Nicolas Geoffray66ab9d62021-03-30 16:49:15 +0100302 const dex::MethodId& method_id = referrer->GetDexFile()->GetMethodId(method_idx);
303 ObjPtr<mirror::Class> cls = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
304 if (cls == nullptr) {
305 // The verifier breaks the invariant that a resolved method must have its
306 // class in the class table. Because this method should only lookup and not
307 // resolve class, return null. The caller is responsible for calling
308 // `ResolveMethod` afterwards.
309 // b/73760543
310 return nullptr;
311 }
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700312 if (CheckInvokeClassMismatch</* kThrow= */ false>(dex_cache, type, method_idx, class_loader)) {
Vladimir Markoba118822017-06-12 15:41:56 +0100313 return nullptr;
314 }
315 // Check access.
316 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
317 if (!referring_class->CanAccessResolvedMethod(resolved_method->GetDeclaringClass(),
318 resolved_method,
319 dex_cache,
320 method_idx)) {
321 return nullptr;
322 }
323 // Check if the invoke type matches the method type.
324 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
325 return nullptr;
326 }
Alex Lightfedd91d2016-01-07 14:49:16 -0800327 }
Vladimir Markoba118822017-06-12 15:41:56 +0100328 return resolved_method;
Alex Lightfedd91d2016-01-07 14:49:16 -0800329}
330
Andreas Gampe42ef8ab2015-12-03 17:27:32 -0800331template <ClassLinker::ResolveMode kResolveMode>
Mathieu Chartierc77f3ab2015-09-03 19:41:50 -0700332inline ArtMethod* ClassLinker::ResolveMethod(Thread* self,
333 uint32_t method_idx,
334 ArtMethod* referrer,
335 InvokeType type) {
Vladimir Markoba118822017-06-12 15:41:56 +0100336 DCHECK(referrer != nullptr);
337 // Note: The referrer can be a Proxy constructor. In that case, we need to do the
338 // lookup in the context of the original method from where it steals the code.
339 // However, we delay the GetInterfaceMethodIfProxy() until needed.
340 DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700341 Thread::PoisonObjectPointersIfDebug();
David Srbecky9f98fc32021-09-21 10:47:59 +0100342 ArtMethod* resolved_method = referrer->GetDexCache()->GetResolvedMethod(method_idx);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100343 DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod());
344 if (UNLIKELY(resolved_method == nullptr)) {
Vladimir Markoba118822017-06-12 15:41:56 +0100345 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700346 ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700347 StackHandleScope<2> hs(self);
Alex Light4ba388a2017-01-27 10:26:49 -0800348 Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700349 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
Vladimir Marko89011192017-12-11 13:45:05 +0000350 resolved_method = ResolveMethod<kResolveMode>(method_idx,
Andreas Gampe42ef8ab2015-12-03 17:27:32 -0800351 h_dex_cache,
352 h_class_loader,
353 referrer,
354 type);
Vladimir Markoba118822017-06-12 15:41:56 +0100355 } else if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
356 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
Nicolas Geoffray28d0a1d2020-07-06 14:04:02 +0100357 const dex::MethodId& method_id = referrer->GetDexFile()->GetMethodId(method_idx);
358 ObjPtr<mirror::Class> cls =
359 LookupResolvedType(method_id.class_idx_,
360 referrer->GetDexCache(),
361 referrer->GetClassLoader());
362 if (cls == nullptr) {
363 // The verifier breaks the invariant that a resolved method must have its
364 // class in the class table, so resolve the type in case we haven't found it.
365 // b/73760543
366 StackHandleScope<2> hs(Thread::Current());
367 Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
368 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(referrer->GetClassLoader()));
369 cls = ResolveType(method_id.class_idx_, h_dex_cache, h_class_loader);
370 if (hs.Self()->IsExceptionPending()) {
371 return nullptr;
372 }
373 }
Vladimir Markoba118822017-06-12 15:41:56 +0100374 // Check if the invoke type matches the class type.
Nicolas Geoffray28d0a1d2020-07-06 14:04:02 +0100375 if (CheckInvokeClassMismatch</* kThrow= */ true>(
376 referrer->GetDexCache(), type, [cls]() { return cls; })) {
Vladimir Markoba118822017-06-12 15:41:56 +0100377 DCHECK(Thread::Current()->IsExceptionPending());
378 return nullptr;
379 }
380 // Check access.
381 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
382 if (!referring_class->CheckResolvedMethodAccess(resolved_method->GetDeclaringClass(),
383 resolved_method,
Nicolas Geoffray28d0a1d2020-07-06 14:04:02 +0100384 referrer->GetDexCache(),
Vladimir Markoba118822017-06-12 15:41:56 +0100385 method_idx,
386 type)) {
387 DCHECK(Thread::Current()->IsExceptionPending());
388 return nullptr;
389 }
390 // Check if the invoke type matches the method type.
391 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
392 ThrowIncompatibleClassChangeError(type,
393 resolved_method->GetInvokeType(),
394 resolved_method,
395 referrer);
396 return nullptr;
397 }
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700398 }
Andreas Gampe58a5af82014-07-31 16:23:49 -0700399 // Note: We cannot check here to see whether we added the method to the cache. It
400 // might be an erroneous class, which results in it being hidden from us.
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700401 return resolved_method;
402}
403
Vladimir Markof44d36c2017-03-14 14:18:46 +0000404inline ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx,
405 ArtMethod* referrer,
406 bool is_static) {
David Srbecky9f98fc32021-09-21 10:47:59 +0100407 ArtField* field = referrer->GetDexCache()->GetResolvedField(field_idx);
Vladimir Markof44d36c2017-03-14 14:18:46 +0000408 if (field == nullptr) {
Nicolas Geoffrayc07f4882021-09-13 09:20:33 +0100409 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000410 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetDeclaringClass()->GetClassLoader();
411 field = LookupResolvedField(field_idx, referrer->GetDexCache(), class_loader, is_static);
Vladimir Markof44d36c2017-03-14 14:18:46 +0000412 }
413 return field;
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700414}
415
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700416inline ArtField* ClassLinker::ResolveField(uint32_t field_idx,
417 ArtMethod* referrer,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700418 bool is_static) {
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700419 Thread::PoisonObjectPointersIfDebug();
David Srbecky9f98fc32021-09-21 10:47:59 +0100420 ArtField* resolved_field = referrer->GetDexCache()->GetResolvedField(field_idx);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700421 if (UNLIKELY(resolved_field == nullptr)) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700422 StackHandleScope<2> hs(Thread::Current());
Nicolas Geoffrayc07f4882021-09-13 09:20:33 +0100423 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000424 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
Alex Lightdba61482016-12-21 08:20:29 -0800425 Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000426 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
Vladimir Markoe11dd502017-12-08 14:09:45 +0000427 resolved_field = ResolveField(field_idx, dex_cache, class_loader, is_static);
Andreas Gampe58a5af82014-07-31 16:23:49 -0700428 // Note: We cannot check here to see whether we added the field to the cache. The type
429 // might be an erroneous class, which results in it being hidden from us.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800430 }
431 return resolved_field;
432}
433
Mathieu Chartier72041a02017-07-14 18:23:25 -0700434template <class Visitor>
435inline void ClassLinker::VisitClassTables(const Visitor& visitor) {
436 Thread* const self = Thread::Current();
437 WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
438 for (const ClassLoaderData& data : class_loaders_) {
439 if (data.class_table != nullptr) {
440 visitor(data.class_table);
441 }
442 }
443}
444
Andreas Gampe88dbad32018-06-26 19:54:12 -0700445template <ReadBarrierOption kReadBarrierOption>
446inline ObjPtr<mirror::ObjectArray<mirror::Class>> ClassLinker::GetClassRoots() {
447 ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
448 class_roots_.Read<kReadBarrierOption>();
449 DCHECK(class_roots != nullptr);
450 return class_roots;
451}
452
Alex Lightabd8f052019-12-06 10:49:17 -0800453template <typename Visitor>
454void ClassLinker::VisitKnownDexFiles(Thread* self, Visitor visitor) {
455 ReaderMutexLock rmu(self, *Locks::dex_lock_);
456 std::for_each(dex_caches_.begin(),
457 dex_caches_.end(),
458 [&](DexCacheData& dcd) REQUIRES(Locks::mutator_lock_) {
459 if (dcd.IsValid()) {
460 visitor(dcd.dex_file);
461 }
462 });
463}
464
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800465} // namespace art
466
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700467#endif // ART_RUNTIME_CLASS_LINKER_INL_H_