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