diff options
| author | 2019-12-23 06:59:06 -0800 | |
|---|---|---|
| committer | 2020-02-08 00:01:36 +0000 | |
| commit | b682ea4d1f9f88ef41589007f385398033d61b65 (patch) | |
| tree | b843077f05e2fe37ce5f566dfc823552f289f562 /runtime/class_loader_context.cc | |
| parent | 77aa6807053a830fe5c951c7cb700813d7e2e27b (diff) | |
Introduce BaseDexClassLoader.computeClassLoaderContextsNative
This will be used to compute the contexts that should be sent over to
the dex load reporter. See associated changes in libcore &
frameworks/base.
Motivation: At the moment of committing there are two classloader
context encoders- one in ART and one in the package manager. The
duplicate logic is susceptible to divergences. For example at the moment
if a package uses shared libraries and has secondary dex files then the
context encoded for secondary dex files will be incorrect[1]. In order to
eliminate this bug and future possible bugs lets centralize where all
classloader context computation is done.
[1]: The context will be incorrect because it doesn't take into account
the shared libraries that are loaded at runtime.
Test: m test-art-host-gtest-class_loader_context_test
Test: m test-art-host-gtest
Test: ./test/testrunner/testrunner.py --host -b
Test: Introduced a set of tests for the new API(s)
Test: See tests in associated libcore & framework/base commits
Bug: 148494302
Change-Id: Id39293a2e1d3d05194f2864f4febb3e652bce075
Diffstat (limited to 'runtime/class_loader_context.cc')
| -rw-r--r-- | runtime/class_loader_context.cc | 71 |
1 files changed, 68 insertions, 3 deletions
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc index e835702baa..5dfbfe945f 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -569,6 +569,46 @@ std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_ return EncodeContext(base_dir, /*for_dex2oat=*/ false, stored_context); } +std::map<std::string, std::string> +ClassLoaderContext::EncodeClassPathContexts(const std::string& base_dir) const { + CheckDexFilesOpened("EncodeClassPathContexts"); + if (class_loader_chain_ == nullptr) { + return std::map<std::string, std::string>{}; + } + + std::map<std::string, std::string> results; + std::vector<std::string> dex_locations; + std::vector<uint32_t> checksums; + dex_locations.reserve(class_loader_chain_->original_classpath.size()); + + std::ostringstream encoded_libs_and_parent_stream; + EncodeSharedLibAndParent(*class_loader_chain_, + base_dir, + /*for_dex2oat=*/true, + /*stored_info=*/nullptr, + encoded_libs_and_parent_stream); + std::string encoded_libs_and_parent(encoded_libs_and_parent_stream.str()); + + std::set<std::string> seen_locations; + for (const std::string& path : class_loader_chain_->classpath) { + // The classpath will contain multiple entries for multidex files, so make sure this is the + // first time we're seeing this file. + const std::string base_location(DexFileLoader::GetBaseLocation(path)); + if (!seen_locations.insert(base_location).second) { + continue; + } + + std::ostringstream out; + EncodeClassPath(base_dir, dex_locations, checksums, class_loader_chain_->type, out); + out << encoded_libs_and_parent; + results.emplace(base_location, out.str()); + + dex_locations.push_back(base_location); + } + + return results; +} + std::string ClassLoaderContext::EncodeContext(const std::string& base_dir, bool for_dex2oat, ClassLoaderContext* stored_context) const { @@ -937,9 +977,7 @@ static bool CollectDexFilesFromSupportedClassLoader(ScopedObjectAccessAlreadyRun Handle<mirror::ClassLoader> class_loader, std::vector<const DexFile*>* out_dex_files) REQUIRES_SHARED(Locks::mutator_lock_) { - CHECK(IsPathOrDexClassLoader(soa, class_loader) || - IsDelegateLastClassLoader(soa, class_loader) || - IsInMemoryDexClassLoader(soa, class_loader)); + CHECK(IsInstanceOfBaseDexClassLoader(soa, class_loader)); // All supported class loaders inherit from BaseDexClassLoader. // We need to get the DexPathList and loop through it. @@ -1152,6 +1190,33 @@ std::unique_ptr<ClassLoaderContext> ClassLoaderContext::CreateContextForClassLoa return result; } +std::map<std::string, std::string> +ClassLoaderContext::EncodeClassPathContextsForClassLoader(jobject class_loader) { + std::unique_ptr<ClassLoaderContext> clc = + ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr); + if (clc != nullptr) { + return clc->EncodeClassPathContexts(""); + } + + ScopedObjectAccess soa(Thread::Current()); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::ClassLoader> h_class_loader = + hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)); + if (!IsInstanceOfBaseDexClassLoader(soa, h_class_loader)) { + return std::map<std::string, std::string>{}; + } + + std::vector<const DexFile*> dex_files_loaded; + CollectDexFilesFromSupportedClassLoader(soa, h_class_loader, &dex_files_loaded); + + std::map<std::string, std::string> results; + for (const DexFile* dex_file : dex_files_loaded) { + results.emplace(DexFileLoader::GetBaseLocation(dex_file->GetLocation()), + ClassLoaderContext::kUnsupportedClassLoaderContextEncoding); + } + return results; +} + ClassLoaderContext::VerificationResult ClassLoaderContext::VerifyClassLoaderContextMatch( const std::string& context_spec, bool verify_names, |