blob: 8a0f4cfa31aa813ef4217c54b9b92bfde9da78ae [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#include "verifier_deps.h"
18
19#include "compiler_callbacks.h"
David Brazdil6f82fbd2016-09-14 11:55:26 +010020#include "leb128.h"
David Brazdilca3c8c32016-09-06 14:04:48 +010021#include "mirror/class-inl.h"
Mathieu Chartier3398c782016-09-30 10:27:43 -070022#include "obj_ptr-inl.h"
David Brazdilca3c8c32016-09-06 14:04:48 +010023#include "runtime.h"
24
25namespace art {
26namespace verifier {
27
28VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files) {
29 MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
30 for (const DexFile* dex_file : dex_files) {
31 DCHECK(GetDexFileDeps(*dex_file) == nullptr);
32 std::unique_ptr<DexFileDeps> deps(new DexFileDeps());
33 dex_deps_.emplace(dex_file, std::move(deps));
34 }
35}
36
37VerifierDeps::DexFileDeps* VerifierDeps::GetDexFileDeps(const DexFile& dex_file) {
38 auto it = dex_deps_.find(&dex_file);
39 return (it == dex_deps_.end()) ? nullptr : it->second.get();
40}
41
Nicolas Geoffrayd01f60c2016-10-28 14:45:48 +010042const VerifierDeps::DexFileDeps* VerifierDeps::GetDexFileDeps(const DexFile& dex_file) const {
43 auto it = dex_deps_.find(&dex_file);
44 return (it == dex_deps_.end()) ? nullptr : it->second.get();
45}
46
David Brazdilca3c8c32016-09-06 14:04:48 +010047template <typename T>
48uint16_t VerifierDeps::GetAccessFlags(T* element) {
49 static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
50 if (element == nullptr) {
51 return VerifierDeps::kUnresolvedMarker;
52 } else {
53 uint16_t access_flags = Low16Bits(element->GetAccessFlags());
54 CHECK_NE(access_flags, VerifierDeps::kUnresolvedMarker);
55 return access_flags;
56 }
57}
58
59template <typename T>
60uint32_t VerifierDeps::GetDeclaringClassStringId(const DexFile& dex_file, T* element) {
61 static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
62 if (element == nullptr) {
63 return VerifierDeps::kUnresolvedMarker;
64 } else {
65 std::string temp;
66 uint32_t string_id = GetIdFromString(
67 dex_file, element->GetDeclaringClass()->GetDescriptor(&temp));
68 return string_id;
69 }
70}
71
72uint32_t VerifierDeps::GetIdFromString(const DexFile& dex_file, const std::string& str) {
73 const DexFile::StringId* string_id = dex_file.FindStringId(str.c_str());
74 if (string_id != nullptr) {
75 // String is in the DEX file. Return its ID.
76 return dex_file.GetIndexForStringId(*string_id);
77 }
78
79 // String is not in the DEX file. Assign a new ID to it which is higher than
80 // the number of strings in the DEX file.
81
82 DexFileDeps* deps = GetDexFileDeps(dex_file);
83 DCHECK(deps != nullptr);
84
85 uint32_t num_ids_in_dex = dex_file.NumStringIds();
86 uint32_t num_extra_ids = deps->strings_.size();
87
88 for (size_t i = 0; i < num_extra_ids; ++i) {
89 if (deps->strings_[i] == str) {
90 return num_ids_in_dex + i;
91 }
92 }
93
94 deps->strings_.push_back(str);
95
96 uint32_t new_id = num_ids_in_dex + num_extra_ids;
97 CHECK_GE(new_id, num_ids_in_dex); // check for overflows
98 DCHECK_EQ(str, GetStringFromId(dex_file, new_id));
99
100 return new_id;
101}
102
Nicolas Geoffrayd01f60c2016-10-28 14:45:48 +0100103std::string VerifierDeps::GetStringFromId(const DexFile& dex_file, uint32_t string_id) const {
David Brazdilca3c8c32016-09-06 14:04:48 +0100104 uint32_t num_ids_in_dex = dex_file.NumStringIds();
105 if (string_id < num_ids_in_dex) {
106 return std::string(dex_file.StringDataByIdx(string_id));
107 } else {
Nicolas Geoffrayd01f60c2016-10-28 14:45:48 +0100108 const DexFileDeps* deps = GetDexFileDeps(dex_file);
David Brazdilca3c8c32016-09-06 14:04:48 +0100109 DCHECK(deps != nullptr);
110 string_id -= num_ids_in_dex;
111 CHECK_LT(string_id, deps->strings_.size());
112 return deps->strings_[string_id];
113 }
114}
115
Nicolas Geoffrayd01f60c2016-10-28 14:45:48 +0100116bool VerifierDeps::IsInClassPath(ObjPtr<mirror::Class> klass) const {
David Brazdilca3c8c32016-09-06 14:04:48 +0100117 DCHECK(klass != nullptr);
118
Mathieu Chartier3398c782016-09-30 10:27:43 -0700119 ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache();
David Brazdilca3c8c32016-09-06 14:04:48 +0100120 if (dex_cache == nullptr) {
121 // This is a synthesized class, in this case always an array. They are not
122 // defined in the compiled DEX files and therefore are part of the classpath.
123 // We could avoid recording dependencies on arrays with component types in
124 // the compiled DEX files but we choose to record them anyway so as to
125 // record the access flags VM sets for array classes.
David Sehr709b0702016-10-13 09:12:37 -0700126 DCHECK(klass->IsArrayClass()) << klass->PrettyDescriptor();
David Brazdilca3c8c32016-09-06 14:04:48 +0100127 return true;
128 }
129
130 const DexFile* dex_file = dex_cache->GetDexFile();
131 DCHECK(dex_file != nullptr);
132
133 // Test if the `dex_deps_` contains an entry for `dex_file`. If not, the dex
134 // file was not registered as being compiled and we assume `klass` is in the
135 // classpath.
136 return (GetDexFileDeps(*dex_file) == nullptr);
137}
138
139void VerifierDeps::AddClassResolution(const DexFile& dex_file,
Andreas Gampea5b09a62016-11-17 15:21:22 -0800140 dex::TypeIndex type_idx,
David Brazdilca3c8c32016-09-06 14:04:48 +0100141 mirror::Class* klass) {
142 DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
143 if (dex_deps == nullptr) {
144 // This invocation is from verification of a dex file which is not being compiled.
145 return;
146 }
147
148 if (klass != nullptr && !IsInClassPath(klass)) {
149 // Class resolved into one of the DEX files which are being compiled.
150 // This is not a classpath dependency.
151 return;
152 }
153
154 MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
155 dex_deps->classes_.emplace(ClassResolution(type_idx, GetAccessFlags(klass)));
156}
157
158void VerifierDeps::AddFieldResolution(const DexFile& dex_file,
159 uint32_t field_idx,
160 ArtField* field) {
161 DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
162 if (dex_deps == nullptr) {
163 // This invocation is from verification of a dex file which is not being compiled.
164 return;
165 }
166
167 if (field != nullptr && !IsInClassPath(field->GetDeclaringClass())) {
168 // Field resolved into one of the DEX files which are being compiled.
169 // This is not a classpath dependency.
170 return;
171 }
172
173 MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
174 dex_deps->fields_.emplace(FieldResolution(
175 field_idx, GetAccessFlags(field), GetDeclaringClassStringId(dex_file, field)));
176}
177
178void VerifierDeps::AddMethodResolution(const DexFile& dex_file,
179 uint32_t method_idx,
180 MethodResolutionKind resolution_kind,
181 ArtMethod* method) {
182 DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
183 if (dex_deps == nullptr) {
184 // This invocation is from verification of a dex file which is not being compiled.
185 return;
186 }
187
188 if (method != nullptr && !IsInClassPath(method->GetDeclaringClass())) {
189 // Method resolved into one of the DEX files which are being compiled.
190 // This is not a classpath dependency.
191 return;
192 }
193
194 MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
195 MethodResolution method_tuple(method_idx,
196 GetAccessFlags(method),
197 GetDeclaringClassStringId(dex_file, method));
198 if (resolution_kind == kDirectMethodResolution) {
199 dex_deps->direct_methods_.emplace(method_tuple);
200 } else if (resolution_kind == kVirtualMethodResolution) {
201 dex_deps->virtual_methods_.emplace(method_tuple);
202 } else {
203 DCHECK_EQ(resolution_kind, kInterfaceMethodResolution);
204 dex_deps->interface_methods_.emplace(method_tuple);
205 }
206}
207
208void VerifierDeps::AddAssignability(const DexFile& dex_file,
209 mirror::Class* destination,
210 mirror::Class* source,
211 bool is_strict,
212 bool is_assignable) {
213 // Test that the method is only called on reference types.
214 // Note that concurrent verification of `destination` and `source` may have
215 // set their status to erroneous. However, the tests performed below rely
216 // merely on no issues with linking (valid access flags, superclass and
217 // implemented interfaces). If the class at any point reached the IsResolved
218 // status, the requirement holds. This is guaranteed by RegTypeCache::ResolveClass.
219 DCHECK(destination != nullptr && !destination->IsPrimitive());
220 DCHECK(source != nullptr && !source->IsPrimitive());
221
222 if (destination == source ||
223 destination->IsObjectClass() ||
224 (!is_strict && destination->IsInterface())) {
225 // Cases when `destination` is trivially assignable from `source`.
226 DCHECK(is_assignable);
227 return;
228 }
229
230 DCHECK_EQ(is_assignable, destination->IsAssignableFrom(source));
231
232 if (destination->IsArrayClass() && source->IsArrayClass()) {
233 // Both types are arrays. Break down to component types and add recursively.
234 // This helps filter out destinations from compiled DEX files (see below)
235 // and deduplicate entries with the same canonical component type.
236 mirror::Class* destination_component = destination->GetComponentType();
237 mirror::Class* source_component = source->GetComponentType();
238
239 // Only perform the optimization if both types are resolved which guarantees
240 // that they linked successfully, as required at the top of this method.
241 if (destination_component->IsResolved() && source_component->IsResolved()) {
242 AddAssignability(dex_file,
243 destination_component,
244 source_component,
245 /* is_strict */ true,
246 is_assignable);
247 return;
248 }
249 }
250
251 DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
252 if (dex_deps == nullptr) {
253 // This invocation is from verification of a DEX file which is not being compiled.
254 return;
255 }
256
257 if (!IsInClassPath(destination) && !IsInClassPath(source)) {
258 // Both `destination` and `source` are defined in the compiled DEX files.
259 // No need to record a dependency.
260 return;
261 }
262
263 MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
264
265 // Get string IDs for both descriptors and store in the appropriate set.
266
267 std::string temp1, temp2;
268 std::string destination_desc(destination->GetDescriptor(&temp1));
269 std::string source_desc(source->GetDescriptor(&temp2));
270 uint32_t destination_id = GetIdFromString(dex_file, destination_desc);
271 uint32_t source_id = GetIdFromString(dex_file, source_desc);
272
273 if (is_assignable) {
274 dex_deps->assignable_types_.emplace(TypeAssignability(destination_id, source_id));
275 } else {
276 dex_deps->unassignable_types_.emplace(TypeAssignability(destination_id, source_id));
277 }
278}
279
280static inline VerifierDeps* GetVerifierDepsSingleton() {
281 CompilerCallbacks* callbacks = Runtime::Current()->GetCompilerCallbacks();
282 if (callbacks == nullptr) {
283 return nullptr;
284 }
285 return callbacks->GetVerifierDeps();
286}
287
Nicolas Geoffray08025182016-10-25 17:20:18 +0100288void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file,
Andreas Gampea5b09a62016-11-17 15:21:22 -0800289 dex::TypeIndex type_idx,
Nicolas Geoffray08025182016-10-25 17:20:18 +0100290 MethodVerifier::FailureKind failure_kind) {
291 if (failure_kind == MethodVerifier::kNoFailure) {
292 // We only record classes that did not fully verify at compile time.
293 return;
294 }
295
296 VerifierDeps* singleton = GetVerifierDepsSingleton();
297 if (singleton != nullptr) {
298 DexFileDeps* dex_deps = singleton->GetDexFileDeps(dex_file);
299 MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
300 dex_deps->unverified_classes_.push_back(type_idx);
301 }
302}
303
David Brazdilca3c8c32016-09-06 14:04:48 +0100304void VerifierDeps::MaybeRecordClassResolution(const DexFile& dex_file,
Andreas Gampea5b09a62016-11-17 15:21:22 -0800305 dex::TypeIndex type_idx,
David Brazdilca3c8c32016-09-06 14:04:48 +0100306 mirror::Class* klass) {
307 VerifierDeps* singleton = GetVerifierDepsSingleton();
308 if (singleton != nullptr) {
309 singleton->AddClassResolution(dex_file, type_idx, klass);
310 }
311}
312
313void VerifierDeps::MaybeRecordFieldResolution(const DexFile& dex_file,
314 uint32_t field_idx,
315 ArtField* field) {
316 VerifierDeps* singleton = GetVerifierDepsSingleton();
317 if (singleton != nullptr) {
318 singleton->AddFieldResolution(dex_file, field_idx, field);
319 }
320}
321
322void VerifierDeps::MaybeRecordMethodResolution(const DexFile& dex_file,
323 uint32_t method_idx,
324 MethodResolutionKind resolution_kind,
325 ArtMethod* method) {
326 VerifierDeps* singleton = GetVerifierDepsSingleton();
327 if (singleton != nullptr) {
328 singleton->AddMethodResolution(dex_file, method_idx, resolution_kind, method);
329 }
330}
331
332void VerifierDeps::MaybeRecordAssignability(const DexFile& dex_file,
333 mirror::Class* destination,
334 mirror::Class* source,
335 bool is_strict,
336 bool is_assignable) {
337 VerifierDeps* singleton = GetVerifierDepsSingleton();
338 if (singleton != nullptr) {
339 singleton->AddAssignability(dex_file, destination, source, is_strict, is_assignable);
340 }
341}
342
Andreas Gampea5b09a62016-11-17 15:21:22 -0800343namespace {
344
David Brazdil6f82fbd2016-09-14 11:55:26 +0100345static inline uint32_t DecodeUint32WithOverflowCheck(const uint8_t** in, const uint8_t* end) {
346 CHECK_LT(*in, end);
347 return DecodeUnsignedLeb128(in);
348}
349
Andreas Gampea5b09a62016-11-17 15:21:22 -0800350template<typename T> inline uint32_t Encode(T in);
351
352template<> inline uint32_t Encode<uint16_t>(uint16_t in) {
353 return in;
354}
355template<> inline uint32_t Encode<uint32_t>(uint32_t in) {
356 return in;
357}
358template<> inline uint32_t Encode<dex::TypeIndex>(dex::TypeIndex in) {
359 return in.index_;
360}
361
362template<typename T> inline T Decode(uint32_t in);
363
364template<> inline uint16_t Decode<uint16_t>(uint32_t in) {
365 return dchecked_integral_cast<uint16_t>(in);
366}
367template<> inline uint32_t Decode<uint32_t>(uint32_t in) {
368 return in;
369}
370template<> inline dex::TypeIndex Decode<dex::TypeIndex>(uint32_t in) {
371 return dex::TypeIndex(in);
372}
373
David Brazdil6f82fbd2016-09-14 11:55:26 +0100374template<typename T1, typename T2>
375static inline void EncodeTuple(std::vector<uint8_t>* out, const std::tuple<T1, T2>& t) {
Andreas Gampea5b09a62016-11-17 15:21:22 -0800376 EncodeUnsignedLeb128(out, Encode(std::get<0>(t)));
377 EncodeUnsignedLeb128(out, Encode(std::get<1>(t)));
David Brazdil6f82fbd2016-09-14 11:55:26 +0100378}
379
380template<typename T1, typename T2>
381static inline void DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2>* t) {
Andreas Gampea5b09a62016-11-17 15:21:22 -0800382 T1 v1 = Decode<T1>(DecodeUint32WithOverflowCheck(in, end));
383 T2 v2 = Decode<T2>(DecodeUint32WithOverflowCheck(in, end));
David Brazdil6f82fbd2016-09-14 11:55:26 +0100384 *t = std::make_tuple(v1, v2);
385}
386
387template<typename T1, typename T2, typename T3>
388static inline void EncodeTuple(std::vector<uint8_t>* out, const std::tuple<T1, T2, T3>& t) {
Andreas Gampea5b09a62016-11-17 15:21:22 -0800389 EncodeUnsignedLeb128(out, Encode(std::get<0>(t)));
390 EncodeUnsignedLeb128(out, Encode(std::get<1>(t)));
391 EncodeUnsignedLeb128(out, Encode(std::get<2>(t)));
David Brazdil6f82fbd2016-09-14 11:55:26 +0100392}
393
394template<typename T1, typename T2, typename T3>
395static inline void DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2, T3>* t) {
Andreas Gampea5b09a62016-11-17 15:21:22 -0800396 T1 v1 = Decode<T1>(DecodeUint32WithOverflowCheck(in, end));
397 T2 v2 = Decode<T2>(DecodeUint32WithOverflowCheck(in, end));
398 T3 v3 = Decode<T2>(DecodeUint32WithOverflowCheck(in, end));
David Brazdil6f82fbd2016-09-14 11:55:26 +0100399 *t = std::make_tuple(v1, v2, v3);
400}
401
402template<typename T>
403static inline void EncodeSet(std::vector<uint8_t>* out, const std::set<T>& set) {
404 EncodeUnsignedLeb128(out, set.size());
405 for (const T& entry : set) {
406 EncodeTuple(out, entry);
407 }
408}
409
Andreas Gampea5b09a62016-11-17 15:21:22 -0800410template <typename T>
Nicolas Geoffray08025182016-10-25 17:20:18 +0100411static inline void EncodeUint16Vector(std::vector<uint8_t>* out,
Andreas Gampea5b09a62016-11-17 15:21:22 -0800412 const std::vector<T>& vector) {
Nicolas Geoffray08025182016-10-25 17:20:18 +0100413 EncodeUnsignedLeb128(out, vector.size());
Andreas Gampea5b09a62016-11-17 15:21:22 -0800414 for (const T& entry : vector) {
415 EncodeUnsignedLeb128(out, Encode(entry));
Nicolas Geoffray08025182016-10-25 17:20:18 +0100416 }
417}
418
David Brazdil6f82fbd2016-09-14 11:55:26 +0100419template<typename T>
420static inline void DecodeSet(const uint8_t** in, const uint8_t* end, std::set<T>* set) {
421 DCHECK(set->empty());
422 size_t num_entries = DecodeUint32WithOverflowCheck(in, end);
423 for (size_t i = 0; i < num_entries; ++i) {
424 T tuple;
425 DecodeTuple(in, end, &tuple);
426 set->emplace(tuple);
427 }
428}
429
Andreas Gampea5b09a62016-11-17 15:21:22 -0800430template<typename T>
Nicolas Geoffray08025182016-10-25 17:20:18 +0100431static inline void DecodeUint16Vector(const uint8_t** in,
432 const uint8_t* end,
Andreas Gampea5b09a62016-11-17 15:21:22 -0800433 std::vector<T>* vector) {
Nicolas Geoffray08025182016-10-25 17:20:18 +0100434 DCHECK(vector->empty());
435 size_t num_entries = DecodeUint32WithOverflowCheck(in, end);
436 vector->reserve(num_entries);
437 for (size_t i = 0; i < num_entries; ++i) {
Andreas Gampea5b09a62016-11-17 15:21:22 -0800438 vector->push_back(
439 Decode<T>(dchecked_integral_cast<uint16_t>(DecodeUint32WithOverflowCheck(in, end))));
Nicolas Geoffray08025182016-10-25 17:20:18 +0100440 }
441}
442
David Brazdil6f82fbd2016-09-14 11:55:26 +0100443static inline void EncodeStringVector(std::vector<uint8_t>* out,
444 const std::vector<std::string>& strings) {
445 EncodeUnsignedLeb128(out, strings.size());
446 for (const std::string& str : strings) {
447 const uint8_t* data = reinterpret_cast<const uint8_t*>(str.c_str());
448 size_t length = str.length() + 1;
449 out->insert(out->end(), data, data + length);
450 DCHECK_EQ(0u, out->back());
451 }
452}
453
454static inline void DecodeStringVector(const uint8_t** in,
455 const uint8_t* end,
456 std::vector<std::string>* strings) {
457 DCHECK(strings->empty());
458 size_t num_strings = DecodeUint32WithOverflowCheck(in, end);
459 strings->reserve(num_strings);
460 for (size_t i = 0; i < num_strings; ++i) {
461 CHECK_LT(*in, end);
462 const char* string_start = reinterpret_cast<const char*>(*in);
463 strings->emplace_back(std::string(string_start));
464 *in += strings->back().length() + 1;
465 }
466}
467
Andreas Gampea5b09a62016-11-17 15:21:22 -0800468} // namespace
469
Nicolas Geoffrayd01f60c2016-10-28 14:45:48 +0100470void VerifierDeps::Encode(const std::vector<const DexFile*>& dex_files,
471 std::vector<uint8_t>* buffer) const {
David Brazdil6f82fbd2016-09-14 11:55:26 +0100472 MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
Nicolas Geoffrayd01f60c2016-10-28 14:45:48 +0100473 for (const DexFile* dex_file : dex_files) {
474 const DexFileDeps& deps = *GetDexFileDeps(*dex_file);
475 EncodeStringVector(buffer, deps.strings_);
476 EncodeSet(buffer, deps.assignable_types_);
477 EncodeSet(buffer, deps.unassignable_types_);
478 EncodeSet(buffer, deps.classes_);
479 EncodeSet(buffer, deps.fields_);
480 EncodeSet(buffer, deps.direct_methods_);
481 EncodeSet(buffer, deps.virtual_methods_);
482 EncodeSet(buffer, deps.interface_methods_);
483 EncodeUint16Vector(buffer, deps.unverified_classes_);
David Brazdil6f82fbd2016-09-14 11:55:26 +0100484 }
485}
486
Nicolas Geoffraye70dd562016-10-30 21:03:35 +0000487VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files,
488 ArrayRef<const uint8_t> data)
David Brazdil6f82fbd2016-09-14 11:55:26 +0100489 : VerifierDeps(dex_files) {
Nicolas Geoffraye70dd562016-10-30 21:03:35 +0000490 if (data.empty()) {
491 // Return eagerly, as the first thing we expect from VerifierDeps data is
492 // the number of created strings, even if there is no dependency.
493 // Currently, only the boot image does not have any VerifierDeps data.
494 return;
495 }
David Brazdil6f82fbd2016-09-14 11:55:26 +0100496 const uint8_t* data_start = data.data();
497 const uint8_t* data_end = data_start + data.size();
Nicolas Geoffrayd01f60c2016-10-28 14:45:48 +0100498 for (const DexFile* dex_file : dex_files) {
499 DexFileDeps* deps = GetDexFileDeps(*dex_file);
500 DecodeStringVector(&data_start, data_end, &deps->strings_);
501 DecodeSet(&data_start, data_end, &deps->assignable_types_);
502 DecodeSet(&data_start, data_end, &deps->unassignable_types_);
503 DecodeSet(&data_start, data_end, &deps->classes_);
504 DecodeSet(&data_start, data_end, &deps->fields_);
505 DecodeSet(&data_start, data_end, &deps->direct_methods_);
506 DecodeSet(&data_start, data_end, &deps->virtual_methods_);
507 DecodeSet(&data_start, data_end, &deps->interface_methods_);
508 DecodeUint16Vector(&data_start, data_end, &deps->unverified_classes_);
David Brazdil6f82fbd2016-09-14 11:55:26 +0100509 }
510 CHECK_LE(data_start, data_end);
511}
512
513bool VerifierDeps::Equals(const VerifierDeps& rhs) const {
514 MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
515
516 if (dex_deps_.size() != rhs.dex_deps_.size()) {
517 return false;
518 }
519
520 auto lhs_it = dex_deps_.begin();
521 auto rhs_it = rhs.dex_deps_.begin();
522
523 for (; (lhs_it != dex_deps_.end()) && (rhs_it != rhs.dex_deps_.end()); lhs_it++, rhs_it++) {
524 const DexFile* lhs_dex_file = lhs_it->first;
525 const DexFile* rhs_dex_file = rhs_it->first;
526 if (lhs_dex_file != rhs_dex_file) {
527 return false;
528 }
529
530 DexFileDeps* lhs_deps = lhs_it->second.get();
531 DexFileDeps* rhs_deps = rhs_it->second.get();
532 if (!lhs_deps->Equals(*rhs_deps)) {
533 return false;
534 }
535 }
536
537 DCHECK((lhs_it == dex_deps_.end()) && (rhs_it == rhs.dex_deps_.end()));
538 return true;
539}
540
541bool VerifierDeps::DexFileDeps::Equals(const VerifierDeps::DexFileDeps& rhs) const {
542 return (strings_ == rhs.strings_) &&
543 (assignable_types_ == rhs.assignable_types_) &&
544 (unassignable_types_ == rhs.unassignable_types_) &&
545 (classes_ == rhs.classes_) &&
546 (fields_ == rhs.fields_) &&
547 (direct_methods_ == rhs.direct_methods_) &&
548 (virtual_methods_ == rhs.virtual_methods_) &&
Nicolas Geoffray08025182016-10-25 17:20:18 +0100549 (interface_methods_ == rhs.interface_methods_) &&
550 (unverified_classes_ == rhs.unverified_classes_);
David Brazdil6f82fbd2016-09-14 11:55:26 +0100551}
552
Nicolas Geoffrayd01f60c2016-10-28 14:45:48 +0100553void VerifierDeps::Dump(VariableIndentationOutputStream* vios) const {
554 for (const auto& dep : dex_deps_) {
555 const DexFile& dex_file = *dep.first;
556 vios->Stream()
557 << "Dependencies of "
558 << dex_file.GetLocation()
559 << ":\n";
560
561 ScopedIndentation indent(vios);
562
563 for (const std::string& str : dep.second->strings_) {
564 vios->Stream() << "Extra string: " << str << "\n";
565 }
566
567 for (const TypeAssignability& entry : dep.second->assignable_types_) {
568 vios->Stream()
569 << GetStringFromId(dex_file, entry.GetSource())
570 << " must be assignable to "
571 << GetStringFromId(dex_file, entry.GetDestination())
572 << "\n";
573 }
574
575 for (const TypeAssignability& entry : dep.second->unassignable_types_) {
576 vios->Stream()
577 << GetStringFromId(dex_file, entry.GetSource())
578 << " must not be assignable to "
579 << GetStringFromId(dex_file, entry.GetDestination())
580 << "\n";
581 }
582
583 for (const ClassResolution& entry : dep.second->classes_) {
584 vios->Stream()
585 << dex_file.StringByTypeIdx(entry.GetDexTypeIndex())
586 << (entry.IsResolved() ? " must be resolved " : "must not be resolved ")
587 << " with access flags " << std::hex << entry.GetAccessFlags() << std::dec
588 << "\n";
589 }
590
591 for (const FieldResolution& entry : dep.second->fields_) {
592 const DexFile::FieldId& field_id = dex_file.GetFieldId(entry.GetDexFieldIndex());
593 vios->Stream()
594 << dex_file.GetFieldDeclaringClassDescriptor(field_id) << "->"
595 << dex_file.GetFieldName(field_id) << ":"
596 << dex_file.GetFieldTypeDescriptor(field_id)
597 << " is expected to be ";
598 if (!entry.IsResolved()) {
599 vios->Stream() << "unresolved\n";
600 } else {
601 vios->Stream()
602 << "in class "
603 << GetStringFromId(dex_file, entry.GetDeclaringClassIndex())
604 << ", and have the access flags " << std::hex << entry.GetAccessFlags() << std::dec
605 << "\n";
606 }
607 }
608
609 for (const auto& entry :
610 { std::make_pair(kDirectMethodResolution, dep.second->direct_methods_),
611 std::make_pair(kVirtualMethodResolution, dep.second->virtual_methods_),
612 std::make_pair(kInterfaceMethodResolution, dep.second->interface_methods_) }) {
613 for (const MethodResolution& method : entry.second) {
614 const DexFile::MethodId& method_id = dex_file.GetMethodId(method.GetDexMethodIndex());
615 vios->Stream()
616 << dex_file.GetMethodDeclaringClassDescriptor(method_id) << "->"
617 << dex_file.GetMethodName(method_id)
618 << dex_file.GetMethodSignature(method_id).ToString()
619 << " is expected to be ";
620 if (!method.IsResolved()) {
621 vios->Stream() << "unresolved\n";
622 } else {
623 vios->Stream()
624 << "in class "
625 << GetStringFromId(dex_file, method.GetDeclaringClassIndex())
626 << ", have the access flags " << std::hex << method.GetAccessFlags() << std::dec
627 << ", and be of kind " << entry.first
628 << "\n";
629 }
630 }
631 }
632
Andreas Gampea5b09a62016-11-17 15:21:22 -0800633 for (dex::TypeIndex type_index : dep.second->unverified_classes_) {
Nicolas Geoffrayd01f60c2016-10-28 14:45:48 +0100634 vios->Stream()
635 << dex_file.StringByTypeIdx(type_index)
636 << " is expected to be verified at runtime\n";
637 }
638 }
639}
640
Nicolas Geoffray6bb7f1b2016-11-03 10:52:49 +0000641bool VerifierDeps::ValidateDependencies(Handle<mirror::ClassLoader> class_loader,
642 Thread* self) const {
Nicolas Geoffray8904b6f2016-10-28 19:50:34 +0100643 for (const auto& entry : dex_deps_) {
644 if (!VerifyDexFile(class_loader, *entry.first, *entry.second, self)) {
645 return false;
646 }
647 }
648 return true;
649}
650
651// TODO: share that helper with other parts of the compiler that have
652// the same lookup pattern.
653static mirror::Class* FindClassAndClearException(ClassLinker* class_linker,
654 Thread* self,
655 const char* name,
656 Handle<mirror::ClassLoader> class_loader)
657 REQUIRES_SHARED(Locks::mutator_lock_) {
658 mirror::Class* result = class_linker->FindClass(self, name, class_loader);
659 if (result == nullptr) {
660 DCHECK(self->IsExceptionPending());
661 self->ClearException();
662 }
663 return result;
664}
665
666bool VerifierDeps::VerifyAssignability(Handle<mirror::ClassLoader> class_loader,
667 const DexFile& dex_file,
668 const std::set<TypeAssignability>& assignables,
669 bool expected_assignability,
670 Thread* self) const {
671 StackHandleScope<2> hs(self);
672 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
673 MutableHandle<mirror::Class> source(hs.NewHandle<mirror::Class>(nullptr));
674 MutableHandle<mirror::Class> destination(hs.NewHandle<mirror::Class>(nullptr));
675
676 for (const auto& entry : assignables) {
677 const std::string& destination_desc = GetStringFromId(dex_file, entry.GetDestination());
678 destination.Assign(
679 FindClassAndClearException(class_linker, self, destination_desc.c_str(), class_loader));
680 const std::string& source_desc = GetStringFromId(dex_file, entry.GetSource());
681 source.Assign(
682 FindClassAndClearException(class_linker, self, source_desc.c_str(), class_loader));
683
684 if (destination.Get() == nullptr) {
685 LOG(INFO) << "VerifiersDeps: Could not resolve class " << destination_desc;
686 return false;
687 }
688
689 if (source.Get() == nullptr) {
690 LOG(INFO) << "VerifierDeps: Could not resolve class " << source_desc;
691 return false;
692 }
693
694 DCHECK(destination->IsResolved() && source->IsResolved());
695 if (destination->IsAssignableFrom(source.Get()) != expected_assignability) {
696 LOG(INFO) << "VerifierDeps: Class "
697 << destination_desc
698 << (expected_assignability ? " not " : " ")
699 << "assignable from "
700 << source_desc;
701 return false;
702 }
703 }
704 return true;
705}
706
707bool VerifierDeps::VerifyClasses(Handle<mirror::ClassLoader> class_loader,
708 const DexFile& dex_file,
709 const std::set<ClassResolution>& classes,
710 Thread* self) const {
711 StackHandleScope<1> hs(self);
712 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
713 MutableHandle<mirror::Class> cls(hs.NewHandle<mirror::Class>(nullptr));
714 for (const auto& entry : classes) {
715 const char* descriptor = dex_file.StringByTypeIdx(entry.GetDexTypeIndex());
716 cls.Assign(FindClassAndClearException(class_linker, self, descriptor, class_loader));
717
718 if (entry.IsResolved()) {
719 if (cls.Get() == nullptr) {
720 LOG(INFO) << "VerifierDeps: Could not resolve class " << descriptor;
721 return false;
722 } else if (entry.GetAccessFlags() != GetAccessFlags(cls.Get())) {
723 LOG(INFO) << "VerifierDeps: Unexpected access flags on class "
724 << descriptor
725 << std::hex
726 << " (expected="
727 << entry.GetAccessFlags()
728 << ", actual="
729 << GetAccessFlags(cls.Get()) << ")"
730 << std::dec;
731 return false;
732 }
733 } else if (cls.Get() != nullptr) {
734 LOG(INFO) << "VerifierDeps: Unexpected successful resolution of class " << descriptor;
735 return false;
736 }
737 }
738 return true;
739}
740
741static std::string GetFieldDescription(const DexFile& dex_file, uint32_t index) {
742 const DexFile::FieldId& field_id = dex_file.GetFieldId(index);
743 return std::string(dex_file.GetFieldDeclaringClassDescriptor(field_id))
744 + "->"
745 + dex_file.GetFieldName(field_id)
746 + ":"
747 + dex_file.GetFieldTypeDescriptor(field_id);
748}
749
750bool VerifierDeps::VerifyFields(Handle<mirror::ClassLoader> class_loader,
751 const DexFile& dex_file,
752 const std::set<FieldResolution>& fields,
753 Thread* self) const {
754 // Check recorded fields are resolved the same way, have the same recorded class,
755 // and have the same recorded flags.
756 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
757 StackHandleScope<1> hs(self);
758 Handle<mirror::DexCache> dex_cache(
759 hs.NewHandle(class_linker->FindDexCache(self, dex_file, /* allow_failure */ false)));
760 for (const auto& entry : fields) {
761 ArtField* field = class_linker->ResolveFieldJLS(
762 dex_file, entry.GetDexFieldIndex(), dex_cache, class_loader);
763
764 if (field == nullptr) {
765 DCHECK(self->IsExceptionPending());
766 self->ClearException();
767 }
768
769 if (entry.IsResolved()) {
770 std::string expected_decl_klass = GetStringFromId(dex_file, entry.GetDeclaringClassIndex());
771 std::string temp;
772 if (field == nullptr) {
773 LOG(INFO) << "VerifierDeps: Could not resolve field "
774 << GetFieldDescription(dex_file, entry.GetDexFieldIndex());
775 return false;
776 } else if (expected_decl_klass != field->GetDeclaringClass()->GetDescriptor(&temp)) {
777 LOG(INFO) << "VerifierDeps: Unexpected declaring class for field resolution "
778 << GetFieldDescription(dex_file, entry.GetDexFieldIndex())
779 << " (expected=" << expected_decl_klass
780 << ", actual=" << field->GetDeclaringClass()->GetDescriptor(&temp) << ")";
781 return false;
782 } else if (entry.GetAccessFlags() != GetAccessFlags(field)) {
783 LOG(INFO) << "VerifierDeps: Unexpected access flags for resolved field "
784 << GetFieldDescription(dex_file, entry.GetDexFieldIndex())
785 << std::hex << " (expected=" << entry.GetAccessFlags()
786 << ", actual=" << GetAccessFlags(field) << ")" << std::dec;
787 return false;
788 }
789 } else if (field != nullptr) {
790 LOG(INFO) << "VerifierDeps: Unexpected successful resolution of field "
791 << GetFieldDescription(dex_file, entry.GetDexFieldIndex());
792 return false;
793 }
794 }
795 return true;
796}
797
798static std::string GetMethodDescription(const DexFile& dex_file, uint32_t index) {
799 const DexFile::MethodId& method_id = dex_file.GetMethodId(index);
800 return std::string(dex_file.GetMethodDeclaringClassDescriptor(method_id))
801 + "->"
802 + dex_file.GetMethodName(method_id)
803 + dex_file.GetMethodSignature(method_id).ToString();
804}
805
806bool VerifierDeps::VerifyMethods(Handle<mirror::ClassLoader> class_loader,
807 const DexFile& dex_file,
808 const std::set<MethodResolution>& methods,
809 MethodResolutionKind kind,
810 Thread* self) const {
811 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
812 PointerSize pointer_size = class_linker->GetImagePointerSize();
813
814 for (const auto& entry : methods) {
815 const DexFile::MethodId& method_id = dex_file.GetMethodId(entry.GetDexMethodIndex());
816
817 const char* name = dex_file.GetMethodName(method_id);
818 const Signature signature = dex_file.GetMethodSignature(method_id);
819 const char* descriptor = dex_file.GetMethodDeclaringClassDescriptor(method_id);
820
821 mirror::Class* cls = FindClassAndClearException(class_linker, self, descriptor, class_loader);
822 if (cls == nullptr) {
823 LOG(INFO) << "VerifierDeps: Could not resolve class " << descriptor;
824 return false;
825 }
826 DCHECK(cls->IsResolved());
827 ArtMethod* method = nullptr;
828 if (kind == kDirectMethodResolution) {
829 method = cls->FindDirectMethod(name, signature, pointer_size);
830 } else if (kind == kVirtualMethodResolution) {
831 method = cls->FindVirtualMethod(name, signature, pointer_size);
832 } else {
833 DCHECK_EQ(kind, kInterfaceMethodResolution);
834 method = cls->FindInterfaceMethod(name, signature, pointer_size);
835 }
836
837 if (entry.IsResolved()) {
838 std::string temp;
839 std::string expected_decl_klass = GetStringFromId(dex_file, entry.GetDeclaringClassIndex());
840 if (method == nullptr) {
841 LOG(INFO) << "VerifierDeps: Could not resolve "
842 << kind
843 << " method "
844 << GetMethodDescription(dex_file, entry.GetDexMethodIndex());
845 return false;
846 } else if (expected_decl_klass != method->GetDeclaringClass()->GetDescriptor(&temp)) {
847 LOG(INFO) << "VerifierDeps: Unexpected declaring class for "
848 << kind
849 << " method resolution "
850 << GetMethodDescription(dex_file, entry.GetDexMethodIndex())
851 << " (expected="
852 << expected_decl_klass
853 << ", actual="
854 << method->GetDeclaringClass()->GetDescriptor(&temp)
855 << ")";
856 return false;
857 } else if (entry.GetAccessFlags() != GetAccessFlags(method)) {
858 LOG(INFO) << "VerifierDeps: Unexpected access flags for resolved "
859 << kind
860 << " method resolution "
861 << GetMethodDescription(dex_file, entry.GetDexMethodIndex())
862 << std::hex
863 << " (expected="
864 << entry.GetAccessFlags()
865 << ", actual="
866 << GetAccessFlags(method) << ")"
867 << std::dec;
868 return false;
869 }
870 } else if (method != nullptr) {
871 LOG(INFO) << "VerifierDeps: Unexpected successful resolution of "
872 << kind
873 << " method "
874 << GetMethodDescription(dex_file, entry.GetDexMethodIndex());
875 return false;
876 }
877 }
878 return true;
879}
880
881bool VerifierDeps::VerifyDexFile(Handle<mirror::ClassLoader> class_loader,
882 const DexFile& dex_file,
883 const DexFileDeps& deps,
884 Thread* self) const {
885 bool result = VerifyAssignability(
886 class_loader, dex_file, deps.assignable_types_, /* expected_assignability */ true, self);
887 result = result && VerifyAssignability(
888 class_loader, dex_file, deps.unassignable_types_, /* expected_assignability */ false, self);
889
890 result = result && VerifyClasses(class_loader, dex_file, deps.classes_, self);
891 result = result && VerifyFields(class_loader, dex_file, deps.fields_, self);
892
893 result = result && VerifyMethods(
894 class_loader, dex_file, deps.direct_methods_, kDirectMethodResolution, self);
895 result = result && VerifyMethods(
896 class_loader, dex_file, deps.virtual_methods_, kVirtualMethodResolution, self);
897 result = result && VerifyMethods(
898 class_loader, dex_file, deps.interface_methods_, kInterfaceMethodResolution, self);
899
900 return result;
901}
902
David Brazdilca3c8c32016-09-06 14:04:48 +0100903} // namespace verifier
904} // namespace art