• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DexIrBuilder(const DexFile & dex_file,bool eagerly_assign_offsets,const Options & options)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 
CheckAndSetRemainingOffsets(const DexFile & dex_file,Collections * collections,const Options & options)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