blob: 83a7c69d7d6952ee40598e45111630849657c172 [file] [log] [blame]
Jeff Haoec7f1a92017-03-13 16:24:24 -07001/*
2 * Copyright (C) 2017 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 * Implementation file of dex ir verifier.
17 *
18 * Compares two dex files at the IR level, allowing differences in layout, but not in data.
19 */
20
21#include "dex_verify.h"
22
Jeff Haocc829592017-03-14 16:13:39 -070023#include <inttypes.h>
24
Vladimir Marko6c702242019-02-07 16:17:33 +000025#include <set>
26
Jeff Haoec7f1a92017-03-13 16:24:24 -070027#include "android-base/stringprintf.h"
28
29namespace art {
30
31using android::base::StringPrintf;
32
33bool VerifyOutputDexFile(dex_ir::Header* orig_header,
34 dex_ir::Header* output_header,
35 std::string* error_msg) {
Jeff Haocc829592017-03-14 16:13:39 -070036 // Compare all id sections. They have a defined order that can't be changed by dexlayout.
David Sehr2b5a38f2018-06-14 15:13:04 -070037 if (!VerifyIds(orig_header->StringIds(), output_header->StringIds(), "string ids", error_msg) ||
38 !VerifyIds(orig_header->TypeIds(), output_header->TypeIds(), "type ids", error_msg) ||
39 !VerifyIds(orig_header->ProtoIds(), output_header->ProtoIds(), "proto ids", error_msg) ||
40 !VerifyIds(orig_header->FieldIds(), output_header->FieldIds(), "field ids", error_msg) ||
41 !VerifyIds(orig_header->MethodIds(), output_header->MethodIds(), "method ids", error_msg)) {
Jeff Haoec7f1a92017-03-13 16:24:24 -070042 return false;
43 }
Jeff Haocc829592017-03-14 16:13:39 -070044 // Compare class defs. The order may have been changed by dexlayout.
David Sehr2b5a38f2018-06-14 15:13:04 -070045 if (!VerifyClassDefs(orig_header->ClassDefs(), output_header->ClassDefs(), error_msg)) {
Jeff Haocc829592017-03-14 16:13:39 -070046 return false;
47 }
Jeff Haoec7f1a92017-03-13 16:24:24 -070048 return true;
49}
50
David Sehr2b5a38f2018-06-14 15:13:04 -070051template<class T> bool VerifyIds(dex_ir::CollectionVector<T>& orig,
52 dex_ir::CollectionVector<T>& output,
Jeff Haoec7f1a92017-03-13 16:24:24 -070053 const char* section_name,
54 std::string* error_msg) {
David Sehr2b5a38f2018-06-14 15:13:04 -070055 auto orig_iter = orig.begin();
56 auto output_iter = output.begin();
57 for (; orig_iter != orig.end() && output_iter != output.end(); ++orig_iter, ++output_iter) {
58 if (!VerifyId(orig_iter->get(), output_iter->get(), error_msg)) {
Jeff Haoec7f1a92017-03-13 16:24:24 -070059 return false;
60 }
61 }
David Sehr2b5a38f2018-06-14 15:13:04 -070062 if (orig_iter != orig.end() || output_iter != output.end()) {
63 const char* longer;
64 if (orig_iter == orig.end()) {
65 longer = "output";
66 } else {
67 longer = "original";
68 }
69 *error_msg = StringPrintf("Mismatch for %s section: %s is longer.", section_name, longer);
70 return false;
71 }
Jeff Haoec7f1a92017-03-13 16:24:24 -070072 return true;
73}
74
75bool VerifyId(dex_ir::StringId* orig, dex_ir::StringId* output, std::string* error_msg) {
76 if (strcmp(orig->Data(), output->Data()) != 0) {
Jeff Haocc829592017-03-14 16:13:39 -070077 *error_msg = StringPrintf("Mismatched string data for string id %u at offset %x: %s vs %s.",
Jeff Haoec7f1a92017-03-13 16:24:24 -070078 orig->GetIndex(),
79 orig->GetOffset(),
80 orig->Data(),
81 output->Data());
82 return false;
83 }
84 return true;
85}
86
87bool VerifyId(dex_ir::TypeId* orig, dex_ir::TypeId* output, std::string* error_msg) {
88 if (orig->GetStringId()->GetIndex() != output->GetStringId()->GetIndex()) {
Jeff Haocc829592017-03-14 16:13:39 -070089 *error_msg = StringPrintf("Mismatched string index for type id %u at offset %x: %u vs %u.",
Jeff Haoec7f1a92017-03-13 16:24:24 -070090 orig->GetIndex(),
91 orig->GetOffset(),
92 orig->GetStringId()->GetIndex(),
93 output->GetStringId()->GetIndex());
94 return false;
95 }
96 return true;
97}
98
99bool VerifyId(dex_ir::ProtoId* orig, dex_ir::ProtoId* output, std::string* error_msg) {
100 if (orig->Shorty()->GetIndex() != output->Shorty()->GetIndex()) {
Jeff Haocc829592017-03-14 16:13:39 -0700101 *error_msg = StringPrintf("Mismatched string index for proto id %u at offset %x: %u vs %u.",
Jeff Haoec7f1a92017-03-13 16:24:24 -0700102 orig->GetIndex(),
103 orig->GetOffset(),
104 orig->Shorty()->GetIndex(),
105 output->Shorty()->GetIndex());
106 return false;
107 }
108 if (orig->ReturnType()->GetIndex() != output->ReturnType()->GetIndex()) {
Jeff Haocc829592017-03-14 16:13:39 -0700109 *error_msg = StringPrintf("Mismatched type index for proto id %u at offset %x: %u vs %u.",
Jeff Haoec7f1a92017-03-13 16:24:24 -0700110 orig->GetIndex(),
111 orig->GetOffset(),
112 orig->ReturnType()->GetIndex(),
113 output->ReturnType()->GetIndex());
114 return false;
115 }
116 if (!VerifyTypeList(orig->Parameters(), output->Parameters())) {
Jeff Haocc829592017-03-14 16:13:39 -0700117 *error_msg = StringPrintf("Mismatched type list for proto id %u at offset %x.",
Jeff Haoec7f1a92017-03-13 16:24:24 -0700118 orig->GetIndex(),
119 orig->GetOffset());
120 }
121 return true;
122}
123
124bool VerifyId(dex_ir::FieldId* orig, dex_ir::FieldId* output, std::string* error_msg) {
125 if (orig->Class()->GetIndex() != output->Class()->GetIndex()) {
126 *error_msg =
Jeff Haocc829592017-03-14 16:13:39 -0700127 StringPrintf("Mismatched class type index for field id %u at offset %x: %u vs %u.",
Jeff Haoec7f1a92017-03-13 16:24:24 -0700128 orig->GetIndex(),
129 orig->GetOffset(),
130 orig->Class()->GetIndex(),
131 output->Class()->GetIndex());
132 return false;
133 }
134 if (orig->Type()->GetIndex() != output->Type()->GetIndex()) {
Jeff Haocc829592017-03-14 16:13:39 -0700135 *error_msg = StringPrintf("Mismatched type index for field id %u at offset %x: %u vs %u.",
Jeff Haoec7f1a92017-03-13 16:24:24 -0700136 orig->GetIndex(),
137 orig->GetOffset(),
138 orig->Class()->GetIndex(),
139 output->Class()->GetIndex());
140 return false;
141 }
142 if (orig->Name()->GetIndex() != output->Name()->GetIndex()) {
Jeff Haocc829592017-03-14 16:13:39 -0700143 *error_msg = StringPrintf("Mismatched string index for field id %u at offset %x: %u vs %u.",
Jeff Haoec7f1a92017-03-13 16:24:24 -0700144 orig->GetIndex(),
145 orig->GetOffset(),
146 orig->Name()->GetIndex(),
147 output->Name()->GetIndex());
148 return false;
149 }
150 return true;
151}
152
153bool VerifyId(dex_ir::MethodId* orig, dex_ir::MethodId* output, std::string* error_msg) {
154 if (orig->Class()->GetIndex() != output->Class()->GetIndex()) {
Jeff Haocc829592017-03-14 16:13:39 -0700155 *error_msg = StringPrintf("Mismatched type index for method id %u at offset %x: %u vs %u.",
Jeff Haoec7f1a92017-03-13 16:24:24 -0700156 orig->GetIndex(),
157 orig->GetOffset(),
158 orig->Class()->GetIndex(),
159 output->Class()->GetIndex());
160 return false;
161 }
162 if (orig->Proto()->GetIndex() != output->Proto()->GetIndex()) {
Jeff Haocc829592017-03-14 16:13:39 -0700163 *error_msg = StringPrintf("Mismatched proto index for method id %u at offset %x: %u vs %u.",
Jeff Haoec7f1a92017-03-13 16:24:24 -0700164 orig->GetIndex(),
165 orig->GetOffset(),
166 orig->Class()->GetIndex(),
167 output->Class()->GetIndex());
168 return false;
169 }
170 if (orig->Name()->GetIndex() != output->Name()->GetIndex()) {
171 *error_msg =
Jeff Haocc829592017-03-14 16:13:39 -0700172 StringPrintf("Mismatched string index for method id %u at offset %x: %u vs %u.",
Jeff Haoec7f1a92017-03-13 16:24:24 -0700173 orig->GetIndex(),
174 orig->GetOffset(),
175 orig->Name()->GetIndex(),
176 output->Name()->GetIndex());
177 return false;
178 }
179 return true;
180}
181
Jeff Haocc829592017-03-14 16:13:39 -0700182struct ClassDefCompare {
183 bool operator()(dex_ir::ClassDef* lhs, dex_ir::ClassDef* rhs) const {
184 return lhs->ClassType()->GetIndex() < rhs->ClassType()->GetIndex();
185 }
186};
187
188// The class defs may have a new order due to dexlayout. Use the class's class_idx to uniquely
189// identify them and sort them for comparison.
David Sehr2b5a38f2018-06-14 15:13:04 -0700190bool VerifyClassDefs(dex_ir::CollectionVector<dex_ir::ClassDef>& orig,
191 dex_ir::CollectionVector<dex_ir::ClassDef>& output,
Jeff Haocc829592017-03-14 16:13:39 -0700192 std::string* error_msg) {
Jeff Haocc829592017-03-14 16:13:39 -0700193 // Store the class defs into sets sorted by the class's type index.
194 std::set<dex_ir::ClassDef*, ClassDefCompare> orig_set;
195 std::set<dex_ir::ClassDef*, ClassDefCompare> output_set;
David Sehr2b5a38f2018-06-14 15:13:04 -0700196 auto orig_iter = orig.begin();
197 auto output_iter = output.begin();
198 for (; orig_iter != orig.end() && output_iter != output.end(); ++orig_iter, ++output_iter) {
199 orig_set.insert(orig_iter->get());
200 output_set.insert(output_iter->get());
Jeff Haocc829592017-03-14 16:13:39 -0700201 }
David Sehr2b5a38f2018-06-14 15:13:04 -0700202 if (orig_iter != orig.end() || output_iter != output.end()) {
203 const char* longer;
204 if (orig_iter == orig.end()) {
205 longer = "output";
206 } else {
207 longer = "original";
208 }
209 *error_msg = StringPrintf("Mismatch for class defs section: %s is longer.", longer);
210 return false;
211 }
212 auto orig_set_iter = orig_set.begin();
213 auto output_set_iter = output_set.begin();
214 while (orig_set_iter != orig_set.end() && output_set_iter != output_set.end()) {
215 if (!VerifyClassDef(*orig_set_iter, *output_set_iter, error_msg)) {
Jeff Haocc829592017-03-14 16:13:39 -0700216 return false;
217 }
David Sehr2b5a38f2018-06-14 15:13:04 -0700218 orig_set_iter++;
219 output_set_iter++;
Jeff Haocc829592017-03-14 16:13:39 -0700220 }
221 return true;
222}
223
224bool VerifyClassDef(dex_ir::ClassDef* orig, dex_ir::ClassDef* output, std::string* error_msg) {
225 if (orig->ClassType()->GetIndex() != output->ClassType()->GetIndex()) {
226 *error_msg =
227 StringPrintf("Mismatched class type index for class def %u at offset %x: %u vs %u.",
228 orig->GetIndex(),
229 orig->GetOffset(),
230 orig->ClassType()->GetIndex(),
231 output->ClassType()->GetIndex());
232 return false;
233 }
234 if (orig->GetAccessFlags() != output->GetAccessFlags()) {
235 *error_msg =
236 StringPrintf("Mismatched access flags for class def %u at offset %x: %x vs %x.",
237 orig->GetIndex(),
238 orig->GetOffset(),
239 orig->GetAccessFlags(),
240 output->GetAccessFlags());
241 return false;
242 }
243 uint32_t orig_super = orig->Superclass() == nullptr ? 0 : orig->Superclass()->GetIndex();
244 uint32_t output_super = output->Superclass() == nullptr ? 0 : output->Superclass()->GetIndex();
245 if (orig_super != output_super) {
246 *error_msg =
247 StringPrintf("Mismatched super class for class def %u at offset %x: %u vs %u.",
248 orig->GetIndex(),
249 orig->GetOffset(),
250 orig_super,
251 output_super);
252 return false;
253 }
254 if (!VerifyTypeList(orig->Interfaces(), output->Interfaces())) {
255 *error_msg = StringPrintf("Mismatched type list for class def %u at offset %x.",
256 orig->GetIndex(),
257 orig->GetOffset());
258 return false;
259 }
260 const char* orig_source = orig->SourceFile() == nullptr ? "" : orig->SourceFile()->Data();
261 const char* output_source = output->SourceFile() == nullptr ? "" : output->SourceFile()->Data();
262 if (strcmp(orig_source, output_source) != 0) {
263 *error_msg = StringPrintf("Mismatched source file for class def %u at offset %x: %s vs %s.",
264 orig->GetIndex(),
265 orig->GetOffset(),
266 orig_source,
267 output_source);
268 return false;
269 }
270 if (!VerifyAnnotationsDirectory(orig->Annotations(), output->Annotations(), error_msg)) {
271 return false;
272 }
273 if (!VerifyClassData(orig->GetClassData(), output->GetClassData(), error_msg)) {
274 return false;
275 }
276 return VerifyEncodedArray(orig->StaticValues(), output->StaticValues(), error_msg);
277}
278
Jeff Haoec7f1a92017-03-13 16:24:24 -0700279bool VerifyTypeList(const dex_ir::TypeList* orig, const dex_ir::TypeList* output) {
280 if (orig == nullptr || output == nullptr) {
281 return orig == output;
282 }
283 const dex_ir::TypeIdVector* orig_list = orig->GetTypeList();
284 const dex_ir::TypeIdVector* output_list = output->GetTypeList();
285 if (orig_list->size() != output_list->size()) {
286 return false;
287 }
288 for (size_t i = 0; i < orig_list->size(); ++i) {
289 if ((*orig_list)[i]->GetIndex() != (*output_list)[i]->GetIndex()) {
290 return false;
291 }
292 }
293 return true;
294}
295
Jeff Haocc829592017-03-14 16:13:39 -0700296bool VerifyAnnotationsDirectory(dex_ir::AnnotationsDirectoryItem* orig,
297 dex_ir::AnnotationsDirectoryItem* output,
298 std::string* error_msg) {
299 if (orig == nullptr || output == nullptr) {
300 if (orig != output) {
301 *error_msg = "Found unexpected empty annotations directory.";
302 return false;
303 }
304 return true;
305 }
306 if (!VerifyAnnotationSet(orig->GetClassAnnotation(), output->GetClassAnnotation(), error_msg)) {
307 return false;
308 }
309 if (!VerifyFieldAnnotations(orig->GetFieldAnnotations(),
310 output->GetFieldAnnotations(),
311 orig->GetOffset(),
312 error_msg)) {
313 return false;
314 }
315 if (!VerifyMethodAnnotations(orig->GetMethodAnnotations(),
316 output->GetMethodAnnotations(),
317 orig->GetOffset(),
318 error_msg)) {
319 return false;
320 }
321 return VerifyParameterAnnotations(orig->GetParameterAnnotations(),
322 output->GetParameterAnnotations(),
323 orig->GetOffset(),
324 error_msg);
325}
326
327bool VerifyFieldAnnotations(dex_ir::FieldAnnotationVector* orig,
328 dex_ir::FieldAnnotationVector* output,
329 uint32_t orig_offset,
330 std::string* error_msg) {
331 if (orig == nullptr || output == nullptr) {
332 if (orig != output) {
333 *error_msg = StringPrintf(
334 "Found unexpected empty field annotations for annotations directory at offset %x.",
335 orig_offset);
336 return false;
337 }
338 return true;
339 }
340 if (orig->size() != output->size()) {
341 *error_msg = StringPrintf(
342 "Mismatched field annotations size for annotations directory at offset %x: %zu vs %zu.",
343 orig_offset,
344 orig->size(),
345 output->size());
346 return false;
347 }
348 for (size_t i = 0; i < orig->size(); ++i) {
349 dex_ir::FieldAnnotation* orig_field = (*orig)[i].get();
350 dex_ir::FieldAnnotation* output_field = (*output)[i].get();
351 if (orig_field->GetFieldId()->GetIndex() != output_field->GetFieldId()->GetIndex()) {
352 *error_msg = StringPrintf(
353 "Mismatched field annotation index for annotations directory at offset %x: %u vs %u.",
354 orig_offset,
355 orig_field->GetFieldId()->GetIndex(),
356 output_field->GetFieldId()->GetIndex());
357 return false;
358 }
359 if (!VerifyAnnotationSet(orig_field->GetAnnotationSetItem(),
360 output_field->GetAnnotationSetItem(),
361 error_msg)) {
362 return false;
363 }
364 }
365 return true;
366}
367
368bool VerifyMethodAnnotations(dex_ir::MethodAnnotationVector* orig,
369 dex_ir::MethodAnnotationVector* output,
370 uint32_t orig_offset,
371 std::string* error_msg) {
372 if (orig == nullptr || output == nullptr) {
373 if (orig != output) {
374 *error_msg = StringPrintf(
375 "Found unexpected empty method annotations for annotations directory at offset %x.",
376 orig_offset);
377 return false;
378 }
379 return true;
380 }
381 if (orig->size() != output->size()) {
382 *error_msg = StringPrintf(
383 "Mismatched method annotations size for annotations directory at offset %x: %zu vs %zu.",
384 orig_offset,
385 orig->size(),
386 output->size());
387 return false;
388 }
389 for (size_t i = 0; i < orig->size(); ++i) {
390 dex_ir::MethodAnnotation* orig_method = (*orig)[i].get();
391 dex_ir::MethodAnnotation* output_method = (*output)[i].get();
392 if (orig_method->GetMethodId()->GetIndex() != output_method->GetMethodId()->GetIndex()) {
393 *error_msg = StringPrintf(
394 "Mismatched method annotation index for annotations directory at offset %x: %u vs %u.",
395 orig_offset,
396 orig_method->GetMethodId()->GetIndex(),
397 output_method->GetMethodId()->GetIndex());
398 return false;
399 }
400 if (!VerifyAnnotationSet(orig_method->GetAnnotationSetItem(),
401 output_method->GetAnnotationSetItem(),
402 error_msg)) {
403 return false;
404 }
405 }
406 return true;
407}
408
409bool VerifyParameterAnnotations(dex_ir::ParameterAnnotationVector* orig,
410 dex_ir::ParameterAnnotationVector* output,
411 uint32_t orig_offset,
412 std::string* error_msg) {
413 if (orig == nullptr || output == nullptr) {
414 if (orig != output) {
415 *error_msg = StringPrintf(
416 "Found unexpected empty parameter annotations for annotations directory at offset %x.",
417 orig_offset);
418 return false;
419 }
420 return true;
421 }
422 if (orig->size() != output->size()) {
423 *error_msg = StringPrintf(
424 "Mismatched parameter annotations size for annotations directory at offset %x: %zu vs %zu.",
425 orig_offset,
426 orig->size(),
427 output->size());
428 return false;
429 }
430 for (size_t i = 0; i < orig->size(); ++i) {
431 dex_ir::ParameterAnnotation* orig_param = (*orig)[i].get();
432 dex_ir::ParameterAnnotation* output_param = (*output)[i].get();
433 if (orig_param->GetMethodId()->GetIndex() != output_param->GetMethodId()->GetIndex()) {
434 *error_msg = StringPrintf(
435 "Mismatched parameter annotation index for annotations directory at offset %x: %u vs %u.",
436 orig_offset,
437 orig_param->GetMethodId()->GetIndex(),
438 output_param->GetMethodId()->GetIndex());
439 return false;
440 }
441 if (!VerifyAnnotationSetRefList(orig_param->GetAnnotations(),
442 output_param->GetAnnotations(),
443 error_msg)) {
444 return false;
445 }
446 }
447 return true;
448}
449
450bool VerifyAnnotationSetRefList(dex_ir::AnnotationSetRefList* orig,
451 dex_ir::AnnotationSetRefList* output,
452 std::string* error_msg) {
453 std::vector<dex_ir::AnnotationSetItem*>* orig_items = orig->GetItems();
454 std::vector<dex_ir::AnnotationSetItem*>* output_items = output->GetItems();
455 if (orig_items->size() != output_items->size()) {
456 *error_msg = StringPrintf(
457 "Mismatched annotation set ref list size at offset %x: %zu vs %zu.",
458 orig->GetOffset(),
459 orig_items->size(),
460 output_items->size());
461 return false;
462 }
463 for (size_t i = 0; i < orig_items->size(); ++i) {
464 if (!VerifyAnnotationSet((*orig_items)[i], (*output_items)[i], error_msg)) {
465 return false;
466 }
467 }
468 return true;
469}
470
471bool VerifyAnnotationSet(dex_ir::AnnotationSetItem* orig,
472 dex_ir::AnnotationSetItem* output,
473 std::string* error_msg) {
474 if (orig == nullptr || output == nullptr) {
475 if (orig != output) {
476 *error_msg = "Found unexpected empty annotation set.";
477 return false;
478 }
479 return true;
480 }
481 std::vector<dex_ir::AnnotationItem*>* orig_items = orig->GetItems();
482 std::vector<dex_ir::AnnotationItem*>* output_items = output->GetItems();
483 if (orig_items->size() != output_items->size()) {
484 *error_msg = StringPrintf("Mismatched size for annotation set at offset %x: %zu vs %zu.",
485 orig->GetOffset(),
486 orig_items->size(),
487 output_items->size());
488 return false;
489 }
490 for (size_t i = 0; i < orig_items->size(); ++i) {
491 if (!VerifyAnnotation((*orig_items)[i], (*output_items)[i], error_msg)) {
492 return false;
493 }
494 }
495 return true;
496}
497
498bool VerifyAnnotation(dex_ir::AnnotationItem* orig,
499 dex_ir::AnnotationItem* output,
500 std::string* error_msg) {
501 if (orig->GetVisibility() != output->GetVisibility()) {
502 *error_msg = StringPrintf("Mismatched visibility for annotation at offset %x: %u vs %u.",
503 orig->GetOffset(),
504 orig->GetVisibility(),
505 output->GetVisibility());
506 return false;
507 }
508 return VerifyEncodedAnnotation(orig->GetAnnotation(),
509 output->GetAnnotation(),
510 orig->GetOffset(),
511 error_msg);
512}
513
514bool VerifyEncodedAnnotation(dex_ir::EncodedAnnotation* orig,
515 dex_ir::EncodedAnnotation* output,
516 uint32_t orig_offset,
517 std::string* error_msg) {
518 if (orig->GetType()->GetIndex() != output->GetType()->GetIndex()) {
519 *error_msg = StringPrintf(
520 "Mismatched encoded annotation type for annotation at offset %x: %u vs %u.",
521 orig_offset,
522 orig->GetType()->GetIndex(),
523 output->GetType()->GetIndex());
524 return false;
525 }
526 dex_ir::AnnotationElementVector* orig_elements = orig->GetAnnotationElements();
527 dex_ir::AnnotationElementVector* output_elements = output->GetAnnotationElements();
528 if (orig_elements->size() != output_elements->size()) {
529 *error_msg = StringPrintf(
530 "Mismatched encoded annotation size for annotation at offset %x: %zu vs %zu.",
531 orig_offset,
532 orig_elements->size(),
533 output_elements->size());
534 return false;
535 }
536 for (size_t i = 0; i < orig_elements->size(); ++i) {
537 if (!VerifyAnnotationElement((*orig_elements)[i].get(),
538 (*output_elements)[i].get(),
539 orig_offset,
540 error_msg)) {
541 return false;
542 }
543 }
544 return true;
545}
546
547bool VerifyAnnotationElement(dex_ir::AnnotationElement* orig,
548 dex_ir::AnnotationElement* output,
549 uint32_t orig_offset,
550 std::string* error_msg) {
551 if (orig->GetName()->GetIndex() != output->GetName()->GetIndex()) {
552 *error_msg = StringPrintf(
553 "Mismatched annotation element name for annotation at offset %x: %u vs %u.",
554 orig_offset,
555 orig->GetName()->GetIndex(),
556 output->GetName()->GetIndex());
557 return false;
558 }
559 return VerifyEncodedValue(orig->GetValue(), output->GetValue(), orig_offset, error_msg);
560}
561
562bool VerifyEncodedValue(dex_ir::EncodedValue* orig,
563 dex_ir::EncodedValue* output,
564 uint32_t orig_offset,
565 std::string* error_msg) {
566 if (orig->Type() != output->Type()) {
567 *error_msg = StringPrintf(
568 "Mismatched encoded value type for annotation or encoded array at offset %x: %d vs %d.",
569 orig_offset,
570 orig->Type(),
571 output->Type());
572 return false;
573 }
574 switch (orig->Type()) {
575 case DexFile::kDexAnnotationByte:
576 if (orig->GetByte() != output->GetByte()) {
577 *error_msg = StringPrintf("Mismatched encoded byte for annotation at offset %x: %d vs %d.",
578 orig_offset,
579 orig->GetByte(),
580 output->GetByte());
581 return false;
582 }
583 break;
584 case DexFile::kDexAnnotationShort:
585 if (orig->GetShort() != output->GetShort()) {
586 *error_msg = StringPrintf("Mismatched encoded short for annotation at offset %x: %d vs %d.",
587 orig_offset,
588 orig->GetShort(),
589 output->GetShort());
590 return false;
591 }
592 break;
593 case DexFile::kDexAnnotationChar:
594 if (orig->GetChar() != output->GetChar()) {
595 *error_msg = StringPrintf("Mismatched encoded char for annotation at offset %x: %c vs %c.",
596 orig_offset,
597 orig->GetChar(),
598 output->GetChar());
599 return false;
600 }
601 break;
602 case DexFile::kDexAnnotationInt:
603 if (orig->GetInt() != output->GetInt()) {
604 *error_msg = StringPrintf("Mismatched encoded int for annotation at offset %x: %d vs %d.",
605 orig_offset,
606 orig->GetInt(),
607 output->GetInt());
608 return false;
609 }
610 break;
611 case DexFile::kDexAnnotationLong:
612 if (orig->GetLong() != output->GetLong()) {
613 *error_msg = StringPrintf(
614 "Mismatched encoded long for annotation at offset %x: %" PRId64 " vs %" PRId64 ".",
615 orig_offset,
616 orig->GetLong(),
617 output->GetLong());
618 return false;
619 }
620 break;
621 case DexFile::kDexAnnotationFloat:
622 // The float value is encoded, so compare as if it's an int.
623 if (orig->GetInt() != output->GetInt()) {
624 *error_msg = StringPrintf(
625 "Mismatched encoded float for annotation at offset %x: %x (encoded) vs %x (encoded).",
626 orig_offset,
627 orig->GetInt(),
628 output->GetInt());
629 return false;
630 }
631 break;
632 case DexFile::kDexAnnotationDouble:
633 // The double value is encoded, so compare as if it's a long.
634 if (orig->GetLong() != output->GetLong()) {
635 *error_msg = StringPrintf(
636 "Mismatched encoded double for annotation at offset %x: %" PRIx64
637 " (encoded) vs %" PRIx64 " (encoded).",
638 orig_offset,
639 orig->GetLong(),
640 output->GetLong());
641 return false;
642 }
643 break;
644 case DexFile::kDexAnnotationString:
645 if (orig->GetStringId()->GetIndex() != output->GetStringId()->GetIndex()) {
646 *error_msg = StringPrintf(
647 "Mismatched encoded string for annotation at offset %x: %s vs %s.",
648 orig_offset,
649 orig->GetStringId()->Data(),
650 output->GetStringId()->Data());
651 return false;
652 }
653 break;
654 case DexFile::kDexAnnotationType:
655 if (orig->GetTypeId()->GetIndex() != output->GetTypeId()->GetIndex()) {
656 *error_msg = StringPrintf("Mismatched encoded type for annotation at offset %x: %u vs %u.",
657 orig_offset,
658 orig->GetTypeId()->GetIndex(),
659 output->GetTypeId()->GetIndex());
660 return false;
661 }
662 break;
663 case DexFile::kDexAnnotationField:
664 case DexFile::kDexAnnotationEnum:
665 if (orig->GetFieldId()->GetIndex() != output->GetFieldId()->GetIndex()) {
666 *error_msg = StringPrintf("Mismatched encoded field for annotation at offset %x: %u vs %u.",
667 orig_offset,
668 orig->GetFieldId()->GetIndex(),
669 output->GetFieldId()->GetIndex());
670 return false;
671 }
672 break;
673 case DexFile::kDexAnnotationMethod:
674 if (orig->GetMethodId()->GetIndex() != output->GetMethodId()->GetIndex()) {
675 *error_msg = StringPrintf(
676 "Mismatched encoded method for annotation at offset %x: %u vs %u.",
677 orig_offset,
678 orig->GetMethodId()->GetIndex(),
679 output->GetMethodId()->GetIndex());
680 return false;
681 }
682 break;
683 case DexFile::kDexAnnotationArray:
684 if (!VerifyEncodedArray(orig->GetEncodedArray(), output->GetEncodedArray(), error_msg)) {
685 return false;
686 }
687 break;
688 case DexFile::kDexAnnotationAnnotation:
689 if (!VerifyEncodedAnnotation(orig->GetEncodedAnnotation(),
690 output->GetEncodedAnnotation(),
691 orig_offset,
692 error_msg)) {
693 return false;
694 }
695 break;
696 case DexFile::kDexAnnotationNull:
697 break;
698 case DexFile::kDexAnnotationBoolean:
699 if (orig->GetBoolean() != output->GetBoolean()) {
700 *error_msg = StringPrintf(
701 "Mismatched encoded boolean for annotation at offset %x: %d vs %d.",
702 orig_offset,
703 orig->GetBoolean(),
704 output->GetBoolean());
705 return false;
706 }
707 break;
708 default:
709 break;
710 }
711 return true;
712}
713
714bool VerifyEncodedArray(dex_ir::EncodedArrayItem* orig,
715 dex_ir::EncodedArrayItem* output,
716 std::string* error_msg) {
717 if (orig == nullptr || output == nullptr) {
718 if (orig != output) {
719 *error_msg = "Found unexpected empty encoded array.";
720 return false;
721 }
722 return true;
723 }
724 dex_ir::EncodedValueVector* orig_vector = orig->GetEncodedValues();
725 dex_ir::EncodedValueVector* output_vector = output->GetEncodedValues();
726 if (orig_vector->size() != output_vector->size()) {
727 *error_msg = StringPrintf("Mismatched size for encoded array at offset %x: %zu vs %zu.",
728 orig->GetOffset(),
729 orig_vector->size(),
730 output_vector->size());
731 return false;
732 }
733 for (size_t i = 0; i < orig_vector->size(); ++i) {
734 if (!VerifyEncodedValue((*orig_vector)[i].get(),
735 (*output_vector)[i].get(),
736 orig->GetOffset(),
737 error_msg)) {
738 return false;
739 }
740 }
741 return true;
742}
743
744bool VerifyClassData(dex_ir::ClassData* orig, dex_ir::ClassData* output, std::string* error_msg) {
745 if (orig == nullptr || output == nullptr) {
746 if (orig != output) {
747 *error_msg = "Found unexpected empty class data.";
748 return false;
749 }
750 return true;
751 }
752 if (!VerifyFields(orig->StaticFields(), output->StaticFields(), orig->GetOffset(), error_msg)) {
753 return false;
754 }
755 if (!VerifyFields(orig->InstanceFields(),
756 output->InstanceFields(),
757 orig->GetOffset(),
758 error_msg)) {
759 return false;
760 }
761 if (!VerifyMethods(orig->DirectMethods(),
762 output->DirectMethods(),
763 orig->GetOffset(),
764 error_msg)) {
765 return false;
766 }
767 return VerifyMethods(orig->VirtualMethods(),
768 output->VirtualMethods(),
769 orig->GetOffset(),
770 error_msg);
771}
772
773bool VerifyFields(dex_ir::FieldItemVector* orig,
774 dex_ir::FieldItemVector* output,
775 uint32_t orig_offset,
776 std::string* error_msg) {
777 if (orig->size() != output->size()) {
778 *error_msg = StringPrintf("Mismatched fields size for class data at offset %x: %zu vs %zu.",
779 orig_offset,
780 orig->size(),
781 output->size());
782 return false;
783 }
784 for (size_t i = 0; i < orig->size(); ++i) {
David Sehrd83437c2018-06-11 14:06:23 -0700785 dex_ir::FieldItem* orig_field = &(*orig)[i];
786 dex_ir::FieldItem* output_field = &(*output)[i];
Jeff Haocc829592017-03-14 16:13:39 -0700787 if (orig_field->GetFieldId()->GetIndex() != output_field->GetFieldId()->GetIndex()) {
788 *error_msg = StringPrintf("Mismatched field index for class data at offset %x: %u vs %u.",
789 orig_offset,
790 orig_field->GetFieldId()->GetIndex(),
791 output_field->GetFieldId()->GetIndex());
792 return false;
793 }
794 if (orig_field->GetAccessFlags() != output_field->GetAccessFlags()) {
795 *error_msg = StringPrintf(
796 "Mismatched field access flags for class data at offset %x: %u vs %u.",
797 orig_offset,
798 orig_field->GetAccessFlags(),
799 output_field->GetAccessFlags());
800 return false;
801 }
802 }
803 return true;
804}
805
806bool VerifyMethods(dex_ir::MethodItemVector* orig,
807 dex_ir::MethodItemVector* output,
808 uint32_t orig_offset,
809 std::string* error_msg) {
810 if (orig->size() != output->size()) {
811 *error_msg = StringPrintf("Mismatched methods size for class data at offset %x: %zu vs %zu.",
812 orig_offset,
813 orig->size(),
814 output->size());
815 return false;
816 }
817 for (size_t i = 0; i < orig->size(); ++i) {
David Sehrd83437c2018-06-11 14:06:23 -0700818 dex_ir::MethodItem* orig_method = &(*orig)[i];
819 dex_ir::MethodItem* output_method = &(*output)[i];
Jeff Haocc829592017-03-14 16:13:39 -0700820 if (orig_method->GetMethodId()->GetIndex() != output_method->GetMethodId()->GetIndex()) {
821 *error_msg = StringPrintf("Mismatched method index for class data at offset %x: %u vs %u.",
822 orig_offset,
823 orig_method->GetMethodId()->GetIndex(),
824 output_method->GetMethodId()->GetIndex());
825 return false;
826 }
827 if (orig_method->GetAccessFlags() != output_method->GetAccessFlags()) {
828 *error_msg = StringPrintf(
829 "Mismatched method access flags for class data at offset %x: %u vs %u.",
830 orig_offset,
831 orig_method->GetAccessFlags(),
832 output_method->GetAccessFlags());
833 return false;
834 }
835 if (!VerifyCode(orig_method->GetCodeItem(), output_method->GetCodeItem(), error_msg)) {
836 return false;
837 }
838 }
839 return true;
840}
841
842bool VerifyCode(dex_ir::CodeItem* orig, dex_ir::CodeItem* output, std::string* error_msg) {
843 if (orig == nullptr || output == nullptr) {
844 if (orig != output) {
845 *error_msg = "Found unexpected empty code item.";
846 return false;
847 }
848 return true;
849 }
850 if (orig->RegistersSize() != output->RegistersSize()) {
851 *error_msg = StringPrintf("Mismatched registers size for code item at offset %x: %u vs %u.",
852 orig->GetOffset(),
853 orig->RegistersSize(),
854 output->RegistersSize());
855 return false;
856 }
857 if (orig->InsSize() != output->InsSize()) {
858 *error_msg = StringPrintf("Mismatched ins size for code item at offset %x: %u vs %u.",
859 orig->GetOffset(),
860 orig->InsSize(),
861 output->InsSize());
862 return false;
863 }
864 if (orig->OutsSize() != output->OutsSize()) {
865 *error_msg = StringPrintf("Mismatched outs size for code item at offset %x: %u vs %u.",
866 orig->GetOffset(),
867 orig->OutsSize(),
868 output->OutsSize());
869 return false;
870 }
871 if (orig->TriesSize() != output->TriesSize()) {
872 *error_msg = StringPrintf("Mismatched tries size for code item at offset %x: %u vs %u.",
873 orig->GetOffset(),
874 orig->TriesSize(),
875 output->TriesSize());
876 return false;
877 }
878 if (!VerifyDebugInfo(orig->DebugInfo(), output->DebugInfo(), error_msg)) {
879 return false;
880 }
881 if (orig->InsnsSize() != output->InsnsSize()) {
882 *error_msg = StringPrintf("Mismatched insns size for code item at offset %x: %u vs %u.",
883 orig->GetOffset(),
884 orig->InsnsSize(),
885 output->InsnsSize());
886 return false;
887 }
888 if (memcmp(orig->Insns(), output->Insns(), orig->InsnsSize()) != 0) {
889 *error_msg = StringPrintf("Mismatched insns for code item at offset %x.",
890 orig->GetOffset());
891 return false;
892 }
893 if (!VerifyTries(orig->Tries(), output->Tries(), orig->GetOffset(), error_msg)) {
894 return false;
895 }
896 return VerifyHandlers(orig->Handlers(), output->Handlers(), orig->GetOffset(), error_msg);
897}
898
899bool VerifyDebugInfo(dex_ir::DebugInfoItem* orig,
900 dex_ir::DebugInfoItem* output,
901 std::string* error_msg) {
902 if (orig == nullptr || output == nullptr) {
903 if (orig != output) {
904 *error_msg = "Found unexpected empty debug info.";
905 return false;
906 }
907 return true;
908 }
David Sehraa6abb02017-10-12 08:25:11 -0700909 // TODO: Test for debug equivalence rather than byte array equality.
910 uint32_t orig_size = orig->GetDebugInfoSize();
911 uint32_t output_size = output->GetDebugInfoSize();
912 if (orig_size != output_size) {
913 *error_msg = "DebugInfoSize disagreed.";
Jeff Haocc829592017-03-14 16:13:39 -0700914 return false;
915 }
David Sehraa6abb02017-10-12 08:25:11 -0700916 uint8_t* orig_data = orig->GetDebugInfo();
917 uint8_t* output_data = output->GetDebugInfo();
918 if ((orig_data == nullptr && output_data != nullptr) ||
919 (orig_data != nullptr && output_data == nullptr)) {
920 *error_msg = "DebugInfo null/non-null mismatch.";
Jeff Haocc829592017-03-14 16:13:39 -0700921 return false;
922 }
Andreas Gampedbf54032018-06-18 14:47:01 -0700923 if (orig_data != nullptr && memcmp(orig_data, output_data, orig_size) != 0) {
David Sehraa6abb02017-10-12 08:25:11 -0700924 *error_msg = "DebugInfo bytes mismatch.";
Jeff Haocc829592017-03-14 16:13:39 -0700925 return false;
926 }
Jeff Haocc829592017-03-14 16:13:39 -0700927 return true;
928}
929
930bool VerifyTries(dex_ir::TryItemVector* orig,
931 dex_ir::TryItemVector* output,
932 uint32_t orig_offset,
933 std::string* error_msg) {
934 if (orig == nullptr || output == nullptr) {
935 if (orig != output) {
936 *error_msg = "Found unexpected empty try items.";
937 return false;
938 }
939 return true;
940 }
941 if (orig->size() != output->size()) {
942 *error_msg = StringPrintf("Mismatched tries size for code item at offset %x: %zu vs %zu.",
943 orig_offset,
944 orig->size(),
945 output->size());
946 return false;
947 }
948 for (size_t i = 0; i < orig->size(); ++i) {
949 const dex_ir::TryItem* orig_try = (*orig)[i].get();
950 const dex_ir::TryItem* output_try = (*output)[i].get();
951 if (orig_try->StartAddr() != output_try->StartAddr()) {
952 *error_msg = StringPrintf(
953 "Mismatched try item start addr for code item at offset %x: %u vs %u.",
954 orig_offset,
955 orig_try->StartAddr(),
956 output_try->StartAddr());
957 return false;
958 }
959 if (orig_try->InsnCount() != output_try->InsnCount()) {
960 *error_msg = StringPrintf(
961 "Mismatched try item insn count for code item at offset %x: %u vs %u.",
962 orig_offset,
963 orig_try->InsnCount(),
964 output_try->InsnCount());
965 return false;
966 }
967 if (!VerifyHandler(orig_try->GetHandlers(),
968 output_try->GetHandlers(),
969 orig_offset,
970 error_msg)) {
971 return false;
972 }
973 }
974 return true;
975}
976
977bool VerifyHandlers(dex_ir::CatchHandlerVector* orig,
978 dex_ir::CatchHandlerVector* output,
979 uint32_t orig_offset,
980 std::string* error_msg) {
981 if (orig == nullptr || output == nullptr) {
982 if (orig != output) {
983 *error_msg = "Found unexpected empty catch handlers.";
984 return false;
985 }
986 return true;
987 }
988 if (orig->size() != output->size()) {
989 *error_msg = StringPrintf(
990 "Mismatched catch handlers size for code item at offset %x: %zu vs %zu.",
991 orig_offset,
992 orig->size(),
993 output->size());
994 return false;
995 }
996 for (size_t i = 0; i < orig->size(); ++i) {
997 if (!VerifyHandler((*orig)[i].get(), (*output)[i].get(), orig_offset, error_msg)) {
998 return false;
999 }
1000 }
1001 return true;
1002}
1003
1004bool VerifyHandler(const dex_ir::CatchHandler* orig,
1005 const dex_ir::CatchHandler* output,
1006 uint32_t orig_offset,
1007 std::string* error_msg) {
1008 dex_ir::TypeAddrPairVector* orig_handlers = orig->GetHandlers();
1009 dex_ir::TypeAddrPairVector* output_handlers = output->GetHandlers();
1010 if (orig_handlers->size() != output_handlers->size()) {
1011 *error_msg = StringPrintf(
1012 "Mismatched number of catch handlers for code item at offset %x: %zu vs %zu.",
1013 orig_offset,
1014 orig_handlers->size(),
1015 output_handlers->size());
1016 return false;
1017 }
1018 for (size_t i = 0; i < orig_handlers->size(); ++i) {
1019 const dex_ir::TypeAddrPair* orig_handler = (*orig_handlers)[i].get();
1020 const dex_ir::TypeAddrPair* output_handler = (*output_handlers)[i].get();
1021 if (orig_handler->GetTypeId() == nullptr || output_handler->GetTypeId() == nullptr) {
1022 if (orig_handler->GetTypeId() != output_handler->GetTypeId()) {
1023 *error_msg = StringPrintf(
1024 "Found unexpected catch all catch handler for code item at offset %x.",
1025 orig_offset);
1026 return false;
1027 }
1028 } else if (orig_handler->GetTypeId()->GetIndex() != output_handler->GetTypeId()->GetIndex()) {
1029 *error_msg = StringPrintf(
1030 "Mismatched catch handler type for code item at offset %x: %u vs %u.",
1031 orig_offset,
1032 orig_handler->GetTypeId()->GetIndex(),
1033 output_handler->GetTypeId()->GetIndex());
1034 return false;
1035 }
1036 if (orig_handler->GetAddress() != output_handler->GetAddress()) {
1037 *error_msg = StringPrintf(
1038 "Mismatched catch handler address for code item at offset %x: %u vs %u.",
1039 orig_offset,
1040 orig_handler->GetAddress(),
1041 output_handler->GetAddress());
1042 return false;
1043 }
1044 }
1045 return true;
1046}
1047
Jeff Haoec7f1a92017-03-13 16:24:24 -07001048} // namespace art