blob: 9d2622de3a920c68d15886bd358849cfb8756335 [file] [log] [blame]
David Brazdilca3c8c32016-09-06 14:04:48 +01001/*
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 "art_field.h"
25#include "art_method.h"
David Brazdil6f82fbd2016-09-14 11:55:26 +010026#include "base/array_ref.h"
David Brazdilca3c8c32016-09-06 14:04:48 +010027#include "base/mutex.h"
28#include "method_resolution_kind.h"
Nicolas Geoffray08025182016-10-25 17:20:18 +010029#include "method_verifier.h" // For MethodVerifier::FailureKind.
Mathieu Chartier3398c782016-09-30 10:27:43 -070030#include "obj_ptr.h"
David Brazdilca3c8c32016-09-06 14:04:48 +010031#include "os.h"
32
33namespace art {
34namespace verifier {
35
36// Verification dependencies collector class used by the MethodVerifier to record
37// resolution outcomes and type assignability tests of classes/methods/fields
38// not present in the set of compiled DEX files, that is classes/methods/fields
39// defined in the classpath.
40// The compilation driver initializes the class and registers all DEX files
41// which are being compiled. Classes defined in DEX files outside of this set
42// (or synthesized classes without associated DEX files) are considered being
43// in the classpath.
44// During code-flow verification, the MethodVerifier informs the VerifierDeps
45// singleton about the outcome of every resolution and assignability test, and
46// the singleton records them if their outcome may change with changes in the
47// classpath.
48class VerifierDeps {
49 public:
50 explicit VerifierDeps(const std::vector<const DexFile*>& dex_files)
51 REQUIRES(!Locks::verifier_deps_lock_);
52
Nicolas Geoffray08025182016-10-25 17:20:18 +010053 // Record the verification status of the class at `type_idx`.
54 static void MaybeRecordVerificationStatus(const DexFile& dex_file,
55 uint16_t type_idx,
56 MethodVerifier::FailureKind failure_kind)
57 REQUIRES(!Locks::verifier_deps_lock_);
58
David Brazdilca3c8c32016-09-06 14:04:48 +010059 // Record the outcome `klass` of resolving type `type_idx` from `dex_file`.
60 // If `klass` is null, the class is assumed unresolved.
61 static void MaybeRecordClassResolution(const DexFile& dex_file,
62 uint16_t type_idx,
63 mirror::Class* klass)
64 REQUIRES_SHARED(Locks::mutator_lock_)
65 REQUIRES(!Locks::verifier_deps_lock_);
66
67 // Record the outcome `field` of resolving field `field_idx` from `dex_file`.
68 // If `field` is null, the field is assumed unresolved.
69 static void MaybeRecordFieldResolution(const DexFile& dex_file,
70 uint32_t field_idx,
71 ArtField* field)
72 REQUIRES_SHARED(Locks::mutator_lock_)
73 REQUIRES(!Locks::verifier_deps_lock_);
74
75 // Record the outcome `method` of resolving method `method_idx` from `dex_file`
76 // using `res_kind` kind of method resolution algorithm. If `method` is null,
77 // the method is assumed unresolved.
78 static void MaybeRecordMethodResolution(const DexFile& dex_file,
79 uint32_t method_idx,
80 MethodResolutionKind res_kind,
81 ArtMethod* method)
82 REQUIRES_SHARED(Locks::mutator_lock_)
83 REQUIRES(!Locks::verifier_deps_lock_);
84
85 // Record the outcome `is_assignable` of type assignability test from `source`
86 // to `destination` as defined by RegType::AssignableFrom. `dex_file` is the
87 // owner of the method for which MethodVerifier performed the assignability test.
88 static void MaybeRecordAssignability(const DexFile& dex_file,
89 mirror::Class* destination,
90 mirror::Class* source,
91 bool is_strict,
92 bool is_assignable)
93 REQUIRES_SHARED(Locks::mutator_lock_)
94 REQUIRES(!Locks::verifier_deps_lock_);
95
David Brazdil6f82fbd2016-09-14 11:55:26 +010096 // Serialize the recorded dependencies and store the data into `buffer`.
97 void Encode(std::vector<uint8_t>* buffer) const
98 REQUIRES(!Locks::verifier_deps_lock_);
99
David Brazdilca3c8c32016-09-06 14:04:48 +0100100 private:
101 static constexpr uint16_t kUnresolvedMarker = static_cast<uint16_t>(-1);
102
David Brazdil6f82fbd2016-09-14 11:55:26 +0100103 // Only used in tests to reconstruct the data structure from serialized data.
104 VerifierDeps(const std::vector<const DexFile*>& dex_files, ArrayRef<uint8_t> data)
105 REQUIRES(!Locks::verifier_deps_lock_);
106
David Brazdilca3c8c32016-09-06 14:04:48 +0100107 using ClassResolutionBase = std::tuple<uint32_t, uint16_t>;
108 struct ClassResolution : public ClassResolutionBase {
David Brazdil6f82fbd2016-09-14 11:55:26 +0100109 ClassResolution() = default;
110 ClassResolution(const ClassResolution&) = default;
David Brazdilca3c8c32016-09-06 14:04:48 +0100111 ClassResolution(uint32_t type_idx, uint16_t access_flags)
112 : ClassResolutionBase(type_idx, access_flags) {}
David Brazdilca3c8c32016-09-06 14:04:48 +0100113
114 bool IsResolved() const { return GetAccessFlags() != kUnresolvedMarker; }
115 uint32_t GetDexTypeIndex() const { return std::get<0>(*this); }
116 uint16_t GetAccessFlags() const { return std::get<1>(*this); }
117 };
118
119 using FieldResolutionBase = std::tuple<uint32_t, uint16_t, uint32_t>;
120 struct FieldResolution : public FieldResolutionBase {
David Brazdil6f82fbd2016-09-14 11:55:26 +0100121 FieldResolution() = default;
122 FieldResolution(const FieldResolution&) = default;
David Brazdilca3c8c32016-09-06 14:04:48 +0100123 FieldResolution(uint32_t field_idx, uint16_t access_flags, uint32_t declaring_class_idx)
124 : FieldResolutionBase(field_idx, access_flags, declaring_class_idx) {}
David Brazdilca3c8c32016-09-06 14:04:48 +0100125
126 bool IsResolved() const { return GetAccessFlags() != kUnresolvedMarker; }
127 uint32_t GetDexFieldIndex() const { return std::get<0>(*this); }
128 uint16_t GetAccessFlags() const { return std::get<1>(*this); }
129 uint32_t GetDeclaringClassIndex() const { return std::get<2>(*this); }
130 };
131
132 using MethodResolutionBase = std::tuple<uint32_t, uint16_t, uint32_t>;
133 struct MethodResolution : public MethodResolutionBase {
David Brazdil6f82fbd2016-09-14 11:55:26 +0100134 MethodResolution() = default;
135 MethodResolution(const MethodResolution&) = default;
David Brazdilca3c8c32016-09-06 14:04:48 +0100136 MethodResolution(uint32_t method_idx, uint16_t access_flags, uint32_t declaring_class_idx)
137 : MethodResolutionBase(method_idx, access_flags, declaring_class_idx) {}
David Brazdilca3c8c32016-09-06 14:04:48 +0100138
139 bool IsResolved() const { return GetAccessFlags() != kUnresolvedMarker; }
140 uint32_t GetDexMethodIndex() const { return std::get<0>(*this); }
141 uint16_t GetAccessFlags() const { return std::get<1>(*this); }
142 uint32_t GetDeclaringClassIndex() const { return std::get<2>(*this); }
143 };
144
145 using TypeAssignabilityBase = std::tuple<uint32_t, uint32_t>;
Nicolas Geoffray08025182016-10-25 17:20:18 +0100146 struct TypeAssignability : public TypeAssignabilityBase {
David Brazdil6f82fbd2016-09-14 11:55:26 +0100147 TypeAssignability() = default;
148 TypeAssignability(const TypeAssignability&) = default;
David Brazdilca3c8c32016-09-06 14:04:48 +0100149 TypeAssignability(uint32_t destination_idx, uint32_t source_idx)
150 : TypeAssignabilityBase(destination_idx, source_idx) {}
David Brazdilca3c8c32016-09-06 14:04:48 +0100151
152 uint32_t GetDestination() const { return std::get<0>(*this); }
153 uint32_t GetSource() const { return std::get<1>(*this); }
154 };
155
156 // Data structure representing dependencies collected during verification of
157 // methods inside one DexFile.
158 struct DexFileDeps {
159 // Vector of strings which are not present in the corresponding DEX file.
160 // These are referred to with ids starting with `NumStringIds()` of that DexFile.
161 std::vector<std::string> strings_;
162
163 // Set of class pairs recording the outcome of assignability test from one
164 // of the two types to the other.
165 std::set<TypeAssignability> assignable_types_;
166 std::set<TypeAssignability> unassignable_types_;
167
168 // Sets of recorded class/field/method resolutions.
169 std::set<ClassResolution> classes_;
170 std::set<FieldResolution> fields_;
171 std::set<MethodResolution> direct_methods_;
172 std::set<MethodResolution> virtual_methods_;
173 std::set<MethodResolution> interface_methods_;
David Brazdil6f82fbd2016-09-14 11:55:26 +0100174
Nicolas Geoffray08025182016-10-25 17:20:18 +0100175 // List of classes that were not fully verified in that dex file.
176 std::vector<uint16_t> unverified_classes_;
177
David Brazdil6f82fbd2016-09-14 11:55:26 +0100178 bool Equals(const DexFileDeps& rhs) const;
David Brazdilca3c8c32016-09-06 14:04:48 +0100179 };
180
181 // Finds the DexFileDep instance associated with `dex_file`, or nullptr if
182 // `dex_file` is not reported as being compiled.
183 // We disable thread safety analysis. The method only reads the key set of
184 // `dex_deps_` which stays constant after initialization.
185 DexFileDeps* GetDexFileDeps(const DexFile& dex_file)
186 NO_THREAD_SAFETY_ANALYSIS;
187
188 // Returns true if `klass` is null or not defined in any of dex files which
189 // were reported as being compiled.
Mathieu Chartier3398c782016-09-30 10:27:43 -0700190 bool IsInClassPath(ObjPtr<mirror::Class> klass)
David Brazdilca3c8c32016-09-06 14:04:48 +0100191 REQUIRES_SHARED(Locks::mutator_lock_);
192
193 // Returns the index of `str`. If it is defined in `dex_file_`, this is the dex
194 // string ID. If not, an ID is assigned to the string and cached in `strings_`
195 // of the corresponding DexFileDeps structure (either provided or inferred from
196 // `dex_file`).
197 uint32_t GetIdFromString(const DexFile& dex_file, const std::string& str)
198 REQUIRES(Locks::verifier_deps_lock_);
199
200 // Returns the string represented by `id`.
201 std::string GetStringFromId(const DexFile& dex_file, uint32_t string_id)
202 REQUIRES(Locks::verifier_deps_lock_);
203
204 // Returns the bytecode access flags of `element` (bottom 16 bits), or
205 // `kUnresolvedMarker` if `element` is null.
206 template <typename T>
207 uint16_t GetAccessFlags(T* element)
208 REQUIRES_SHARED(Locks::mutator_lock_);
209
210 // Returns a string ID of the descriptor of the declaring class of `element`,
211 // or `kUnresolvedMarker` if `element` is null.
212 template <typename T>
213 uint32_t GetDeclaringClassStringId(const DexFile& dex_file, T* element)
214 REQUIRES_SHARED(Locks::mutator_lock_)
215 REQUIRES(Locks::verifier_deps_lock_);
216
217 void AddClassResolution(const DexFile& dex_file,
218 uint16_t type_idx,
219 mirror::Class* klass)
220 REQUIRES_SHARED(Locks::mutator_lock_)
221 REQUIRES(!Locks::verifier_deps_lock_);
222
223 void AddFieldResolution(const DexFile& dex_file,
224 uint32_t field_idx,
225 ArtField* field)
226 REQUIRES_SHARED(Locks::mutator_lock_)
227 REQUIRES(!Locks::verifier_deps_lock_);
228
229 void AddMethodResolution(const DexFile& dex_file,
230 uint32_t method_idx,
231 MethodResolutionKind res_kind,
232 ArtMethod* method)
233 REQUIRES_SHARED(Locks::mutator_lock_)
234 REQUIRES(!Locks::verifier_deps_lock_);
235
236 void AddAssignability(const DexFile& dex_file,
237 mirror::Class* destination,
238 mirror::Class* source,
239 bool is_strict,
240 bool is_assignable)
241 REQUIRES_SHARED(Locks::mutator_lock_)
242 REQUIRES(!Locks::verifier_deps_lock_);
243
David Brazdil6f82fbd2016-09-14 11:55:26 +0100244 bool Equals(const VerifierDeps& rhs) const
245 REQUIRES(!Locks::verifier_deps_lock_);
246
David Brazdilca3c8c32016-09-06 14:04:48 +0100247 // Map from DexFiles into dependencies collected from verification of their methods.
248 std::map<const DexFile*, std::unique_ptr<DexFileDeps>> dex_deps_
249 GUARDED_BY(Locks::verifier_deps_lock_);
250
251 friend class VerifierDepsTest;
252 ART_FRIEND_TEST(VerifierDepsTest, StringToId);
David Brazdil6f82fbd2016-09-14 11:55:26 +0100253 ART_FRIEND_TEST(VerifierDepsTest, EncodeDecode);
David Brazdilca3c8c32016-09-06 14:04:48 +0100254};
255
256} // namespace verifier
257} // namespace art
258
259#endif // ART_RUNTIME_VERIFIER_VERIFIER_DEPS_H_