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