1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_CLASS_LOADER_CONTEXT_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_CLASS_LOADER_CONTEXT_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <string> 21*795d594fSAndroid Build Coastguard Worker #include <vector> 22*795d594fSAndroid Build Coastguard Worker #include <set> 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h" 25*795d594fSAndroid Build Coastguard Worker #include "base/dchecked_vector.h" 26*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 27*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h" 28*795d594fSAndroid Build Coastguard Worker #include "handle_scope.h" 29*795d594fSAndroid Build Coastguard Worker #include "mirror/class_loader.h" 30*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file.h" 31*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change.h" 32*795d594fSAndroid Build Coastguard Worker 33*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 34*795d594fSAndroid Build Coastguard Worker 35*795d594fSAndroid Build Coastguard Worker class DexFile; 36*795d594fSAndroid Build Coastguard Worker class OatFile; 37*795d594fSAndroid Build Coastguard Worker 38*795d594fSAndroid Build Coastguard Worker // Utility class which holds the class loader context used during compilation/verification. 39*795d594fSAndroid Build Coastguard Worker class EXPORT ClassLoaderContext { 40*795d594fSAndroid Build Coastguard Worker public: 41*795d594fSAndroid Build Coastguard Worker enum class VerificationResult { 42*795d594fSAndroid Build Coastguard Worker kVerifies, 43*795d594fSAndroid Build Coastguard Worker kMismatch, 44*795d594fSAndroid Build Coastguard Worker }; 45*795d594fSAndroid Build Coastguard Worker 46*795d594fSAndroid Build Coastguard Worker enum ClassLoaderType { 47*795d594fSAndroid Build Coastguard Worker kInvalidClassLoader = 0, 48*795d594fSAndroid Build Coastguard Worker kPathClassLoader = 1, 49*795d594fSAndroid Build Coastguard Worker kDelegateLastClassLoader = 2, 50*795d594fSAndroid Build Coastguard Worker kInMemoryDexClassLoader = 3 51*795d594fSAndroid Build Coastguard Worker }; 52*795d594fSAndroid Build Coastguard Worker 53*795d594fSAndroid Build Coastguard Worker // Special encoding used to denote a foreign ClassLoader was found when trying to encode class 54*795d594fSAndroid Build Coastguard Worker // loader contexts for each classpath element in a ClassLoader. See 55*795d594fSAndroid Build Coastguard Worker // EncodeClassPathContextsForClassLoader. Keep in sync with PackageDexUsage in the framework 56*795d594fSAndroid Build Coastguard Worker // (frameworks/base/services/core/java/com/android/server/pm/dex/PackageDexUsage.java) and 57*795d594fSAndroid Build Coastguard Worker // DexUseManager in ART Services 58*795d594fSAndroid Build Coastguard Worker // (art/libartservice/service/java/com/android/server/art/DexUseManager.java). 59*795d594fSAndroid Build Coastguard Worker static constexpr const char* kUnsupportedClassLoaderContextEncoding = 60*795d594fSAndroid Build Coastguard Worker "=UnsupportedClassLoaderContext="; 61*795d594fSAndroid Build Coastguard Worker 62*795d594fSAndroid Build Coastguard Worker ~ClassLoaderContext(); 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker // Opens requested class path files and appends them to ClassLoaderInfo::opened_dex_files. 65*795d594fSAndroid Build Coastguard Worker // If the dex files have been stripped, the method opens them from their oat files which are added 66*795d594fSAndroid Build Coastguard Worker // to ClassLoaderInfo::opened_oat_files. The 'classpath_dir' argument specifies the directory to 67*795d594fSAndroid Build Coastguard Worker // use for the relative class paths. 68*795d594fSAndroid Build Coastguard Worker // Returns true if all dex files where successfully opened. 69*795d594fSAndroid Build Coastguard Worker // It may be called only once per ClassLoaderContext. Subsequent calls will return the same 70*795d594fSAndroid Build Coastguard Worker // result without doing anything. 71*795d594fSAndroid Build Coastguard Worker // If `context_fds` is an empty vector, files will be opened using the class path locations as 72*795d594fSAndroid Build Coastguard Worker // filenames. Otherwise `context_fds` is expected to contain file descriptors to class path dex 73*795d594fSAndroid Build Coastguard Worker // files, following the order of dex file locations in a flattened class loader context. If their 74*795d594fSAndroid Build Coastguard Worker // number (size of `context_fds`) does not match the number of dex files, OpenDexFiles will fail. 75*795d594fSAndroid Build Coastguard Worker // 76*795d594fSAndroid Build Coastguard Worker // This will replace the class path locations with the locations of the opened dex files. 77*795d594fSAndroid Build Coastguard Worker // (Note that one dex file can contain multidexes. Each multidex will be added to the classpath 78*795d594fSAndroid Build Coastguard Worker // separately.) 79*795d594fSAndroid Build Coastguard Worker // 80*795d594fSAndroid Build Coastguard Worker // only_read_checksums controls whether or not we only read the dex locations and the checksums 81*795d594fSAndroid Build Coastguard Worker // from the apk instead of fully opening the dex files. 82*795d594fSAndroid Build Coastguard Worker // 83*795d594fSAndroid Build Coastguard Worker // This method is not thread safe. 84*795d594fSAndroid Build Coastguard Worker // 85*795d594fSAndroid Build Coastguard Worker // Note that a "false" return could mean that either an apk/jar contained no dex files or 86*795d594fSAndroid Build Coastguard Worker // that we hit a I/O or checksum mismatch error. 87*795d594fSAndroid Build Coastguard Worker // TODO(calin): Currently there's no easy way to tell the difference. 88*795d594fSAndroid Build Coastguard Worker // 89*795d594fSAndroid Build Coastguard Worker // TODO(calin): we're forced to complicate the flow in this class with a different 90*795d594fSAndroid Build Coastguard Worker // OpenDexFiles step because the current dex2oat flow requires the dex files be opened before 91*795d594fSAndroid Build Coastguard Worker // the class loader is created. Consider reworking the dex2oat part. 92*795d594fSAndroid Build Coastguard Worker bool OpenDexFiles(const std::string& classpath_dir = "", 93*795d594fSAndroid Build Coastguard Worker const std::vector<int>& context_fds = std::vector<int>(), 94*795d594fSAndroid Build Coastguard Worker bool only_read_checksums = false); 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Worker // Remove the specified compilation sources from all classpaths present in this context. 97*795d594fSAndroid Build Coastguard Worker // Should only be called before the first call to OpenDexFiles(). 98*795d594fSAndroid Build Coastguard Worker bool RemoveLocationsFromClassPaths(const dchecked_vector<std::string>& compilation_sources); 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker // Creates the entire class loader hierarchy according to the current context. 101*795d594fSAndroid Build Coastguard Worker // Returns the first class loader from the chain. 102*795d594fSAndroid Build Coastguard Worker // 103*795d594fSAndroid Build Coastguard Worker // For example: if the context was built from the spec 104*795d594fSAndroid Build Coastguard Worker // "ClassLoaderType1[ClasspathElem1:ClasspathElem2...];ClassLoaderType2[...]..." 105*795d594fSAndroid Build Coastguard Worker // the method returns the class loader correponding to ClassLoader1. The parent chain will be 106*795d594fSAndroid Build Coastguard Worker // ClassLoader1 --> ClassLoader2 --> ... --> BootClassLoader. 107*795d594fSAndroid Build Coastguard Worker // 108*795d594fSAndroid Build Coastguard Worker // The compilation sources are appended to the classpath of the first class loader (in the above 109*795d594fSAndroid Build Coastguard Worker // example ClassLoader1). 110*795d594fSAndroid Build Coastguard Worker // 111*795d594fSAndroid Build Coastguard Worker // If the context is empty, this method only creates a single PathClassLoader with the 112*795d594fSAndroid Build Coastguard Worker // given compilation_sources. 113*795d594fSAndroid Build Coastguard Worker // 114*795d594fSAndroid Build Coastguard Worker // Shared libraries found in the chain will be canonicalized based on the dex files they 115*795d594fSAndroid Build Coastguard Worker // contain. 116*795d594fSAndroid Build Coastguard Worker // 117*795d594fSAndroid Build Coastguard Worker // Implementation notes: 118*795d594fSAndroid Build Coastguard Worker // 1) the objects are not completely set up. Do not use this outside of tests and the compiler. 119*795d594fSAndroid Build Coastguard Worker // 2) should only be called before the first call to OpenDexFiles(). 120*795d594fSAndroid Build Coastguard Worker jobject CreateClassLoader(const std::vector<const DexFile*>& compilation_sources) const; 121*795d594fSAndroid Build Coastguard Worker 122*795d594fSAndroid Build Coastguard Worker // Encodes the context as a string suitable to be added in oat files. 123*795d594fSAndroid Build Coastguard Worker // (so that it can be read and verified at runtime against the actual class 124*795d594fSAndroid Build Coastguard Worker // loader hierarchy). 125*795d594fSAndroid Build Coastguard Worker // Should only be called if OpenDexFiles() returned true. 126*795d594fSAndroid Build Coastguard Worker // If stored context is non-null, the stored names are overwritten by the class path from the 127*795d594fSAndroid Build Coastguard Worker // stored context. 128*795d594fSAndroid Build Coastguard Worker // E.g. if the context is PCL[a.dex:b.dex] this will return 129*795d594fSAndroid Build Coastguard Worker // "PCL[a.dex*a_checksum*b.dex*a_checksum]". 130*795d594fSAndroid Build Coastguard Worker std::string EncodeContextForOatFile(const std::string& base_dir, 131*795d594fSAndroid Build Coastguard Worker ClassLoaderContext* stored_context = nullptr) const; 132*795d594fSAndroid Build Coastguard Worker 133*795d594fSAndroid Build Coastguard Worker // Encodes the context as a string suitable to be passed to dex2oat. 134*795d594fSAndroid Build Coastguard Worker // This is the same as EncodeContextForOatFile but without adding the checksums 135*795d594fSAndroid Build Coastguard Worker // and only adding each dex files once (no multidex). 136*795d594fSAndroid Build Coastguard Worker // Should only be called if OpenDexFiles() returned true. 137*795d594fSAndroid Build Coastguard Worker std::string EncodeContextForDex2oat(const std::string& base_dir) const; 138*795d594fSAndroid Build Coastguard Worker 139*795d594fSAndroid Build Coastguard Worker // Encodes the contexts for each of the classpath elements in the child-most 140*795d594fSAndroid Build Coastguard Worker // classloader. Under the hood EncodeContextForDex2oat is used, so no checksums 141*795d594fSAndroid Build Coastguard Worker // will be encoded. 142*795d594fSAndroid Build Coastguard Worker // Should only be called if the dex files are opened (either via OpenDexFiles() or by creating the 143*795d594fSAndroid Build Coastguard Worker // context from a live class loader). 144*795d594fSAndroid Build Coastguard Worker // Notably, for each classpath element the encoded classloader context will contain only the 145*795d594fSAndroid Build Coastguard Worker // elements that appear before it in the containing classloader. E.g. if `this` contains 146*795d594fSAndroid Build Coastguard Worker // (from child to parent): 147*795d594fSAndroid Build Coastguard Worker // 148*795d594fSAndroid Build Coastguard Worker // PathClassLoader { multidex.apk!classes.dex, multidex.apk!classes2.dex, foo.dex, bar.dex } -> 149*795d594fSAndroid Build Coastguard Worker // PathClassLoader { baz.dex } -> BootClassLoader 150*795d594fSAndroid Build Coastguard Worker // 151*795d594fSAndroid Build Coastguard Worker // then the return value will look like: 152*795d594fSAndroid Build Coastguard Worker // 153*795d594fSAndroid Build Coastguard Worker // `{ "multidex.apk": "PCL[];PCL[baz.dex]", 154*795d594fSAndroid Build Coastguard Worker // "foo.dex" : "PCL[multidex.apk];PCL[baz.dex]", 155*795d594fSAndroid Build Coastguard Worker // "bar.dex" : "PCL[multidex.apk:foo.dex];PCL[baz.dex]" }` 156*795d594fSAndroid Build Coastguard Worker std::map<std::string, std::string> EncodeClassPathContexts(const std::string& base_dir) const; 157*795d594fSAndroid Build Coastguard Worker 158*795d594fSAndroid Build Coastguard Worker // Flattens the opened dex files into the given vector. 159*795d594fSAndroid Build Coastguard Worker // Should only be called if OpenDexFiles() returned true. 160*795d594fSAndroid Build Coastguard Worker std::vector<const DexFile*> FlattenOpenedDexFiles() const; 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker // Return a list of dex file locations from this class loader context after flattening. 163*795d594fSAndroid Build Coastguard Worker std::vector<std::string> FlattenDexPaths() const; 164*795d594fSAndroid Build Coastguard Worker 165*795d594fSAndroid Build Coastguard Worker // Verifies that the current context is identical to the context encoded as `context_spec`. 166*795d594fSAndroid Build Coastguard Worker // Identical means: 167*795d594fSAndroid Build Coastguard Worker // - the number and type of the class loaders from the chain matches 168*795d594fSAndroid Build Coastguard Worker // - the class loader from the same position have the same classpath 169*795d594fSAndroid Build Coastguard Worker // (the order and checksum of the dex files matches) 170*795d594fSAndroid Build Coastguard Worker // This should be called after OpenDexFiles() with only_read_checksums=true. There's no 171*795d594fSAndroid Build Coastguard Worker // need to fully open the dex files if the only thing that needs to be done is to verify 172*795d594fSAndroid Build Coastguard Worker // the context. 173*795d594fSAndroid Build Coastguard Worker // 174*795d594fSAndroid Build Coastguard Worker // Names are only verified if verify_names is true. 175*795d594fSAndroid Build Coastguard Worker // Checksums are only verified if verify_checksums is true. 176*795d594fSAndroid Build Coastguard Worker VerificationResult VerifyClassLoaderContextMatch(const std::string& context_spec, 177*795d594fSAndroid Build Coastguard Worker bool verify_names = true, 178*795d594fSAndroid Build Coastguard Worker bool verify_checksums = true) const; 179*795d594fSAndroid Build Coastguard Worker 180*795d594fSAndroid Build Coastguard Worker // Checks if any of the given dex files is already loaded in the current class loader context. 181*795d594fSAndroid Build Coastguard Worker // It only checks the first class loader. 182*795d594fSAndroid Build Coastguard Worker // Returns the list of duplicate dex files (empty if there are no duplicates). 183*795d594fSAndroid Build Coastguard Worker std::set<const DexFile*> CheckForDuplicateDexFiles( 184*795d594fSAndroid Build Coastguard Worker const std::vector<const DexFile*>& dex_files); 185*795d594fSAndroid Build Coastguard Worker 186*795d594fSAndroid Build Coastguard Worker // Creates the class loader context from the given string. 187*795d594fSAndroid Build Coastguard Worker // The format: ClassLoaderType1[ClasspathElem1:ClasspathElem2...];ClassLoaderType2[...]... 188*795d594fSAndroid Build Coastguard Worker // ClassLoaderType is either "PCL" (PathClassLoader) or "DLC" (DelegateLastClassLoader). 189*795d594fSAndroid Build Coastguard Worker // ClasspathElem is the path of dex/jar/apk file. 190*795d594fSAndroid Build Coastguard Worker // 191*795d594fSAndroid Build Coastguard Worker // The spec represents a class loader chain with the natural interpretation: 192*795d594fSAndroid Build Coastguard Worker // ClassLoader1 has ClassLoader2 as parent which has ClassLoader3 as a parent and so on. 193*795d594fSAndroid Build Coastguard Worker // The last class loader is assumed to have the BootClassLoader as a parent. 194*795d594fSAndroid Build Coastguard Worker // 195*795d594fSAndroid Build Coastguard Worker // Note that we allowed class loaders with an empty class path in order to support a custom 196*795d594fSAndroid Build Coastguard Worker // class loader for the source dex files. 197*795d594fSAndroid Build Coastguard Worker static std::unique_ptr<ClassLoaderContext> Create(const std::string& spec); 198*795d594fSAndroid Build Coastguard Worker 199*795d594fSAndroid Build Coastguard Worker // Creates a context for the given class_loader and dex_elements. 200*795d594fSAndroid Build Coastguard Worker // The method will walk the parent chain starting from `class_loader` and add their dex files 201*795d594fSAndroid Build Coastguard Worker // to the current class loaders chain. The `dex_elements` will be added at the end of the 202*795d594fSAndroid Build Coastguard Worker // classpath belonging to the `class_loader` argument. 203*795d594fSAndroid Build Coastguard Worker // The ownership of the opened dex files will be retained by the given `class_loader`. 204*795d594fSAndroid Build Coastguard Worker // If there are errors in processing the class loader chain (e.g. unsupported elements) the 205*795d594fSAndroid Build Coastguard Worker // method returns null. 206*795d594fSAndroid Build Coastguard Worker static std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader, 207*795d594fSAndroid Build Coastguard Worker jobjectArray dex_elements); 208*795d594fSAndroid Build Coastguard Worker 209*795d594fSAndroid Build Coastguard Worker // Returns the default class loader context to be used when none is specified. 210*795d594fSAndroid Build Coastguard Worker // This will return a context with a single and empty PathClassLoader. 211*795d594fSAndroid Build Coastguard Worker static std::unique_ptr<ClassLoaderContext> Default(); 212*795d594fSAndroid Build Coastguard Worker 213*795d594fSAndroid Build Coastguard Worker // Encodes the contexts for each of the classpath elements in `class_loader`. See 214*795d594fSAndroid Build Coastguard Worker // ClassLoaderContext::EncodeClassPathContexts for more information about the return value. 215*795d594fSAndroid Build Coastguard Worker // 216*795d594fSAndroid Build Coastguard Worker // If `class_loader` does not derive from BaseDexClassLoader then an empty map is returned. 217*795d594fSAndroid Build Coastguard Worker // Otherwise if a foreign ClassLoader is found in the class loader chain then the results values 218*795d594fSAndroid Build Coastguard Worker // will all be ClassLoaderContext::kUnsupportedClassLoaderContextEncoding. 219*795d594fSAndroid Build Coastguard Worker static std::map<std::string, std::string> EncodeClassPathContextsForClassLoader( 220*795d594fSAndroid Build Coastguard Worker jobject class_loader); 221*795d594fSAndroid Build Coastguard Worker 222*795d594fSAndroid Build Coastguard Worker // Returns whether `encoded_class_loader_context` is a valid encoded ClassLoaderContext or 223*795d594fSAndroid Build Coastguard Worker // EncodedUnsupportedClassLoaderContext. 224*795d594fSAndroid Build Coastguard Worker static bool IsValidEncoding(const std::string& possible_encoded_class_loader_context); 225*795d594fSAndroid Build Coastguard Worker 226*795d594fSAndroid Build Coastguard Worker struct ClassLoaderInfo { 227*795d594fSAndroid Build Coastguard Worker // The type of this class loader. 228*795d594fSAndroid Build Coastguard Worker ClassLoaderType type; 229*795d594fSAndroid Build Coastguard Worker // Shared libraries this context has. 230*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<ClassLoaderInfo>> shared_libraries; 231*795d594fSAndroid Build Coastguard Worker // Shared libraries that will be loaded after apks code that this context has. 232*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<ClassLoaderInfo>> shared_libraries_after; 233*795d594fSAndroid Build Coastguard Worker // The list of class path elements that this loader loads. 234*795d594fSAndroid Build Coastguard Worker // Note that this list may contain relative paths. 235*795d594fSAndroid Build Coastguard Worker std::vector<std::string> classpath; 236*795d594fSAndroid Build Coastguard Worker // Original opened class path (ignoring multidex). 237*795d594fSAndroid Build Coastguard Worker std::vector<std::string> original_classpath; 238*795d594fSAndroid Build Coastguard Worker // The list of class path elements checksums. 239*795d594fSAndroid Build Coastguard Worker // May be empty if the checksums are not given when the context is created. 240*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> checksums; 241*795d594fSAndroid Build Coastguard Worker // After OpenDexFiles is called this holds the opened dex files. 242*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> opened_dex_files; 243*795d594fSAndroid Build Coastguard Worker // After OpenDexFiles, in case some of the dex files were opened from their oat files 244*795d594fSAndroid Build Coastguard Worker // this holds the list of opened oat files. 245*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<OatFile>> opened_oat_files; 246*795d594fSAndroid Build Coastguard Worker // The parent class loader. 247*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ClassLoaderInfo> parent; 248*795d594fSAndroid Build Coastguard Worker ClassLoaderInfoClassLoaderInfo249*795d594fSAndroid Build Coastguard Worker explicit ClassLoaderInfo(ClassLoaderType cl_type) : type(cl_type) {} 250*795d594fSAndroid Build Coastguard Worker }; 251*795d594fSAndroid Build Coastguard Worker 252*795d594fSAndroid Build Coastguard Worker private: 253*795d594fSAndroid Build Coastguard Worker // Creates an empty context (with no class loaders). 254*795d594fSAndroid Build Coastguard Worker ClassLoaderContext(); 255*795d594fSAndroid Build Coastguard Worker 256*795d594fSAndroid Build Coastguard Worker // Get the parent of the class loader chain at depth `index`. GetParent(size_t index)257*795d594fSAndroid Build Coastguard Worker ClassLoaderInfo* GetParent(size_t index) const { 258*795d594fSAndroid Build Coastguard Worker ClassLoaderInfo* result = class_loader_chain_.get(); 259*795d594fSAndroid Build Coastguard Worker while ((result != nullptr) && (index-- != 0)) { 260*795d594fSAndroid Build Coastguard Worker result = result->parent.get(); 261*795d594fSAndroid Build Coastguard Worker } 262*795d594fSAndroid Build Coastguard Worker return result; 263*795d594fSAndroid Build Coastguard Worker } 264*795d594fSAndroid Build Coastguard Worker GetParentChainSize()265*795d594fSAndroid Build Coastguard Worker size_t GetParentChainSize() const { 266*795d594fSAndroid Build Coastguard Worker size_t result = 0; 267*795d594fSAndroid Build Coastguard Worker ClassLoaderInfo* info = class_loader_chain_.get(); 268*795d594fSAndroid Build Coastguard Worker while (info != nullptr) { 269*795d594fSAndroid Build Coastguard Worker ++result; 270*795d594fSAndroid Build Coastguard Worker info = info->parent.get(); 271*795d594fSAndroid Build Coastguard Worker } 272*795d594fSAndroid Build Coastguard Worker return result; 273*795d594fSAndroid Build Coastguard Worker } 274*795d594fSAndroid Build Coastguard Worker 275*795d594fSAndroid Build Coastguard Worker // Constructs an empty context. 276*795d594fSAndroid Build Coastguard Worker // `owns_the_dex_files` specifies whether or not the context will own the opened dex files 277*795d594fSAndroid Build Coastguard Worker // present in the class loader chain. If `owns_the_dex_files` is true then OpenDexFiles cannot 278*795d594fSAndroid Build Coastguard Worker // be called on this context (dex_files_open_attempted_ and dex_files_open_result_ will be set 279*795d594fSAndroid Build Coastguard Worker // to true as well) 280*795d594fSAndroid Build Coastguard Worker explicit ClassLoaderContext(bool owns_the_dex_files); 281*795d594fSAndroid Build Coastguard Worker 282*795d594fSAndroid Build Coastguard Worker // Reads the class loader spec in place and returns true if the spec is valid and the 283*795d594fSAndroid Build Coastguard Worker // compilation context was constructed. 284*795d594fSAndroid Build Coastguard Worker bool Parse(const std::string& spec, bool parse_checksums = false); 285*795d594fSAndroid Build Coastguard Worker ClassLoaderInfo* ParseInternal(const std::string& spec, bool parse_checksums); 286*795d594fSAndroid Build Coastguard Worker 287*795d594fSAndroid Build Coastguard Worker // Attempts to parse a single class loader spec. 288*795d594fSAndroid Build Coastguard Worker // Returns the ClassLoaderInfo abstraction for this spec, or null if it cannot be parsed. 289*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ClassLoaderInfo> ParseClassLoaderSpec( 290*795d594fSAndroid Build Coastguard Worker const std::string& class_loader_spec, 291*795d594fSAndroid Build Coastguard Worker bool parse_checksums = false); 292*795d594fSAndroid Build Coastguard Worker 293*795d594fSAndroid Build Coastguard Worker // CHECKs that the dex files were opened (OpenDexFiles was called and set dex_files_open_result_ 294*795d594fSAndroid Build Coastguard Worker // to true). Aborts if not. The `calling_method` is used in the log message to identify the source 295*795d594fSAndroid Build Coastguard Worker // of the call. 296*795d594fSAndroid Build Coastguard Worker void CheckDexFilesOpened(const std::string& calling_method) const; 297*795d594fSAndroid Build Coastguard Worker 298*795d594fSAndroid Build Coastguard Worker // Creates the `ClassLoaderInfo` representing`class_loader` and attach it to `this`. 299*795d594fSAndroid Build Coastguard Worker // The dex file present in `dex_elements` array (if not null) will be added at the end of 300*795d594fSAndroid Build Coastguard Worker // the classpath. 301*795d594fSAndroid Build Coastguard Worker bool CreateInfoFromClassLoader(ScopedObjectAccessAlreadyRunnable& soa, 302*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader, 303*795d594fSAndroid Build Coastguard Worker Handle<mirror::ObjectArray<mirror::Object>> dex_elements, 304*795d594fSAndroid Build Coastguard Worker ClassLoaderInfo* child_info, 305*795d594fSAndroid Build Coastguard Worker bool is_shared_library, 306*795d594fSAndroid Build Coastguard Worker bool is_after) 307*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 308*795d594fSAndroid Build Coastguard Worker 309*795d594fSAndroid Build Coastguard Worker // Encodes the context as a string suitable to be passed to dex2oat or to be added to the 310*795d594fSAndroid Build Coastguard Worker // oat file as the class path key. 311*795d594fSAndroid Build Coastguard Worker // If for_dex2oat is true, the encoding adds each file once (i.e. it does not add multidex 312*795d594fSAndroid Build Coastguard Worker // location). Otherwise, for oat files, the encoding adds all the dex files (including multidex) 313*795d594fSAndroid Build Coastguard Worker // together with their checksums. 314*795d594fSAndroid Build Coastguard Worker // Should only be called if OpenDexFiles() returned true. 315*795d594fSAndroid Build Coastguard Worker std::string EncodeContext(const std::string& base_dir, 316*795d594fSAndroid Build Coastguard Worker bool for_dex2oat, 317*795d594fSAndroid Build Coastguard Worker ClassLoaderContext* stored_context) const; 318*795d594fSAndroid Build Coastguard Worker 319*795d594fSAndroid Build Coastguard Worker // Internal version of `EncodeContext`, which will be called recursively 320*795d594fSAndroid Build Coastguard Worker // on the parent and shared libraries. 321*795d594fSAndroid Build Coastguard Worker void EncodeContextInternal(const ClassLoaderInfo& info, 322*795d594fSAndroid Build Coastguard Worker const std::string& base_dir, 323*795d594fSAndroid Build Coastguard Worker bool for_dex2oat, 324*795d594fSAndroid Build Coastguard Worker ClassLoaderInfo* stored_info, 325*795d594fSAndroid Build Coastguard Worker std::ostringstream& out) const; 326*795d594fSAndroid Build Coastguard Worker 327*795d594fSAndroid Build Coastguard Worker // Encodes e.g. PCL[foo.dex:bar.dex] 328*795d594fSAndroid Build Coastguard Worker void EncodeClassPath(const std::string& base_dir, 329*795d594fSAndroid Build Coastguard Worker const std::vector<std::string>& dex_locations, 330*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& checksums, 331*795d594fSAndroid Build Coastguard Worker ClassLoaderType type, 332*795d594fSAndroid Build Coastguard Worker std::ostringstream& out) const; 333*795d594fSAndroid Build Coastguard Worker 334*795d594fSAndroid Build Coastguard Worker // Encodes the shared libraries classloaders and the parent classloader if 335*795d594fSAndroid Build Coastguard Worker // either are present in info, e.g. {PCL[foo.dex]#PCL[bar.dex]};PCL[baz.dex] 336*795d594fSAndroid Build Coastguard Worker void EncodeSharedLibAndParent(const ClassLoaderInfo& info, 337*795d594fSAndroid Build Coastguard Worker const std::string& base_dir, 338*795d594fSAndroid Build Coastguard Worker bool for_dex2oat, 339*795d594fSAndroid Build Coastguard Worker ClassLoaderInfo* stored_info, 340*795d594fSAndroid Build Coastguard Worker std::ostringstream& out) const; 341*795d594fSAndroid Build Coastguard Worker 342*795d594fSAndroid Build Coastguard Worker bool ClassLoaderInfoMatch(const ClassLoaderInfo& info, 343*795d594fSAndroid Build Coastguard Worker const ClassLoaderInfo& expected_info, 344*795d594fSAndroid Build Coastguard Worker const std::string& context_spec, 345*795d594fSAndroid Build Coastguard Worker bool verify_names, 346*795d594fSAndroid Build Coastguard Worker bool verify_checksums) const; 347*795d594fSAndroid Build Coastguard Worker 348*795d594fSAndroid Build Coastguard Worker // Extracts the class loader type from the given spec. 349*795d594fSAndroid Build Coastguard Worker // Return ClassLoaderContext::kInvalidClassLoader if the class loader type is not 350*795d594fSAndroid Build Coastguard Worker // recognized. 351*795d594fSAndroid Build Coastguard Worker static ClassLoaderType ExtractClassLoaderType(const std::string& class_loader_spec); 352*795d594fSAndroid Build Coastguard Worker 353*795d594fSAndroid Build Coastguard Worker // Returns the string representation of the class loader type. 354*795d594fSAndroid Build Coastguard Worker // The returned format can be used when parsing a context spec. 355*795d594fSAndroid Build Coastguard Worker static const char* GetClassLoaderTypeName(ClassLoaderType type); 356*795d594fSAndroid Build Coastguard Worker 357*795d594fSAndroid Build Coastguard Worker // Encodes the state of processing the dex files associated with the context. 358*795d594fSAndroid Build Coastguard Worker enum ContextDexFilesState { 359*795d594fSAndroid Build Coastguard Worker // The dex files are not opened. 360*795d594fSAndroid Build Coastguard Worker kDexFilesNotOpened = 1, 361*795d594fSAndroid Build Coastguard Worker // The dex checksums/locations were read from the apk/dex but the dex files were not opened. 362*795d594fSAndroid Build Coastguard Worker kDexFilesChecksumsRead = 2, 363*795d594fSAndroid Build Coastguard Worker // The dex files are opened (either because we called OpenDexFiles, or we used a class loader 364*795d594fSAndroid Build Coastguard Worker // to create the context). This implies kDexFilesChecksumsRead. 365*795d594fSAndroid Build Coastguard Worker kDexFilesOpened = 3, 366*795d594fSAndroid Build Coastguard Worker // We failed to open the dex files or read the checksums. 367*795d594fSAndroid Build Coastguard Worker kDexFilesOpenFailed = 4 368*795d594fSAndroid Build Coastguard Worker }; 369*795d594fSAndroid Build Coastguard Worker 370*795d594fSAndroid Build Coastguard Worker // The class loader chain. 371*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ClassLoaderInfo> class_loader_chain_; 372*795d594fSAndroid Build Coastguard Worker 373*795d594fSAndroid Build Coastguard Worker // The opening state of the dex files. 374*795d594fSAndroid Build Coastguard Worker ContextDexFilesState dex_files_state_; 375*795d594fSAndroid Build Coastguard Worker 376*795d594fSAndroid Build Coastguard Worker // Whether or not the context owns the opened dex and oat files. 377*795d594fSAndroid Build Coastguard Worker // If true, the opened dex files will be de-allocated when the context is destructed. 378*795d594fSAndroid Build Coastguard Worker // If false, the objects will continue to be alive. 379*795d594fSAndroid Build Coastguard Worker // Note that for convenience the the opened dex/oat files are stored as unique pointers 380*795d594fSAndroid Build Coastguard Worker // which will release their ownership in the destructor based on this flag. 381*795d594fSAndroid Build Coastguard Worker const bool owns_the_dex_files_; 382*795d594fSAndroid Build Coastguard Worker 383*795d594fSAndroid Build Coastguard Worker friend class ClassLoaderContextTest; 384*795d594fSAndroid Build Coastguard Worker 385*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ClassLoaderContext); 386*795d594fSAndroid Build Coastguard Worker }; 387*795d594fSAndroid Build Coastguard Worker 388*795d594fSAndroid Build Coastguard Worker } // namespace art 389*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_CLASS_LOADER_CONTEXT_H_ 390