Home | History | Annotate | Download | only in dexlayout
      1 /*
      2  * Copyright (C) 2016 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  * Header file of an in-memory representation of DEX files.
     17  */
     18 
     19 #include <stdint.h>
     20 #include <vector>
     21 
     22 #include "dex_ir_builder.h"
     23 #include "dexlayout.h"
     24 
     25 namespace art {
     26 namespace dex_ir {
     27 
     28 static void CheckAndSetRemainingOffsets(const DexFile& dex_file,
     29                                         Collections* collections,
     30                                         const Options& options);
     31 
     32 Header* DexIrBuilder(const DexFile& dex_file,
     33                      bool eagerly_assign_offsets,
     34                      const Options& options) {
     35   const DexFile::Header& disk_header = dex_file.GetHeader();
     36   Header* header = new Header(disk_header.magic_,
     37                               disk_header.checksum_,
     38                               disk_header.signature_,
     39                               disk_header.endian_tag_,
     40                               disk_header.file_size_,
     41                               disk_header.header_size_,
     42                               disk_header.link_size_,
     43                               disk_header.link_off_,
     44                               disk_header.data_size_,
     45                               disk_header.data_off_,
     46                               dex_file.SupportsDefaultMethods());
     47   Collections& collections = header->GetCollections();
     48   collections.SetEagerlyAssignOffsets(eagerly_assign_offsets);
     49   // Walk the rest of the header fields.
     50   // StringId table.
     51   collections.SetStringIdsOffset(disk_header.string_ids_off_);
     52   for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) {
     53     collections.CreateStringId(dex_file, i);
     54   }
     55   // TypeId table.
     56   collections.SetTypeIdsOffset(disk_header.type_ids_off_);
     57   for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
     58     collections.CreateTypeId(dex_file, i);
     59   }
     60   // ProtoId table.
     61   collections.SetProtoIdsOffset(disk_header.proto_ids_off_);
     62   for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) {
     63     collections.CreateProtoId(dex_file, i);
     64   }
     65   // FieldId table.
     66   collections.SetFieldIdsOffset(disk_header.field_ids_off_);
     67   for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) {
     68     collections.CreateFieldId(dex_file, i);
     69   }
     70   // MethodId table.
     71   collections.SetMethodIdsOffset(disk_header.method_ids_off_);
     72   for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) {
     73     collections.CreateMethodId(dex_file, i);
     74   }
     75   // ClassDef table.
     76   collections.SetClassDefsOffset(disk_header.class_defs_off_);
     77   for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
     78     if (!options.class_filter_.empty()) {
     79       // If the filter is enabled (not empty), filter out classes that don't have a matching
     80       // descriptor.
     81       const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
     82       const char* descriptor = dex_file.GetClassDescriptor(class_def);
     83       if (options.class_filter_.find(descriptor) == options.class_filter_.end()) {
     84         continue;
     85       }
     86     }
     87     collections.CreateClassDef(dex_file, i);
     88   }
     89   // MapItem.
     90   collections.SetMapListOffset(disk_header.map_off_);
     91   // CallSiteIds and MethodHandleItems.
     92   collections.CreateCallSitesAndMethodHandles(dex_file);
     93   CheckAndSetRemainingOffsets(dex_file, &collections, options);
     94 
     95   // Sort the vectors by the map order (same order as the file).
     96   collections.SortVectorsByMapOrder();
     97 
     98   // Load the link data if it exists.
     99   collections.SetLinkData(std::vector<uint8_t>(
    100       dex_file.DataBegin() + dex_file.GetHeader().link_off_,
    101       dex_file.DataBegin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_));
    102 
    103   return header;
    104 }
    105 
    106 static void CheckAndSetRemainingOffsets(const DexFile& dex_file,
    107                                         Collections* collections,
    108                                         const Options& options) {
    109   const DexFile::Header& disk_header = dex_file.GetHeader();
    110   // Read MapItems and validate/set remaining offsets.
    111   const DexFile::MapList* map = dex_file.GetMapList();
    112   const uint32_t count = map->size_;
    113   for (uint32_t i = 0; i < count; ++i) {
    114     const DexFile::MapItem* item = map->list_ + i;
    115     switch (item->type_) {
    116       case DexFile::kDexTypeHeaderItem:
    117         CHECK_EQ(item->size_, 1u);
    118         CHECK_EQ(item->offset_, 0u);
    119         break;
    120       case DexFile::kDexTypeStringIdItem:
    121         CHECK_EQ(item->size_, collections->StringIdsSize());
    122         CHECK_EQ(item->offset_, collections->StringIdsOffset());
    123         break;
    124       case DexFile::kDexTypeTypeIdItem:
    125         CHECK_EQ(item->size_, collections->TypeIdsSize());
    126         CHECK_EQ(item->offset_, collections->TypeIdsOffset());
    127         break;
    128       case DexFile::kDexTypeProtoIdItem:
    129         CHECK_EQ(item->size_, collections->ProtoIdsSize());
    130         CHECK_EQ(item->offset_, collections->ProtoIdsOffset());
    131         break;
    132       case DexFile::kDexTypeFieldIdItem:
    133         CHECK_EQ(item->size_, collections->FieldIdsSize());
    134         CHECK_EQ(item->offset_, collections->FieldIdsOffset());
    135         break;
    136       case DexFile::kDexTypeMethodIdItem:
    137         CHECK_EQ(item->size_, collections->MethodIdsSize());
    138         CHECK_EQ(item->offset_, collections->MethodIdsOffset());
    139         break;
    140       case DexFile::kDexTypeClassDefItem:
    141         if (options.class_filter_.empty()) {
    142           // The filter may have removed some classes, this will get fixed up during writing.
    143           CHECK_EQ(item->size_, collections->ClassDefsSize());
    144         }
    145         CHECK_EQ(item->offset_, collections->ClassDefsOffset());
    146         break;
    147       case DexFile::kDexTypeCallSiteIdItem:
    148         CHECK_EQ(item->size_, collections->CallSiteIdsSize());
    149         CHECK_EQ(item->offset_, collections->CallSiteIdsOffset());
    150         break;
    151       case DexFile::kDexTypeMethodHandleItem:
    152         CHECK_EQ(item->size_, collections->MethodHandleItemsSize());
    153         CHECK_EQ(item->offset_, collections->MethodHandleItemsOffset());
    154         break;
    155       case DexFile::kDexTypeMapList:
    156         CHECK_EQ(item->size_, 1u);
    157         CHECK_EQ(item->offset_, disk_header.map_off_);
    158         break;
    159       case DexFile::kDexTypeTypeList:
    160         collections->SetTypeListsOffset(item->offset_);
    161         break;
    162       case DexFile::kDexTypeAnnotationSetRefList:
    163         collections->SetAnnotationSetRefListsOffset(item->offset_);
    164         break;
    165       case DexFile::kDexTypeAnnotationSetItem:
    166         collections->SetAnnotationSetItemsOffset(item->offset_);
    167         break;
    168       case DexFile::kDexTypeClassDataItem:
    169         collections->SetClassDatasOffset(item->offset_);
    170         break;
    171       case DexFile::kDexTypeCodeItem:
    172         collections->SetCodeItemsOffset(item->offset_);
    173         break;
    174       case DexFile::kDexTypeStringDataItem:
    175         collections->SetStringDatasOffset(item->offset_);
    176         break;
    177       case DexFile::kDexTypeDebugInfoItem:
    178         collections->SetDebugInfoItemsOffset(item->offset_);
    179         break;
    180       case DexFile::kDexTypeAnnotationItem:
    181         collections->SetAnnotationItemsOffset(item->offset_);
    182         collections->AddAnnotationsFromMapListSection(dex_file, item->offset_, item->size_);
    183         break;
    184       case DexFile::kDexTypeEncodedArrayItem:
    185         collections->SetEncodedArrayItemsOffset(item->offset_);
    186         break;
    187       case DexFile::kDexTypeAnnotationsDirectoryItem:
    188         collections->SetAnnotationsDirectoryItemsOffset(item->offset_);
    189         break;
    190       default:
    191         LOG(ERROR) << "Unknown map list item type.";
    192     }
    193   }
    194 }
    195 
    196 }  // namespace dex_ir
    197 }  // namespace art
    198