• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&parameters[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