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 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 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 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 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 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 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 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 { 177 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. 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 // TODO: Test for debug equivalence rather than byte array equality. 897 uint32_t orig_size = orig->GetDebugInfoSize(); 898 uint32_t output_size = output->GetDebugInfoSize(); 899 if (orig_size != output_size) { 900 *error_msg = "DebugInfoSize disagreed."; 901 return false; 902 } 903 uint8_t* orig_data = orig->GetDebugInfo(); 904 uint8_t* output_data = output->GetDebugInfo(); 905 if ((orig_data == nullptr && output_data != nullptr) || 906 (orig_data != nullptr && output_data == nullptr)) { 907 *error_msg = "DebugInfo null/non-null mismatch."; 908 return false; 909 } 910 if (memcmp(orig_data, output_data, orig_size) != 0) { 911 *error_msg = "DebugInfo bytes mismatch."; 912 return false; 913 } 914 return true; 915 } 916 917 bool VerifyTries(dex_ir::TryItemVector* orig, 918 dex_ir::TryItemVector* output, 919 uint32_t orig_offset, 920 std::string* error_msg) { 921 if (orig == nullptr || output == nullptr) { 922 if (orig != output) { 923 *error_msg = "Found unexpected empty try items."; 924 return false; 925 } 926 return true; 927 } 928 if (orig->size() != output->size()) { 929 *error_msg = StringPrintf("Mismatched tries size for code item at offset %x: %zu vs %zu.", 930 orig_offset, 931 orig->size(), 932 output->size()); 933 return false; 934 } 935 for (size_t i = 0; i < orig->size(); ++i) { 936 const dex_ir::TryItem* orig_try = (*orig)[i].get(); 937 const dex_ir::TryItem* output_try = (*output)[i].get(); 938 if (orig_try->StartAddr() != output_try->StartAddr()) { 939 *error_msg = StringPrintf( 940 "Mismatched try item start addr for code item at offset %x: %u vs %u.", 941 orig_offset, 942 orig_try->StartAddr(), 943 output_try->StartAddr()); 944 return false; 945 } 946 if (orig_try->InsnCount() != output_try->InsnCount()) { 947 *error_msg = StringPrintf( 948 "Mismatched try item insn count for code item at offset %x: %u vs %u.", 949 orig_offset, 950 orig_try->InsnCount(), 951 output_try->InsnCount()); 952 return false; 953 } 954 if (!VerifyHandler(orig_try->GetHandlers(), 955 output_try->GetHandlers(), 956 orig_offset, 957 error_msg)) { 958 return false; 959 } 960 } 961 return true; 962 } 963 964 bool VerifyHandlers(dex_ir::CatchHandlerVector* orig, 965 dex_ir::CatchHandlerVector* output, 966 uint32_t orig_offset, 967 std::string* error_msg) { 968 if (orig == nullptr || output == nullptr) { 969 if (orig != output) { 970 *error_msg = "Found unexpected empty catch handlers."; 971 return false; 972 } 973 return true; 974 } 975 if (orig->size() != output->size()) { 976 *error_msg = StringPrintf( 977 "Mismatched catch handlers size for code item at offset %x: %zu vs %zu.", 978 orig_offset, 979 orig->size(), 980 output->size()); 981 return false; 982 } 983 for (size_t i = 0; i < orig->size(); ++i) { 984 if (!VerifyHandler((*orig)[i].get(), (*output)[i].get(), orig_offset, error_msg)) { 985 return false; 986 } 987 } 988 return true; 989 } 990 991 bool VerifyHandler(const dex_ir::CatchHandler* orig, 992 const dex_ir::CatchHandler* output, 993 uint32_t orig_offset, 994 std::string* error_msg) { 995 dex_ir::TypeAddrPairVector* orig_handlers = orig->GetHandlers(); 996 dex_ir::TypeAddrPairVector* output_handlers = output->GetHandlers(); 997 if (orig_handlers->size() != output_handlers->size()) { 998 *error_msg = StringPrintf( 999 "Mismatched number of catch handlers for code item at offset %x: %zu vs %zu.", 1000 orig_offset, 1001 orig_handlers->size(), 1002 output_handlers->size()); 1003 return false; 1004 } 1005 for (size_t i = 0; i < orig_handlers->size(); ++i) { 1006 const dex_ir::TypeAddrPair* orig_handler = (*orig_handlers)[i].get(); 1007 const dex_ir::TypeAddrPair* output_handler = (*output_handlers)[i].get(); 1008 if (orig_handler->GetTypeId() == nullptr || output_handler->GetTypeId() == nullptr) { 1009 if (orig_handler->GetTypeId() != output_handler->GetTypeId()) { 1010 *error_msg = StringPrintf( 1011 "Found unexpected catch all catch handler for code item at offset %x.", 1012 orig_offset); 1013 return false; 1014 } 1015 } else if (orig_handler->GetTypeId()->GetIndex() != output_handler->GetTypeId()->GetIndex()) { 1016 *error_msg = StringPrintf( 1017 "Mismatched catch handler type for code item at offset %x: %u vs %u.", 1018 orig_offset, 1019 orig_handler->GetTypeId()->GetIndex(), 1020 output_handler->GetTypeId()->GetIndex()); 1021 return false; 1022 } 1023 if (orig_handler->GetAddress() != output_handler->GetAddress()) { 1024 *error_msg = StringPrintf( 1025 "Mismatched catch handler address for code item at offset %x: %u vs %u.", 1026 orig_offset, 1027 orig_handler->GetAddress(), 1028 output_handler->GetAddress()); 1029 return false; 1030 } 1031 } 1032 return true; 1033 } 1034 1035 } // namespace art 1036