summaryrefslogtreecommitdiff
path: root/runtime/class_loader_context.cc
diff options
context:
space:
mode:
author Dan Zimmerman <danzimm@fb.com> 2019-12-23 06:59:06 -0800
committer Calin Juravle <calin@google.com> 2020-02-08 00:01:36 +0000
commitb682ea4d1f9f88ef41589007f385398033d61b65 (patch)
treeb843077f05e2fe37ce5f566dfc823552f289f562 /runtime/class_loader_context.cc
parent77aa6807053a830fe5c951c7cb700813d7e2e27b (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.cc71
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,