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