1 /* 2 * Copyright (C) 2016 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 #ifndef ART_RUNTIME_VERIFIER_VERIFIER_DEPS_H_ 18 #define ART_RUNTIME_VERIFIER_VERIFIER_DEPS_H_ 19 20 #include <map> 21 #include <set> 22 #include <vector> 23 24 #include "base/array_ref.h" 25 #include "base/locks.h" 26 #include "base/macros.h" 27 #include "dex/dex_file_structs.h" 28 #include "dex/dex_file_types.h" 29 #include "handle.h" 30 #include "obj_ptr.h" 31 #include "thread.h" 32 #include "verifier_enums.h" // For MethodVerifier::FailureKind. 33 34 namespace art HIDDEN { 35 36 class ArtField; 37 class ArtMethod; 38 class DexFile; 39 class VariableIndentationOutputStream; 40 41 namespace mirror { 42 class Class; 43 class ClassLoader; 44 } // namespace mirror 45 46 namespace verifier { 47 48 class RegType; 49 50 // Verification dependencies collector class used by the MethodVerifier to record 51 // resolution outcomes and type assignability tests of classes/methods/fields 52 // not present in the set of compiled DEX files, that is classes/methods/fields 53 // defined in the classpath. 54 // The compilation driver initializes the class and registers all DEX files 55 // which are being compiled. Classes defined in DEX files outside of this set 56 // (or synthesized classes without associated DEX files) are considered being 57 // in the classpath. 58 // During code-flow verification, the MethodVerifier informs VerifierDeps 59 // about the outcome of every resolution and assignability test, and 60 // the VerifierDeps object records them if their outcome may change with 61 // changes in the classpath. 62 class VerifierDeps { 63 public: 64 EXPORT explicit VerifierDeps(const std::vector<const DexFile*>& dex_files, 65 bool output_only = true); 66 67 // Marker to know whether a class is verified. A non-verified class will have 68 // this marker as its offset entry in the encoded data. 69 static uint32_t constexpr kNotVerifiedMarker = std::numeric_limits<uint32_t>::max(); 70 71 // Fill dependencies from stored data. Returns true on success, false on failure. 72 EXPORT bool ParseStoredData(const std::vector<const DexFile*>& dex_files, 73 ArrayRef<const uint8_t> data); 74 75 // Merge `other` into this `VerifierDeps`'. `other` and `this` must be for the 76 // same set of dex files. 77 EXPORT void MergeWith(std::unique_ptr<VerifierDeps> other, 78 const std::vector<const DexFile*>& dex_files); 79 80 // Record information that a class was verified. 81 // Note that this function is different from MaybeRecordVerificationStatus() which 82 // looks up thread-local VerifierDeps first. 83 void RecordClassVerified(const DexFile& dex_file, const dex::ClassDef& class_def) 84 REQUIRES(!Locks::verifier_deps_lock_); 85 86 // Record the verification status of the class defined in `class_def`. 87 EXPORT static void MaybeRecordVerificationStatus(VerifierDeps* verifier_deps, 88 const DexFile& dex_file, 89 const dex::ClassDef& class_def, 90 FailureKind failure_kind) 91 REQUIRES(!Locks::verifier_deps_lock_); 92 93 // Record the outcome `is_assignable` of type assignability test from `source` 94 // to `destination` as defined by RegType::AssignableFrom. `dex_file` is the 95 // owner of the method for which MethodVerifier performed the assignability test. 96 static void MaybeRecordAssignability(VerifierDeps* verifier_deps, 97 const DexFile& dex_file, 98 const dex::ClassDef& class_def, 99 ObjPtr<mirror::Class> destination, 100 ObjPtr<mirror::Class> source) 101 REQUIRES_SHARED(Locks::mutator_lock_) 102 REQUIRES(!Locks::verifier_deps_lock_); 103 104 // Record that `source` is assignable to `destination`. `dex_file` is the 105 // owner of the method for which MethodVerifier performed the assignability test. 106 static void MaybeRecordAssignability(VerifierDeps* verifier_deps, 107 const DexFile& dex_file, 108 const dex::ClassDef& class_def, 109 const RegType& destination, 110 const RegType& source) 111 REQUIRES_SHARED(Locks::mutator_lock_) 112 REQUIRES(!Locks::verifier_deps_lock_); 113 114 // Serialize the recorded dependencies and store the data into `buffer`. 115 // `dex_files` provides the order of the dex files in which the dependencies 116 // should be emitted. 117 EXPORT void Encode(const std::vector<const DexFile*>& dex_files, 118 std::vector<uint8_t>* buffer) const; 119 120 EXPORT void Dump(VariableIndentationOutputStream* vios) const; 121 122 // Verifies the encoded dependencies of this `VerifierDeps` are still valid. 123 // Returns whether all dependencies were validated. 124 EXPORT bool ValidateDependenciesAndUpdateStatus( 125 Thread* self, 126 Handle<mirror::ClassLoader> class_loader, 127 const std::vector<const DexFile*>& dex_files) 128 REQUIRES_SHARED(Locks::mutator_lock_); 129 GetVerifiedClasses(const DexFile & dex_file)130 const std::vector<bool>& GetVerifiedClasses(const DexFile& dex_file) const { 131 return GetDexFileDeps(dex_file)->verified_classes_; 132 } 133 134 // Whether this `verifier_deps` has recorded that the given class is verified. 135 bool HasRecordedVerifiedStatus(const DexFile& dex_file, const dex::ClassDef& class_def) 136 REQUIRES(!Locks::verifier_deps_lock_); 137 OutputOnly()138 bool OutputOnly() const { 139 return output_only_; 140 } 141 ContainsDexFile(const DexFile & dex_file)142 bool ContainsDexFile(const DexFile& dex_file) const { 143 return GetDexFileDeps(dex_file) != nullptr; 144 } 145 146 // Parses raw VerifierDeps data to extract bitvectors of which class def indices 147 // were verified or not. The given `dex_files` must match the order and count of 148 // dex files used to create the VerifierDeps. 149 static bool ParseVerifiedClasses( 150 const std::vector<const DexFile*>& dex_files, 151 ArrayRef<const uint8_t> data, 152 /*out*/std::vector<std::vector<bool>>* verified_classes_per_dex); 153 154 using TypeAssignabilityBase = std::tuple<dex::StringIndex, dex::StringIndex>; 155 struct TypeAssignability : public TypeAssignabilityBase { 156 TypeAssignability() = default; 157 TypeAssignability(const TypeAssignability&) = default; TypeAssignabilityTypeAssignability158 TypeAssignability(dex::StringIndex destination_idx, dex::StringIndex source_idx) 159 : TypeAssignabilityBase(destination_idx, source_idx) {} 160 GetDestinationTypeAssignability161 dex::StringIndex GetDestination() const { return std::get<0>(*this); } GetSourceTypeAssignability162 dex::StringIndex GetSource() const { return std::get<1>(*this); } 163 }; 164 165 private: 166 // Data structure representing dependencies collected during verification of 167 // methods inside one DexFile. 168 struct DexFileDeps { DexFileDepsDexFileDeps169 explicit DexFileDeps(size_t num_class_defs) 170 : assignable_types_(num_class_defs), 171 verified_classes_(num_class_defs) {} 172 173 // Vector of strings which are not present in the corresponding DEX file. 174 // These are referred to with ids starting with `NumStringIds()` of that DexFile. 175 std::vector<std::string> strings_; 176 177 // Vector that contains for each class def defined in a dex file, a set of class pairs recording 178 // the outcome of assignability test from one of the two types to the other. 179 std::vector<std::set<TypeAssignability>> assignable_types_; 180 181 // Bit vector indexed by class def indices indicating whether the corresponding 182 // class was successfully verified. 183 std::vector<bool> verified_classes_; 184 185 bool Equals(const DexFileDeps& rhs) const; 186 }; 187 188 // Helper function to share DexFileDeps decoding code. 189 // Returns true on success, false on failure. 190 template <bool kOnlyVerifiedClasses> 191 static bool DecodeDexFileDeps(DexFileDeps& deps, 192 const uint8_t** cursor, 193 const uint8_t* data_start, 194 const uint8_t* data_end, 195 size_t num_class_defs); 196 197 // Finds the DexFileDep instance associated with `dex_file`, or nullptr if 198 // `dex_file` is not reported as being compiled. 199 DexFileDeps* GetDexFileDeps(const DexFile& dex_file); 200 201 EXPORT const DexFileDeps* GetDexFileDeps(const DexFile& dex_file) const; 202 203 // Returns the index of `str`. If it is defined in `dex_file_`, this is the dex 204 // string ID. If not, an ID is assigned to the string and cached in `strings_` 205 // of the corresponding DexFileDeps structure (either provided or inferred from 206 // `dex_file`). 207 dex::StringIndex GetIdFromString(const DexFile& dex_file, const std::string& str) 208 REQUIRES(!Locks::verifier_deps_lock_); 209 210 // Returns the string represented by `id`. 211 std::string GetStringFromId(const DexFile& dex_file, dex::StringIndex string_id) const; 212 213 // Returns a string ID of the descriptor of the class. 214 dex::StringIndex GetClassDescriptorStringId(const DexFile& dex_file, ObjPtr<mirror::Class> klass) 215 REQUIRES_SHARED(Locks::mutator_lock_) 216 REQUIRES(!Locks::verifier_deps_lock_); 217 218 void AddAssignability(const DexFile& dex_file, 219 const dex::ClassDef& class_def, 220 ObjPtr<mirror::Class> destination, 221 ObjPtr<mirror::Class> source) 222 REQUIRES_SHARED(Locks::mutator_lock_); 223 224 void AddAssignability(const DexFile& dex_file, 225 const dex::ClassDef& class_def, 226 const RegType& destination, 227 const RegType& source) 228 REQUIRES_SHARED(Locks::mutator_lock_); 229 230 bool Equals(const VerifierDeps& rhs) const; 231 232 // Verify `dex_file` according to the `deps`, that is going over each 233 // `DexFileDeps` field, and checking that the recorded information still 234 // holds. 235 // Returns whether all dependencies were validated. 236 bool VerifyDexFileAndUpdateStatus( 237 Handle<mirror::ClassLoader> class_loader, 238 const DexFile& dex_file, 239 DexFileDeps& deps, 240 Thread* self) 241 REQUIRES_SHARED(Locks::mutator_lock_); 242 243 // Iterates over `dex_files` and tries to find a class def matching `descriptor`. 244 // Returns true if such class def is found. 245 bool IsInDexFiles(const char* descriptor, 246 size_t hash, 247 const std::vector<const DexFile*>& dex_files, 248 /* out */ const DexFile** cp_dex_file) const; 249 250 // Map from DexFiles into dependencies collected from verification of their methods. 251 std::map<const DexFile*, std::unique_ptr<DexFileDeps>> dex_deps_; 252 253 // Output only signifies if we are using the verifier deps to verify or just to generate them. 254 const bool output_only_; 255 256 friend class VerifierDepsTest; 257 ART_FRIEND_TEST(VerifierDepsTest, StringToId); 258 ART_FRIEND_TEST(VerifierDepsTest, EncodeDecode); 259 ART_FRIEND_TEST(VerifierDepsTest, EncodeDecodeMulti); 260 ART_FRIEND_TEST(VerifierDepsTest, VerifyDeps); 261 ART_FRIEND_TEST(VerifierDepsTest, CompilerDriver); 262 }; 263 264 } // namespace verifier 265 } // namespace art 266 267 #endif // ART_RUNTIME_VERIFIER_VERIFIER_DEPS_H_ 268