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