blob: dc8dfaf2f1cdb7975c4e5876764c7e0d4bc04de6 [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"
29#include "os.h"
30
31namespace art {
32namespace verifier {
33
34// Verification dependencies collector class used by the MethodVerifier to record
35// resolution outcomes and type assignability tests of classes/methods/fields
36// not present in the set of compiled DEX files, that is classes/methods/fields
37// defined in the classpath.
38// The compilation driver initializes the class and registers all DEX files
39// which are being compiled. Classes defined in DEX files outside of this set
40// (or synthesized classes without associated DEX files) are considered being
41// in the classpath.
42// During code-flow verification, the MethodVerifier informs the VerifierDeps
43// singleton about the outcome of every resolution and assignability test, and
44// the singleton records them if their outcome may change with changes in the
45// classpath.
46class VerifierDeps {
47 public:
48 explicit VerifierDeps(const std::vector<const DexFile*>& dex_files)
49 REQUIRES(!Locks::verifier_deps_lock_);
50
51 // Record the outcome `klass` of resolving type `type_idx` from `dex_file`.
52 // If `klass` is null, the class is assumed unresolved.
53 static void MaybeRecordClassResolution(const DexFile& dex_file,
54 uint16_t type_idx,
55 mirror::Class* klass)
56 REQUIRES_SHARED(Locks::mutator_lock_)
57 REQUIRES(!Locks::verifier_deps_lock_);
58
59 // Record the outcome `field` of resolving field `field_idx` from `dex_file`.
60 // If `field` is null, the field is assumed unresolved.
61 static void MaybeRecordFieldResolution(const DexFile& dex_file,
62 uint32_t field_idx,
63 ArtField* field)
64 REQUIRES_SHARED(Locks::mutator_lock_)
65 REQUIRES(!Locks::verifier_deps_lock_);
66
67 // Record the outcome `method` of resolving method `method_idx` from `dex_file`
68 // using `res_kind` kind of method resolution algorithm. If `method` is null,
69 // the method is assumed unresolved.
70 static void MaybeRecordMethodResolution(const DexFile& dex_file,
71 uint32_t method_idx,
72 MethodResolutionKind res_kind,
73 ArtMethod* method)
74 REQUIRES_SHARED(Locks::mutator_lock_)
75 REQUIRES(!Locks::verifier_deps_lock_);
76
77 // Record the outcome `is_assignable` of type assignability test from `source`
78 // to `destination` as defined by RegType::AssignableFrom. `dex_file` is the
79 // owner of the method for which MethodVerifier performed the assignability test.
80 static void MaybeRecordAssignability(const DexFile& dex_file,
81 mirror::Class* destination,
82 mirror::Class* source,
83 bool is_strict,
84 bool is_assignable)
85 REQUIRES_SHARED(Locks::mutator_lock_)
86 REQUIRES(!Locks::verifier_deps_lock_);
87
David Brazdil6f82fbd2016-09-14 11:55:26 +010088 // Serialize the recorded dependencies and store the data into `buffer`.
89 void Encode(std::vector<uint8_t>* buffer) const
90 REQUIRES(!Locks::verifier_deps_lock_);
91
David Brazdilca3c8c32016-09-06 14:04:48 +010092 private:
93 static constexpr uint16_t kUnresolvedMarker = static_cast<uint16_t>(-1);
94
David Brazdil6f82fbd2016-09-14 11:55:26 +010095 // Only used in tests to reconstruct the data structure from serialized data.
96 VerifierDeps(const std::vector<const DexFile*>& dex_files, ArrayRef<uint8_t> data)
97 REQUIRES(!Locks::verifier_deps_lock_);
98
David Brazdilca3c8c32016-09-06 14:04:48 +010099 using ClassResolutionBase = std::tuple<uint32_t, uint16_t>;
100 struct ClassResolution : public ClassResolutionBase {
David Brazdil6f82fbd2016-09-14 11:55:26 +0100101 ClassResolution() = default;
102 ClassResolution(const ClassResolution&) = default;
David Brazdilca3c8c32016-09-06 14:04:48 +0100103 ClassResolution(uint32_t type_idx, uint16_t access_flags)
104 : ClassResolutionBase(type_idx, access_flags) {}
David Brazdilca3c8c32016-09-06 14:04:48 +0100105
106 bool IsResolved() const { return GetAccessFlags() != kUnresolvedMarker; }
107 uint32_t GetDexTypeIndex() const { return std::get<0>(*this); }
108 uint16_t GetAccessFlags() const { return std::get<1>(*this); }
109 };
110
111 using FieldResolutionBase = std::tuple<uint32_t, uint16_t, uint32_t>;
112 struct FieldResolution : public FieldResolutionBase {
David Brazdil6f82fbd2016-09-14 11:55:26 +0100113 FieldResolution() = default;
114 FieldResolution(const FieldResolution&) = default;
David Brazdilca3c8c32016-09-06 14:04:48 +0100115 FieldResolution(uint32_t field_idx, uint16_t access_flags, uint32_t declaring_class_idx)
116 : FieldResolutionBase(field_idx, access_flags, declaring_class_idx) {}
David Brazdilca3c8c32016-09-06 14:04:48 +0100117
118 bool IsResolved() const { return GetAccessFlags() != kUnresolvedMarker; }
119 uint32_t GetDexFieldIndex() const { return std::get<0>(*this); }
120 uint16_t GetAccessFlags() const { return std::get<1>(*this); }
121 uint32_t GetDeclaringClassIndex() const { return std::get<2>(*this); }
122 };
123
124 using MethodResolutionBase = std::tuple<uint32_t, uint16_t, uint32_t>;
125 struct MethodResolution : public MethodResolutionBase {
David Brazdil6f82fbd2016-09-14 11:55:26 +0100126 MethodResolution() = default;
127 MethodResolution(const MethodResolution&) = default;
David Brazdilca3c8c32016-09-06 14:04:48 +0100128 MethodResolution(uint32_t method_idx, uint16_t access_flags, uint32_t declaring_class_idx)
129 : MethodResolutionBase(method_idx, access_flags, declaring_class_idx) {}
David Brazdilca3c8c32016-09-06 14:04:48 +0100130
131 bool IsResolved() const { return GetAccessFlags() != kUnresolvedMarker; }
132 uint32_t GetDexMethodIndex() const { return std::get<0>(*this); }
133 uint16_t GetAccessFlags() const { return std::get<1>(*this); }
134 uint32_t GetDeclaringClassIndex() const { return std::get<2>(*this); }
135 };
136
137 using TypeAssignabilityBase = std::tuple<uint32_t, uint32_t>;
138 struct TypeAssignability : public std::tuple<uint32_t, uint32_t> {
David Brazdil6f82fbd2016-09-14 11:55:26 +0100139 TypeAssignability() = default;
140 TypeAssignability(const TypeAssignability&) = default;
David Brazdilca3c8c32016-09-06 14:04:48 +0100141 TypeAssignability(uint32_t destination_idx, uint32_t source_idx)
142 : TypeAssignabilityBase(destination_idx, source_idx) {}
David Brazdilca3c8c32016-09-06 14:04:48 +0100143
144 uint32_t GetDestination() const { return std::get<0>(*this); }
145 uint32_t GetSource() const { return std::get<1>(*this); }
146 };
147
148 // Data structure representing dependencies collected during verification of
149 // methods inside one DexFile.
150 struct DexFileDeps {
151 // Vector of strings which are not present in the corresponding DEX file.
152 // These are referred to with ids starting with `NumStringIds()` of that DexFile.
153 std::vector<std::string> strings_;
154
155 // Set of class pairs recording the outcome of assignability test from one
156 // of the two types to the other.
157 std::set<TypeAssignability> assignable_types_;
158 std::set<TypeAssignability> unassignable_types_;
159
160 // Sets of recorded class/field/method resolutions.
161 std::set<ClassResolution> classes_;
162 std::set<FieldResolution> fields_;
163 std::set<MethodResolution> direct_methods_;
164 std::set<MethodResolution> virtual_methods_;
165 std::set<MethodResolution> interface_methods_;
David Brazdil6f82fbd2016-09-14 11:55:26 +0100166
167 bool Equals(const DexFileDeps& rhs) const;
David Brazdilca3c8c32016-09-06 14:04:48 +0100168 };
169
170 // Finds the DexFileDep instance associated with `dex_file`, or nullptr if
171 // `dex_file` is not reported as being compiled.
172 // We disable thread safety analysis. The method only reads the key set of
173 // `dex_deps_` which stays constant after initialization.
174 DexFileDeps* GetDexFileDeps(const DexFile& dex_file)
175 NO_THREAD_SAFETY_ANALYSIS;
176
177 // Returns true if `klass` is null or not defined in any of dex files which
178 // were reported as being compiled.
179 bool IsInClassPath(mirror::Class* klass)
180 REQUIRES_SHARED(Locks::mutator_lock_);
181
182 // Returns the index of `str`. If it is defined in `dex_file_`, this is the dex
183 // string ID. If not, an ID is assigned to the string and cached in `strings_`
184 // of the corresponding DexFileDeps structure (either provided or inferred from
185 // `dex_file`).
186 uint32_t GetIdFromString(const DexFile& dex_file, const std::string& str)
187 REQUIRES(Locks::verifier_deps_lock_);
188
189 // Returns the string represented by `id`.
190 std::string GetStringFromId(const DexFile& dex_file, uint32_t string_id)
191 REQUIRES(Locks::verifier_deps_lock_);
192
193 // Returns the bytecode access flags of `element` (bottom 16 bits), or
194 // `kUnresolvedMarker` if `element` is null.
195 template <typename T>
196 uint16_t GetAccessFlags(T* element)
197 REQUIRES_SHARED(Locks::mutator_lock_);
198
199 // Returns a string ID of the descriptor of the declaring class of `element`,
200 // or `kUnresolvedMarker` if `element` is null.
201 template <typename T>
202 uint32_t GetDeclaringClassStringId(const DexFile& dex_file, T* element)
203 REQUIRES_SHARED(Locks::mutator_lock_)
204 REQUIRES(Locks::verifier_deps_lock_);
205
206 void AddClassResolution(const DexFile& dex_file,
207 uint16_t type_idx,
208 mirror::Class* klass)
209 REQUIRES_SHARED(Locks::mutator_lock_)
210 REQUIRES(!Locks::verifier_deps_lock_);
211
212 void AddFieldResolution(const DexFile& dex_file,
213 uint32_t field_idx,
214 ArtField* field)
215 REQUIRES_SHARED(Locks::mutator_lock_)
216 REQUIRES(!Locks::verifier_deps_lock_);
217
218 void AddMethodResolution(const DexFile& dex_file,
219 uint32_t method_idx,
220 MethodResolutionKind res_kind,
221 ArtMethod* method)
222 REQUIRES_SHARED(Locks::mutator_lock_)
223 REQUIRES(!Locks::verifier_deps_lock_);
224
225 void AddAssignability(const DexFile& dex_file,
226 mirror::Class* destination,
227 mirror::Class* source,
228 bool is_strict,
229 bool is_assignable)
230 REQUIRES_SHARED(Locks::mutator_lock_)
231 REQUIRES(!Locks::verifier_deps_lock_);
232
David Brazdil6f82fbd2016-09-14 11:55:26 +0100233 bool Equals(const VerifierDeps& rhs) const
234 REQUIRES(!Locks::verifier_deps_lock_);
235
David Brazdilca3c8c32016-09-06 14:04:48 +0100236 // Map from DexFiles into dependencies collected from verification of their methods.
237 std::map<const DexFile*, std::unique_ptr<DexFileDeps>> dex_deps_
238 GUARDED_BY(Locks::verifier_deps_lock_);
239
240 friend class VerifierDepsTest;
241 ART_FRIEND_TEST(VerifierDepsTest, StringToId);
David Brazdil6f82fbd2016-09-14 11:55:26 +0100242 ART_FRIEND_TEST(VerifierDepsTest, EncodeDecode);
David Brazdilca3c8c32016-09-06 14:04:48 +0100243};
244
245} // namespace verifier
246} // namespace art
247
248#endif // ART_RUNTIME_VERIFIER_VERIFIER_DEPS_H_