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