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