1 /* 2 * Copyright (C) 2017 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 "class_loader_context.h" 18 19 #include <android-base/parseint.h> 20 #include <android-base/strings.h> 21 22 #include "art_field-inl.h" 23 #include "base/casts.h" 24 #include "base/dchecked_vector.h" 25 #include "base/stl_util.h" 26 #include "class_linker.h" 27 #include "class_loader_utils.h" 28 #include "class_root.h" 29 #include "dex/art_dex_file_loader.h" 30 #include "dex/dex_file.h" 31 #include "dex/dex_file_loader.h" 32 #include "handle_scope-inl.h" 33 #include "jni/jni_internal.h" 34 #include "mirror/class_loader-inl.h" 35 #include "mirror/object_array-alloc-inl.h" 36 #include "nativehelper/scoped_local_ref.h" 37 #include "oat_file_assistant.h" 38 #include "obj_ptr-inl.h" 39 #include "runtime.h" 40 #include "scoped_thread_state_change-inl.h" 41 #include "thread.h" 42 #include "well_known_classes.h" 43 44 namespace art { 45 46 static constexpr char kPathClassLoaderString[] = "PCL"; 47 static constexpr char kDelegateLastClassLoaderString[] = "DLC"; 48 static constexpr char kInMemoryDexClassLoaderString[] = "IMC"; 49 static constexpr char kClassLoaderOpeningMark = '['; 50 static constexpr char kClassLoaderClosingMark = ']'; 51 static constexpr char kClassLoaderSharedLibraryOpeningMark = '{'; 52 static constexpr char kClassLoaderSharedLibraryClosingMark = '}'; 53 static constexpr char kClassLoaderSharedLibrarySeparator = '#'; 54 static constexpr char kClassLoaderSeparator = ';'; 55 static constexpr char kClasspathSeparator = ':'; 56 static constexpr char kDexFileChecksumSeparator = '*'; 57 static constexpr char kInMemoryDexClassLoaderDexLocationMagic[] = "<unknown>"; 58 59 ClassLoaderContext::ClassLoaderContext() 60 : special_shared_library_(false), 61 dex_files_open_attempted_(false), 62 dex_files_open_result_(false), 63 owns_the_dex_files_(true) {} 64 65 ClassLoaderContext::ClassLoaderContext(bool owns_the_dex_files) 66 : special_shared_library_(false), 67 dex_files_open_attempted_(true), 68 dex_files_open_result_(true), 69 owns_the_dex_files_(owns_the_dex_files) {} 70 71 // Utility method to add parent and shared libraries of `info` into 72 // the `work_list`. 73 static void AddToWorkList( 74 ClassLoaderContext::ClassLoaderInfo* info, 75 std::vector<ClassLoaderContext::ClassLoaderInfo*>& work_list) { 76 if (info->parent != nullptr) { 77 work_list.push_back(info->parent.get()); 78 } 79 for (size_t i = 0; i < info->shared_libraries.size(); ++i) { 80 work_list.push_back(info->shared_libraries[i].get()); 81 } 82 } 83 84 ClassLoaderContext::~ClassLoaderContext() { 85 if (!owns_the_dex_files_ && class_loader_chain_ != nullptr) { 86 // If the context does not own the dex/oat files release the unique pointers to 87 // make sure we do not de-allocate them. 88 std::vector<ClassLoaderInfo*> work_list; 89 work_list.push_back(class_loader_chain_.get()); 90 while (!work_list.empty()) { 91 ClassLoaderInfo* info = work_list.back(); 92 work_list.pop_back(); 93 for (std::unique_ptr<OatFile>& oat_file : info->opened_oat_files) { 94 oat_file.release(); // NOLINT b/117926937 95 } 96 for (std::unique_ptr<const DexFile>& dex_file : info->opened_dex_files) { 97 dex_file.release(); // NOLINT b/117926937 98 } 99 AddToWorkList(info, work_list); 100 } 101 } 102 } 103 104 std::unique_ptr<ClassLoaderContext> ClassLoaderContext::Default() { 105 return Create(""); 106 } 107 108 std::unique_ptr<ClassLoaderContext> ClassLoaderContext::Create(const std::string& spec) { 109 std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext()); 110 if (result->Parse(spec)) { 111 return result; 112 } else { 113 return nullptr; 114 } 115 } 116 117 static size_t FindMatchingSharedLibraryCloseMarker(const std::string& spec, 118 size_t shared_library_open_index) { 119 // Counter of opened shared library marker we've encountered so far. 120 uint32_t counter = 1; 121 // The index at which we're operating in the loop. 122 uint32_t string_index = shared_library_open_index + 1; 123 size_t shared_library_close = std::string::npos; 124 while (counter != 0) { 125 shared_library_close = 126 spec.find_first_of(kClassLoaderSharedLibraryClosingMark, string_index); 127 size_t shared_library_open = 128 spec.find_first_of(kClassLoaderSharedLibraryOpeningMark, string_index); 129 if (shared_library_close == std::string::npos) { 130 // No matching closing marker. Return an error. 131 break; 132 } 133 134 if ((shared_library_open == std::string::npos) || 135 (shared_library_close < shared_library_open)) { 136 // We have seen a closing marker. Decrement the counter. 137 --counter; 138 // Move the search index forward. 139 string_index = shared_library_close + 1; 140 } else { 141 // New nested opening marker. Increment the counter and move the search 142 // index after the marker. 143 ++counter; 144 string_index = shared_library_open + 1; 145 } 146 } 147 return shared_library_close; 148 } 149 150 // The expected format is: 151 // "ClassLoaderType1[ClasspathElem1*Checksum1:ClasspathElem2*Checksum2...]{ClassLoaderType2[...]}". 152 // The checksum part of the format is expected only if parse_cheksums is true. 153 std::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseClassLoaderSpec( 154 const std::string& class_loader_spec, 155 bool parse_checksums) { 156 ClassLoaderType class_loader_type = ExtractClassLoaderType(class_loader_spec); 157 if (class_loader_type == kInvalidClassLoader) { 158 return nullptr; 159 } 160 161 // InMemoryDexClassLoader's dex location is always bogus. Special-case it. 162 if (class_loader_type == kInMemoryDexClassLoader) { 163 if (parse_checksums) { 164 // Make sure that OpenDexFiles() will never be attempted on this context 165 // because the dex locations of IMC do not correspond to real files. 166 CHECK(!dex_files_open_attempted_ || !dex_files_open_result_) 167 << "Parsing spec not supported when context created from a ClassLoader object"; 168 dex_files_open_attempted_ = true; 169 dex_files_open_result_ = false; 170 } else { 171 // Checksums are not provided and dex locations themselves have no meaning 172 // (although we keep them in the spec to simplify parsing). Treat this as 173 // an unknown class loader. 174 // We can hit this case if dex2oat is invoked with a spec containing IMC. 175 // Because the dex file data is only available at runtime, we cannot proceed. 176 return nullptr; 177 } 178 } 179 180 const char* class_loader_type_str = GetClassLoaderTypeName(class_loader_type); 181 size_t type_str_size = strlen(class_loader_type_str); 182 183 CHECK_EQ(0, class_loader_spec.compare(0, type_str_size, class_loader_type_str)); 184 185 // Check the opening and closing markers. 186 if (class_loader_spec[type_str_size] != kClassLoaderOpeningMark) { 187 return nullptr; 188 } 189 if ((class_loader_spec[class_loader_spec.length() - 1] != kClassLoaderClosingMark) && 190 (class_loader_spec[class_loader_spec.length() - 1] != kClassLoaderSharedLibraryClosingMark)) { 191 return nullptr; 192 } 193 194 size_t closing_index = class_loader_spec.find_first_of(kClassLoaderClosingMark); 195 196 // At this point we know the format is ok; continue and extract the classpath. 197 // Note that class loaders with an empty class path are allowed. 198 std::string classpath = class_loader_spec.substr(type_str_size + 1, 199 closing_index - type_str_size - 1); 200 201 std::unique_ptr<ClassLoaderInfo> info(new ClassLoaderInfo(class_loader_type)); 202 203 if (!parse_checksums) { 204 DCHECK(class_loader_type != kInMemoryDexClassLoader); 205 Split(classpath, kClasspathSeparator, &info->classpath); 206 } else { 207 std::vector<std::string> classpath_elements; 208 Split(classpath, kClasspathSeparator, &classpath_elements); 209 for (const std::string& element : classpath_elements) { 210 std::vector<std::string> dex_file_with_checksum; 211 Split(element, kDexFileChecksumSeparator, &dex_file_with_checksum); 212 if (dex_file_with_checksum.size() != 2) { 213 return nullptr; 214 } 215 uint32_t checksum = 0; 216 if (!android::base::ParseUint(dex_file_with_checksum[1].c_str(), &checksum)) { 217 return nullptr; 218 } 219 if ((class_loader_type == kInMemoryDexClassLoader) && 220 (dex_file_with_checksum[0] != kInMemoryDexClassLoaderDexLocationMagic)) { 221 return nullptr; 222 } 223 224 info->classpath.push_back(dex_file_with_checksum[0]); 225 info->checksums.push_back(checksum); 226 } 227 } 228 229 if ((class_loader_spec[class_loader_spec.length() - 1] == kClassLoaderSharedLibraryClosingMark) && 230 (class_loader_spec[class_loader_spec.length() - 2] != kClassLoaderSharedLibraryOpeningMark)) { 231 // Non-empty list of shared libraries. 232 size_t start_index = class_loader_spec.find_first_of(kClassLoaderSharedLibraryOpeningMark); 233 if (start_index == std::string::npos) { 234 return nullptr; 235 } 236 std::string shared_libraries_spec = 237 class_loader_spec.substr(start_index + 1, class_loader_spec.length() - start_index - 2); 238 std::vector<std::string> shared_libraries; 239 size_t cursor = 0; 240 while (cursor != shared_libraries_spec.length()) { 241 size_t shared_library_separator = 242 shared_libraries_spec.find_first_of(kClassLoaderSharedLibrarySeparator, cursor); 243 size_t shared_library_open = 244 shared_libraries_spec.find_first_of(kClassLoaderSharedLibraryOpeningMark, cursor); 245 std::string shared_library_spec; 246 if (shared_library_separator == std::string::npos) { 247 // Only one shared library, for example: 248 // PCL[...] 249 shared_library_spec = 250 shared_libraries_spec.substr(cursor, shared_libraries_spec.length() - cursor); 251 cursor = shared_libraries_spec.length(); 252 } else if ((shared_library_open == std::string::npos) || 253 (shared_library_open > shared_library_separator)) { 254 // We found a shared library without nested shared libraries, for example: 255 // PCL[...]#PCL[...]{...} 256 shared_library_spec = 257 shared_libraries_spec.substr(cursor, shared_library_separator - cursor); 258 cursor = shared_library_separator + 1; 259 } else { 260 // The shared library contains nested shared libraries. Find the matching closing shared 261 // marker for it. 262 size_t closing_marker = 263 FindMatchingSharedLibraryCloseMarker(shared_libraries_spec, shared_library_open); 264 if (closing_marker == std::string::npos) { 265 // No matching closing marker, return an error. 266 return nullptr; 267 } 268 shared_library_spec = shared_libraries_spec.substr(cursor, closing_marker + 1 - cursor); 269 cursor = closing_marker + 1; 270 if (cursor != shared_libraries_spec.length() && 271 shared_libraries_spec[cursor] == kClassLoaderSharedLibrarySeparator) { 272 // Pass the shared library separator marker. 273 ++cursor; 274 } 275 } 276 std::unique_ptr<ClassLoaderInfo> shared_library( 277 ParseInternal(shared_library_spec, parse_checksums)); 278 if (shared_library == nullptr) { 279 return nullptr; 280 } 281 info->shared_libraries.push_back(std::move(shared_library)); 282 } 283 } 284 285 return info; 286 } 287 288 // Extracts the class loader type from the given spec. 289 // Return ClassLoaderContext::kInvalidClassLoader if the class loader type is not 290 // recognized. 291 ClassLoaderContext::ClassLoaderType 292 ClassLoaderContext::ExtractClassLoaderType(const std::string& class_loader_spec) { 293 const ClassLoaderType kValidTypes[] = { kPathClassLoader, 294 kDelegateLastClassLoader, 295 kInMemoryDexClassLoader }; 296 for (const ClassLoaderType& type : kValidTypes) { 297 const char* type_str = GetClassLoaderTypeName(type); 298 if (class_loader_spec.compare(0, strlen(type_str), type_str) == 0) { 299 return type; 300 } 301 } 302 return kInvalidClassLoader; 303 } 304 305 // The format: ClassLoaderType1[ClasspathElem1:ClasspathElem2...];ClassLoaderType2[...]... 306 // ClassLoaderType is either "PCL" (PathClassLoader) or "DLC" (DelegateLastClassLoader). 307 // ClasspathElem is the path of dex/jar/apk file. 308 bool ClassLoaderContext::Parse(const std::string& spec, bool parse_checksums) { 309 if (spec.empty()) { 310 // By default we load the dex files in a PathClassLoader. 311 // So an empty spec is equivalent to an empty PathClassLoader (this happens when running 312 // tests) 313 class_loader_chain_.reset(new ClassLoaderInfo(kPathClassLoader)); 314 return true; 315 } 316 317 // Stop early if we detect the special shared library, which may be passed as the classpath 318 // for dex2oat when we want to skip the shared libraries check. 319 if (spec == OatFile::kSpecialSharedLibrary) { 320 LOG(INFO) << "The ClassLoaderContext is a special shared library."; 321 special_shared_library_ = true; 322 return true; 323 } 324 325 CHECK(class_loader_chain_ == nullptr); 326 class_loader_chain_.reset(ParseInternal(spec, parse_checksums)); 327 return class_loader_chain_ != nullptr; 328 } 329 330 ClassLoaderContext::ClassLoaderInfo* ClassLoaderContext::ParseInternal( 331 const std::string& spec, bool parse_checksums) { 332 CHECK(!spec.empty()); 333 CHECK_NE(spec, OatFile::kSpecialSharedLibrary); 334 std::string remaining = spec; 335 std::unique_ptr<ClassLoaderInfo> first(nullptr); 336 ClassLoaderInfo* previous_iteration = nullptr; 337 while (!remaining.empty()) { 338 std::string class_loader_spec; 339 size_t first_class_loader_separator = remaining.find_first_of(kClassLoaderSeparator); 340 size_t first_shared_library_open = 341 remaining.find_first_of(kClassLoaderSharedLibraryOpeningMark); 342 if (first_class_loader_separator == std::string::npos) { 343 // Only one class loader, for example: 344 // PCL[...] 345 class_loader_spec = remaining; 346 remaining = ""; 347 } else if ((first_shared_library_open == std::string::npos) || 348 (first_shared_library_open > first_class_loader_separator)) { 349 // We found a class loader spec without shared libraries, for example: 350 // PCL[...];PCL[...]{...} 351 class_loader_spec = remaining.substr(0, first_class_loader_separator); 352 remaining = remaining.substr(first_class_loader_separator + 1, 353 remaining.size() - first_class_loader_separator - 1); 354 } else { 355 // The class loader spec contains shared libraries. Find the matching closing 356 // shared library marker for it. 357 358 uint32_t shared_library_close = 359 FindMatchingSharedLibraryCloseMarker(remaining, first_shared_library_open); 360 if (shared_library_close == std::string::npos) { 361 LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec; 362 return nullptr; 363 } 364 class_loader_spec = remaining.substr(0, shared_library_close + 1); 365 366 // Compute the remaining string to analyze. 367 if (remaining.size() == shared_library_close + 1) { 368 remaining = ""; 369 } else if ((remaining.size() == shared_library_close + 2) || 370 (remaining.at(shared_library_close + 1) != kClassLoaderSeparator)) { 371 LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec; 372 return nullptr; 373 } else { 374 remaining = remaining.substr(shared_library_close + 2, 375 remaining.size() - shared_library_close - 2); 376 } 377 } 378 379 std::unique_ptr<ClassLoaderInfo> info = 380 ParseClassLoaderSpec(class_loader_spec, parse_checksums); 381 if (info == nullptr) { 382 LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec; 383 return nullptr; 384 } 385 if (first == nullptr) { 386 first = std::move(info); 387 previous_iteration = first.get(); 388 } else { 389 CHECK(previous_iteration != nullptr); 390 previous_iteration->parent = std::move(info); 391 previous_iteration = previous_iteration->parent.get(); 392 } 393 } 394 return first.release(); 395 } 396 397 // Opens requested class path files and appends them to opened_dex_files. If the dex files have 398 // been stripped, this opens them from their oat files (which get added to opened_oat_files). 399 bool ClassLoaderContext::OpenDexFiles(InstructionSet isa, 400 const std::string& classpath_dir, 401 const std::vector<int>& fds) { 402 if (dex_files_open_attempted_) { 403 // Do not attempt to re-open the files if we already tried. 404 return dex_files_open_result_; 405 } 406 407 dex_files_open_attempted_ = true; 408 // Assume we can open all dex files. If not, we will set this to false as we go. 409 dex_files_open_result_ = true; 410 411 if (special_shared_library_) { 412 // Nothing to open if the context is a special shared library. 413 return true; 414 } 415 416 // Note that we try to open all dex files even if some fail. 417 // We may get resource-only apks which we cannot load. 418 // TODO(calin): Refine the dex opening interface to be able to tell if an archive contains 419 // no dex files. So that we can distinguish the real failures... 420 const ArtDexFileLoader dex_file_loader; 421 std::vector<ClassLoaderInfo*> work_list; 422 CHECK(class_loader_chain_ != nullptr); 423 work_list.push_back(class_loader_chain_.get()); 424 size_t dex_file_index = 0; 425 while (!work_list.empty()) { 426 ClassLoaderInfo* info = work_list.back(); 427 work_list.pop_back(); 428 DCHECK(info->type != kInMemoryDexClassLoader) << __FUNCTION__ << " not supported for IMC"; 429 430 size_t opened_dex_files_index = info->opened_dex_files.size(); 431 for (const std::string& cp_elem : info->classpath) { 432 // If path is relative, append it to the provided base directory. 433 std::string location = cp_elem; 434 if (location[0] != '/' && !classpath_dir.empty()) { 435 location = classpath_dir + (classpath_dir.back() == '/' ? "" : "/") + location; 436 } 437 438 // If file descriptors were provided for the class loader context dex paths, 439 // get the descriptor which correponds to this dex path. We assume the `fds` 440 // vector follows the same order as a flattened class loader context. 441 int fd = -1; 442 if (!fds.empty()) { 443 if (dex_file_index >= fds.size()) { 444 LOG(WARNING) << "Number of FDs is smaller than number of dex files in the context"; 445 dex_files_open_result_ = false; 446 return false; 447 } 448 449 fd = fds[dex_file_index++]; 450 DCHECK_GE(fd, 0); 451 } 452 453 std::string error_msg; 454 // When opening the dex files from the context we expect their checksum to match their 455 // contents. So pass true to verify_checksum. 456 if (fd < 0) { 457 if (!dex_file_loader.Open(location.c_str(), 458 location.c_str(), 459 Runtime::Current()->IsVerificationEnabled(), 460 /*verify_checksum=*/ true, 461 &error_msg, 462 &info->opened_dex_files)) { 463 // If we fail to open the dex file because it's been stripped, try to 464 // open the dex file from its corresponding oat file. 465 // This could happen when we need to recompile a pre-build whose dex 466 // code has been stripped (for example, if the pre-build is only 467 // quicken and we want to re-compile it speed-profile). 468 // TODO(calin): Use the vdex directly instead of going through the oat file. 469 OatFileAssistant oat_file_assistant(location.c_str(), isa, false); 470 std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile()); 471 std::vector<std::unique_ptr<const DexFile>> oat_dex_files; 472 if (oat_file != nullptr && 473 OatFileAssistant::LoadDexFiles(*oat_file, location, &oat_dex_files)) { 474 info->opened_oat_files.push_back(std::move(oat_file)); 475 info->opened_dex_files.insert(info->opened_dex_files.end(), 476 std::make_move_iterator(oat_dex_files.begin()), 477 std::make_move_iterator(oat_dex_files.end())); 478 } else { 479 LOG(WARNING) << "Could not open dex files from location: " << location; 480 dex_files_open_result_ = false; 481 } 482 } 483 } else if (!dex_file_loader.Open(fd, 484 location.c_str(), 485 Runtime::Current()->IsVerificationEnabled(), 486 /*verify_checksum=*/ true, 487 &error_msg, 488 &info->opened_dex_files)) { 489 LOG(WARNING) << "Could not open dex files from fd " << fd << " for location: " << location; 490 dex_files_open_result_ = false; 491 } 492 } 493 494 // We finished opening the dex files from the classpath. 495 // Now update the classpath and the checksum with the locations of the dex files. 496 // 497 // We do this because initially the classpath contains the paths of the dex files; and 498 // some of them might be multi-dexes. So in order to have a consistent view we replace all the 499 // file paths with the actual dex locations being loaded. 500 // This will allow the context to VerifyClassLoaderContextMatch which expects or multidex 501 // location in the class paths. 502 // Note that this will also remove the paths that could not be opened. 503 info->original_classpath = std::move(info->classpath); 504 info->classpath.clear(); 505 info->checksums.clear(); 506 for (size_t k = opened_dex_files_index; k < info->opened_dex_files.size(); k++) { 507 std::unique_ptr<const DexFile>& dex = info->opened_dex_files[k]; 508 info->classpath.push_back(dex->GetLocation()); 509 info->checksums.push_back(dex->GetLocationChecksum()); 510 } 511 AddToWorkList(info, work_list); 512 } 513 514 // Check that if file descriptors were provided, there were exactly as many 515 // as we have encountered while iterating over this class loader context. 516 if (dex_file_index != fds.size()) { 517 LOG(WARNING) << fds.size() << " FDs provided but only " << dex_file_index 518 << " dex files are in the class loader context"; 519 dex_files_open_result_ = false; 520 } 521 522 return dex_files_open_result_; 523 } 524 525 bool ClassLoaderContext::RemoveLocationsFromClassPaths( 526 const dchecked_vector<std::string>& locations) { 527 CHECK(!dex_files_open_attempted_) 528 << "RemoveLocationsFromClasspaths cannot be call after OpenDexFiles"; 529 530 if (class_loader_chain_ == nullptr) { 531 return false; 532 } 533 534 std::set<std::string> canonical_locations; 535 for (const std::string& location : locations) { 536 canonical_locations.insert(DexFileLoader::GetDexCanonicalLocation(location.c_str())); 537 } 538 bool removed_locations = false; 539 std::vector<ClassLoaderInfo*> work_list; 540 work_list.push_back(class_loader_chain_.get()); 541 while (!work_list.empty()) { 542 ClassLoaderInfo* info = work_list.back(); 543 work_list.pop_back(); 544 size_t initial_size = info->classpath.size(); 545 auto kept_it = std::remove_if( 546 info->classpath.begin(), 547 info->classpath.end(), 548 [canonical_locations](const std::string& location) { 549 return ContainsElement(canonical_locations, 550 DexFileLoader::GetDexCanonicalLocation(location.c_str())); 551 }); 552 info->classpath.erase(kept_it, info->classpath.end()); 553 if (initial_size != info->classpath.size()) { 554 removed_locations = true; 555 } 556 AddToWorkList(info, work_list); 557 } 558 return removed_locations; 559 } 560 561 std::string ClassLoaderContext::EncodeContextForDex2oat(const std::string& base_dir) const { 562 return EncodeContext(base_dir, /*for_dex2oat=*/ true, /*stored_context=*/ nullptr); 563 } 564 565 std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_dir, 566 ClassLoaderContext* stored_context) const { 567 return EncodeContext(base_dir, /*for_dex2oat=*/ false, stored_context); 568 } 569 570 std::string ClassLoaderContext::EncodeContext(const std::string& base_dir, 571 bool for_dex2oat, 572 ClassLoaderContext* stored_context) const { 573 CheckDexFilesOpened("EncodeContextForOatFile"); 574 if (special_shared_library_) { 575 return OatFile::kSpecialSharedLibrary; 576 } 577 578 if (stored_context != nullptr) { 579 DCHECK_EQ(GetParentChainSize(), stored_context->GetParentChainSize()); 580 } 581 582 std::ostringstream out; 583 if (class_loader_chain_ == nullptr) { 584 // We can get in this situation if the context was created with a class path containing the 585 // source dex files which were later removed (happens during run-tests). 586 out << GetClassLoaderTypeName(kPathClassLoader) 587 << kClassLoaderOpeningMark 588 << kClassLoaderClosingMark; 589 return out.str(); 590 } 591 592 EncodeContextInternal( 593 *class_loader_chain_, 594 base_dir, 595 for_dex2oat, 596 (stored_context == nullptr ? nullptr : stored_context->class_loader_chain_.get()), 597 out); 598 return out.str(); 599 } 600 601 void ClassLoaderContext::EncodeContextInternal(const ClassLoaderInfo& info, 602 const std::string& base_dir, 603 bool for_dex2oat, 604 ClassLoaderInfo* stored_info, 605 std::ostringstream& out) const { 606 out << GetClassLoaderTypeName(info.type); 607 out << kClassLoaderOpeningMark; 608 std::set<std::string> seen_locations; 609 SafeMap<std::string, std::string> remap; 610 if (stored_info != nullptr) { 611 for (size_t k = 0; k < info.original_classpath.size(); ++k) { 612 // Note that we don't care if the same name appears twice. 613 remap.Put(info.original_classpath[k], stored_info->classpath[k]); 614 } 615 } 616 for (size_t k = 0; k < info.opened_dex_files.size(); k++) { 617 const std::unique_ptr<const DexFile>& dex_file = info.opened_dex_files[k]; 618 if (for_dex2oat) { 619 // dex2oat only needs the base location. It cannot accept multidex locations. 620 // So ensure we only add each file once. 621 bool new_insert = seen_locations.insert( 622 DexFileLoader::GetBaseLocation(dex_file->GetLocation())).second; 623 if (!new_insert) { 624 continue; 625 } 626 } 627 std::string location = dex_file->GetLocation(); 628 // If there is a stored class loader remap, fix up the multidex strings. 629 if (!remap.empty()) { 630 std::string base_dex_location = DexFileLoader::GetBaseLocation(location); 631 auto it = remap.find(base_dex_location); 632 CHECK(it != remap.end()) << base_dex_location; 633 location = it->second + DexFileLoader::GetMultiDexSuffix(location); 634 } 635 if (k > 0) { 636 out << kClasspathSeparator; 637 } 638 if (info.type == kInMemoryDexClassLoader) { 639 out << kInMemoryDexClassLoaderDexLocationMagic; 640 } else if (!base_dir.empty() && location.substr(0, base_dir.length()) == base_dir) { 641 // Find paths that were relative and convert them back from absolute. 642 out << location.substr(base_dir.length() + 1).c_str(); 643 } else { 644 out << location.c_str(); 645 } 646 // dex2oat does not need the checksums. 647 if (!for_dex2oat) { 648 out << kDexFileChecksumSeparator; 649 out << dex_file->GetLocationChecksum(); 650 } 651 } 652 out << kClassLoaderClosingMark; 653 654 if (!info.shared_libraries.empty()) { 655 out << kClassLoaderSharedLibraryOpeningMark; 656 for (uint32_t i = 0; i < info.shared_libraries.size(); ++i) { 657 if (i > 0) { 658 out << kClassLoaderSharedLibrarySeparator; 659 } 660 EncodeContextInternal( 661 *info.shared_libraries[i].get(), 662 base_dir, 663 for_dex2oat, 664 (stored_info == nullptr ? nullptr : stored_info->shared_libraries[i].get()), 665 out); 666 } 667 out << kClassLoaderSharedLibraryClosingMark; 668 } 669 if (info.parent != nullptr) { 670 out << kClassLoaderSeparator; 671 EncodeContextInternal( 672 *info.parent.get(), 673 base_dir, 674 for_dex2oat, 675 (stored_info == nullptr ? nullptr : stored_info->parent.get()), 676 out); 677 } 678 } 679 680 // Returns the WellKnownClass for the given class loader type. 681 static jclass GetClassLoaderClass(ClassLoaderContext::ClassLoaderType type) { 682 switch (type) { 683 case ClassLoaderContext::kPathClassLoader: 684 return WellKnownClasses::dalvik_system_PathClassLoader; 685 case ClassLoaderContext::kDelegateLastClassLoader: 686 return WellKnownClasses::dalvik_system_DelegateLastClassLoader; 687 case ClassLoaderContext::kInMemoryDexClassLoader: 688 return WellKnownClasses::dalvik_system_InMemoryDexClassLoader; 689 case ClassLoaderContext::kInvalidClassLoader: break; // will fail after the switch. 690 } 691 LOG(FATAL) << "Invalid class loader type " << type; 692 UNREACHABLE(); 693 } 694 695 static std::string FlattenClasspath(const std::vector<std::string>& classpath) { 696 return android::base::Join(classpath, ':'); 697 } 698 699 static ObjPtr<mirror::ClassLoader> CreateClassLoaderInternal( 700 Thread* self, 701 ScopedObjectAccess& soa, 702 const ClassLoaderContext::ClassLoaderInfo& info, 703 bool for_shared_library, 704 VariableSizedHandleScope& map_scope, 705 std::map<std::string, Handle<mirror::ClassLoader>>& canonicalized_libraries, 706 bool add_compilation_sources, 707 const std::vector<const DexFile*>& compilation_sources) 708 REQUIRES_SHARED(Locks::mutator_lock_) { 709 if (for_shared_library) { 710 // Check if the shared library has already been created. 711 auto search = canonicalized_libraries.find(FlattenClasspath(info.classpath)); 712 if (search != canonicalized_libraries.end()) { 713 return search->second.Get(); 714 } 715 } 716 717 StackHandleScope<3> hs(self); 718 MutableHandle<mirror::ObjectArray<mirror::ClassLoader>> libraries( 719 hs.NewHandle<mirror::ObjectArray<mirror::ClassLoader>>(nullptr)); 720 721 if (!info.shared_libraries.empty()) { 722 libraries.Assign(mirror::ObjectArray<mirror::ClassLoader>::Alloc( 723 self, 724 GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(), 725 info.shared_libraries.size())); 726 for (uint32_t i = 0; i < info.shared_libraries.size(); ++i) { 727 // We should only add the compilation sources to the first class loader. 728 libraries->Set(i, 729 CreateClassLoaderInternal( 730 self, 731 soa, 732 *info.shared_libraries[i].get(), 733 /* for_shared_library= */ true, 734 map_scope, 735 canonicalized_libraries, 736 /* add_compilation_sources= */ false, 737 compilation_sources)); 738 } 739 } 740 741 MutableHandle<mirror::ClassLoader> parent = hs.NewHandle<mirror::ClassLoader>(nullptr); 742 if (info.parent != nullptr) { 743 // We should only add the compilation sources to the first class loader. 744 parent.Assign(CreateClassLoaderInternal( 745 self, 746 soa, 747 *info.parent.get(), 748 /* for_shared_library= */ false, 749 map_scope, 750 canonicalized_libraries, 751 /* add_compilation_sources= */ false, 752 compilation_sources)); 753 } 754 std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector( 755 info.opened_dex_files); 756 if (add_compilation_sources) { 757 // For the first class loader, its classpath comes first, followed by compilation sources. 758 // This ensures that whenever we need to resolve classes from it the classpath elements 759 // come first. 760 class_path_files.insert(class_path_files.end(), 761 compilation_sources.begin(), 762 compilation_sources.end()); 763 } 764 Handle<mirror::Class> loader_class = hs.NewHandle<mirror::Class>( 765 soa.Decode<mirror::Class>(GetClassLoaderClass(info.type))); 766 ObjPtr<mirror::ClassLoader> loader = 767 Runtime::Current()->GetClassLinker()->CreateWellKnownClassLoader( 768 self, 769 class_path_files, 770 loader_class, 771 parent, 772 libraries); 773 if (for_shared_library) { 774 canonicalized_libraries[FlattenClasspath(info.classpath)] = 775 map_scope.NewHandle<mirror::ClassLoader>(loader); 776 } 777 return loader; 778 } 779 780 jobject ClassLoaderContext::CreateClassLoader( 781 const std::vector<const DexFile*>& compilation_sources) const { 782 CheckDexFilesOpened("CreateClassLoader"); 783 784 Thread* self = Thread::Current(); 785 ScopedObjectAccess soa(self); 786 787 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); 788 789 if (class_loader_chain_ == nullptr) { 790 CHECK(special_shared_library_); 791 return class_linker->CreatePathClassLoader(self, compilation_sources); 792 } 793 794 // Create a map of canonicalized shared libraries. As we're holding objects, 795 // we're creating a variable size handle scope to put handles in the map. 796 VariableSizedHandleScope map_scope(self); 797 std::map<std::string, Handle<mirror::ClassLoader>> canonicalized_libraries; 798 799 // Create the class loader. 800 ObjPtr<mirror::ClassLoader> loader = 801 CreateClassLoaderInternal(self, 802 soa, 803 *class_loader_chain_.get(), 804 /* for_shared_library= */ false, 805 map_scope, 806 canonicalized_libraries, 807 /* add_compilation_sources= */ true, 808 compilation_sources); 809 // Make it a global ref and return. 810 ScopedLocalRef<jobject> local_ref( 811 soa.Env(), soa.Env()->AddLocalReference<jobject>(loader)); 812 return soa.Env()->NewGlobalRef(local_ref.get()); 813 } 814 815 std::vector<const DexFile*> ClassLoaderContext::FlattenOpenedDexFiles() const { 816 CheckDexFilesOpened("FlattenOpenedDexFiles"); 817 818 std::vector<const DexFile*> result; 819 if (class_loader_chain_ == nullptr) { 820 return result; 821 } 822 std::vector<ClassLoaderInfo*> work_list; 823 work_list.push_back(class_loader_chain_.get()); 824 while (!work_list.empty()) { 825 ClassLoaderInfo* info = work_list.back(); 826 work_list.pop_back(); 827 for (const std::unique_ptr<const DexFile>& dex_file : info->opened_dex_files) { 828 result.push_back(dex_file.get()); 829 } 830 AddToWorkList(info, work_list); 831 } 832 return result; 833 } 834 835 std::string ClassLoaderContext::FlattenDexPaths() const { 836 if (class_loader_chain_ == nullptr) { 837 return ""; 838 } 839 840 std::vector<std::string> result; 841 std::vector<ClassLoaderInfo*> work_list; 842 work_list.push_back(class_loader_chain_.get()); 843 while (!work_list.empty()) { 844 ClassLoaderInfo* info = work_list.back(); 845 work_list.pop_back(); 846 for (const std::string& dex_path : info->classpath) { 847 result.push_back(dex_path); 848 } 849 AddToWorkList(info, work_list); 850 } 851 return FlattenClasspath(result); 852 } 853 854 const char* ClassLoaderContext::GetClassLoaderTypeName(ClassLoaderType type) { 855 switch (type) { 856 case kPathClassLoader: return kPathClassLoaderString; 857 case kDelegateLastClassLoader: return kDelegateLastClassLoaderString; 858 case kInMemoryDexClassLoader: return kInMemoryDexClassLoaderString; 859 default: 860 LOG(FATAL) << "Invalid class loader type " << type; 861 UNREACHABLE(); 862 } 863 } 864 865 void ClassLoaderContext::CheckDexFilesOpened(const std::string& calling_method) const { 866 CHECK(dex_files_open_attempted_) 867 << "Dex files were not successfully opened before the call to " << calling_method 868 << "attempt=" << dex_files_open_attempted_ << ", result=" << dex_files_open_result_; 869 } 870 871 // Collects the dex files from the give Java dex_file object. Only the dex files with 872 // at least 1 class are collected. If a null java_dex_file is passed this method does nothing. 873 static bool CollectDexFilesFromJavaDexFile(ObjPtr<mirror::Object> java_dex_file, 874 ArtField* const cookie_field, 875 std::vector<const DexFile*>* out_dex_files) 876 REQUIRES_SHARED(Locks::mutator_lock_) { 877 if (java_dex_file == nullptr) { 878 return true; 879 } 880 // On the Java side, the dex files are stored in the cookie field. 881 ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(java_dex_file)->AsLongArray(); 882 if (long_array == nullptr) { 883 // This should never happen so log a warning. 884 LOG(ERROR) << "Unexpected null cookie"; 885 return false; 886 } 887 int32_t long_array_size = long_array->GetLength(); 888 // Index 0 from the long array stores the oat file. The dex files start at index 1. 889 for (int32_t j = 1; j < long_array_size; ++j) { 890 const DexFile* cp_dex_file = 891 reinterpret_cast64<const DexFile*>(long_array->GetWithoutChecks(j)); 892 if (cp_dex_file != nullptr && cp_dex_file->NumClassDefs() > 0) { 893 // TODO(calin): It's unclear why the dex files with no classes are skipped here and when 894 // cp_dex_file can be null. 895 out_dex_files->push_back(cp_dex_file); 896 } 897 } 898 return true; 899 } 900 901 // Collects all the dex files loaded by the given class loader. 902 // Returns true for success or false if an unexpected state is discovered (e.g. a null dex cookie, 903 // a null list of dex elements or a null dex element). 904 static bool CollectDexFilesFromSupportedClassLoader(ScopedObjectAccessAlreadyRunnable& soa, 905 Handle<mirror::ClassLoader> class_loader, 906 std::vector<const DexFile*>* out_dex_files) 907 REQUIRES_SHARED(Locks::mutator_lock_) { 908 CHECK(IsPathOrDexClassLoader(soa, class_loader) || 909 IsDelegateLastClassLoader(soa, class_loader) || 910 IsInMemoryDexClassLoader(soa, class_loader)); 911 912 // All supported class loaders inherit from BaseDexClassLoader. 913 // We need to get the DexPathList and loop through it. 914 ArtField* const cookie_field = 915 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie); 916 ArtField* const dex_file_field = 917 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); 918 ObjPtr<mirror::Object> dex_path_list = 919 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)-> 920 GetObject(class_loader.Get()); 921 CHECK(cookie_field != nullptr); 922 CHECK(dex_file_field != nullptr); 923 if (dex_path_list == nullptr) { 924 // This may be null if the current class loader is under construction and it does not 925 // have its fields setup yet. 926 return true; 927 } 928 // DexPathList has an array dexElements of Elements[] which each contain a dex file. 929 ObjPtr<mirror::Object> dex_elements_obj = 930 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> 931 GetObject(dex_path_list); 932 // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look 933 // at the mCookie which is a DexFile vector. 934 if (dex_elements_obj == nullptr) { 935 // TODO(calin): It's unclear if we should just assert here. For now be prepared for the worse 936 // and assume we have no elements. 937 return true; 938 } else { 939 StackHandleScope<1> hs(soa.Self()); 940 Handle<mirror::ObjectArray<mirror::Object>> dex_elements( 941 hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>())); 942 for (int32_t i = 0; i < dex_elements->GetLength(); ++i) { 943 ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i); 944 if (element == nullptr) { 945 // Should never happen, log an error and break. 946 // TODO(calin): It's unclear if we should just assert here. 947 // This code was propagated to oat_file_manager from the class linker where it would 948 // throw a NPE. For now, return false which will mark this class loader as unsupported. 949 LOG(ERROR) << "Unexpected null in the dex element list"; 950 return false; 951 } 952 ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element); 953 if (!CollectDexFilesFromJavaDexFile(dex_file, cookie_field, out_dex_files)) { 954 return false; 955 } 956 } 957 } 958 959 return true; 960 } 961 962 static bool GetDexFilesFromDexElementsArray( 963 ScopedObjectAccessAlreadyRunnable& soa, 964 Handle<mirror::ObjectArray<mirror::Object>> dex_elements, 965 std::vector<const DexFile*>* out_dex_files) REQUIRES_SHARED(Locks::mutator_lock_) { 966 DCHECK(dex_elements != nullptr); 967 968 ArtField* const cookie_field = 969 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie); 970 ArtField* const dex_file_field = 971 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); 972 const ObjPtr<mirror::Class> element_class = soa.Decode<mirror::Class>( 973 WellKnownClasses::dalvik_system_DexPathList__Element); 974 const ObjPtr<mirror::Class> dexfile_class = soa.Decode<mirror::Class>( 975 WellKnownClasses::dalvik_system_DexFile); 976 977 for (int32_t i = 0; i < dex_elements->GetLength(); ++i) { 978 ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i); 979 // We can hit a null element here because this is invoked with a partially filled dex_elements 980 // array from DexPathList. DexPathList will open each dex sequentially, each time passing the 981 // list of dex files which were opened before. 982 if (element == nullptr) { 983 continue; 984 } 985 986 // We support this being dalvik.system.DexPathList$Element and dalvik.system.DexFile. 987 // TODO(calin): Code caried over oat_file_manager: supporting both classes seem to be 988 // a historical glitch. All the java code opens dex files using an array of Elements. 989 ObjPtr<mirror::Object> dex_file; 990 if (element_class == element->GetClass()) { 991 dex_file = dex_file_field->GetObject(element); 992 } else if (dexfile_class == element->GetClass()) { 993 dex_file = element; 994 } else { 995 LOG(ERROR) << "Unsupported element in dex_elements: " 996 << mirror::Class::PrettyClass(element->GetClass()); 997 return false; 998 } 999 1000 if (!CollectDexFilesFromJavaDexFile(dex_file, cookie_field, out_dex_files)) { 1001 return false; 1002 } 1003 } 1004 return true; 1005 } 1006 1007 // Adds the `class_loader` info to the `context`. 1008 // The dex file present in `dex_elements` array (if not null) will be added at the end of 1009 // the classpath. 1010 // This method is recursive (w.r.t. the class loader parent) and will stop once it reaches the 1011 // BootClassLoader. Note that the class loader chain is expected to be short. 1012 bool ClassLoaderContext::CreateInfoFromClassLoader( 1013 ScopedObjectAccessAlreadyRunnable& soa, 1014 Handle<mirror::ClassLoader> class_loader, 1015 Handle<mirror::ObjectArray<mirror::Object>> dex_elements, 1016 ClassLoaderInfo* child_info, 1017 bool is_shared_library) 1018 REQUIRES_SHARED(Locks::mutator_lock_) { 1019 if (ClassLinker::IsBootClassLoader(soa, class_loader.Get())) { 1020 // Nothing to do for the boot class loader as we don't add its dex files to the context. 1021 return true; 1022 } 1023 1024 ClassLoaderContext::ClassLoaderType type; 1025 if (IsPathOrDexClassLoader(soa, class_loader)) { 1026 type = kPathClassLoader; 1027 } else if (IsDelegateLastClassLoader(soa, class_loader)) { 1028 type = kDelegateLastClassLoader; 1029 } else if (IsInMemoryDexClassLoader(soa, class_loader)) { 1030 type = kInMemoryDexClassLoader; 1031 } else { 1032 LOG(WARNING) << "Unsupported class loader"; 1033 return false; 1034 } 1035 1036 // Inspect the class loader for its dex files. 1037 std::vector<const DexFile*> dex_files_loaded; 1038 CollectDexFilesFromSupportedClassLoader(soa, class_loader, &dex_files_loaded); 1039 1040 // If we have a dex_elements array extract its dex elements now. 1041 // This is used in two situations: 1042 // 1) when a new ClassLoader is created DexPathList will open each dex file sequentially 1043 // passing the list of already open dex files each time. This ensures that we see the 1044 // correct context even if the ClassLoader under construction is not fully build. 1045 // 2) when apk splits are loaded on the fly, the framework will load their dex files by 1046 // appending them to the current class loader. When the new code paths are loaded in 1047 // BaseDexClassLoader, the paths already present in the class loader will be passed 1048 // in the dex_elements array. 1049 if (dex_elements != nullptr) { 1050 GetDexFilesFromDexElementsArray(soa, dex_elements, &dex_files_loaded); 1051 } 1052 1053 ClassLoaderInfo* info = new ClassLoaderContext::ClassLoaderInfo(type); 1054 // Attach the `ClassLoaderInfo` now, before populating dex files, as only the 1055 // `ClassLoaderContext` knows whether these dex files should be deleted or not. 1056 if (child_info == nullptr) { 1057 class_loader_chain_.reset(info); 1058 } else if (is_shared_library) { 1059 child_info->shared_libraries.push_back(std::unique_ptr<ClassLoaderInfo>(info)); 1060 } else { 1061 child_info->parent.reset(info); 1062 } 1063 1064 // Now that `info` is in the chain, populate dex files. 1065 for (const DexFile* dex_file : dex_files_loaded) { 1066 // Dex location of dex files loaded with InMemoryDexClassLoader is always bogus. 1067 // Use a magic value for the classpath instead. 1068 info->classpath.push_back((type == kInMemoryDexClassLoader) 1069 ? kInMemoryDexClassLoaderDexLocationMagic 1070 : dex_file->GetLocation()); 1071 info->checksums.push_back(dex_file->GetLocationChecksum()); 1072 info->opened_dex_files.emplace_back(dex_file); 1073 } 1074 1075 // Note that dex_elements array is null here. The elements are considered to be part of the 1076 // current class loader and are not passed to the parents. 1077 ScopedNullHandle<mirror::ObjectArray<mirror::Object>> null_dex_elements; 1078 1079 // Add the shared libraries. 1080 StackHandleScope<3> hs(Thread::Current()); 1081 ArtField* field = 1082 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders); 1083 ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader.Get()); 1084 if (raw_shared_libraries != nullptr) { 1085 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries = 1086 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()); 1087 MutableHandle<mirror::ClassLoader> temp_loader = hs.NewHandle<mirror::ClassLoader>(nullptr); 1088 for (int32_t i = 0; i < shared_libraries->GetLength(); ++i) { 1089 temp_loader.Assign(shared_libraries->Get(i)); 1090 if (!CreateInfoFromClassLoader( 1091 soa, temp_loader, null_dex_elements, info, /*is_shared_library=*/ true)) { 1092 return false; 1093 } 1094 } 1095 } 1096 1097 // We created the ClassLoaderInfo for the current loader. Move on to its parent. 1098 Handle<mirror::ClassLoader> parent = hs.NewHandle(class_loader->GetParent()); 1099 if (!CreateInfoFromClassLoader( 1100 soa, parent, null_dex_elements, info, /*is_shared_library=*/ false)) { 1101 return false; 1102 } 1103 return true; 1104 } 1105 1106 std::unique_ptr<ClassLoaderContext> ClassLoaderContext::CreateContextForClassLoader( 1107 jobject class_loader, 1108 jobjectArray dex_elements) { 1109 CHECK(class_loader != nullptr); 1110 1111 ScopedObjectAccess soa(Thread::Current()); 1112 StackHandleScope<2> hs(soa.Self()); 1113 Handle<mirror::ClassLoader> h_class_loader = 1114 hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)); 1115 Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements = 1116 hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Object>>(dex_elements)); 1117 std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext(/*owns_the_dex_files=*/ false)); 1118 if (!result->CreateInfoFromClassLoader( 1119 soa, h_class_loader, h_dex_elements, nullptr, /*is_shared_library=*/ false)) { 1120 return nullptr; 1121 } 1122 return result; 1123 } 1124 1125 ClassLoaderContext::VerificationResult ClassLoaderContext::VerifyClassLoaderContextMatch( 1126 const std::string& context_spec, 1127 bool verify_names, 1128 bool verify_checksums) const { 1129 if (verify_names || verify_checksums) { 1130 DCHECK(dex_files_open_attempted_); 1131 DCHECK(dex_files_open_result_); 1132 } 1133 1134 ClassLoaderContext expected_context; 1135 if (!expected_context.Parse(context_spec, verify_checksums)) { 1136 LOG(WARNING) << "Invalid class loader context: " << context_spec; 1137 return VerificationResult::kMismatch; 1138 } 1139 1140 // Special shared library contexts always match. They essentially instruct the runtime 1141 // to ignore the class path check because the oat file is known to be loaded in different 1142 // contexts. OatFileManager will further verify if the oat file can be loaded based on the 1143 // collision check. 1144 if (expected_context.special_shared_library_) { 1145 // Special case where we are the only entry in the class path. 1146 if (class_loader_chain_ != nullptr && 1147 class_loader_chain_->parent == nullptr && 1148 class_loader_chain_->classpath.size() == 0) { 1149 return VerificationResult::kVerifies; 1150 } 1151 return VerificationResult::kForcedToSkipChecks; 1152 } else if (special_shared_library_) { 1153 return VerificationResult::kForcedToSkipChecks; 1154 } 1155 1156 ClassLoaderInfo* info = class_loader_chain_.get(); 1157 ClassLoaderInfo* expected = expected_context.class_loader_chain_.get(); 1158 CHECK(info != nullptr); 1159 CHECK(expected != nullptr); 1160 if (!ClassLoaderInfoMatch(*info, *expected, context_spec, verify_names, verify_checksums)) { 1161 return VerificationResult::kMismatch; 1162 } 1163 return VerificationResult::kVerifies; 1164 } 1165 1166 bool ClassLoaderContext::ClassLoaderInfoMatch( 1167 const ClassLoaderInfo& info, 1168 const ClassLoaderInfo& expected_info, 1169 const std::string& context_spec, 1170 bool verify_names, 1171 bool verify_checksums) const { 1172 if (info.type != expected_info.type) { 1173 LOG(WARNING) << "ClassLoaderContext type mismatch" 1174 << ". expected=" << GetClassLoaderTypeName(expected_info.type) 1175 << ", found=" << GetClassLoaderTypeName(info.type) 1176 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")"; 1177 return false; 1178 } 1179 if (info.classpath.size() != expected_info.classpath.size()) { 1180 LOG(WARNING) << "ClassLoaderContext classpath size mismatch" 1181 << ". expected=" << expected_info.classpath.size() 1182 << ", found=" << info.classpath.size() 1183 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")"; 1184 return false; 1185 } 1186 1187 if (verify_checksums) { 1188 DCHECK_EQ(info.classpath.size(), info.checksums.size()); 1189 DCHECK_EQ(expected_info.classpath.size(), expected_info.checksums.size()); 1190 } 1191 1192 if (verify_names) { 1193 for (size_t k = 0; k < info.classpath.size(); k++) { 1194 // Compute the dex location that must be compared. 1195 // We shouldn't do a naive comparison `info.classpath[k] == expected_info.classpath[k]` 1196 // because even if they refer to the same file, one could be encoded as a relative location 1197 // and the other as an absolute one. 1198 bool is_dex_name_absolute = IsAbsoluteLocation(info.classpath[k]); 1199 bool is_expected_dex_name_absolute = IsAbsoluteLocation(expected_info.classpath[k]); 1200 std::string dex_name; 1201 std::string expected_dex_name; 1202 1203 if (is_dex_name_absolute == is_expected_dex_name_absolute) { 1204 // If both locations are absolute or relative then compare them as they are. 1205 // This is usually the case for: shared libraries and secondary dex files. 1206 dex_name = info.classpath[k]; 1207 expected_dex_name = expected_info.classpath[k]; 1208 } else if (is_dex_name_absolute) { 1209 // The runtime name is absolute but the compiled name (the expected one) is relative. 1210 // This is the case for split apks which depend on base or on other splits. 1211 dex_name = info.classpath[k]; 1212 OatFile::ResolveRelativeEncodedDexLocation(info.classpath[k].c_str(), 1213 expected_info.classpath[k], 1214 &expected_dex_name); 1215 } else if (is_expected_dex_name_absolute) { 1216 // The runtime name is relative but the compiled name is absolute. 1217 // There is no expected use case that would end up here as dex files are always loaded 1218 // with their absolute location. However, be tolerant and do the best effort (in case 1219 // there are unexpected new use case...). 1220 OatFile::ResolveRelativeEncodedDexLocation(expected_info.classpath[k].c_str(), 1221 info.classpath[k], 1222 &dex_name); 1223 expected_dex_name = expected_info.classpath[k]; 1224 } else { 1225 // Both locations are relative. In this case there's not much we can be sure about 1226 // except that the names are the same. The checksum will ensure that the files are 1227 // are same. This should not happen outside testing and manual invocations. 1228 dex_name = info.classpath[k]; 1229 expected_dex_name = expected_info.classpath[k]; 1230 } 1231 1232 // Compare the locations. 1233 if (dex_name != expected_dex_name) { 1234 LOG(WARNING) << "ClassLoaderContext classpath element mismatch" 1235 << ". expected=" << expected_info.classpath[k] 1236 << ", found=" << info.classpath[k] 1237 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")"; 1238 return false; 1239 } 1240 1241 // Compare the checksums. 1242 if (info.checksums[k] != expected_info.checksums[k]) { 1243 LOG(WARNING) << "ClassLoaderContext classpath element checksum mismatch" 1244 << ". expected=" << expected_info.checksums[k] 1245 << ", found=" << info.checksums[k] 1246 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")"; 1247 return false; 1248 } 1249 } 1250 } 1251 1252 if (info.shared_libraries.size() != expected_info.shared_libraries.size()) { 1253 LOG(WARNING) << "ClassLoaderContext shared library size mismatch. " 1254 << "Expected=" << expected_info.shared_libraries.size() 1255 << ", found=" << info.shared_libraries.size() 1256 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")"; 1257 return false; 1258 } 1259 for (size_t i = 0; i < info.shared_libraries.size(); ++i) { 1260 if (!ClassLoaderInfoMatch(*info.shared_libraries[i].get(), 1261 *expected_info.shared_libraries[i].get(), 1262 context_spec, 1263 verify_names, 1264 verify_checksums)) { 1265 return false; 1266 } 1267 } 1268 if (info.parent.get() == nullptr) { 1269 if (expected_info.parent.get() != nullptr) { 1270 LOG(WARNING) << "ClassLoaderContext parent mismatch. " 1271 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")"; 1272 return false; 1273 } 1274 return true; 1275 } else if (expected_info.parent.get() == nullptr) { 1276 LOG(WARNING) << "ClassLoaderContext parent mismatch. " 1277 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")"; 1278 return false; 1279 } else { 1280 return ClassLoaderInfoMatch(*info.parent.get(), 1281 *expected_info.parent.get(), 1282 context_spec, 1283 verify_names, 1284 verify_checksums); 1285 } 1286 } 1287 1288 } // namespace art 1289