• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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