blob: a04a2349c4bc17e15302892fab18806aa3aa3356 [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"
David Sehr2b5a38f2018-06-14 15:13:04 -070023
24#include "dex/code_item_accessors-inl.h"
25#include "dex/dex_file_exception_helpers.h"
Mathieu Chartier75175552018-01-25 11:23:01 -080026#include "dexlayout.h"
David Sehr853a8e12016-09-01 13:03:50 -070027
28namespace art {
29namespace dex_ir {
30
David Sehr2b5a38f2018-06-14 15:13:04 -070031static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) {
32 uint64_t value = 0;
33 for (uint32_t i = 0; i <= length; i++) {
34 value |= static_cast<uint64_t>(*(*data)++) << (i * 8);
35 }
36 if (sign_extend) {
37 int shift = (7 - length) * 8;
38 return (static_cast<int64_t>(value) << shift) >> shift;
39 }
40 return value;
41}
42
43static uint32_t GetDebugInfoStreamSize(const uint8_t* debug_info_stream) {
44 const uint8_t* stream = debug_info_stream;
45 DecodeUnsignedLeb128(&stream); // line_start
46 uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
47 for (uint32_t i = 0; i < parameters_size; ++i) {
48 DecodeUnsignedLeb128P1(&stream); // Parameter name.
49 }
50
51 for (;;) {
52 uint8_t opcode = *stream++;
53 switch (opcode) {
54 case DexFile::DBG_END_SEQUENCE:
55 return stream - debug_info_stream; // end of stream.
56 case DexFile::DBG_ADVANCE_PC:
57 DecodeUnsignedLeb128(&stream); // addr_diff
58 break;
59 case DexFile::DBG_ADVANCE_LINE:
60 DecodeSignedLeb128(&stream); // line_diff
61 break;
62 case DexFile::DBG_START_LOCAL:
63 DecodeUnsignedLeb128(&stream); // register_num
64 DecodeUnsignedLeb128P1(&stream); // name_idx
65 DecodeUnsignedLeb128P1(&stream); // type_idx
66 break;
67 case DexFile::DBG_START_LOCAL_EXTENDED:
68 DecodeUnsignedLeb128(&stream); // register_num
69 DecodeUnsignedLeb128P1(&stream); // name_idx
70 DecodeUnsignedLeb128P1(&stream); // type_idx
71 DecodeUnsignedLeb128P1(&stream); // sig_idx
72 break;
73 case DexFile::DBG_END_LOCAL:
74 case DexFile::DBG_RESTART_LOCAL:
75 DecodeUnsignedLeb128(&stream); // register_num
76 break;
77 case DexFile::DBG_SET_PROLOGUE_END:
78 case DexFile::DBG_SET_EPILOGUE_BEGIN:
79 break;
80 case DexFile::DBG_SET_FILE: {
81 DecodeUnsignedLeb128P1(&stream); // name_idx
82 break;
83 }
84 default: {
85 break;
86 }
87 }
88 }
89}
90
91template<class T> class CollectionMap : public CollectionBase {
92 public:
93 CollectionMap() = default;
94 virtual ~CollectionMap() OVERRIDE { }
95
96 template <class... Args>
97 T* CreateAndAddItem(CollectionVector<T>& vector,
98 bool eagerly_assign_offsets,
99 uint32_t offset,
100 Args&&... args) {
101 T* item = vector.CreateAndAddItem(std::forward<Args>(args)...);
102 DCHECK(!GetExistingObject(offset));
103 DCHECK(!item->OffsetAssigned());
104 if (eagerly_assign_offsets) {
105 item->SetOffset(offset);
106 }
107 AddItem(item, offset);
108 return item;
109 }
110
111 // Returns the existing item if it is already inserted, null otherwise.
112 T* GetExistingObject(uint32_t offset) {
113 auto it = collection_.find(offset);
114 return it != collection_.end() ? it->second : nullptr;
115 }
116
117 // Lower case for template interop with std::map.
118 uint32_t size() const { return collection_.size(); }
119 std::map<uint32_t, T*>& Collection() { return collection_; }
120
121 private:
122 std::map<uint32_t, T*> collection_;
123
124 // CollectionMaps do not own the objects they contain, therefore AddItem is supported
125 // rather than CreateAndAddItem.
126 void AddItem(T* object, uint32_t offset) {
127 auto it = collection_.emplace(offset, object);
128 CHECK(it.second) << "CollectionMap already has an object with offset " << offset << " "
129 << " and address " << it.first->second;
130 }
131
132 DISALLOW_COPY_AND_ASSIGN(CollectionMap);
133};
134
135class BuilderMaps {
136 public:
137 BuilderMaps(Header* header, bool eagerly_assign_offsets)
138 : header_(header), eagerly_assign_offsets_(eagerly_assign_offsets) { }
139
140 void CreateStringId(const DexFile& dex_file, uint32_t i);
141 void CreateTypeId(const DexFile& dex_file, uint32_t i);
142 void CreateProtoId(const DexFile& dex_file, uint32_t i);
143 void CreateFieldId(const DexFile& dex_file, uint32_t i);
144 void CreateMethodId(const DexFile& dex_file, uint32_t i);
145 void CreateClassDef(const DexFile& dex_file, uint32_t i);
146 void CreateCallSiteId(const DexFile& dex_file, uint32_t i);
147 void CreateMethodHandleItem(const DexFile& dex_file, uint32_t i);
148
149 void CreateCallSitesAndMethodHandles(const DexFile& dex_file);
150
151 TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset);
152 EncodedArrayItem* CreateEncodedArrayItem(const DexFile& dex_file,
153 const uint8_t* static_data,
154 uint32_t offset);
155 AnnotationItem* CreateAnnotationItem(const DexFile& dex_file,
156 const DexFile::AnnotationItem* annotation);
157 AnnotationSetItem* CreateAnnotationSetItem(const DexFile& dex_file,
158 const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset);
159 AnnotationsDirectoryItem* CreateAnnotationsDirectoryItem(const DexFile& dex_file,
160 const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset);
161 CodeItem* DedupeOrCreateCodeItem(const DexFile& dex_file,
162 const DexFile::CodeItem* disk_code_item,
163 uint32_t offset,
164 uint32_t dex_method_index);
165 ClassData* CreateClassData(const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset);
166
167 void AddAnnotationsFromMapListSection(const DexFile& dex_file,
168 uint32_t start_offset,
169 uint32_t count);
170
171 void CheckAndSetRemainingOffsets(const DexFile& dex_file, const Options& options);
172
173 // Sort the vectors buy map order (same order that was used in the input file).
174 void SortVectorsByMapOrder();
175
176 private:
177 bool GetIdsFromByteCode(const CodeItem* code,
178 std::vector<TypeId*>* type_ids,
179 std::vector<StringId*>* string_ids,
180 std::vector<MethodId*>* method_ids,
181 std::vector<FieldId*>* field_ids);
182
183 bool GetIdFromInstruction(const Instruction* dec_insn,
184 std::vector<TypeId*>* type_ids,
185 std::vector<StringId*>* string_ids,
186 std::vector<MethodId*>* method_ids,
187 std::vector<FieldId*>* field_ids);
188
189 EncodedValue* ReadEncodedValue(const DexFile& dex_file, const uint8_t** data);
190 EncodedValue* ReadEncodedValue(const DexFile& dex_file,
191 const uint8_t** data,
192 uint8_t type,
193 uint8_t length);
194 void ReadEncodedValue(const DexFile& dex_file,
195 const uint8_t** data,
196 uint8_t type,
197 uint8_t length,
198 EncodedValue* item);
199
200 MethodItem GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii);
201
202 ParameterAnnotation* GenerateParameterAnnotation(
203 const DexFile& dex_file,
204 MethodId* method_id,
205 const DexFile::AnnotationSetRefList* annotation_set_ref_list,
206 uint32_t offset);
207
208 template <typename Type, class... Args>
209 Type* CreateAndAddIndexedItem(IndexedCollectionVector<Type>& vector,
210 uint32_t offset,
211 uint32_t index,
212 Args&&... args) {
213 Type* item = vector.CreateAndAddIndexedItem(index, std::forward<Args>(args)...);
214 DCHECK(!item->OffsetAssigned());
215 if (eagerly_assign_offsets_) {
216 item->SetOffset(offset);
217 }
218 return item;
219 }
220
221 Header* header_;
222 // If we eagerly assign offsets during IR building or later after layout. Must be false if
223 // changing the layout is enabled.
224 bool eagerly_assign_offsets_;
225
226 // Note: maps do not have ownership.
227 CollectionMap<StringData> string_datas_map_;
228 CollectionMap<TypeList> type_lists_map_;
229 CollectionMap<EncodedArrayItem> encoded_array_items_map_;
230 CollectionMap<AnnotationItem> annotation_items_map_;
231 CollectionMap<AnnotationSetItem> annotation_set_items_map_;
232 CollectionMap<AnnotationSetRefList> annotation_set_ref_lists_map_;
233 CollectionMap<AnnotationsDirectoryItem> annotations_directory_items_map_;
234 CollectionMap<DebugInfoItem> debug_info_items_map_;
235 // Code item maps need to check both the debug info offset and debug info offset, do not use
236 // CollectionMap.
237 // First offset is the code item offset, second is the debug info offset.
238 std::map<std::pair<uint32_t, uint32_t>, CodeItem*> code_items_map_;
239 CollectionMap<ClassData> class_datas_map_;
240
241 DISALLOW_COPY_AND_ASSIGN(BuilderMaps);
242};
David Sehrcdcfde72016-09-26 07:44:04 -0700243
Mathieu Chartier75175552018-01-25 11:23:01 -0800244Header* DexIrBuilder(const DexFile& dex_file,
245 bool eagerly_assign_offsets,
246 const Options& options) {
David Sehr853a8e12016-09-01 13:03:50 -0700247 const DexFile::Header& disk_header = dex_file.GetHeader();
248 Header* header = new Header(disk_header.magic_,
249 disk_header.checksum_,
250 disk_header.signature_,
251 disk_header.endian_tag_,
252 disk_header.file_size_,
253 disk_header.header_size_,
254 disk_header.link_size_,
255 disk_header.link_off_,
256 disk_header.data_size_,
Mathieu Chartierf6e31472017-12-28 13:32:08 -0800257 disk_header.data_off_,
David Sehrd83437c2018-06-11 14:06:23 -0700258 dex_file.SupportsDefaultMethods(),
259 dex_file.NumStringIds(),
260 dex_file.NumTypeIds(),
261 dex_file.NumProtoIds(),
262 dex_file.NumFieldIds(),
263 dex_file.NumMethodIds(),
264 dex_file.NumClassDefs());
David Sehr2b5a38f2018-06-14 15:13:04 -0700265 BuilderMaps builder_maps(header, eagerly_assign_offsets);
David Sehr853a8e12016-09-01 13:03:50 -0700266 // Walk the rest of the header fields.
267 // StringId table.
David Sehr2b5a38f2018-06-14 15:13:04 -0700268 header->StringIds().SetOffset(disk_header.string_ids_off_);
David Sehr853a8e12016-09-01 13:03:50 -0700269 for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700270 builder_maps.CreateStringId(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -0700271 }
272 // TypeId table.
David Sehr2b5a38f2018-06-14 15:13:04 -0700273 header->TypeIds().SetOffset(disk_header.type_ids_off_);
David Sehr853a8e12016-09-01 13:03:50 -0700274 for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700275 builder_maps.CreateTypeId(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -0700276 }
277 // ProtoId table.
David Sehr2b5a38f2018-06-14 15:13:04 -0700278 header->ProtoIds().SetOffset(disk_header.proto_ids_off_);
David Sehr853a8e12016-09-01 13:03:50 -0700279 for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700280 builder_maps.CreateProtoId(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -0700281 }
282 // FieldId table.
David Sehr2b5a38f2018-06-14 15:13:04 -0700283 header->FieldIds().SetOffset(disk_header.field_ids_off_);
David Sehr853a8e12016-09-01 13:03:50 -0700284 for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700285 builder_maps.CreateFieldId(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -0700286 }
287 // MethodId table.
David Sehr2b5a38f2018-06-14 15:13:04 -0700288 header->MethodIds().SetOffset(disk_header.method_ids_off_);
David Sehr853a8e12016-09-01 13:03:50 -0700289 for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700290 builder_maps.CreateMethodId(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -0700291 }
292 // ClassDef table.
David Sehr2b5a38f2018-06-14 15:13:04 -0700293 header->ClassDefs().SetOffset(disk_header.class_defs_off_);
David Sehr853a8e12016-09-01 13:03:50 -0700294 for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
Mathieu Chartier75175552018-01-25 11:23:01 -0800295 if (!options.class_filter_.empty()) {
296 // If the filter is enabled (not empty), filter out classes that don't have a matching
297 // descriptor.
298 const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
299 const char* descriptor = dex_file.GetClassDescriptor(class_def);
300 if (options.class_filter_.find(descriptor) == options.class_filter_.end()) {
301 continue;
302 }
303 }
David Sehr2b5a38f2018-06-14 15:13:04 -0700304 builder_maps.CreateClassDef(dex_file, i);
David Sehr853a8e12016-09-01 13:03:50 -0700305 }
Jeff Haoa8621002016-10-04 18:13:44 +0000306 // MapItem.
David Sehr2b5a38f2018-06-14 15:13:04 -0700307 header->SetMapListOffset(disk_header.map_off_);
Jeff Hao5daee902017-04-27 18:00:38 -0700308 // CallSiteIds and MethodHandleItems.
David Sehr2b5a38f2018-06-14 15:13:04 -0700309 builder_maps.CreateCallSitesAndMethodHandles(dex_file);
310 builder_maps.CheckAndSetRemainingOffsets(dex_file, options);
David Sehrcdcfde72016-09-26 07:44:04 -0700311
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800312 // Sort the vectors by the map order (same order as the file).
David Sehr2b5a38f2018-06-14 15:13:04 -0700313 builder_maps.SortVectorsByMapOrder();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800314
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -0800315 // Load the link data if it exists.
David Sehr2b5a38f2018-06-14 15:13:04 -0700316 header->SetLinkData(std::vector<uint8_t>(
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -0800317 dex_file.DataBegin() + dex_file.GetHeader().link_off_,
318 dex_file.DataBegin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_));
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -0800319
David Sehr853a8e12016-09-01 13:03:50 -0700320 return header;
321}
322
David Sehr2b5a38f2018-06-14 15:13:04 -0700323/*
324 * Get all the types, strings, methods, and fields referred to from bytecode.
325 */
326void BuilderMaps::CheckAndSetRemainingOffsets(const DexFile& dex_file, const Options& options) {
David Sehrcdcfde72016-09-26 07:44:04 -0700327 const DexFile::Header& disk_header = dex_file.GetHeader();
328 // Read MapItems and validate/set remaining offsets.
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -0800329 const DexFile::MapList* map = dex_file.GetMapList();
David Sehrcdcfde72016-09-26 07:44:04 -0700330 const uint32_t count = map->size_;
331 for (uint32_t i = 0; i < count; ++i) {
332 const DexFile::MapItem* item = map->list_ + i;
333 switch (item->type_) {
334 case DexFile::kDexTypeHeaderItem:
335 CHECK_EQ(item->size_, 1u);
336 CHECK_EQ(item->offset_, 0u);
337 break;
338 case DexFile::kDexTypeStringIdItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700339 CHECK_EQ(item->size_, header_->StringIds().Size());
340 CHECK_EQ(item->offset_, header_->StringIds().GetOffset());
David Sehrcdcfde72016-09-26 07:44:04 -0700341 break;
342 case DexFile::kDexTypeTypeIdItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700343 CHECK_EQ(item->size_, header_->TypeIds().Size());
344 CHECK_EQ(item->offset_, header_->TypeIds().GetOffset());
David Sehrcdcfde72016-09-26 07:44:04 -0700345 break;
346 case DexFile::kDexTypeProtoIdItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700347 CHECK_EQ(item->size_, header_->ProtoIds().Size());
348 CHECK_EQ(item->offset_, header_->ProtoIds().GetOffset());
David Sehrcdcfde72016-09-26 07:44:04 -0700349 break;
350 case DexFile::kDexTypeFieldIdItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700351 CHECK_EQ(item->size_, header_->FieldIds().Size());
352 CHECK_EQ(item->offset_, header_->FieldIds().GetOffset());
David Sehrcdcfde72016-09-26 07:44:04 -0700353 break;
354 case DexFile::kDexTypeMethodIdItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700355 CHECK_EQ(item->size_, header_->MethodIds().Size());
356 CHECK_EQ(item->offset_, header_->MethodIds().GetOffset());
David Sehrcdcfde72016-09-26 07:44:04 -0700357 break;
358 case DexFile::kDexTypeClassDefItem:
Mathieu Chartier75175552018-01-25 11:23:01 -0800359 if (options.class_filter_.empty()) {
360 // The filter may have removed some classes, this will get fixed up during writing.
David Sehr2b5a38f2018-06-14 15:13:04 -0700361 CHECK_EQ(item->size_, header_->ClassDefs().Size());
Mathieu Chartier75175552018-01-25 11:23:01 -0800362 }
David Sehr2b5a38f2018-06-14 15:13:04 -0700363 CHECK_EQ(item->offset_, header_->ClassDefs().GetOffset());
David Sehrcdcfde72016-09-26 07:44:04 -0700364 break;
Jeff Hao5daee902017-04-27 18:00:38 -0700365 case DexFile::kDexTypeCallSiteIdItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700366 CHECK_EQ(item->size_, header_->CallSiteIds().Size());
367 CHECK_EQ(item->offset_, header_->CallSiteIds().GetOffset());
Jeff Hao5daee902017-04-27 18:00:38 -0700368 break;
369 case DexFile::kDexTypeMethodHandleItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700370 CHECK_EQ(item->size_, header_->MethodHandleItems().Size());
371 CHECK_EQ(item->offset_, header_->MethodHandleItems().GetOffset());
Jeff Hao5daee902017-04-27 18:00:38 -0700372 break;
David Sehrcdcfde72016-09-26 07:44:04 -0700373 case DexFile::kDexTypeMapList:
374 CHECK_EQ(item->size_, 1u);
375 CHECK_EQ(item->offset_, disk_header.map_off_);
376 break;
377 case DexFile::kDexTypeTypeList:
David Sehr2b5a38f2018-06-14 15:13:04 -0700378 header_->TypeLists().SetOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700379 break;
380 case DexFile::kDexTypeAnnotationSetRefList:
David Sehr2b5a38f2018-06-14 15:13:04 -0700381 header_->AnnotationSetRefLists().SetOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700382 break;
383 case DexFile::kDexTypeAnnotationSetItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700384 header_->AnnotationSetItems().SetOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700385 break;
386 case DexFile::kDexTypeClassDataItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700387 header_->ClassDatas().SetOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700388 break;
389 case DexFile::kDexTypeCodeItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700390 header_->CodeItems().SetOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700391 break;
392 case DexFile::kDexTypeStringDataItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700393 header_->StringDatas().SetOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700394 break;
395 case DexFile::kDexTypeDebugInfoItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700396 header_->DebugInfoItems().SetOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700397 break;
398 case DexFile::kDexTypeAnnotationItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700399 header_->AnnotationItems().SetOffset(item->offset_);
400 AddAnnotationsFromMapListSection(dex_file, item->offset_, item->size_);
David Sehrcdcfde72016-09-26 07:44:04 -0700401 break;
402 case DexFile::kDexTypeEncodedArrayItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700403 header_->EncodedArrayItems().SetOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700404 break;
405 case DexFile::kDexTypeAnnotationsDirectoryItem:
David Sehr2b5a38f2018-06-14 15:13:04 -0700406 header_->AnnotationsDirectoryItems().SetOffset(item->offset_);
David Sehrcdcfde72016-09-26 07:44:04 -0700407 break;
408 default:
409 LOG(ERROR) << "Unknown map list item type.";
410 }
411 }
412}
413
David Sehr2b5a38f2018-06-14 15:13:04 -0700414void BuilderMaps::CreateStringId(const DexFile& dex_file, uint32_t i) {
415 const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i));
416 StringData* string_data =
417 string_datas_map_.CreateAndAddItem(header_->StringDatas(),
418 eagerly_assign_offsets_,
419 disk_string_id.string_data_off_,
420 dex_file.GetStringData(disk_string_id));
421 CreateAndAddIndexedItem(header_->StringIds(),
422 header_->StringIds().GetOffset() + i * StringId::ItemSize(),
423 i,
424 string_data);
425}
426
427void BuilderMaps::CreateTypeId(const DexFile& dex_file, uint32_t i) {
428 const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i));
429 CreateAndAddIndexedItem(header_->TypeIds(),
430 header_->TypeIds().GetOffset() + i * TypeId::ItemSize(),
431 i,
432 header_->StringIds()[disk_type_id.descriptor_idx_.index_]);
433}
434
435void BuilderMaps::CreateProtoId(const DexFile& dex_file, uint32_t i) {
436 const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(dex::ProtoIndex(i));
437 const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
438 TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_);
439
440 CreateAndAddIndexedItem(header_->ProtoIds(),
441 header_->ProtoIds().GetOffset() + i * ProtoId::ItemSize(),
442 i,
443 header_->StringIds()[disk_proto_id.shorty_idx_.index_],
444 header_->TypeIds()[disk_proto_id.return_type_idx_.index_],
445 parameter_type_list);
446}
447
448void BuilderMaps::CreateFieldId(const DexFile& dex_file, uint32_t i) {
449 const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
450 CreateAndAddIndexedItem(header_->FieldIds(),
451 header_->FieldIds().GetOffset() + i * FieldId::ItemSize(),
452 i,
453 header_->TypeIds()[disk_field_id.class_idx_.index_],
454 header_->TypeIds()[disk_field_id.type_idx_.index_],
455 header_->StringIds()[disk_field_id.name_idx_.index_]);
456}
457
458void BuilderMaps::CreateMethodId(const DexFile& dex_file, uint32_t i) {
459 const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
460 CreateAndAddIndexedItem(header_->MethodIds(),
461 header_->MethodIds().GetOffset() + i * MethodId::ItemSize(),
462 i,
463 header_->TypeIds()[disk_method_id.class_idx_.index_],
464 header_->ProtoIds()[disk_method_id.proto_idx_.index_],
465 header_->StringIds()[disk_method_id.name_idx_.index_]);
466}
467
468void BuilderMaps::CreateClassDef(const DexFile& dex_file, uint32_t i) {
469 const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
470 const TypeId* class_type = header_->TypeIds()[disk_class_def.class_idx_.index_];
471 uint32_t access_flags = disk_class_def.access_flags_;
472 const TypeId* superclass = header_->GetTypeIdOrNullPtr(disk_class_def.superclass_idx_.index_);
473
474 const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
475 TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_);
476
477 const StringId* source_file =
478 header_->GetStringIdOrNullPtr(disk_class_def.source_file_idx_.index_);
479 // Annotations.
480 AnnotationsDirectoryItem* annotations = nullptr;
481 const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
482 dex_file.GetAnnotationsDirectory(disk_class_def);
483 if (disk_annotations_directory_item != nullptr) {
484 annotations = CreateAnnotationsDirectoryItem(
485 dex_file, disk_annotations_directory_item, disk_class_def.annotations_off_);
486 }
487 // Static field initializers.
488 const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def);
489 EncodedArrayItem* static_values =
490 CreateEncodedArrayItem(dex_file, static_data, disk_class_def.static_values_off_);
491 ClassData* class_data = CreateClassData(
492 dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_);
493 CreateAndAddIndexedItem(header_->ClassDefs(),
494 header_->ClassDefs().GetOffset() + i * ClassDef::ItemSize(),
495 i,
496 class_type,
497 access_flags,
498 superclass,
499 interfaces_type_list,
500 source_file,
501 annotations,
502 static_values,
503 class_data);
504}
505
506void BuilderMaps::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
507 const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i);
508 const uint8_t* disk_call_item_ptr = dex_file.DataBegin() + disk_call_site_id.data_off_;
509 EncodedArrayItem* call_site_item =
510 CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_);
511
512 CreateAndAddIndexedItem(header_->CallSiteIds(),
513 header_->CallSiteIds().GetOffset() + i * CallSiteId::ItemSize(),
514 i,
515 call_site_item);
516}
517
518void BuilderMaps::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
519 const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i);
520 uint16_t index = disk_method_handle.field_or_method_idx_;
521 DexFile::MethodHandleType type =
522 static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_);
523 bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic ||
524 type == DexFile::MethodHandleType::kInvokeInstance ||
525 type == DexFile::MethodHandleType::kInvokeConstructor ||
526 type == DexFile::MethodHandleType::kInvokeDirect ||
527 type == DexFile::MethodHandleType::kInvokeInterface;
528 static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeInterface,
529 "Unexpected method handle types.");
530 IndexedItem* field_or_method_id;
531 if (is_invoke) {
532 field_or_method_id = header_->MethodIds()[index];
533 } else {
534 field_or_method_id = header_->FieldIds()[index];
535 }
536 CreateAndAddIndexedItem(header_->MethodHandleItems(),
537 header_->MethodHandleItems().GetOffset() +
538 i * MethodHandleItem::ItemSize(),
539 i,
540 type,
541 field_or_method_id);
542}
543
544void BuilderMaps::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
545 // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems.
546 const DexFile::MapList* map = dex_file.GetMapList();
547 for (uint32_t i = 0; i < map->size_; ++i) {
548 const DexFile::MapItem* item = map->list_ + i;
549 switch (item->type_) {
550 case DexFile::kDexTypeCallSiteIdItem:
551 header_->CallSiteIds().SetOffset(item->offset_);
552 break;
553 case DexFile::kDexTypeMethodHandleItem:
554 header_->MethodHandleItems().SetOffset(item->offset_);
555 break;
556 default:
557 break;
558 }
559 }
560 // Populate MethodHandleItems first (CallSiteIds may depend on them).
561 for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) {
562 CreateMethodHandleItem(dex_file, i);
563 }
564 // Populate CallSiteIds.
565 for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) {
566 CreateCallSiteId(dex_file, i);
567 }
568}
569
570TypeList* BuilderMaps::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) {
571 if (dex_type_list == nullptr) {
572 return nullptr;
573 }
574 TypeList* type_list = type_lists_map_.GetExistingObject(offset);
575 if (type_list == nullptr) {
576 TypeIdVector* type_vector = new TypeIdVector();
577 uint32_t size = dex_type_list->Size();
578 for (uint32_t index = 0; index < size; ++index) {
579 type_vector->push_back(header_->TypeIds()[
580 dex_type_list->GetTypeItem(index).type_idx_.index_]);
581 }
582 type_list = type_lists_map_.CreateAndAddItem(header_->TypeLists(),
583 eagerly_assign_offsets_,
584 offset,
585 type_vector);
586 }
587 return type_list;
588}
589
590EncodedArrayItem* BuilderMaps::CreateEncodedArrayItem(const DexFile& dex_file,
591 const uint8_t* static_data,
592 uint32_t offset) {
593 if (static_data == nullptr) {
594 return nullptr;
595 }
596 EncodedArrayItem* encoded_array_item = encoded_array_items_map_.GetExistingObject(offset);
597 if (encoded_array_item == nullptr) {
598 uint32_t size = DecodeUnsignedLeb128(&static_data);
599 EncodedValueVector* values = new EncodedValueVector();
600 for (uint32_t i = 0; i < size; ++i) {
601 values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, &static_data)));
602 }
603 // TODO: Calculate the size of the encoded array.
604 encoded_array_item = encoded_array_items_map_.CreateAndAddItem(header_->EncodedArrayItems(),
605 eagerly_assign_offsets_,
606 offset,
607 values);
608 }
609 return encoded_array_item;
610}
611
612void BuilderMaps::AddAnnotationsFromMapListSection(const DexFile& dex_file,
613 uint32_t start_offset,
614 uint32_t count) {
615 uint32_t current_offset = start_offset;
616 for (size_t i = 0; i < count; ++i) {
617 // Annotation that we didn't process already, add it to the set.
618 const DexFile::AnnotationItem* annotation = dex_file.GetAnnotationItemAtOffset(current_offset);
619 AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation);
620 DCHECK(annotation_item != nullptr);
621 current_offset += annotation_item->GetSize();
622 }
623}
624
625AnnotationItem* BuilderMaps::CreateAnnotationItem(const DexFile& dex_file,
626 const DexFile::AnnotationItem* annotation) {
627 const uint8_t* const start_data = reinterpret_cast<const uint8_t*>(annotation);
628 const uint32_t offset = start_data - dex_file.DataBegin();
629 AnnotationItem* annotation_item = annotation_items_map_.GetExistingObject(offset);
630 if (annotation_item == nullptr) {
631 uint8_t visibility = annotation->visibility_;
632 const uint8_t* annotation_data = annotation->annotation_;
633 std::unique_ptr<EncodedValue> encoded_value(
634 ReadEncodedValue(dex_file, &annotation_data, DexFile::kDexAnnotationAnnotation, 0));
635 annotation_item =
636 annotation_items_map_.CreateAndAddItem(header_->AnnotationItems(),
637 eagerly_assign_offsets_,
638 offset,
639 visibility,
640 encoded_value->ReleaseEncodedAnnotation());
641 annotation_item->SetSize(annotation_data - start_data);
642 }
643 return annotation_item;
644}
645
646
647AnnotationSetItem* BuilderMaps::CreateAnnotationSetItem(const DexFile& dex_file,
648 const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset) {
649 if (disk_annotations_item == nullptr || (disk_annotations_item->size_ == 0 && offset == 0)) {
650 return nullptr;
651 }
652 AnnotationSetItem* annotation_set_item = annotation_set_items_map_.GetExistingObject(offset);
653 if (annotation_set_item == nullptr) {
654 std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
655 for (uint32_t i = 0; i < disk_annotations_item->size_; ++i) {
656 const DexFile::AnnotationItem* annotation =
657 dex_file.GetAnnotationItem(disk_annotations_item, i);
658 if (annotation == nullptr) {
659 continue;
660 }
661 AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation);
662 items->push_back(annotation_item);
663 }
664 annotation_set_item =
665 annotation_set_items_map_.CreateAndAddItem(header_->AnnotationSetItems(),
666 eagerly_assign_offsets_,
667 offset,
668 items);
669 }
670 return annotation_set_item;
671}
672
673AnnotationsDirectoryItem* BuilderMaps::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
674 const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
675 AnnotationsDirectoryItem* annotations_directory_item =
676 annotations_directory_items_map_.GetExistingObject(offset);
677 if (annotations_directory_item != nullptr) {
678 return annotations_directory_item;
679 }
680 const DexFile::AnnotationSetItem* class_set_item =
681 dex_file.GetClassAnnotationSet(disk_annotations_item);
682 AnnotationSetItem* class_annotation = nullptr;
683 if (class_set_item != nullptr) {
684 uint32_t item_offset = disk_annotations_item->class_annotations_off_;
685 class_annotation = CreateAnnotationSetItem(dex_file, class_set_item, item_offset);
686 }
687 const DexFile::FieldAnnotationsItem* fields =
688 dex_file.GetFieldAnnotations(disk_annotations_item);
689 FieldAnnotationVector* field_annotations = nullptr;
690 if (fields != nullptr) {
691 field_annotations = new FieldAnnotationVector();
692 for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
693 FieldId* field_id = header_->FieldIds()[fields[i].field_idx_];
694 const DexFile::AnnotationSetItem* field_set_item =
695 dex_file.GetFieldAnnotationSetItem(fields[i]);
696 uint32_t annotation_set_offset = fields[i].annotations_off_;
697 AnnotationSetItem* annotation_set_item =
698 CreateAnnotationSetItem(dex_file, field_set_item, annotation_set_offset);
699 field_annotations->push_back(std::unique_ptr<FieldAnnotation>(
700 new FieldAnnotation(field_id, annotation_set_item)));
701 }
702 }
703 const DexFile::MethodAnnotationsItem* methods =
704 dex_file.GetMethodAnnotations(disk_annotations_item);
705 MethodAnnotationVector* method_annotations = nullptr;
706 if (methods != nullptr) {
707 method_annotations = new MethodAnnotationVector();
708 for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
709 MethodId* method_id = header_->MethodIds()[methods[i].method_idx_];
710 const DexFile::AnnotationSetItem* method_set_item =
711 dex_file.GetMethodAnnotationSetItem(methods[i]);
712 uint32_t annotation_set_offset = methods[i].annotations_off_;
713 AnnotationSetItem* annotation_set_item =
714 CreateAnnotationSetItem(dex_file, method_set_item, annotation_set_offset);
715 method_annotations->push_back(std::unique_ptr<MethodAnnotation>(
716 new MethodAnnotation(method_id, annotation_set_item)));
717 }
718 }
719 const DexFile::ParameterAnnotationsItem* parameters =
720 dex_file.GetParameterAnnotations(disk_annotations_item);
721 ParameterAnnotationVector* parameter_annotations = nullptr;
722 if (parameters != nullptr) {
723 parameter_annotations = new ParameterAnnotationVector();
724 for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
725 MethodId* method_id = header_->MethodIds()[parameters[i].method_idx_];
726 const DexFile::AnnotationSetRefList* list =
727 dex_file.GetParameterAnnotationSetRefList(&parameters[i]);
728 parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
729 GenerateParameterAnnotation(dex_file, method_id, list, parameters[i].annotations_off_)));
730 }
731 }
732 // TODO: Calculate the size of the annotations directory.
733 return annotations_directory_items_map_.CreateAndAddItem(header_->AnnotationsDirectoryItems(),
734 eagerly_assign_offsets_,
735 offset,
736 class_annotation,
737 field_annotations,
738 method_annotations,
739 parameter_annotations);
740}
741
742CodeItem* BuilderMaps::DedupeOrCreateCodeItem(const DexFile& dex_file,
743 const DexFile::CodeItem* disk_code_item,
744 uint32_t offset,
745 uint32_t dex_method_index) {
746 if (disk_code_item == nullptr) {
747 return nullptr;
748 }
749 CodeItemDebugInfoAccessor accessor(dex_file, disk_code_item, dex_method_index);
750 const uint32_t debug_info_offset = accessor.DebugInfoOffset();
751
752 // Create the offsets pair and dedupe based on it.
753 std::pair<uint32_t, uint32_t> offsets_pair(offset, debug_info_offset);
754 auto existing = code_items_map_.find(offsets_pair);
755 if (existing != code_items_map_.end()) {
756 return existing->second;
757 }
758
759 const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(debug_info_offset);
760 DebugInfoItem* debug_info = nullptr;
761 if (debug_info_stream != nullptr) {
762 debug_info = debug_info_items_map_.GetExistingObject(debug_info_offset);
763 if (debug_info == nullptr) {
764 uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream);
765 uint8_t* debug_info_buffer = new uint8_t[debug_info_size];
766 memcpy(debug_info_buffer, debug_info_stream, debug_info_size);
767 debug_info = debug_info_items_map_.CreateAndAddItem(header_->DebugInfoItems(),
768 eagerly_assign_offsets_,
769 debug_info_offset,
770 debug_info_size,
771 debug_info_buffer);
772 }
773 }
774
775 uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
776 uint16_t* insns = new uint16_t[insns_size];
777 memcpy(insns, accessor.Insns(), insns_size * sizeof(uint16_t));
778
779 TryItemVector* tries = nullptr;
780 CatchHandlerVector* handler_list = nullptr;
781 if (accessor.TriesSize() > 0) {
782 tries = new TryItemVector();
783 handler_list = new CatchHandlerVector();
784 for (const DexFile::TryItem& disk_try_item : accessor.TryItems()) {
785 uint32_t start_addr = disk_try_item.start_addr_;
786 uint16_t insn_count = disk_try_item.insn_count_;
787 uint16_t handler_off = disk_try_item.handler_off_;
788 const CatchHandler* handlers = nullptr;
789 for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
790 if (handler_off == existing_handlers->GetListOffset()) {
791 handlers = existing_handlers.get();
792 break;
793 }
794 }
795 if (handlers == nullptr) {
796 bool catch_all = false;
797 TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
798 for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) {
799 const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
800 const TypeId* type_id = header_->GetTypeIdOrNullPtr(type_index.index_);
801 catch_all |= type_id == nullptr;
802 addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>(
803 new TypeAddrPair(type_id, it.GetHandlerAddress())));
804 }
805 handlers = new CatchHandler(catch_all, handler_off, addr_pairs);
806 handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers));
807 }
808 TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
809 tries->push_back(std::unique_ptr<const TryItem>(try_item));
810 }
811 // Manually walk catch handlers list and add any missing handlers unreferenced by try items.
812 const uint8_t* handlers_base = accessor.GetCatchHandlerData();
813 const uint8_t* handlers_data = handlers_base;
814 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data);
815 while (handlers_size > handler_list->size()) {
816 bool already_added = false;
817 uint16_t handler_off = handlers_data - handlers_base;
818 for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
819 if (handler_off == existing_handlers->GetListOffset()) {
820 already_added = true;
821 break;
822 }
823 }
824 int32_t size = DecodeSignedLeb128(&handlers_data);
825 bool has_catch_all = size <= 0;
826 if (has_catch_all) {
827 size = -size;
828 }
829 if (already_added) {
830 for (int32_t i = 0; i < size; i++) {
831 DecodeUnsignedLeb128(&handlers_data);
832 DecodeUnsignedLeb128(&handlers_data);
833 }
834 if (has_catch_all) {
835 DecodeUnsignedLeb128(&handlers_data);
836 }
837 continue;
838 }
839 TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
840 for (int32_t i = 0; i < size; i++) {
841 const TypeId* type_id =
842 header_->GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data));
843 uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
844 addr_pairs->push_back(
845 std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr)));
846 }
847 if (has_catch_all) {
848 uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
849 addr_pairs->push_back(
850 std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr)));
851 }
852 const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs);
853 handler_list->push_back(std::unique_ptr<const CatchHandler>(handler));
854 }
855 }
856
857 uint32_t size = dex_file.GetCodeItemSize(*disk_code_item);
858 CodeItem* code_item = header_->CodeItems().CreateAndAddItem(accessor.RegistersSize(),
859 accessor.InsSize(),
860 accessor.OutsSize(),
861 debug_info,
862 insns_size,
863 insns,
864 tries,
865 handler_list);
866 code_item->SetSize(size);
867
868 // Add the code item to the map.
869 DCHECK(!code_item->OffsetAssigned());
870 if (eagerly_assign_offsets_) {
871 code_item->SetOffset(offset);
872 }
873 code_items_map_.emplace(offsets_pair, code_item);
874
875 // Add "fixup" references to types, strings, methods, and fields.
876 // This is temporary, as we will probably want more detailed parsing of the
877 // instructions here.
878 std::vector<TypeId*> type_ids;
879 std::vector<StringId*> string_ids;
880 std::vector<MethodId*> method_ids;
881 std::vector<FieldId*> field_ids;
882 if (GetIdsFromByteCode(code_item,
883 /*out*/ &type_ids,
884 /*out*/ &string_ids,
885 /*out*/ &method_ids,
886 /*out*/ &field_ids)) {
887 CodeFixups* fixups = new CodeFixups(std::move(type_ids),
888 std::move(string_ids),
889 std::move(method_ids),
890 std::move(field_ids));
891 code_item->SetCodeFixups(fixups);
892 }
893
894 return code_item;
895}
896
897ClassData* BuilderMaps::CreateClassData(
898 const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
899 // Read the fields and methods defined by the class, resolving the circular reference from those
900 // to classes by setting class at the same time.
901 ClassData* class_data = class_datas_map_.GetExistingObject(offset);
902 if (class_data == nullptr && encoded_data != nullptr) {
903 ClassDataItemIterator cdii(dex_file, encoded_data);
904 // Static fields.
905 FieldItemVector* static_fields = new FieldItemVector();
906 for (; cdii.HasNextStaticField(); cdii.Next()) {
907 FieldId* field_item = header_->FieldIds()[cdii.GetMemberIndex()];
908 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
909 static_fields->emplace_back(access_flags, field_item);
910 }
911 // Instance fields.
912 FieldItemVector* instance_fields = new FieldItemVector();
913 for (; cdii.HasNextInstanceField(); cdii.Next()) {
914 FieldId* field_item = header_->FieldIds()[cdii.GetMemberIndex()];
915 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
916 instance_fields->emplace_back(access_flags, field_item);
917 }
918 // Direct methods.
919 MethodItemVector* direct_methods = new MethodItemVector();
920 for (; cdii.HasNextDirectMethod(); cdii.Next()) {
921 direct_methods->push_back(GenerateMethodItem(dex_file, cdii));
922 }
923 // Virtual methods.
924 MethodItemVector* virtual_methods = new MethodItemVector();
925 for (; cdii.HasNextVirtualMethod(); cdii.Next()) {
926 virtual_methods->push_back(GenerateMethodItem(dex_file, cdii));
927 }
928 class_data = class_datas_map_.CreateAndAddItem(header_->ClassDatas(),
929 eagerly_assign_offsets_,
930 offset,
931 static_fields,
932 instance_fields,
933 direct_methods,
934 virtual_methods);
935 class_data->SetSize(cdii.EndDataPointer() - encoded_data);
936 }
937 return class_data;
938}
939
940void BuilderMaps::SortVectorsByMapOrder() {
941 header_->StringDatas().SortByMapOrder(string_datas_map_.Collection());
942 header_->TypeLists().SortByMapOrder(type_lists_map_.Collection());
943 header_->EncodedArrayItems().SortByMapOrder(encoded_array_items_map_.Collection());
944 header_->AnnotationItems().SortByMapOrder(annotation_items_map_.Collection());
945 header_->AnnotationSetItems().SortByMapOrder(annotation_set_items_map_.Collection());
946 header_->AnnotationSetRefLists().SortByMapOrder(annotation_set_ref_lists_map_.Collection());
947 header_->AnnotationsDirectoryItems().SortByMapOrder(
948 annotations_directory_items_map_.Collection());
949 header_->DebugInfoItems().SortByMapOrder(debug_info_items_map_.Collection());
950 header_->CodeItems().SortByMapOrder(code_items_map_);
951 header_->ClassDatas().SortByMapOrder(class_datas_map_.Collection());
952}
953
954bool BuilderMaps::GetIdsFromByteCode(const CodeItem* code,
955 std::vector<TypeId*>* type_ids,
956 std::vector<StringId*>* string_ids,
957 std::vector<MethodId*>* method_ids,
958 std::vector<FieldId*>* field_ids) {
959 bool has_id = false;
960 IterationRange<DexInstructionIterator> instructions = code->Instructions();
961 SafeDexInstructionIterator it(instructions.begin(), instructions.end());
962 for (; !it.IsErrorState() && it < instructions.end(); ++it) {
963 // In case the instruction goes past the end of the code item, make sure to not process it.
964 SafeDexInstructionIterator next = it;
965 ++next;
966 if (next.IsErrorState()) {
967 break;
968 }
969 has_id |= GetIdFromInstruction(&it.Inst(), type_ids, string_ids, method_ids, field_ids);
970 } // for
971 return has_id;
972}
973
974bool BuilderMaps::GetIdFromInstruction(const Instruction* dec_insn,
975 std::vector<TypeId*>* type_ids,
976 std::vector<StringId*>* string_ids,
977 std::vector<MethodId*>* method_ids,
978 std::vector<FieldId*>* field_ids) {
979 // Determine index and width of the string.
980 uint32_t index = 0;
981 switch (Instruction::FormatOf(dec_insn->Opcode())) {
982 // SOME NOT SUPPORTED:
983 // case Instruction::k20bc:
984 case Instruction::k21c:
985 case Instruction::k35c:
986 // case Instruction::k35ms:
987 case Instruction::k3rc:
988 // case Instruction::k3rms:
989 // case Instruction::k35mi:
990 // case Instruction::k3rmi:
991 case Instruction::k45cc:
992 case Instruction::k4rcc:
993 index = dec_insn->VRegB();
994 break;
995 case Instruction::k31c:
996 index = dec_insn->VRegB();
997 break;
998 case Instruction::k22c:
999 // case Instruction::k22cs:
1000 index = dec_insn->VRegC();
1001 break;
1002 default:
1003 break;
1004 } // switch
1005
1006 // Determine index type, and add reference to the appropriate collection.
1007 switch (Instruction::IndexTypeOf(dec_insn->Opcode())) {
1008 case Instruction::kIndexTypeRef:
1009 if (index < header_->TypeIds().Size()) {
1010 type_ids->push_back(header_->TypeIds()[index]);
1011 return true;
1012 }
1013 break;
1014 case Instruction::kIndexStringRef:
1015 if (index < header_->StringIds().Size()) {
1016 string_ids->push_back(header_->StringIds()[index]);
1017 return true;
1018 }
1019 break;
1020 case Instruction::kIndexMethodRef:
1021 case Instruction::kIndexMethodAndProtoRef:
1022 if (index < header_->MethodIds().Size()) {
1023 method_ids->push_back(header_->MethodIds()[index]);
1024 return true;
1025 }
1026 break;
1027 case Instruction::kIndexFieldRef:
1028 if (index < header_->FieldIds().Size()) {
1029 field_ids->push_back(header_->FieldIds()[index]);
1030 return true;
1031 }
1032 break;
1033 case Instruction::kIndexUnknown:
1034 case Instruction::kIndexNone:
1035 case Instruction::kIndexVtableOffset:
1036 case Instruction::kIndexFieldOffset:
1037 default:
1038 break;
1039 } // switch
1040 return false;
1041}
1042
1043EncodedValue* BuilderMaps::ReadEncodedValue(const DexFile& dex_file, const uint8_t** data) {
1044 const uint8_t encoded_value = *(*data)++;
1045 const uint8_t type = encoded_value & 0x1f;
1046 EncodedValue* item = new EncodedValue(type);
1047 ReadEncodedValue(dex_file, data, type, encoded_value >> 5, item);
1048 return item;
1049}
1050
1051EncodedValue* BuilderMaps::ReadEncodedValue(const DexFile& dex_file,
1052 const uint8_t** data,
1053 uint8_t type,
1054 uint8_t length) {
1055 EncodedValue* item = new EncodedValue(type);
1056 ReadEncodedValue(dex_file, data, type, length, item);
1057 return item;
1058}
1059
1060void BuilderMaps::ReadEncodedValue(const DexFile& dex_file,
1061 const uint8_t** data,
1062 uint8_t type,
1063 uint8_t length,
1064 EncodedValue* item) {
1065 switch (type) {
1066 case DexFile::kDexAnnotationByte:
1067 item->SetByte(static_cast<int8_t>(ReadVarWidth(data, length, false)));
1068 break;
1069 case DexFile::kDexAnnotationShort:
1070 item->SetShort(static_cast<int16_t>(ReadVarWidth(data, length, true)));
1071 break;
1072 case DexFile::kDexAnnotationChar:
1073 item->SetChar(static_cast<uint16_t>(ReadVarWidth(data, length, false)));
1074 break;
1075 case DexFile::kDexAnnotationInt:
1076 item->SetInt(static_cast<int32_t>(ReadVarWidth(data, length, true)));
1077 break;
1078 case DexFile::kDexAnnotationLong:
1079 item->SetLong(static_cast<int64_t>(ReadVarWidth(data, length, true)));
1080 break;
1081 case DexFile::kDexAnnotationFloat: {
1082 // Fill on right.
1083 union {
1084 float f;
1085 uint32_t data;
1086 } conv;
1087 conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
1088 item->SetFloat(conv.f);
1089 break;
1090 }
1091 case DexFile::kDexAnnotationDouble: {
1092 // Fill on right.
1093 union {
1094 double d;
1095 uint64_t data;
1096 } conv;
1097 conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
1098 item->SetDouble(conv.d);
1099 break;
1100 }
1101 case DexFile::kDexAnnotationMethodType: {
1102 const uint32_t proto_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
1103 item->SetProtoId(header_->ProtoIds()[proto_index]);
1104 break;
1105 }
1106 case DexFile::kDexAnnotationMethodHandle: {
1107 const uint32_t method_handle_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
1108 item->SetMethodHandle(header_->MethodHandleItems()[method_handle_index]);
1109 break;
1110 }
1111 case DexFile::kDexAnnotationString: {
1112 const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
1113 item->SetStringId(header_->StringIds()[string_index]);
1114 break;
1115 }
1116 case DexFile::kDexAnnotationType: {
1117 const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
1118 item->SetTypeId(header_->TypeIds()[string_index]);
1119 break;
1120 }
1121 case DexFile::kDexAnnotationField:
1122 case DexFile::kDexAnnotationEnum: {
1123 const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
1124 item->SetFieldId(header_->FieldIds()[field_index]);
1125 break;
1126 }
1127 case DexFile::kDexAnnotationMethod: {
1128 const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
1129 item->SetMethodId(header_->MethodIds()[method_index]);
1130 break;
1131 }
1132 case DexFile::kDexAnnotationArray: {
1133 EncodedValueVector* values = new EncodedValueVector();
1134 const uint32_t offset = *data - dex_file.DataBegin();
1135 const uint32_t size = DecodeUnsignedLeb128(data);
1136 // Decode all elements.
1137 for (uint32_t i = 0; i < size; i++) {
1138 values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, data)));
1139 }
1140 EncodedArrayItem* array_item = new EncodedArrayItem(values);
1141 if (eagerly_assign_offsets_) {
1142 array_item->SetOffset(offset);
1143 }
1144 item->SetEncodedArray(array_item);
1145 break;
1146 }
1147 case DexFile::kDexAnnotationAnnotation: {
1148 AnnotationElementVector* elements = new AnnotationElementVector();
1149 const uint32_t type_idx = DecodeUnsignedLeb128(data);
1150 const uint32_t size = DecodeUnsignedLeb128(data);
1151 // Decode all name=value pairs.
1152 for (uint32_t i = 0; i < size; i++) {
1153 const uint32_t name_index = DecodeUnsignedLeb128(data);
1154 elements->push_back(std::unique_ptr<AnnotationElement>(
1155 new AnnotationElement(header_->StringIds()[name_index],
1156 ReadEncodedValue(dex_file, data))));
1157 }
1158 item->SetEncodedAnnotation(new EncodedAnnotation(header_->TypeIds()[type_idx], elements));
1159 break;
1160 }
1161 case DexFile::kDexAnnotationNull:
1162 break;
1163 case DexFile::kDexAnnotationBoolean:
1164 item->SetBoolean(length != 0);
1165 break;
1166 default:
1167 break;
1168 }
1169}
1170
1171MethodItem BuilderMaps::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
1172 MethodId* method_id = header_->MethodIds()[cdii.GetMemberIndex()];
1173 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
1174 const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
1175 // Temporary hack to prevent incorrectly deduping code items if they have the same offset since
1176 // they may have different debug info streams.
1177 CodeItem* code_item = DedupeOrCreateCodeItem(dex_file,
1178 disk_code_item,
1179 cdii.GetMethodCodeItemOffset(),
1180 cdii.GetMemberIndex());
1181 return MethodItem(access_flags, method_id, code_item);
1182}
1183
1184ParameterAnnotation* BuilderMaps::GenerateParameterAnnotation(
1185 const DexFile& dex_file,
1186 MethodId* method_id,
1187 const DexFile::AnnotationSetRefList* annotation_set_ref_list,
1188 uint32_t offset) {
1189 AnnotationSetRefList* set_ref_list = annotation_set_ref_lists_map_.GetExistingObject(offset);
1190 if (set_ref_list == nullptr) {
1191 std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
1192 for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
1193 const DexFile::AnnotationSetItem* annotation_set_item =
1194 dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
1195 uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
1196 annotations->push_back(CreateAnnotationSetItem(dex_file, annotation_set_item, set_offset));
1197 }
1198 set_ref_list =
1199 annotation_set_ref_lists_map_.CreateAndAddItem(header_->AnnotationSetRefLists(),
1200 eagerly_assign_offsets_,
1201 offset,
1202 annotations);
1203 }
1204 return new ParameterAnnotation(method_id, set_ref_list);
1205}
1206
David Sehr853a8e12016-09-01 13:03:50 -07001207} // namespace dex_ir
1208} // namespace art