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