blob: 4f9bcdd7426b4521a9309f13d949aa3cb9b8879f [file] [log] [blame]
David Sehr853a8e12016-09-01 13:03:50 -07001/*
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"
Mathieu Chartier75175552018-01-25 11:23:01 -080023#include "dexlayout.h"
David Sehr853a8e12016-09-01 13:03:50 -070024
25namespace art {
26namespace dex_ir {
27
Mathieu Chartier75175552018-01-25 11:23:01 -080028static void CheckAndSetRemainingOffsets(const DexFile& dex_file,
29 Collections* collections,
30 const Options& options);
David Sehrcdcfde72016-09-26 07:44:04 -070031
Mathieu Chartier75175552018-01-25 11:23:01 -080032Header* DexIrBuilder(const DexFile& dex_file,
33 bool eagerly_assign_offsets,
34 const Options& options) {
David Sehr853a8e12016-09-01 13:03:50 -070035 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_,
Mathieu Chartierf6e31472017-12-28 13:32:08 -080045 disk_header.data_off_,
46 dex_file.SupportsDefaultMethods());
Jeff Hao3ab96b42016-09-09 18:35:01 -070047 Collections& collections = header->GetCollections();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -080048 collections.SetEagerlyAssignOffsets(eagerly_assign_offsets);
David Sehr853a8e12016-09-01 13:03:50 -070049 // Walk the rest of the header fields.
50 // StringId table.
Jeff Hao3ab96b42016-09-09 18:35:01 -070051 collections.SetStringIdsOffset(disk_header.string_ids_off_);
David Sehr853a8e12016-09-01 13:03:50 -070052 for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) {
Jeff Hao3ab96b42016-09-09 18:35:01 -070053 collections.CreateStringId(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -070054 }
55 // TypeId table.
Jeff Hao3ab96b42016-09-09 18:35:01 -070056 collections.SetTypeIdsOffset(disk_header.type_ids_off_);
David Sehr853a8e12016-09-01 13:03:50 -070057 for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
Jeff Hao3ab96b42016-09-09 18:35:01 -070058 collections.CreateTypeId(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -070059 }
60 // ProtoId table.
Jeff Hao3ab96b42016-09-09 18:35:01 -070061 collections.SetProtoIdsOffset(disk_header.proto_ids_off_);
David Sehr853a8e12016-09-01 13:03:50 -070062 for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) {
Jeff Hao3ab96b42016-09-09 18:35:01 -070063 collections.CreateProtoId(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -070064 }
65 // FieldId table.
Jeff Hao3ab96b42016-09-09 18:35:01 -070066 collections.SetFieldIdsOffset(disk_header.field_ids_off_);
David Sehr853a8e12016-09-01 13:03:50 -070067 for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) {
Jeff Hao3ab96b42016-09-09 18:35:01 -070068 collections.CreateFieldId(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -070069 }
70 // MethodId table.
Jeff Hao3ab96b42016-09-09 18:35:01 -070071 collections.SetMethodIdsOffset(disk_header.method_ids_off_);
David Sehr853a8e12016-09-01 13:03:50 -070072 for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) {
Jeff Hao3ab96b42016-09-09 18:35:01 -070073 collections.CreateMethodId(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -070074 }
75 // ClassDef table.
Jeff Hao3ab96b42016-09-09 18:35:01 -070076 collections.SetClassDefsOffset(disk_header.class_defs_off_);
David Sehr853a8e12016-09-01 13:03:50 -070077 for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
Mathieu Chartier75175552018-01-25 11:23:01 -080078 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 }
Jeff Hao3ab96b42016-09-09 18:35:01 -070087 collections.CreateClassDef(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -070088 }
Jeff Haoa8621002016-10-04 18:13:44 +000089 // MapItem.
Jeff Haoea7c6292016-11-14 18:10:16 -080090 collections.SetMapListOffset(disk_header.map_off_);
Jeff Hao5daee902017-04-27 18:00:38 -070091 // CallSiteIds and MethodHandleItems.
92 collections.CreateCallSitesAndMethodHandles(dex_file);
Mathieu Chartier75175552018-01-25 11:23:01 -080093 CheckAndSetRemainingOffsets(dex_file, &collections, options);
David Sehrcdcfde72016-09-26 07:44:04 -070094
Mathieu Chartier3e0c5172017-11-12 12:58:40 -080095 // Sort the vectors by the map order (same order as the file).
96 collections.SortVectorsByMapOrder();
97
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -080098 // Load the link data if it exists.
99 collections.SetLinkData(std::vector<uint8_t>(
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -0800100 dex_file.DataBegin() + dex_file.GetHeader().link_off_,
101 dex_file.DataBegin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_));
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -0800102
David Sehr853a8e12016-09-01 13:03:50 -0700103 return header;
104}
105
Mathieu Chartier75175552018-01-25 11:23:01 -0800106static void CheckAndSetRemainingOffsets(const DexFile& dex_file,
107 Collections* collections,
108 const Options& options) {
David Sehrcdcfde72016-09-26 07:44:04 -0700109 const DexFile::Header& disk_header = dex_file.GetHeader();
110 // Read MapItems and validate/set remaining offsets.
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -0800111 const DexFile::MapList* map = dex_file.GetMapList();
David Sehrcdcfde72016-09-26 07:44:04 -0700112 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:
Mathieu Chartier75175552018-01-25 11:23:01 -0800141 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 }
David Sehrcdcfde72016-09-26 07:44:04 -0700145 CHECK_EQ(item->offset_, collections->ClassDefsOffset());
146 break;
Jeff Hao5daee902017-04-27 18:00:38 -0700147 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;
David Sehrcdcfde72016-09-26 07:44:04 -0700155 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:
Jeff Haoa8621002016-10-04 18:13:44 +0000166 collections->SetAnnotationSetItemsOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700167 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:
Jeff Haoa8621002016-10-04 18:13:44 +0000178 collections->SetDebugInfoItemsOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700179 break;
180 case DexFile::kDexTypeAnnotationItem:
Jeff Haoa8621002016-10-04 18:13:44 +0000181 collections->SetAnnotationItemsOffset(item->offset_);
Mathieu Chartier24066ec2017-10-21 16:01:08 -0700182 collections->AddAnnotationsFromMapListSection(dex_file, item->offset_, item->size_);
David Sehrcdcfde72016-09-26 07:44:04 -0700183 break;
184 case DexFile::kDexTypeEncodedArrayItem:
Jeff Haoa8621002016-10-04 18:13:44 +0000185 collections->SetEncodedArrayItemsOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700186 break;
187 case DexFile::kDexTypeAnnotationsDirectoryItem:
Jeff Haoa8621002016-10-04 18:13:44 +0000188 collections->SetAnnotationsDirectoryItemsOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700189 break;
190 default:
191 LOG(ERROR) << "Unknown map list item type.";
192 }
193 }
194}
195
David Sehr853a8e12016-09-01 13:03:50 -0700196} // namespace dex_ir
197} // namespace art