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 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 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 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 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 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 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 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> 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> 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 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> 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> 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 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 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 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> 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