Home | History | Annotate | Download | only in dexlayout
      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