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 <set> 26 27 #include "android-base/stringprintf.h" 28 29 namespace art { 30 31 using android::base::StringPrintf; 32 33 bool VerifyOutputDexFile(dex_ir::Header* orig_header, 34 dex_ir::Header* output_header, 35 std::string* error_msg) { 36 // Compare all id sections. They have a defined order that can't be changed by dexlayout. 37 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)) { 42 return false; 43 } 44 // Compare class defs. The order may have been changed by dexlayout. 45 if (!VerifyClassDefs(orig_header->ClassDefs(), output_header->ClassDefs(), error_msg)) { 46 return false; 47 } 48 return true; 49 } 50 51 template<class T> bool VerifyIds(dex_ir::CollectionVector<T>& orig, 52 dex_ir::CollectionVector<T>& output, 53 const char* section_name, 54 std::string* error_msg) { 55 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)) { 59 return false; 60 } 61 } 62 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 } 72 return true; 73 } 74 75 bool VerifyId(dex_ir::StringId* orig, dex_ir::StringId* output, std::string* error_msg) { 76 if (strcmp(orig->Data(), output->Data()) != 0) { 77 *error_msg = StringPrintf("Mismatched string data for string id %u at offset %x: %s vs %s.", 78 orig->GetIndex(), 79 orig->GetOffset(), 80 orig->Data(), 81 output->Data()); 82 return false; 83 } 84 return true; 85 } 86 87 bool VerifyId(dex_ir::TypeId* orig, dex_ir::TypeId* output, std::string* error_msg) { 88 if (orig->GetStringId()->GetIndex() != output->GetStringId()->GetIndex()) { 89 *error_msg = StringPrintf("Mismatched string index for type id %u at offset %x: %u vs %u.", 90 orig->GetIndex(), 91 orig->GetOffset(), 92 orig->GetStringId()->GetIndex(), 93 output->GetStringId()->GetIndex()); 94 return false; 95 } 96 return true; 97 } 98 99 bool VerifyId(dex_ir::ProtoId* orig, dex_ir::ProtoId* output, std::string* error_msg) { 100 if (orig->Shorty()->GetIndex() != output->Shorty()->GetIndex()) { 101 *error_msg = StringPrintf("Mismatched string index for proto id %u at offset %x: %u vs %u.", 102 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()) { 109 *error_msg = StringPrintf("Mismatched type index for proto id %u at offset %x: %u vs %u.", 110 orig->GetIndex(), 111 orig->GetOffset(), 112 orig->ReturnType()->GetIndex(), 113 output->ReturnType()->GetIndex()); 114 return false; 115 } 116 if (!VerifyTypeList(orig->Parameters(), output->Parameters())) { 117 *error_msg = StringPrintf("Mismatched type list for proto id %u at offset %x.", 118 orig->GetIndex(), 119 orig->GetOffset()); 120 } 121 return true; 122 } 123 124 bool VerifyId(dex_ir::FieldId* orig, dex_ir::FieldId* output, std::string* error_msg) { 125 if (orig->Class()->GetIndex() != output->Class()->GetIndex()) { 126 *error_msg = 127 StringPrintf("Mismatched class type index for field id %u at offset %x: %u vs %u.", 128 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()) { 135 *error_msg = StringPrintf("Mismatched type index for field id %u at offset %x: %u vs %u.", 136 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()) { 143 *error_msg = StringPrintf("Mismatched string index for field id %u at offset %x: %u vs %u.", 144 orig->GetIndex(), 145 orig->GetOffset(), 146 orig->Name()->GetIndex(), 147 output->Name()->GetIndex()); 148 return false; 149 } 150 return true; 151 } 152 153 bool VerifyId(dex_ir::MethodId* orig, dex_ir::MethodId* output, std::string* error_msg) { 154 if (orig->Class()->GetIndex() != output->Class()->GetIndex()) { 155 *error_msg = StringPrintf("Mismatched type index for method id %u at offset %x: %u vs %u.", 156 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()) { 163 *error_msg = StringPrintf("Mismatched proto index for method id %u at offset %x: %u vs %u.", 164 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 = 172 StringPrintf("Mismatched string index for method id %u at offset %x: %u vs %u.", 173 orig->GetIndex(), 174 orig->GetOffset(), 175 orig->Name()->GetIndex(), 176 output->Name()->GetIndex()); 177 return false; 178 } 179 return true; 180 } 181 182 struct 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. 190 bool VerifyClassDefs(dex_ir::CollectionVector<dex_ir::ClassDef>& orig, 191 dex_ir::CollectionVector<dex_ir::ClassDef>& output, 192 std::string* error_msg) { 193 // 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; 196 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()); 201 } 202 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)) { 216 return false; 217 } 218 orig_set_iter++; 219 output_set_iter++; 220 } 221 return true; 222 } 223 224 bool 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 279 bool 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 296 bool 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 327 bool 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 368 bool 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 409 bool 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 450 bool 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 471 bool 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 498 bool 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 514 bool 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 547 bool 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 562 bool 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 714 bool 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 744 bool 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 773 bool 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) { 785 dex_ir::FieldItem* orig_field = &(*orig)[i]; 786 dex_ir::FieldItem* output_field = &(*output)[i]; 787 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 806 bool 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) { 818 dex_ir::MethodItem* orig_method = &(*orig)[i]; 819 dex_ir::MethodItem* output_method = &(*output)[i]; 820 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 842 bool 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 899 bool 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 } 909 // 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."; 914 return false; 915 } 916 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."; 921 return false; 922 } 923 if (orig_data != nullptr && memcmp(orig_data, output_data, orig_size) != 0) { 924 *error_msg = "DebugInfo bytes mismatch."; 925 return false; 926 } 927 return true; 928 } 929 930 bool 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 977 bool 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 1004 bool 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 1048 } // namespace art 1049