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