1 /* 2 * Copyright (C) 2018 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 #include "resolver.h" 18 19 #include "dex/class_accessor-inl.h" 20 #include "dex/dex_file-inl.h" 21 #include "dex/primitive.h" 22 #include "dex/signature-inl.h" 23 #include "hidden_api.h" 24 #include "veridex.h" 25 26 namespace art { 27 28 void VeridexResolver::Run() { 29 for (ClassAccessor accessor : dex_file_.GetClasses()) { 30 std::string name(accessor.GetDescriptor()); 31 auto existing = type_map_.find(name); 32 const uint32_t type_idx = accessor.GetClassIdx().index_; 33 if (existing != type_map_.end()) { 34 // Class already exists, cache it and move on. 35 type_infos_[type_idx] = *existing->second; 36 continue; 37 } 38 type_infos_[type_idx] = VeriClass(Primitive::Type::kPrimNot, 0, &accessor.GetClassDef()); 39 type_map_[name] = &type_infos_[type_idx]; 40 for (const ClassAccessor::Field& field : accessor.GetFields()) { 41 field_infos_[field.GetIndex()] = field.GetDataPointer(); 42 } 43 for (const ClassAccessor::Method& method : accessor.GetMethods()) { 44 method_infos_[method.GetIndex()] = method.GetDataPointer(); 45 } 46 } 47 } 48 49 static bool HasSameNameAndSignature(const DexFile& dex_file, 50 const dex::MethodId& method_id, 51 const char* method_name, 52 const char* type) { 53 return strcmp(method_name, dex_file.GetMethodName(method_id)) == 0 && 54 strcmp(type, dex_file.GetMethodSignature(method_id).ToString().c_str()) == 0; 55 } 56 57 static bool HasSameNameAndSignature(const DexFile& dex_file, 58 const dex::MethodId& method_id, 59 const char* method_name, 60 const Signature& signature) { 61 return strcmp(method_name, dex_file.GetMethodName(method_id)) == 0 && 62 dex_file.GetMethodSignature(method_id) == signature; 63 } 64 65 static bool HasSameNameAndType(const DexFile& dex_file, 66 const dex::FieldId& field_id, 67 const char* field_name, 68 const char* field_type) { 69 return strcmp(field_name, dex_file.GetFieldName(field_id)) == 0 && 70 strcmp(field_type, dex_file.GetFieldTypeDescriptor(field_id)) == 0; 71 } 72 73 VeriClass* VeridexResolver::GetVeriClass(dex::TypeIndex index) { 74 CHECK_LT(index.index_, dex_file_.NumTypeIds()); 75 // Lookup in our local cache. 76 VeriClass* cls = &type_infos_[index.index_]; 77 if (cls->IsUninitialized()) { 78 // Class is defined in another dex file. Lookup in the global cache. 79 std::string name(dex_file_.StringByTypeIdx(index)); 80 auto existing = type_map_.find(name); 81 if (existing == type_map_.end()) { 82 // Class hasn't been defined, so check if it's an array class. 83 size_t last_array = name.find_last_of('['); 84 if (last_array == std::string::npos) { 85 // There is no such class. 86 return nullptr; 87 } else { 88 // Class is an array class. Check if its most enclosed component type (which is not 89 // an array class) has been defined. 90 std::string klass_name = name.substr(last_array + 1); 91 existing = type_map_.find(klass_name); 92 if (existing == type_map_.end()) { 93 // There is no such class, so there is no such array. 94 return nullptr; 95 } else { 96 // Create the type, and cache it locally and globally. 97 type_infos_[index.index_] = VeriClass( 98 existing->second->GetKind(), last_array + 1, existing->second->GetClassDef()); 99 cls = &(type_infos_[index.index_]); 100 type_map_[name] = cls; 101 } 102 } 103 } else { 104 // Cache the found class. 105 cls = existing->second; 106 type_infos_[index.index_] = *cls; 107 } 108 } 109 return cls; 110 } 111 112 VeridexResolver* VeridexResolver::GetResolverOf(const VeriClass& kls) const { 113 auto resolver_it = dex_resolvers_.lower_bound(reinterpret_cast<uintptr_t>(kls.GetClassDef())); 114 --resolver_it; 115 116 // Check the class def pointer is indeed in the mapped dex file range. 117 const DexFile& dex_file = resolver_it->second->dex_file_; 118 CHECK_LT(reinterpret_cast<uintptr_t>(dex_file.Begin()), 119 reinterpret_cast<uintptr_t>(kls.GetClassDef())); 120 CHECK_GT(reinterpret_cast<uintptr_t>(dex_file.Begin()) + dex_file.Size(), 121 reinterpret_cast<uintptr_t>(kls.GetClassDef())); 122 return resolver_it->second; 123 } 124 125 VeriMethod VeridexResolver::LookupMethodIn(const VeriClass& kls, 126 const char* method_name, 127 const Signature& method_signature) { 128 if (kls.IsPrimitive()) { 129 // Primitive classes don't have methods. 130 return nullptr; 131 } 132 if (kls.IsArray()) { 133 // Array classes don't have methods, but inherit the ones in j.l.Object. 134 return LookupMethodIn(*VeriClass::object_, method_name, method_signature); 135 } 136 // Get the resolver where `kls` is from. 137 VeridexResolver* resolver = GetResolverOf(kls); 138 139 // Look at methods declared in `kls`. 140 const DexFile& other_dex_file = resolver->dex_file_; 141 ClassAccessor other_dex_accessor(other_dex_file, *kls.GetClassDef()); 142 for (const ClassAccessor::Method& method : other_dex_accessor.GetMethods()) { 143 const dex::MethodId& other_method_id = other_dex_file.GetMethodId(method.GetIndex()); 144 if (HasSameNameAndSignature(other_dex_file, 145 other_method_id, 146 method_name, 147 method_signature)) { 148 return method.GetDataPointer(); 149 } 150 } 151 152 // Look at methods in `kls`'s super class hierarchy. 153 if (kls.GetClassDef()->superclass_idx_.IsValid()) { 154 VeriClass* super = resolver->GetVeriClass(kls.GetClassDef()->superclass_idx_); 155 if (super != nullptr) { 156 VeriMethod super_method = resolver->LookupMethodIn(*super, method_name, method_signature); 157 if (super_method != nullptr) { 158 return super_method; 159 } 160 } 161 } 162 163 // Look at methods in `kls`'s interface hierarchy. 164 const dex::TypeList* interfaces = other_dex_file.GetInterfacesList(*kls.GetClassDef()); 165 if (interfaces != nullptr) { 166 for (size_t i = 0; i < interfaces->Size(); i++) { 167 dex::TypeIndex idx = interfaces->GetTypeItem(i).type_idx_; 168 VeriClass* itf = resolver->GetVeriClass(idx); 169 if (itf != nullptr) { 170 VeriMethod itf_method = resolver->LookupMethodIn(*itf, method_name, method_signature); 171 if (itf_method != nullptr) { 172 return itf_method; 173 } 174 } 175 } 176 } 177 return nullptr; 178 } 179 180 VeriField VeridexResolver::LookupFieldIn(const VeriClass& kls, 181 const char* field_name, 182 const char* field_type) { 183 if (kls.IsPrimitive()) { 184 // Primitive classes don't have fields. 185 return nullptr; 186 } 187 if (kls.IsArray()) { 188 // Array classes don't have fields. 189 return nullptr; 190 } 191 // Get the resolver where `kls` is from. 192 VeridexResolver* resolver = GetResolverOf(kls); 193 194 // Look at fields declared in `kls`. 195 const DexFile& other_dex_file = resolver->dex_file_; 196 ClassAccessor other_dex_accessor(other_dex_file, *kls.GetClassDef()); 197 for (const ClassAccessor::Field& field : other_dex_accessor.GetFields()) { 198 const dex::FieldId& other_field_id = other_dex_file.GetFieldId(field.GetIndex()); 199 if (HasSameNameAndType(other_dex_file, 200 other_field_id, 201 field_name, 202 field_type)) { 203 return field.GetDataPointer(); 204 } 205 } 206 207 // Look at fields in `kls`'s interface hierarchy. 208 const dex::TypeList* interfaces = other_dex_file.GetInterfacesList(*kls.GetClassDef()); 209 if (interfaces != nullptr) { 210 for (size_t i = 0; i < interfaces->Size(); i++) { 211 dex::TypeIndex idx = interfaces->GetTypeItem(i).type_idx_; 212 VeriClass* itf = resolver->GetVeriClass(idx); 213 if (itf != nullptr) { 214 VeriField itf_field = resolver->LookupFieldIn(*itf, field_name, field_type); 215 if (itf_field != nullptr) { 216 return itf_field; 217 } 218 } 219 } 220 } 221 222 // Look at fields in `kls`'s super class hierarchy. 223 if (kls.GetClassDef()->superclass_idx_.IsValid()) { 224 VeriClass* super = resolver->GetVeriClass(kls.GetClassDef()->superclass_idx_); 225 if (super != nullptr) { 226 VeriField super_field = resolver->LookupFieldIn(*super, field_name, field_type); 227 if (super_field != nullptr) { 228 return super_field; 229 } 230 } 231 } 232 return nullptr; 233 } 234 235 VeriMethod VeridexResolver::LookupDeclaredMethodIn(const VeriClass& kls, 236 const char* method_name, 237 const char* type) const { 238 if (kls.IsPrimitive()) { 239 return nullptr; 240 } 241 if (kls.IsArray()) { 242 return nullptr; 243 } 244 VeridexResolver* resolver = GetResolverOf(kls); 245 const DexFile& other_dex_file = resolver->dex_file_; 246 ClassAccessor other_dex_accessor(other_dex_file, *kls.GetClassDef()); 247 for (const ClassAccessor::Method& method : other_dex_accessor.GetMethods()) { 248 if (HasSameNameAndSignature(other_dex_file, 249 other_dex_file.GetMethodId(method.GetIndex()), 250 method_name, 251 type)) { 252 return method.GetDataPointer(); 253 } 254 } 255 return nullptr; 256 } 257 258 VeriMethod VeridexResolver::GetMethod(uint32_t method_index) { 259 VeriMethod method_info = method_infos_[method_index]; 260 if (method_info == nullptr) { 261 // Method is defined in another dex file. 262 const dex::MethodId& method_id = dex_file_.GetMethodId(method_index); 263 VeriClass* kls = GetVeriClass(method_id.class_idx_); 264 if (kls == nullptr) { 265 return nullptr; 266 } 267 // Class found, now lookup the method in it. 268 method_info = LookupMethodIn(*kls, 269 dex_file_.GetMethodName(method_id), 270 dex_file_.GetMethodSignature(method_id)); 271 method_infos_[method_index] = method_info; 272 } 273 return method_info; 274 } 275 276 VeriField VeridexResolver::GetField(uint32_t field_index) { 277 VeriField field_info = field_infos_[field_index]; 278 if (field_info == nullptr) { 279 // Field is defined in another dex file. 280 const dex::FieldId& field_id = dex_file_.GetFieldId(field_index); 281 VeriClass* kls = GetVeriClass(field_id.class_idx_); 282 if (kls == nullptr) { 283 return nullptr; 284 } 285 // Class found, now lookup the field in it. 286 field_info = LookupFieldIn(*kls, 287 dex_file_.GetFieldName(field_id), 288 dex_file_.GetFieldTypeDescriptor(field_id)); 289 field_infos_[field_index] = field_info; 290 } 291 return field_info; 292 } 293 294 void VeridexResolver::ResolveAll() { 295 for (uint32_t i = 0; i < dex_file_.NumTypeIds(); ++i) { 296 if (GetVeriClass(dex::TypeIndex(i)) == nullptr) { 297 LOG(WARNING) << "Unresolved " << dex_file_.PrettyType(dex::TypeIndex(i)); 298 } 299 } 300 301 for (uint32_t i = 0; i < dex_file_.NumMethodIds(); ++i) { 302 if (GetMethod(i) == nullptr) { 303 LOG(WARNING) << "Unresolved: " << dex_file_.PrettyMethod(i); 304 } 305 } 306 307 for (uint32_t i = 0; i < dex_file_.NumFieldIds(); ++i) { 308 if (GetField(i) == nullptr) { 309 LOG(WARNING) << "Unresolved: " << dex_file_.PrettyField(i); 310 } 311 } 312 } 313 314 } // namespace art 315