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 "art_field.h"
21 #include "class_linker.h"
22 #include "gc/heap-inl.h"
23 #include "gc_root-inl.h"
24 #include "handle_scope-inl.h"
25 #include "mirror/class_loader.h"
26 #include "mirror/dex_cache-inl.h"
27 #include "mirror/iftable.h"
28 #include "mirror/object_array-inl.h"
29 #include "obj_ptr-inl.h"
30 #include "scoped_thread_state_change-inl.h"
31 
32 #include <atomic>
33 
34 namespace art {
35 
FindArrayClass(Thread * self,ObjPtr<mirror::Class> * element_class)36 inline mirror::Class* ClassLinker::FindArrayClass(Thread* self,
37                                                   ObjPtr<mirror::Class>* element_class) {
38   for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
39     // Read the cached array class once to avoid races with other threads setting it.
40     ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read();
41     if (array_class != nullptr && array_class->GetComponentType() == *element_class) {
42       return array_class.Ptr();
43     }
44   }
45   std::string descriptor = "[";
46   std::string temp;
47   descriptor += (*element_class)->GetDescriptor(&temp);
48   StackHandleScope<2> hs(Thread::Current());
49   Handle<mirror::ClassLoader> class_loader(hs.NewHandle((*element_class)->GetClassLoader()));
50   HandleWrapperObjPtr<mirror::Class> h_element_class(hs.NewHandleWrapper(element_class));
51   ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader);
52   if (array_class != nullptr) {
53     // Benign races in storing array class and incrementing index.
54     size_t victim_index = find_array_class_cache_next_victim_;
55     find_array_class_cache_[victim_index] = GcRoot<mirror::Class>(array_class);
56     find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize;
57   } else {
58     // We should have a NoClassDefFoundError.
59     self->AssertPendingException();
60   }
61   return array_class.Ptr();
62 }
63 
ResolveType(dex::TypeIndex type_idx,ObjPtr<mirror::Class> referrer)64 inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
65                                                       ObjPtr<mirror::Class> referrer) {
66   if (kObjPtrPoisoning) {
67     StackHandleScope<1> hs(Thread::Current());
68     HandleWrapperObjPtr<mirror::Class> referrer_wrapper = hs.NewHandleWrapper(&referrer);
69     Thread::Current()->PoisonObjectPointers();
70   }
71   if (kIsDebugBuild) {
72     Thread::Current()->AssertNoPendingException();
73   }
74   // We do not need the read barrier for getting the DexCache for the initial resolved type
75   // lookup as both from-space and to-space copies point to the same native resolved types array.
76   ObjPtr<mirror::Class> resolved_type =
77       referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
78   if (resolved_type == nullptr) {
79     StackHandleScope<2> hs(Thread::Current());
80     Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
81     Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
82     resolved_type = DoResolveType(type_idx, h_dex_cache, class_loader);
83   }
84   return resolved_type;
85 }
86 
ResolveType(dex::TypeIndex type_idx,ArtMethod * referrer)87 inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
88                                                       ArtMethod* referrer) {
89   Thread::PoisonObjectPointersIfDebug();
90   if (kIsDebugBuild) {
91     Thread::Current()->AssertNoPendingException();
92   }
93   // We do not need the read barrier for getting the DexCache for the initial resolved type
94   // lookup as both from-space and to-space copies point to the same native resolved types array.
95   ObjPtr<mirror::Class> resolved_type =
96       referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
97   if (UNLIKELY(resolved_type == nullptr)) {
98     StackHandleScope<2> hs(Thread::Current());
99     ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
100     Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
101     Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
102     resolved_type = DoResolveType(type_idx, dex_cache, class_loader);
103   }
104   return resolved_type;
105 }
106 
ResolveType(dex::TypeIndex type_idx,Handle<mirror::DexCache> dex_cache,Handle<mirror::ClassLoader> class_loader)107 inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
108                                                       Handle<mirror::DexCache> dex_cache,
109                                                       Handle<mirror::ClassLoader> class_loader) {
110   DCHECK(dex_cache != nullptr);
111   Thread::PoisonObjectPointersIfDebug();
112   ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx);
113   if (resolved == nullptr) {
114     resolved = DoResolveType(type_idx, dex_cache, class_loader);
115   }
116   return resolved;
117 }
118 
LookupResolvedType(dex::TypeIndex type_idx,ObjPtr<mirror::Class> referrer)119 inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
120                                                              ObjPtr<mirror::Class> referrer) {
121   // We do not need the read barrier for getting the DexCache for the initial resolved type
122   // lookup as both from-space and to-space copies point to the same native resolved types array.
123   ObjPtr<mirror::Class> type =
124       referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
125   if (type == nullptr) {
126     type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader());
127   }
128   return type;
129 }
130 
LookupResolvedType(dex::TypeIndex type_idx,ArtMethod * referrer)131 inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
132                                                              ArtMethod* referrer) {
133   // We do not need the read barrier for getting the DexCache for the initial resolved type
134   // lookup as both from-space and to-space copies point to the same native resolved types array.
135   ObjPtr<mirror::Class> type =
136       referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
137   if (type == nullptr) {
138     type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader());
139   }
140   return type;
141 }
142 
LookupResolvedType(dex::TypeIndex type_idx,ObjPtr<mirror::DexCache> dex_cache,ObjPtr<mirror::ClassLoader> class_loader)143 inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(
144     dex::TypeIndex type_idx,
145     ObjPtr<mirror::DexCache> dex_cache,
146     ObjPtr<mirror::ClassLoader> class_loader) {
147   ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx);
148   if (type == nullptr) {
149     type = DoLookupResolvedType(type_idx, dex_cache, class_loader);
150   }
151   return type;
152 }
153 
154 template <bool kThrowOnError, typename ClassGetter>
CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,InvokeType type,ClassGetter class_getter)155 inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
156                                                   InvokeType type,
157                                                   ClassGetter class_getter) {
158   switch (type) {
159     case kStatic:
160     case kSuper:
161       break;
162     case kInterface: {
163       // We have to check whether the method id really belongs to an interface (dex static bytecode
164       // constraints A15, A16). Otherwise you must not invoke-interface on it.
165       ObjPtr<mirror::Class> klass = class_getter();
166       if (UNLIKELY(!klass->IsInterface())) {
167         if (kThrowOnError) {
168           ThrowIncompatibleClassChangeError(klass,
169                                             "Found class %s, but interface was expected",
170                                             klass->PrettyDescriptor().c_str());
171         }
172         return true;
173       }
174       break;
175     }
176     case kDirect:
177       if (dex_cache->GetDexFile()->SupportsDefaultMethods()) {
178         break;
179       }
180       FALLTHROUGH_INTENDED;
181     case kVirtual: {
182       // Similarly, invoke-virtual (and invoke-direct without default methods) must reference
183       // a non-interface class (dex static bytecode constraint A24, A25).
184       ObjPtr<mirror::Class> klass = class_getter();
185       if (UNLIKELY(klass->IsInterface())) {
186         if (kThrowOnError) {
187           ThrowIncompatibleClassChangeError(klass,
188                                             "Found interface %s, but class was expected",
189                                             klass->PrettyDescriptor().c_str());
190         }
191         return true;
192       }
193       break;
194     }
195     default:
196       LOG(FATAL) << "Unreachable - invocation type: " << type;
197       UNREACHABLE();
198   }
199   return false;
200 }
201 
202 template <bool kThrow>
CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,InvokeType type,uint32_t method_idx,ObjPtr<mirror::ClassLoader> class_loader)203 inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
204                                                   InvokeType type,
205                                                   uint32_t method_idx,
206                                                   ObjPtr<mirror::ClassLoader> class_loader) {
207   return CheckInvokeClassMismatch<kThrow>(
208       dex_cache,
209       type,
210       [this, dex_cache, method_idx, class_loader]() REQUIRES_SHARED(Locks::mutator_lock_) {
211         const DexFile::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx);
212         ObjPtr<mirror::Class> klass =
213             LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
214         DCHECK(klass != nullptr);
215         return klass;
216       });
217 }
218 
LookupResolvedMethod(uint32_t method_idx,ObjPtr<mirror::DexCache> dex_cache,ObjPtr<mirror::ClassLoader> class_loader)219 inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx,
220                                                     ObjPtr<mirror::DexCache> dex_cache,
221                                                     ObjPtr<mirror::ClassLoader> class_loader) {
222   PointerSize pointer_size = image_pointer_size_;
223   ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, pointer_size);
224   if (resolved == nullptr) {
225     const DexFile& dex_file = *dex_cache->GetDexFile();
226     const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
227     ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
228     if (klass != nullptr) {
229       resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx);
230     }
231   }
232   return resolved;
233 }
234 
235 template <InvokeType type, ClassLinker::ResolveMode kResolveMode>
GetResolvedMethod(uint32_t method_idx,ArtMethod * referrer)236 inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer) {
237   DCHECK(referrer != nullptr);
238   // Note: The referrer can be a Proxy constructor. In that case, we need to do the
239   // lookup in the context of the original method from where it steals the code.
240   // However, we delay the GetInterfaceMethodIfProxy() until needed.
241   DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
242   // We do not need the read barrier for getting the DexCache for the initial resolved method
243   // lookup as both from-space and to-space copies point to the same native resolved methods array.
244   ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
245       method_idx, image_pointer_size_);
246   if (resolved_method == nullptr) {
247     return nullptr;
248   }
249   DCHECK(!resolved_method->IsRuntimeMethod());
250   if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
251     referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
252     // Check if the invoke type matches the class type.
253     ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
254     ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
255     if (CheckInvokeClassMismatch</* kThrow */ false>(dex_cache, type, method_idx, class_loader)) {
256       return nullptr;
257     }
258     // Check access.
259     ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
260     if (!referring_class->CanAccessResolvedMethod(resolved_method->GetDeclaringClass(),
261                                                   resolved_method,
262                                                   dex_cache,
263                                                   method_idx)) {
264       return nullptr;
265     }
266     // Check if the invoke type matches the method type.
267     if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
268       return nullptr;
269     }
270   }
271   return resolved_method;
272 }
273 
274 template <ClassLinker::ResolveMode kResolveMode>
ResolveMethod(Thread * self,uint32_t method_idx,ArtMethod * referrer,InvokeType type)275 inline ArtMethod* ClassLinker::ResolveMethod(Thread* self,
276                                              uint32_t method_idx,
277                                              ArtMethod* referrer,
278                                              InvokeType type) {
279   DCHECK(referrer != nullptr);
280   // Note: The referrer can be a Proxy constructor. In that case, we need to do the
281   // lookup in the context of the original method from where it steals the code.
282   // However, we delay the GetInterfaceMethodIfProxy() until needed.
283   DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
284   Thread::PoisonObjectPointersIfDebug();
285   // We do not need the read barrier for getting the DexCache for the initial resolved method
286   // lookup as both from-space and to-space copies point to the same native resolved methods array.
287   ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
288       method_idx, image_pointer_size_);
289   DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod());
290   if (UNLIKELY(resolved_method == nullptr)) {
291     referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
292     ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass();
293     StackHandleScope<2> hs(self);
294     Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
295     Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
296     resolved_method = ResolveMethod<kResolveMode>(method_idx,
297                                                   h_dex_cache,
298                                                   h_class_loader,
299                                                   referrer,
300                                                   type);
301   } else if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
302     referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
303     // Check if the invoke type matches the class type.
304     ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
305     ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
306     if (CheckInvokeClassMismatch</* kThrow */ true>(dex_cache, type, method_idx, class_loader)) {
307       DCHECK(Thread::Current()->IsExceptionPending());
308       return nullptr;
309     }
310     // Check access.
311     ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
312     if (!referring_class->CheckResolvedMethodAccess(resolved_method->GetDeclaringClass(),
313                                                     resolved_method,
314                                                     dex_cache,
315                                                     method_idx,
316                                                     type)) {
317       DCHECK(Thread::Current()->IsExceptionPending());
318       return nullptr;
319     }
320     // Check if the invoke type matches the method type.
321     if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
322       ThrowIncompatibleClassChangeError(type,
323                                         resolved_method->GetInvokeType(),
324                                         resolved_method,
325                                         referrer);
326       return nullptr;
327     }
328   }
329   // Note: We cannot check here to see whether we added the method to the cache. It
330   //       might be an erroneous class, which results in it being hidden from us.
331   return resolved_method;
332 }
333 
LookupResolvedField(uint32_t field_idx,ArtMethod * referrer,bool is_static)334 inline ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx,
335                                                   ArtMethod* referrer,
336                                                   bool is_static) {
337   // We do not need the read barrier for getting the DexCache for the initial resolved field
338   // lookup as both from-space and to-space copies point to the same native resolved fields array.
339   ArtField* field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
340       field_idx, image_pointer_size_);
341   if (field == nullptr) {
342     ObjPtr<mirror::ClassLoader> class_loader = referrer->GetDeclaringClass()->GetClassLoader();
343     field = LookupResolvedField(field_idx, referrer->GetDexCache(), class_loader, is_static);
344   }
345   return field;
346 }
347 
ResolveField(uint32_t field_idx,ArtMethod * referrer,bool is_static)348 inline ArtField* ClassLinker::ResolveField(uint32_t field_idx,
349                                            ArtMethod* referrer,
350                                            bool is_static) {
351   Thread::PoisonObjectPointersIfDebug();
352   // We do not need the read barrier for getting the DexCache for the initial resolved field
353   // lookup as both from-space and to-space copies point to the same native resolved fields array.
354   ArtField* resolved_field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
355       field_idx, image_pointer_size_);
356   if (UNLIKELY(resolved_field == nullptr)) {
357     StackHandleScope<2> hs(Thread::Current());
358     ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
359     Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
360     Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
361     resolved_field = ResolveField(field_idx, dex_cache, class_loader, is_static);
362     // Note: We cannot check here to see whether we added the field to the cache. The type
363     //       might be an erroneous class, which results in it being hidden from us.
364   }
365   return resolved_field;
366 }
367 
GetClassRoot(ClassRoot class_root)368 inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root) {
369   DCHECK(!class_roots_.IsNull());
370   mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read();
371   ObjPtr<mirror::Class> klass = class_roots->Get(class_root);
372   DCHECK(klass != nullptr);
373   return klass.Ptr();
374 }
375 
376 template <class Visitor>
VisitClassTables(const Visitor & visitor)377 inline void ClassLinker::VisitClassTables(const Visitor& visitor) {
378   Thread* const self = Thread::Current();
379   WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
380   for (const ClassLoaderData& data : class_loaders_) {
381     if (data.class_table != nullptr) {
382       visitor(data.class_table);
383     }
384   }
385 }
386 
387 }  // namespace art
388 
389 #endif  // ART_RUNTIME_CLASS_LINKER_INL_H_
390