1 /*
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
17 #ifndef ART_RUNTIME_CLASS_LINKER_INL_H_
18 #define ART_RUNTIME_CLASS_LINKER_INL_H_
19
20 #include <atomic>
21
22 #include "android-base/thread_annotations.h"
23 #include "art_field-inl.h"
24 #include "art_method-inl.h"
25 #include "base/mutex.h"
26 #include "class_linker.h"
27 #include "dex/dex_file.h"
28 #include "dex/dex_file_structs.h"
29 #include "gc_root-inl.h"
30 #include "handle_scope-inl.h"
31 #include "jni/jni_internal.h"
32 #include "mirror/class_loader.h"
33 #include "mirror/dex_cache-inl.h"
34 #include "mirror/iftable.h"
35 #include "mirror/object_array-inl.h"
36 #include "obj_ptr-inl.h"
37 #include "scoped_thread_state_change-inl.h"
38 #include "well_known_classes.h"
39
40 namespace art {
41
FindArrayClass(Thread * self,ObjPtr<mirror::Class> element_class)42 inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self,
43 ObjPtr<mirror::Class> element_class) {
44 for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
45 // Read the cached array class once to avoid races with other threads setting it.
46 ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read();
47 if (array_class != nullptr && array_class->GetComponentType() == element_class) {
48 return array_class;
49 }
50 }
51 std::string descriptor = "[";
52 std::string temp;
53 descriptor += element_class->GetDescriptor(&temp);
54 StackHandleScope<1> hs(Thread::Current());
55 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
56 ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader);
57 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 }
66 return array_class;
67 }
68
ResolveString(dex::StringIndex string_idx,ArtField * referrer)69 inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
70 ArtField* referrer) {
71 Thread::PoisonObjectPointersIfDebug();
72 DCHECK(!Thread::Current()->IsExceptionPending());
73 // We do not need the read barrier for getting the DexCache for the initial resolved type
74 // lookup as both from-space and to-space copies point to the same native resolved types array.
75 ObjPtr<mirror::String> resolved =
76 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
77 if (resolved == nullptr) {
78 resolved = DoResolveString(string_idx, referrer->GetDexCache());
79 }
80 return resolved;
81 }
82
ResolveString(dex::StringIndex string_idx,ArtMethod * referrer)83 inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
84 ArtMethod* referrer) {
85 Thread::PoisonObjectPointersIfDebug();
86 DCHECK(!Thread::Current()->IsExceptionPending());
87 // We do not need the read barrier for getting the DexCache for the initial resolved type
88 // lookup as both from-space and to-space copies point to the same native resolved types array.
89 ObjPtr<mirror::String> resolved =
90 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
91 if (resolved == nullptr) {
92 resolved = DoResolveString(string_idx, referrer->GetDexCache());
93 }
94 return resolved;
95 }
96
ResolveString(dex::StringIndex string_idx,Handle<mirror::DexCache> dex_cache)97 inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
98 Handle<mirror::DexCache> dex_cache) {
99 Thread::PoisonObjectPointersIfDebug();
100 DCHECK(!Thread::Current()->IsExceptionPending());
101 ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
102 if (resolved == nullptr) {
103 resolved = DoResolveString(string_idx, dex_cache);
104 }
105 return resolved;
106 }
107
LookupString(dex::StringIndex string_idx,ObjPtr<mirror::DexCache> dex_cache)108 inline ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
109 ObjPtr<mirror::DexCache> dex_cache) {
110 ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
111 if (resolved == nullptr) {
112 resolved = DoLookupString(string_idx, dex_cache);
113 }
114 return resolved;
115 }
116
ResolveType(dex::TypeIndex type_idx,ObjPtr<mirror::Class> referrer)117 inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
118 ObjPtr<mirror::Class> referrer) {
119 if (kObjPtrPoisoning) {
120 StackHandleScope<1> hs(Thread::Current());
121 HandleWrapperObjPtr<mirror::Class> referrer_wrapper = hs.NewHandleWrapper(&referrer);
122 Thread::Current()->PoisonObjectPointers();
123 }
124 DCHECK(!Thread::Current()->IsExceptionPending());
125 // We do not need the read barrier for getting the DexCache for the initial resolved type
126 // lookup as both from-space and to-space copies point to the same native resolved types array.
127 ObjPtr<mirror::Class> resolved_type =
128 referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
129 if (resolved_type == nullptr) {
130 resolved_type = DoResolveType(type_idx, referrer);
131 }
132 return resolved_type;
133 }
134
ResolveType(dex::TypeIndex type_idx,ArtField * referrer)135 inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
136 ArtField* referrer) {
137 Thread::PoisonObjectPointersIfDebug();
138 DCHECK(!Thread::Current()->IsExceptionPending());
139 // We do not need the read barrier for getting the DexCache for the initial resolved type
140 // lookup as both from-space and to-space copies point to the same native resolved types array.
141 ObjPtr<mirror::Class> resolved_type =
142 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
143 if (UNLIKELY(resolved_type == nullptr)) {
144 resolved_type = DoResolveType(type_idx, referrer);
145 }
146 return resolved_type;
147 }
148
ResolveType(dex::TypeIndex type_idx,ArtMethod * referrer)149 inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
150 ArtMethod* referrer) {
151 Thread::PoisonObjectPointersIfDebug();
152 DCHECK(!Thread::Current()->IsExceptionPending());
153 // We do not need the read barrier for getting the DexCache for the initial resolved type
154 // lookup as both from-space and to-space copies point to the same native resolved types array.
155 ObjPtr<mirror::Class> resolved_type =
156 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
157 if (UNLIKELY(resolved_type == nullptr)) {
158 resolved_type = DoResolveType(type_idx, referrer);
159 }
160 return resolved_type;
161 }
162
ResolveType(dex::TypeIndex type_idx,Handle<mirror::DexCache> dex_cache,Handle<mirror::ClassLoader> class_loader)163 inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
164 Handle<mirror::DexCache> dex_cache,
165 Handle<mirror::ClassLoader> class_loader) {
166 DCHECK(dex_cache != nullptr);
167 DCHECK(dex_cache->GetClassLoader() == class_loader.Get());
168 Thread::PoisonObjectPointersIfDebug();
169 ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx);
170 if (resolved == nullptr) {
171 resolved = DoResolveType(type_idx, dex_cache, class_loader);
172 }
173 return resolved;
174 }
175
LookupResolvedType(dex::TypeIndex type_idx,ObjPtr<mirror::Class> referrer)176 inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
177 ObjPtr<mirror::Class> referrer) {
178 // We do not need the read barrier for getting the DexCache for the initial resolved type
179 // lookup as both from-space and to-space copies point to the same native resolved types array.
180 ObjPtr<mirror::Class> type =
181 referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
182 if (type == nullptr) {
183 type = DoLookupResolvedType(type_idx, referrer);
184 }
185 return type;
186 }
187
LookupResolvedType(dex::TypeIndex type_idx,ArtField * referrer)188 inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
189 ArtField* referrer) {
190 // We do not need the read barrier for getting the DexCache for the initial resolved type
191 // lookup as both from-space and to-space copies point to the same native resolved types array.
192 ObjPtr<mirror::Class> type =
193 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
194 if (type == nullptr) {
195 type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
196 }
197 return type;
198 }
199
LookupResolvedType(dex::TypeIndex type_idx,ArtMethod * referrer)200 inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
201 ArtMethod* referrer) {
202 // We do not need the read barrier for getting the DexCache for the initial resolved type
203 // lookup as both from-space and to-space copies point to the same native resolved types array.
204 ObjPtr<mirror::Class> type =
205 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
206 if (type == nullptr) {
207 type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
208 }
209 return type;
210 }
211
LookupResolvedType(dex::TypeIndex type_idx,ObjPtr<mirror::DexCache> dex_cache,ObjPtr<mirror::ClassLoader> class_loader)212 inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(
213 dex::TypeIndex type_idx,
214 ObjPtr<mirror::DexCache> dex_cache,
215 ObjPtr<mirror::ClassLoader> class_loader) {
216 DCHECK(dex_cache->GetClassLoader() == class_loader);
217 ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx);
218 if (type == nullptr) {
219 type = DoLookupResolvedType(type_idx, dex_cache, class_loader);
220 }
221 return type;
222 }
223
224 template <bool kThrowOnError, typename ClassGetter>
CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,InvokeType type,ClassGetter class_getter)225 inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
226 InvokeType type,
227 ClassGetter class_getter) {
228 switch (type) {
229 case kStatic:
230 case kSuper:
231 case kPolymorphic:
232 break;
233 case kInterface: {
234 // We have to check whether the method id really belongs to an interface (dex static bytecode
235 // constraints A15, A16). Otherwise you must not invoke-interface on it.
236 ObjPtr<mirror::Class> klass = class_getter();
237 if (UNLIKELY(!klass->IsInterface())) {
238 if (kThrowOnError) {
239 ThrowIncompatibleClassChangeError(klass,
240 "Found class %s, but interface was expected",
241 klass->PrettyDescriptor().c_str());
242 }
243 return true;
244 }
245 break;
246 }
247 case kDirect:
248 if (dex_cache->GetDexFile()->SupportsDefaultMethods()) {
249 break;
250 }
251 FALLTHROUGH_INTENDED;
252 case kVirtual: {
253 // Similarly, invoke-virtual (and invoke-direct without default methods) must reference
254 // a non-interface class (dex static bytecode constraint A24, A25).
255 ObjPtr<mirror::Class> klass = class_getter();
256 if (UNLIKELY(klass->IsInterface())) {
257 if (kThrowOnError) {
258 ThrowIncompatibleClassChangeError(klass,
259 "Found interface %s, but class was expected",
260 klass->PrettyDescriptor().c_str());
261 }
262 return true;
263 }
264 break;
265 }
266 default:
267 LOG(FATAL) << "Unreachable - invocation type: " << type;
268 UNREACHABLE();
269 }
270 return false;
271 }
272
273 template <bool kThrow>
CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,InvokeType type,uint32_t method_idx,ObjPtr<mirror::ClassLoader> class_loader)274 inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
275 InvokeType type,
276 uint32_t method_idx,
277 ObjPtr<mirror::ClassLoader> class_loader) {
278 DCHECK(dex_cache->GetClassLoader().Ptr() == class_loader.Ptr());
279 return CheckInvokeClassMismatch<kThrow>(
280 dex_cache,
281 type,
282 [this, dex_cache, method_idx, class_loader]() REQUIRES_SHARED(Locks::mutator_lock_) {
283 const dex::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx);
284 ObjPtr<mirror::Class> klass =
285 LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
286 DCHECK(klass != nullptr) << dex_cache->GetDexFile()->PrettyMethod(method_idx);
287 return klass;
288 });
289 }
290
LookupResolvedMethod(uint32_t method_idx,ObjPtr<mirror::DexCache> dex_cache,ObjPtr<mirror::ClassLoader> class_loader)291 inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx,
292 ObjPtr<mirror::DexCache> dex_cache,
293 ObjPtr<mirror::ClassLoader> class_loader) {
294 DCHECK(dex_cache->GetClassLoader() == class_loader);
295 ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx);
296 if (resolved == nullptr) {
297 const DexFile& dex_file = *dex_cache->GetDexFile();
298 const dex::MethodId& method_id = dex_file.GetMethodId(method_idx);
299 ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
300 if (klass != nullptr) {
301 resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx);
302 }
303 }
304 return resolved;
305 }
306
307 template <InvokeType type, ClassLinker::ResolveMode kResolveMode>
GetResolvedMethod(uint32_t method_idx,ArtMethod * referrer)308 inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer) {
309 DCHECK(referrer != nullptr);
310 // Note: The referrer can be a Proxy constructor. In that case, we need to do the
311 // lookup in the context of the original method from where it steals the code.
312 // However, we delay the GetInterfaceMethodIfProxy() until needed.
313 DCHECK_IMPLIES(referrer->IsProxyMethod(), referrer->IsConstructor());
314 // We do not need the read barrier for getting the DexCache for the initial resolved method
315 // lookup as both from-space and to-space copies point to the same native resolved methods array.
316 ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
317 method_idx);
318 if (resolved_method == nullptr) {
319 return nullptr;
320 }
321 DCHECK(!resolved_method->IsRuntimeMethod());
322 if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
323 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
324 // Check if the invoke type matches the class type.
325 ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
326 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
327 const dex::MethodId& method_id = referrer->GetDexFile()->GetMethodId(method_idx);
328 ObjPtr<mirror::Class> cls = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
329 if (cls == nullptr) {
330 // The verifier breaks the invariant that a resolved method must have its
331 // class in the class table. Because this method should only lookup and not
332 // resolve class, return null. The caller is responsible for calling
333 // `ResolveMethod` afterwards.
334 // b/73760543
335 return nullptr;
336 }
337 if (CheckInvokeClassMismatch</* kThrow= */ false>(dex_cache, type, method_idx, class_loader)) {
338 return nullptr;
339 }
340 // Check access.
341 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
342 if (!referring_class->CanAccessResolvedMethod(resolved_method->GetDeclaringClass(),
343 resolved_method,
344 dex_cache,
345 method_idx)) {
346 return nullptr;
347 }
348 // Check if the invoke type matches the method type.
349 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
350 return nullptr;
351 }
352 }
353 return resolved_method;
354 }
355
356 template <ClassLinker::ResolveMode kResolveMode>
ResolveMethod(Thread * self,uint32_t method_idx,ArtMethod * referrer,InvokeType type)357 inline ArtMethod* ClassLinker::ResolveMethod(Thread* self,
358 uint32_t method_idx,
359 ArtMethod* referrer,
360 InvokeType type) {
361 DCHECK(referrer != nullptr);
362 // Note: The referrer can be a Proxy constructor. In that case, we need to do the
363 // lookup in the context of the original method from where it steals the code.
364 // However, we delay the GetInterfaceMethodIfProxy() until needed.
365 DCHECK_IMPLIES(referrer->IsProxyMethod(), referrer->IsConstructor());
366 Thread::PoisonObjectPointersIfDebug();
367 // We do not need the read barrier for getting the DexCache for the initial resolved method
368 // lookup as both from-space and to-space copies point to the same native resolved methods array.
369 ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
370 method_idx);
371 DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod());
372 if (UNLIKELY(resolved_method == nullptr)) {
373 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
374 ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass();
375 StackHandleScope<2> hs(self);
376 Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
377 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
378 resolved_method = ResolveMethod<kResolveMode>(method_idx,
379 h_dex_cache,
380 h_class_loader,
381 referrer,
382 type);
383 } else if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
384 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
385 const dex::MethodId& method_id = referrer->GetDexFile()->GetMethodId(method_idx);
386 ObjPtr<mirror::Class> cls =
387 LookupResolvedType(method_id.class_idx_,
388 referrer->GetDexCache(),
389 referrer->GetClassLoader());
390 if (cls == nullptr) {
391 // The verifier breaks the invariant that a resolved method must have its
392 // class in the class table, so resolve the type in case we haven't found it.
393 // b/73760543
394 StackHandleScope<2> hs(Thread::Current());
395 Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
396 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(referrer->GetClassLoader()));
397 cls = ResolveType(method_id.class_idx_, h_dex_cache, h_class_loader);
398 if (hs.Self()->IsExceptionPending()) {
399 return nullptr;
400 }
401 }
402 // Check if the invoke type matches the class type.
403 if (CheckInvokeClassMismatch</* kThrow= */ true>(
404 referrer->GetDexCache(), type, [cls]() { return cls; })) {
405 DCHECK(Thread::Current()->IsExceptionPending());
406 return nullptr;
407 }
408 // Check access.
409 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
410 if (!referring_class->CheckResolvedMethodAccess(resolved_method->GetDeclaringClass(),
411 resolved_method,
412 referrer->GetDexCache(),
413 method_idx,
414 type)) {
415 DCHECK(Thread::Current()->IsExceptionPending());
416 return nullptr;
417 }
418 // Check if the invoke type matches the method type.
419 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
420 ThrowIncompatibleClassChangeError(type,
421 resolved_method->GetInvokeType(),
422 resolved_method,
423 referrer);
424 return nullptr;
425 }
426 }
427 // Note: We cannot check here to see whether we added the method to the cache. It
428 // might be an erroneous class, which results in it being hidden from us.
429 return resolved_method;
430 }
431
432 template <ClassLinker::ResolveMode kResolveMode>
ResolveMethod(uint32_t method_idx,Handle<mirror::DexCache> dex_cache,Handle<mirror::ClassLoader> class_loader,ArtMethod * referrer,InvokeType type)433 inline ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx,
434 Handle<mirror::DexCache> dex_cache,
435 Handle<mirror::ClassLoader> class_loader,
436 ArtMethod* referrer,
437 InvokeType type) {
438 DCHECK(dex_cache->GetClassLoader() == class_loader.Get());
439 DCHECK(!Thread::Current()->IsExceptionPending()) << Thread::Current()->GetException()->Dump();
440 DCHECK(dex_cache != nullptr);
441 DCHECK(referrer == nullptr || !referrer->IsProxyMethod());
442 // Check for hit in the dex cache.
443 ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx);
444 Thread::PoisonObjectPointersIfDebug();
445 DCHECK(resolved == nullptr || !resolved->IsRuntimeMethod());
446 bool valid_dex_cache_method = resolved != nullptr;
447 if (kResolveMode == ResolveMode::kNoChecks && valid_dex_cache_method) {
448 // We have a valid method from the DexCache and no checks to perform.
449 DCHECK(resolved->GetDeclaringClassUnchecked() != nullptr) << resolved->GetDexMethodIndex();
450 return resolved;
451 }
452 const DexFile& dex_file = *dex_cache->GetDexFile();
453 const dex::MethodId& method_id = dex_file.GetMethodId(method_idx);
454 ObjPtr<mirror::Class> klass = nullptr;
455 if (valid_dex_cache_method) {
456 // We have a valid method from the DexCache but we need to perform ICCE and IAE checks.
457 DCHECK(resolved->GetDeclaringClassUnchecked() != nullptr) << resolved->GetDexMethodIndex();
458 klass = LookupResolvedType(method_id.class_idx_, dex_cache.Get(), class_loader.Get());
459 if (UNLIKELY(klass == nullptr)) {
460 // We normaly should not end up here. However the verifier currently doesn't guarantee
461 // the invariant of having the klass in the class table. b/73760543
462 klass = ResolveType(method_id.class_idx_, dex_cache, class_loader);
463 if (klass == nullptr) {
464 // This can only happen if the current thread is not allowed to load
465 // classes.
466 DCHECK(!Thread::Current()->CanLoadClasses());
467 DCHECK(Thread::Current()->IsExceptionPending());
468 return nullptr;
469 }
470 }
471 } else {
472 // The method was not in the DexCache, resolve the declaring class.
473 klass = ResolveType(method_id.class_idx_, dex_cache, class_loader);
474 if (klass == nullptr) {
475 DCHECK(Thread::Current()->IsExceptionPending());
476 return nullptr;
477 }
478 }
479
480 // Check if the invoke type matches the class type.
481 if (kResolveMode == ResolveMode::kCheckICCEAndIAE &&
482 CheckInvokeClassMismatch</* kThrow= */ true>(
483 dex_cache.Get(), type, [klass]() { return klass; })) {
484 DCHECK(Thread::Current()->IsExceptionPending());
485 return nullptr;
486 }
487
488 if (!valid_dex_cache_method) {
489 resolved = FindResolvedMethod(klass, dex_cache.Get(), class_loader.Get(), method_idx);
490 }
491
492 // Note: We can check for IllegalAccessError only if we have a referrer.
493 if (kResolveMode == ResolveMode::kCheckICCEAndIAE && resolved != nullptr && referrer != nullptr) {
494 ObjPtr<mirror::Class> methods_class = resolved->GetDeclaringClass();
495 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
496 if (!referring_class->CheckResolvedMethodAccess(methods_class,
497 resolved,
498 dex_cache.Get(),
499 method_idx,
500 type)) {
501 DCHECK(Thread::Current()->IsExceptionPending());
502 return nullptr;
503 }
504 }
505
506 // If we found a method, check for incompatible class changes.
507 if (LIKELY(resolved != nullptr) &&
508 LIKELY(kResolveMode == ResolveMode::kNoChecks ||
509 !resolved->CheckIncompatibleClassChange(type))) {
510 return resolved;
511 } else {
512 // If we had a method, or if we can find one with another lookup type,
513 // it's an incompatible-class-change error.
514 if (resolved == nullptr) {
515 resolved = FindIncompatibleMethod(klass, dex_cache.Get(), class_loader.Get(), method_idx);
516 }
517 if (resolved != nullptr) {
518 ThrowIncompatibleClassChangeError(type, resolved->GetInvokeType(), resolved, referrer);
519 } else {
520 // We failed to find the method (using all lookup types), so throw a NoSuchMethodError.
521 const char* name = dex_file.StringDataByIdx(method_id.name_idx_);
522 const Signature signature = dex_file.GetMethodSignature(method_id);
523 ThrowNoSuchMethodError(type, klass, name, signature);
524 }
525 Thread::Current()->AssertPendingException();
526 return nullptr;
527 }
528 }
529
LookupResolvedField(uint32_t field_idx,ArtMethod * referrer,bool is_static)530 inline ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx,
531 ArtMethod* referrer,
532 bool is_static) {
533 // We do not need the read barrier for getting the DexCache for the initial resolved field
534 // lookup as both from-space and to-space copies point to the same native resolved fields array.
535 ArtField* field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
536 field_idx);
537 if (field == nullptr) {
538 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
539 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetDeclaringClass()->GetClassLoader();
540 field = LookupResolvedField(field_idx, referrer->GetDexCache(), class_loader, is_static);
541 }
542 return field;
543 }
544
ResolveField(uint32_t field_idx,ArtMethod * referrer,bool is_static)545 inline ArtField* ClassLinker::ResolveField(uint32_t field_idx,
546 ArtMethod* referrer,
547 bool is_static) {
548 Thread::PoisonObjectPointersIfDebug();
549 // We do not need the read barrier for getting the DexCache for the initial resolved field
550 // lookup as both from-space and to-space copies point to the same native resolved fields array.
551 ArtField* resolved_field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
552 field_idx);
553 if (UNLIKELY(resolved_field == nullptr)) {
554 StackHandleScope<2> hs(Thread::Current());
555 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
556 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
557 Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
558 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
559 resolved_field = ResolveField(field_idx, dex_cache, class_loader, is_static);
560 // Note: We cannot check here to see whether we added the field to the cache. The type
561 // might be an erroneous class, which results in it being hidden from us.
562 }
563 return resolved_field;
564 }
565
ResolveField(uint32_t field_idx,Handle<mirror::DexCache> dex_cache,Handle<mirror::ClassLoader> class_loader,bool is_static)566 inline ArtField* ClassLinker::ResolveField(uint32_t field_idx,
567 Handle<mirror::DexCache> dex_cache,
568 Handle<mirror::ClassLoader> class_loader,
569 bool is_static) {
570 DCHECK(dex_cache != nullptr);
571 DCHECK(dex_cache->GetClassLoader().Ptr() == class_loader.Get());
572 DCHECK(!Thread::Current()->IsExceptionPending()) << Thread::Current()->GetException()->Dump();
573 ArtField* resolved = dex_cache->GetResolvedField(field_idx);
574 Thread::PoisonObjectPointersIfDebug();
575 if (resolved != nullptr) {
576 return resolved;
577 }
578 const DexFile& dex_file = *dex_cache->GetDexFile();
579 const dex::FieldId& field_id = dex_file.GetFieldId(field_idx);
580 ObjPtr<mirror::Class> klass = ResolveType(field_id.class_idx_, dex_cache, class_loader);
581 if (klass == nullptr) {
582 DCHECK(Thread::Current()->IsExceptionPending());
583 return nullptr;
584 }
585
586 resolved = FindResolvedField(klass, dex_cache.Get(), class_loader.Get(), field_idx, is_static);
587 if (resolved == nullptr) {
588 const char* name = dex_file.GetFieldName(field_id);
589 const char* type = dex_file.GetFieldTypeDescriptor(field_id);
590 ThrowNoSuchFieldError(is_static ? "static " : "instance ", klass, type, name);
591 }
592 return resolved;
593 }
594
595 template <class Visitor>
VisitClassTables(const Visitor & visitor)596 inline void ClassLinker::VisitClassTables(const Visitor& visitor) {
597 Thread* const self = Thread::Current();
598 WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
599 for (const ClassLoaderData& data : class_loaders_) {
600 if (data.class_table != nullptr) {
601 visitor(data.class_table);
602 }
603 }
604 }
605
606 template <ReadBarrierOption kReadBarrierOption>
GetClassRoots()607 inline ObjPtr<mirror::ObjectArray<mirror::Class>> ClassLinker::GetClassRoots() {
608 ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
609 class_roots_.Read<kReadBarrierOption>();
610 DCHECK(class_roots != nullptr);
611 return class_roots;
612 }
613
614 template <typename Visitor>
VisitKnownDexFiles(Thread * self,Visitor visitor)615 void ClassLinker::VisitKnownDexFiles(Thread* self, Visitor visitor) {
616 ReaderMutexLock rmu(self, *Locks::dex_lock_);
617 std::for_each(dex_caches_.begin(),
618 dex_caches_.end(),
619 [&](const auto& entry) REQUIRES(Locks::mutator_lock_) {
620 visitor(/*dex_file=*/entry.first);
621 });
622 }
623
624 } // namespace art
625
626 #endif // ART_RUNTIME_CLASS_LINKER_INL_H_
627