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