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 
24 namespace art {
25 namespace dex_ir {
26 
27 static void CheckAndSetRemainingOffsets(const DexFile& dex_file, Collections* collections);
28 
DexIrBuilder(const DexFile & dex_file)29 Header* DexIrBuilder(const DexFile& dex_file) {
30   const DexFile::Header& disk_header = dex_file.GetHeader();
31   Header* header = new Header(disk_header.magic_,
32                               disk_header.checksum_,
33                               disk_header.signature_,
34                               disk_header.endian_tag_,
35                               disk_header.file_size_,
36                               disk_header.header_size_,
37                               disk_header.link_size_,
38                               disk_header.link_off_,
39                               disk_header.data_size_,
40                               disk_header.data_off_);
41   Collections& collections = header->GetCollections();
42   // Walk the rest of the header fields.
43   // StringId table.
44   collections.SetStringIdsOffset(disk_header.string_ids_off_);
45   for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) {
46     collections.CreateStringId(dex_file, i);
47   }
48   // TypeId table.
49   collections.SetTypeIdsOffset(disk_header.type_ids_off_);
50   for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
51     collections.CreateTypeId(dex_file, i);
52   }
53   // ProtoId table.
54   collections.SetProtoIdsOffset(disk_header.proto_ids_off_);
55   for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) {
56     collections.CreateProtoId(dex_file, i);
57   }
58   // FieldId table.
59   collections.SetFieldIdsOffset(disk_header.field_ids_off_);
60   for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) {
61     collections.CreateFieldId(dex_file, i);
62   }
63   // MethodId table.
64   collections.SetMethodIdsOffset(disk_header.method_ids_off_);
65   for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) {
66     collections.CreateMethodId(dex_file, i);
67   }
68   // ClassDef table.
69   collections.SetClassDefsOffset(disk_header.class_defs_off_);
70   for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
71     collections.CreateClassDef(dex_file, i);
72   }
73   // MapItem.
74   collections.SetMapListOffset(disk_header.map_off_);
75   // CallSiteIds and MethodHandleItems.
76   collections.CreateCallSitesAndMethodHandles(dex_file);
77 
78   CheckAndSetRemainingOffsets(dex_file, &collections);
79 
80   return header;
81 }
82 
CheckAndSetRemainingOffsets(const DexFile & dex_file,Collections * collections)83 static void CheckAndSetRemainingOffsets(const DexFile& dex_file, Collections* collections) {
84   const DexFile::Header& disk_header = dex_file.GetHeader();
85   // Read MapItems and validate/set remaining offsets.
86   const DexFile::MapList* map =
87       reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + disk_header.map_off_);
88   const uint32_t count = map->size_;
89   for (uint32_t i = 0; i < count; ++i) {
90     const DexFile::MapItem* item = map->list_ + i;
91     switch (item->type_) {
92       case DexFile::kDexTypeHeaderItem:
93         CHECK_EQ(item->size_, 1u);
94         CHECK_EQ(item->offset_, 0u);
95         break;
96       case DexFile::kDexTypeStringIdItem:
97         CHECK_EQ(item->size_, collections->StringIdsSize());
98         CHECK_EQ(item->offset_, collections->StringIdsOffset());
99         break;
100       case DexFile::kDexTypeTypeIdItem:
101         CHECK_EQ(item->size_, collections->TypeIdsSize());
102         CHECK_EQ(item->offset_, collections->TypeIdsOffset());
103         break;
104       case DexFile::kDexTypeProtoIdItem:
105         CHECK_EQ(item->size_, collections->ProtoIdsSize());
106         CHECK_EQ(item->offset_, collections->ProtoIdsOffset());
107         break;
108       case DexFile::kDexTypeFieldIdItem:
109         CHECK_EQ(item->size_, collections->FieldIdsSize());
110         CHECK_EQ(item->offset_, collections->FieldIdsOffset());
111         break;
112       case DexFile::kDexTypeMethodIdItem:
113         CHECK_EQ(item->size_, collections->MethodIdsSize());
114         CHECK_EQ(item->offset_, collections->MethodIdsOffset());
115         break;
116       case DexFile::kDexTypeClassDefItem:
117         CHECK_EQ(item->size_, collections->ClassDefsSize());
118         CHECK_EQ(item->offset_, collections->ClassDefsOffset());
119         break;
120       case DexFile::kDexTypeCallSiteIdItem:
121         CHECK_EQ(item->size_, collections->CallSiteIdsSize());
122         CHECK_EQ(item->offset_, collections->CallSiteIdsOffset());
123         break;
124       case DexFile::kDexTypeMethodHandleItem:
125         CHECK_EQ(item->size_, collections->MethodHandleItemsSize());
126         CHECK_EQ(item->offset_, collections->MethodHandleItemsOffset());
127         break;
128       case DexFile::kDexTypeMapList:
129         CHECK_EQ(item->size_, 1u);
130         CHECK_EQ(item->offset_, disk_header.map_off_);
131         break;
132       case DexFile::kDexTypeTypeList:
133         collections->SetTypeListsOffset(item->offset_);
134         break;
135       case DexFile::kDexTypeAnnotationSetRefList:
136         collections->SetAnnotationSetRefListsOffset(item->offset_);
137         break;
138       case DexFile::kDexTypeAnnotationSetItem:
139         collections->SetAnnotationSetItemsOffset(item->offset_);
140         break;
141       case DexFile::kDexTypeClassDataItem:
142         collections->SetClassDatasOffset(item->offset_);
143         break;
144       case DexFile::kDexTypeCodeItem:
145         collections->SetCodeItemsOffset(item->offset_);
146         break;
147       case DexFile::kDexTypeStringDataItem:
148         collections->SetStringDatasOffset(item->offset_);
149         break;
150       case DexFile::kDexTypeDebugInfoItem:
151         collections->SetDebugInfoItemsOffset(item->offset_);
152         break;
153       case DexFile::kDexTypeAnnotationItem:
154         collections->SetAnnotationItemsOffset(item->offset_);
155         break;
156       case DexFile::kDexTypeEncodedArrayItem:
157         collections->SetEncodedArrayItemsOffset(item->offset_);
158         break;
159       case DexFile::kDexTypeAnnotationsDirectoryItem:
160         collections->SetAnnotationsDirectoryItemsOffset(item->offset_);
161         break;
162       default:
163         LOG(ERROR) << "Unknown map list item type.";
164     }
165   }
166 }
167 
168 }  // namespace dex_ir
169 }  // namespace art
170