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  * Implementation file of the dexlayout utility.
17  *
18  * This is a tool to read dex files into an internal representation,
19  * reorganize the representation, and emit dex files with a better
20  * file layout.
21  */
22 
23 #include "dex_ir.h"
24 #include "dex_instruction-inl.h"
25 #include "dex_ir_builder.h"
26 
27 namespace art {
28 namespace dex_ir {
29 
ReadVarWidth(const uint8_t ** data,uint8_t length,bool sign_extend)30 static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) {
31   uint64_t value = 0;
32   for (uint32_t i = 0; i <= length; i++) {
33     value |= static_cast<uint64_t>(*(*data)++) << (i * 8);
34   }
35   if (sign_extend) {
36     int shift = (7 - length) * 8;
37     return (static_cast<int64_t>(value) << shift) >> shift;
38   }
39   return value;
40 }
41 
GetPositionsCb(void * context,const DexFile::PositionInfo & entry)42 static bool GetPositionsCb(void* context, const DexFile::PositionInfo& entry) {
43   DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
44   PositionInfoVector& positions = debug_info->GetPositionInfo();
45   positions.push_back(std::unique_ptr<PositionInfo>(new PositionInfo(entry.address_, entry.line_)));
46   return false;
47 }
48 
GetLocalsCb(void * context,const DexFile::LocalInfo & entry)49 static void GetLocalsCb(void* context, const DexFile::LocalInfo& entry) {
50   DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
51   LocalInfoVector& locals = debug_info->GetLocalInfo();
52   const char* name = entry.name_ != nullptr ? entry.name_ : "(null)";
53   const char* descriptor = entry.descriptor_ != nullptr ? entry.descriptor_ : "";
54   const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
55   locals.push_back(std::unique_ptr<LocalInfo>(
56       new LocalInfo(name, descriptor, signature, entry.start_address_, entry.end_address_,
57                     entry.reg_)));
58 }
59 
GetCodeItemSize(const DexFile::CodeItem & disk_code_item)60 static uint32_t GetCodeItemSize(const DexFile::CodeItem& disk_code_item) {
61   uintptr_t code_item_start = reinterpret_cast<uintptr_t>(&disk_code_item);
62   uint32_t insns_size = disk_code_item.insns_size_in_code_units_;
63   uint32_t tries_size = disk_code_item.tries_size_;
64   if (tries_size == 0) {
65     uintptr_t insns_end = reinterpret_cast<uintptr_t>(&disk_code_item.insns_[insns_size]);
66     return insns_end - code_item_start;
67   } else {
68     // Get the start of the handler data.
69     const uint8_t* handler_data = DexFile::GetCatchHandlerData(disk_code_item, 0);
70     uint32_t handlers_size = DecodeUnsignedLeb128(&handler_data);
71     // Manually read each handler.
72     for (uint32_t i = 0; i < handlers_size; ++i) {
73       int32_t uleb128_count = DecodeSignedLeb128(&handler_data) * 2;
74       if (uleb128_count <= 0) {
75         uleb128_count = -uleb128_count + 1;
76       }
77       for (int32_t j = 0; j < uleb128_count; ++j) {
78         DecodeUnsignedLeb128(&handler_data);
79       }
80     }
81     return reinterpret_cast<uintptr_t>(handler_data) - code_item_start;
82   }
83 }
84 
GetDebugInfoStreamSize(const uint8_t * debug_info_stream)85 static uint32_t GetDebugInfoStreamSize(const uint8_t* debug_info_stream) {
86   const uint8_t* stream = debug_info_stream;
87   DecodeUnsignedLeb128(&stream);  // line_start
88   uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
89   for (uint32_t i = 0; i < parameters_size; ++i) {
90     DecodeUnsignedLeb128P1(&stream);  // Parameter name.
91   }
92 
93   for (;;)  {
94     uint8_t opcode = *stream++;
95     switch (opcode) {
96       case DexFile::DBG_END_SEQUENCE:
97         return stream - debug_info_stream;  // end of stream.
98       case DexFile::DBG_ADVANCE_PC:
99         DecodeUnsignedLeb128(&stream);  // addr_diff
100         break;
101       case DexFile::DBG_ADVANCE_LINE:
102         DecodeSignedLeb128(&stream);  // line_diff
103         break;
104       case DexFile::DBG_START_LOCAL:
105         DecodeUnsignedLeb128(&stream);  // register_num
106         DecodeUnsignedLeb128P1(&stream);  // name_idx
107         DecodeUnsignedLeb128P1(&stream);  // type_idx
108         break;
109       case DexFile::DBG_START_LOCAL_EXTENDED:
110         DecodeUnsignedLeb128(&stream);  // register_num
111         DecodeUnsignedLeb128P1(&stream);  // name_idx
112         DecodeUnsignedLeb128P1(&stream);  // type_idx
113         DecodeUnsignedLeb128P1(&stream);  // sig_idx
114         break;
115       case DexFile::DBG_END_LOCAL:
116       case DexFile::DBG_RESTART_LOCAL:
117         DecodeUnsignedLeb128(&stream);  // register_num
118         break;
119       case DexFile::DBG_SET_PROLOGUE_END:
120       case DexFile::DBG_SET_EPILOGUE_BEGIN:
121         break;
122       case DexFile::DBG_SET_FILE: {
123         DecodeUnsignedLeb128P1(&stream);  // name_idx
124         break;
125       }
126       default: {
127         break;
128       }
129     }
130   }
131 }
132 
GetIdFromInstruction(Collections & collections,const Instruction * dec_insn,std::vector<TypeId * > * type_ids,std::vector<StringId * > * string_ids,std::vector<MethodId * > * method_ids,std::vector<FieldId * > * field_ids)133 static bool GetIdFromInstruction(Collections& collections,
134                                  const Instruction* dec_insn,
135                                  std::vector<TypeId*>* type_ids,
136                                  std::vector<StringId*>* string_ids,
137                                  std::vector<MethodId*>* method_ids,
138                                  std::vector<FieldId*>* field_ids) {
139   // Determine index and width of the string.
140   uint32_t index = 0;
141   switch (Instruction::FormatOf(dec_insn->Opcode())) {
142     // SOME NOT SUPPORTED:
143     // case Instruction::k20bc:
144     case Instruction::k21c:
145     case Instruction::k35c:
146     // case Instruction::k35ms:
147     case Instruction::k3rc:
148     // case Instruction::k3rms:
149     // case Instruction::k35mi:
150     // case Instruction::k3rmi:
151     case Instruction::k45cc:
152     case Instruction::k4rcc:
153       index = dec_insn->VRegB();
154       break;
155     case Instruction::k31c:
156       index = dec_insn->VRegB();
157       break;
158     case Instruction::k22c:
159     // case Instruction::k22cs:
160       index = dec_insn->VRegC();
161       break;
162     default:
163       break;
164   }  // switch
165 
166   // Determine index type, and add reference to the appropriate collection.
167   switch (Instruction::IndexTypeOf(dec_insn->Opcode())) {
168     case Instruction::kIndexTypeRef:
169       if (index < collections.TypeIdsSize()) {
170         type_ids->push_back(collections.GetTypeId(index));
171         return true;
172       }
173       break;
174     case Instruction::kIndexStringRef:
175       if (index < collections.StringIdsSize()) {
176         string_ids->push_back(collections.GetStringId(index));
177         return true;
178       }
179       break;
180     case Instruction::kIndexMethodRef:
181     case Instruction::kIndexMethodAndProtoRef:
182       if (index < collections.MethodIdsSize()) {
183         method_ids->push_back(collections.GetMethodId(index));
184         return true;
185       }
186       break;
187     case Instruction::kIndexFieldRef:
188       if (index < collections.FieldIdsSize()) {
189         field_ids->push_back(collections.GetFieldId(index));
190         return true;
191       }
192       break;
193     case Instruction::kIndexUnknown:
194     case Instruction::kIndexNone:
195     case Instruction::kIndexVtableOffset:
196     case Instruction::kIndexFieldOffset:
197     default:
198       break;
199   }  // switch
200   return false;
201 }
202 
203 /*
204  * Get all the types, strings, methods, and fields referred to from bytecode.
205  */
GetIdsFromByteCode(Collections & collections,const CodeItem * code,std::vector<TypeId * > * type_ids,std::vector<StringId * > * string_ids,std::vector<MethodId * > * method_ids,std::vector<FieldId * > * field_ids)206 static bool GetIdsFromByteCode(Collections& collections,
207                                const CodeItem* code,
208                                std::vector<TypeId*>* type_ids,
209                                std::vector<StringId*>* string_ids,
210                                std::vector<MethodId*>* method_ids,
211                                std::vector<FieldId*>* field_ids) {
212   bool has_id = false;
213   // Iterate over all instructions.
214   const uint16_t* insns = code->Insns();
215   for (uint32_t insn_idx = 0; insn_idx < code->InsnsSize();) {
216     const Instruction* instruction = Instruction::At(&insns[insn_idx]);
217     const uint32_t insn_width = instruction->SizeInCodeUnits();
218     if (insn_width == 0) {
219       break;
220     }
221     has_id |= GetIdFromInstruction(collections,
222                                    instruction,
223                                    type_ids,
224                                    string_ids,
225                                    method_ids,
226                                    field_ids);
227     insn_idx += insn_width;
228   }  // for
229   return has_id;
230 }
231 
ReadEncodedValue(const uint8_t ** data)232 EncodedValue* Collections::ReadEncodedValue(const uint8_t** data) {
233   const uint8_t encoded_value = *(*data)++;
234   const uint8_t type = encoded_value & 0x1f;
235   EncodedValue* item = new EncodedValue(type);
236   ReadEncodedValue(data, type, encoded_value >> 5, item);
237   return item;
238 }
239 
ReadEncodedValue(const uint8_t ** data,uint8_t type,uint8_t length)240 EncodedValue* Collections::ReadEncodedValue(const uint8_t** data, uint8_t type, uint8_t length) {
241   EncodedValue* item = new EncodedValue(type);
242   ReadEncodedValue(data, type, length, item);
243   return item;
244 }
245 
ReadEncodedValue(const uint8_t ** data,uint8_t type,uint8_t length,EncodedValue * item)246 void Collections::ReadEncodedValue(
247     const uint8_t** data, uint8_t type, uint8_t length, EncodedValue* item) {
248   switch (type) {
249     case DexFile::kDexAnnotationByte:
250       item->SetByte(static_cast<int8_t>(ReadVarWidth(data, length, false)));
251       break;
252     case DexFile::kDexAnnotationShort:
253       item->SetShort(static_cast<int16_t>(ReadVarWidth(data, length, true)));
254       break;
255     case DexFile::kDexAnnotationChar:
256       item->SetChar(static_cast<uint16_t>(ReadVarWidth(data, length, false)));
257       break;
258     case DexFile::kDexAnnotationInt:
259       item->SetInt(static_cast<int32_t>(ReadVarWidth(data, length, true)));
260       break;
261     case DexFile::kDexAnnotationLong:
262       item->SetLong(static_cast<int64_t>(ReadVarWidth(data, length, true)));
263       break;
264     case DexFile::kDexAnnotationFloat: {
265       // Fill on right.
266       union {
267         float f;
268         uint32_t data;
269       } conv;
270       conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
271       item->SetFloat(conv.f);
272       break;
273     }
274     case DexFile::kDexAnnotationDouble: {
275       // Fill on right.
276       union {
277         double d;
278         uint64_t data;
279       } conv;
280       conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
281       item->SetDouble(conv.d);
282       break;
283     }
284     case DexFile::kDexAnnotationMethodType: {
285       const uint32_t proto_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
286       item->SetProtoId(GetProtoId(proto_index));
287       break;
288     }
289     case DexFile::kDexAnnotationMethodHandle: {
290       const uint32_t method_handle_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
291       item->SetMethodHandle(GetMethodHandle(method_handle_index));
292       break;
293     }
294     case DexFile::kDexAnnotationString: {
295       const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
296       item->SetStringId(GetStringId(string_index));
297       break;
298     }
299     case DexFile::kDexAnnotationType: {
300       const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
301       item->SetTypeId(GetTypeId(string_index));
302       break;
303     }
304     case DexFile::kDexAnnotationField:
305     case DexFile::kDexAnnotationEnum: {
306       const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
307       item->SetFieldId(GetFieldId(field_index));
308       break;
309     }
310     case DexFile::kDexAnnotationMethod: {
311       const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
312       item->SetMethodId(GetMethodId(method_index));
313       break;
314     }
315     case DexFile::kDexAnnotationArray: {
316       EncodedValueVector* values = new EncodedValueVector();
317       const uint32_t size = DecodeUnsignedLeb128(data);
318       // Decode all elements.
319       for (uint32_t i = 0; i < size; i++) {
320         values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(data)));
321       }
322       item->SetEncodedArray(new EncodedArrayItem(values));
323       break;
324     }
325     case DexFile::kDexAnnotationAnnotation: {
326       AnnotationElementVector* elements = new AnnotationElementVector();
327       const uint32_t type_idx = DecodeUnsignedLeb128(data);
328       const uint32_t size = DecodeUnsignedLeb128(data);
329       // Decode all name=value pairs.
330       for (uint32_t i = 0; i < size; i++) {
331         const uint32_t name_index = DecodeUnsignedLeb128(data);
332         elements->push_back(std::unique_ptr<AnnotationElement>(
333             new AnnotationElement(GetStringId(name_index), ReadEncodedValue(data))));
334       }
335       item->SetEncodedAnnotation(new EncodedAnnotation(GetTypeId(type_idx), elements));
336       break;
337     }
338     case DexFile::kDexAnnotationNull:
339       break;
340     case DexFile::kDexAnnotationBoolean:
341       item->SetBoolean(length != 0);
342       break;
343     default:
344       break;
345   }
346 }
347 
CreateStringId(const DexFile & dex_file,uint32_t i)348 void Collections::CreateStringId(const DexFile& dex_file, uint32_t i) {
349   const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i));
350   StringData* string_data = new StringData(dex_file.GetStringData(disk_string_id));
351   string_datas_.AddItem(string_data, disk_string_id.string_data_off_);
352 
353   StringId* string_id = new StringId(string_data);
354   string_ids_.AddIndexedItem(string_id, StringIdsOffset() + i * StringId::ItemSize(), i);
355 }
356 
CreateTypeId(const DexFile & dex_file,uint32_t i)357 void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) {
358   const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i));
359   TypeId* type_id = new TypeId(GetStringId(disk_type_id.descriptor_idx_.index_));
360   type_ids_.AddIndexedItem(type_id, TypeIdsOffset() + i * TypeId::ItemSize(), i);
361 }
362 
CreateProtoId(const DexFile & dex_file,uint32_t i)363 void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) {
364   const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i);
365   const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
366   TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_);
367 
368   ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_.index_),
369                                   GetTypeId(disk_proto_id.return_type_idx_.index_),
370                                   parameter_type_list);
371   proto_ids_.AddIndexedItem(proto_id, ProtoIdsOffset() + i * ProtoId::ItemSize(), i);
372 }
373 
CreateFieldId(const DexFile & dex_file,uint32_t i)374 void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) {
375   const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
376   FieldId* field_id = new FieldId(GetTypeId(disk_field_id.class_idx_.index_),
377                                   GetTypeId(disk_field_id.type_idx_.index_),
378                                   GetStringId(disk_field_id.name_idx_.index_));
379   field_ids_.AddIndexedItem(field_id, FieldIdsOffset() + i * FieldId::ItemSize(), i);
380 }
381 
CreateMethodId(const DexFile & dex_file,uint32_t i)382 void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) {
383   const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
384   MethodId* method_id = new MethodId(GetTypeId(disk_method_id.class_idx_.index_),
385                                      GetProtoId(disk_method_id.proto_idx_),
386                                      GetStringId(disk_method_id.name_idx_.index_));
387   method_ids_.AddIndexedItem(method_id, MethodIdsOffset() + i * MethodId::ItemSize(), i);
388 }
389 
CreateClassDef(const DexFile & dex_file,uint32_t i)390 void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) {
391   const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
392   const TypeId* class_type = GetTypeId(disk_class_def.class_idx_.index_);
393   uint32_t access_flags = disk_class_def.access_flags_;
394   const TypeId* superclass = GetTypeIdOrNullPtr(disk_class_def.superclass_idx_.index_);
395 
396   const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
397   TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_);
398 
399   const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_.index_);
400   // Annotations.
401   AnnotationsDirectoryItem* annotations = nullptr;
402   const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
403       dex_file.GetAnnotationsDirectory(disk_class_def);
404   if (disk_annotations_directory_item != nullptr) {
405     annotations = CreateAnnotationsDirectoryItem(
406         dex_file, disk_annotations_directory_item, disk_class_def.annotations_off_);
407   }
408   // Static field initializers.
409   const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def);
410   EncodedArrayItem* static_values =
411       CreateEncodedArrayItem(static_data, disk_class_def.static_values_off_);
412   ClassData* class_data = CreateClassData(
413       dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_);
414   ClassDef* class_def = new ClassDef(class_type, access_flags, superclass, interfaces_type_list,
415                                      source_file, annotations, static_values, class_data);
416   class_defs_.AddIndexedItem(class_def, ClassDefsOffset() + i * ClassDef::ItemSize(), i);
417 }
418 
CreateTypeList(const DexFile::TypeList * dex_type_list,uint32_t offset)419 TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) {
420   if (dex_type_list == nullptr) {
421     return nullptr;
422   }
423   auto found_type_list = TypeLists().find(offset);
424   if (found_type_list != TypeLists().end()) {
425     return found_type_list->second.get();
426   }
427   TypeIdVector* type_vector = new TypeIdVector();
428   uint32_t size = dex_type_list->Size();
429   for (uint32_t index = 0; index < size; ++index) {
430     type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_.index_));
431   }
432   TypeList* new_type_list = new TypeList(type_vector);
433   type_lists_.AddItem(new_type_list, offset);
434   return new_type_list;
435 }
436 
CreateEncodedArrayItem(const uint8_t * static_data,uint32_t offset)437 EncodedArrayItem* Collections::CreateEncodedArrayItem(const uint8_t* static_data, uint32_t offset) {
438   if (static_data == nullptr) {
439     return nullptr;
440   }
441   auto found_encoded_array_item = EncodedArrayItems().find(offset);
442   if (found_encoded_array_item != EncodedArrayItems().end()) {
443     return found_encoded_array_item->second.get();
444   }
445   uint32_t size = DecodeUnsignedLeb128(&static_data);
446   EncodedValueVector* values = new EncodedValueVector();
447   for (uint32_t i = 0; i < size; ++i) {
448     values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(&static_data)));
449   }
450   // TODO: Calculate the size of the encoded array.
451   EncodedArrayItem* encoded_array_item = new EncodedArrayItem(values);
452   encoded_array_items_.AddItem(encoded_array_item, offset);
453   return encoded_array_item;
454 }
455 
CreateAnnotationItem(const DexFile::AnnotationItem * annotation,uint32_t offset)456 AnnotationItem* Collections::CreateAnnotationItem(const DexFile::AnnotationItem* annotation,
457                                                   uint32_t offset) {
458   auto found_annotation_item = AnnotationItems().find(offset);
459   if (found_annotation_item != AnnotationItems().end()) {
460     return found_annotation_item->second.get();
461   }
462   uint8_t visibility = annotation->visibility_;
463   const uint8_t* annotation_data = annotation->annotation_;
464   EncodedValue* encoded_value =
465       ReadEncodedValue(&annotation_data, DexFile::kDexAnnotationAnnotation, 0);
466   // TODO: Calculate the size of the annotation.
467   AnnotationItem* annotation_item =
468       new AnnotationItem(visibility, encoded_value->ReleaseEncodedAnnotation());
469   annotation_items_.AddItem(annotation_item, offset);
470   return annotation_item;
471 }
472 
473 
CreateAnnotationSetItem(const DexFile & dex_file,const DexFile::AnnotationSetItem * disk_annotations_item,uint32_t offset)474 AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file,
475     const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset) {
476   if (disk_annotations_item == nullptr || (disk_annotations_item->size_ == 0 && offset == 0)) {
477     return nullptr;
478   }
479   auto found_anno_set_item = AnnotationSetItems().find(offset);
480   if (found_anno_set_item != AnnotationSetItems().end()) {
481     return found_anno_set_item->second.get();
482   }
483   std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
484   for (uint32_t i = 0; i < disk_annotations_item->size_; ++i) {
485     const DexFile::AnnotationItem* annotation =
486         dex_file.GetAnnotationItem(disk_annotations_item, i);
487     if (annotation == nullptr) {
488       continue;
489     }
490     AnnotationItem* annotation_item =
491         CreateAnnotationItem(annotation, disk_annotations_item->entries_[i]);
492     items->push_back(annotation_item);
493   }
494   AnnotationSetItem* annotation_set_item = new AnnotationSetItem(items);
495   annotation_set_items_.AddItem(annotation_set_item, offset);
496   return annotation_set_item;
497 }
498 
CreateAnnotationsDirectoryItem(const DexFile & dex_file,const DexFile::AnnotationsDirectoryItem * disk_annotations_item,uint32_t offset)499 AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
500     const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
501   auto found_anno_dir_item = AnnotationsDirectoryItems().find(offset);
502   if (found_anno_dir_item != AnnotationsDirectoryItems().end()) {
503     return found_anno_dir_item->second.get();
504   }
505   const DexFile::AnnotationSetItem* class_set_item =
506       dex_file.GetClassAnnotationSet(disk_annotations_item);
507   AnnotationSetItem* class_annotation = nullptr;
508   if (class_set_item != nullptr) {
509     uint32_t item_offset = disk_annotations_item->class_annotations_off_;
510     class_annotation = CreateAnnotationSetItem(dex_file, class_set_item, item_offset);
511   }
512   const DexFile::FieldAnnotationsItem* fields =
513       dex_file.GetFieldAnnotations(disk_annotations_item);
514   FieldAnnotationVector* field_annotations = nullptr;
515   if (fields != nullptr) {
516     field_annotations = new FieldAnnotationVector();
517     for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
518       FieldId* field_id = GetFieldId(fields[i].field_idx_);
519       const DexFile::AnnotationSetItem* field_set_item =
520           dex_file.GetFieldAnnotationSetItem(fields[i]);
521       uint32_t annotation_set_offset = fields[i].annotations_off_;
522       AnnotationSetItem* annotation_set_item =
523           CreateAnnotationSetItem(dex_file, field_set_item, annotation_set_offset);
524       field_annotations->push_back(std::unique_ptr<FieldAnnotation>(
525           new FieldAnnotation(field_id, annotation_set_item)));
526     }
527   }
528   const DexFile::MethodAnnotationsItem* methods =
529       dex_file.GetMethodAnnotations(disk_annotations_item);
530   MethodAnnotationVector* method_annotations = nullptr;
531   if (methods != nullptr) {
532     method_annotations = new MethodAnnotationVector();
533     for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
534       MethodId* method_id = GetMethodId(methods[i].method_idx_);
535       const DexFile::AnnotationSetItem* method_set_item =
536           dex_file.GetMethodAnnotationSetItem(methods[i]);
537       uint32_t annotation_set_offset = methods[i].annotations_off_;
538       AnnotationSetItem* annotation_set_item =
539           CreateAnnotationSetItem(dex_file, method_set_item, annotation_set_offset);
540       method_annotations->push_back(std::unique_ptr<MethodAnnotation>(
541           new MethodAnnotation(method_id, annotation_set_item)));
542     }
543   }
544   const DexFile::ParameterAnnotationsItem* parameters =
545       dex_file.GetParameterAnnotations(disk_annotations_item);
546   ParameterAnnotationVector* parameter_annotations = nullptr;
547   if (parameters != nullptr) {
548     parameter_annotations = new ParameterAnnotationVector();
549     for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
550       MethodId* method_id = GetMethodId(parameters[i].method_idx_);
551       const DexFile::AnnotationSetRefList* list =
552           dex_file.GetParameterAnnotationSetRefList(&parameters[i]);
553       parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
554           GenerateParameterAnnotation(dex_file, method_id, list, parameters[i].annotations_off_)));
555     }
556   }
557   // TODO: Calculate the size of the annotations directory.
558   AnnotationsDirectoryItem* annotations_directory_item = new AnnotationsDirectoryItem(
559       class_annotation, field_annotations, method_annotations, parameter_annotations);
560   annotations_directory_items_.AddItem(annotations_directory_item, offset);
561   return annotations_directory_item;
562 }
563 
GenerateParameterAnnotation(const DexFile & dex_file,MethodId * method_id,const DexFile::AnnotationSetRefList * annotation_set_ref_list,uint32_t offset)564 ParameterAnnotation* Collections::GenerateParameterAnnotation(
565     const DexFile& dex_file, MethodId* method_id,
566     const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) {
567   AnnotationSetRefList* set_ref_list = nullptr;
568   auto found_set_ref_list = AnnotationSetRefLists().find(offset);
569   if (found_set_ref_list != AnnotationSetRefLists().end()) {
570     set_ref_list = found_set_ref_list->second.get();
571   }
572   if (set_ref_list == nullptr) {
573     std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
574     for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
575       const DexFile::AnnotationSetItem* annotation_set_item =
576           dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
577       uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
578       annotations->push_back(CreateAnnotationSetItem(dex_file, annotation_set_item, set_offset));
579     }
580     set_ref_list = new AnnotationSetRefList(annotations);
581     annotation_set_ref_lists_.AddItem(set_ref_list, offset);
582   }
583   return new ParameterAnnotation(method_id, set_ref_list);
584 }
585 
CreateCodeItem(const DexFile & dex_file,const DexFile::CodeItem & disk_code_item,uint32_t offset)586 CodeItem* Collections::CreateCodeItem(const DexFile& dex_file,
587                                       const DexFile::CodeItem& disk_code_item, uint32_t offset) {
588   uint16_t registers_size = disk_code_item.registers_size_;
589   uint16_t ins_size = disk_code_item.ins_size_;
590   uint16_t outs_size = disk_code_item.outs_size_;
591   uint32_t tries_size = disk_code_item.tries_size_;
592 
593   // TODO: Calculate the size of the debug info.
594   const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(&disk_code_item);
595   DebugInfoItem* debug_info = nullptr;
596   if (debug_info_stream != nullptr) {
597     debug_info = debug_info_items_.GetExistingObject(disk_code_item.debug_info_off_);
598     if (debug_info == nullptr) {
599       uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream);
600       uint8_t* debug_info_buffer = new uint8_t[debug_info_size];
601       memcpy(debug_info_buffer, debug_info_stream, debug_info_size);
602       debug_info = new DebugInfoItem(debug_info_size, debug_info_buffer);
603       debug_info_items_.AddItem(debug_info, disk_code_item.debug_info_off_);
604     }
605   }
606 
607   uint32_t insns_size = disk_code_item.insns_size_in_code_units_;
608   uint16_t* insns = new uint16_t[insns_size];
609   memcpy(insns, disk_code_item.insns_, insns_size * sizeof(uint16_t));
610 
611   TryItemVector* tries = nullptr;
612   CatchHandlerVector* handler_list = nullptr;
613   if (tries_size > 0) {
614     tries = new TryItemVector();
615     handler_list = new CatchHandlerVector();
616     for (uint32_t i = 0; i < tries_size; ++i) {
617       const DexFile::TryItem* disk_try_item = dex_file.GetTryItems(disk_code_item, i);
618       uint32_t start_addr = disk_try_item->start_addr_;
619       uint16_t insn_count = disk_try_item->insn_count_;
620       uint16_t handler_off = disk_try_item->handler_off_;
621       const CatchHandler* handlers = nullptr;
622       for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
623         if (handler_off == existing_handlers->GetListOffset()) {
624           handlers = existing_handlers.get();
625           break;
626         }
627       }
628       if (handlers == nullptr) {
629         bool catch_all = false;
630         TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
631         for (CatchHandlerIterator it(disk_code_item, *disk_try_item); it.HasNext(); it.Next()) {
632           const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
633           const TypeId* type_id = GetTypeIdOrNullPtr(type_index.index_);
634           catch_all |= type_id == nullptr;
635           addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>(
636               new TypeAddrPair(type_id, it.GetHandlerAddress())));
637         }
638         handlers = new CatchHandler(catch_all, handler_off, addr_pairs);
639         handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers));
640       }
641       TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
642       tries->push_back(std::unique_ptr<const TryItem>(try_item));
643     }
644     // Manually walk catch handlers list and add any missing handlers unreferenced by try items.
645     const uint8_t* handlers_base = DexFile::GetCatchHandlerData(disk_code_item, 0);
646     const uint8_t* handlers_data = handlers_base;
647     uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data);
648     while (handlers_size > handler_list->size()) {
649       bool already_added = false;
650       uint16_t handler_off = handlers_data - handlers_base;
651       for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
652         if (handler_off == existing_handlers->GetListOffset()) {
653           already_added = true;
654           break;
655         }
656       }
657       int32_t size = DecodeSignedLeb128(&handlers_data);
658       bool has_catch_all = size <= 0;
659       if (has_catch_all) {
660         size = -size;
661       }
662       if (already_added) {
663         for (int32_t i = 0; i < size; i++) {
664           DecodeUnsignedLeb128(&handlers_data);
665           DecodeUnsignedLeb128(&handlers_data);
666         }
667         if (has_catch_all) {
668           DecodeUnsignedLeb128(&handlers_data);
669         }
670         continue;
671       }
672       TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
673       for (int32_t i = 0; i < size; i++) {
674         const TypeId* type_id = GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data));
675         uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
676         addr_pairs->push_back(
677             std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr)));
678       }
679       if (has_catch_all) {
680         uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
681         addr_pairs->push_back(
682             std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr)));
683       }
684       const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs);
685       handler_list->push_back(std::unique_ptr<const CatchHandler>(handler));
686     }
687   }
688 
689   uint32_t size = GetCodeItemSize(disk_code_item);
690   CodeItem* code_item = new CodeItem(
691       registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries, handler_list);
692   code_item->SetSize(size);
693   code_items_.AddItem(code_item, offset);
694   // Add "fixup" references to types, strings, methods, and fields.
695   // This is temporary, as we will probably want more detailed parsing of the
696   // instructions here.
697   std::unique_ptr<std::vector<TypeId*>> type_ids(new std::vector<TypeId*>());
698   std::unique_ptr<std::vector<StringId*>> string_ids(new std::vector<StringId*>());
699   std::unique_ptr<std::vector<MethodId*>> method_ids(new std::vector<MethodId*>());
700   std::unique_ptr<std::vector<FieldId*>> field_ids(new std::vector<FieldId*>());
701   if (GetIdsFromByteCode(*this,
702                          code_item,
703                          type_ids.get(),
704                          string_ids.get(),
705                          method_ids.get(),
706                          field_ids.get())) {
707     CodeFixups* fixups = new CodeFixups(type_ids.release(),
708                                         string_ids.release(),
709                                         method_ids.release(),
710                                         field_ids.release());
711     code_item->SetCodeFixups(fixups);
712   }
713 
714   return code_item;
715 }
716 
GenerateMethodItem(const DexFile & dex_file,ClassDataItemIterator & cdii)717 MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
718   MethodId* method_id = GetMethodId(cdii.GetMemberIndex());
719   uint32_t access_flags = cdii.GetRawMemberAccessFlags();
720   const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
721   CodeItem* code_item = code_items_.GetExistingObject(cdii.GetMethodCodeItemOffset());
722   DebugInfoItem* debug_info = nullptr;
723   if (disk_code_item != nullptr) {
724     if (code_item == nullptr) {
725       code_item = CreateCodeItem(dex_file, *disk_code_item, cdii.GetMethodCodeItemOffset());
726     }
727     debug_info = code_item->DebugInfo();
728   }
729   if (debug_info != nullptr) {
730     bool is_static = (access_flags & kAccStatic) != 0;
731     dex_file.DecodeDebugLocalInfo(
732         disk_code_item, is_static, cdii.GetMemberIndex(), GetLocalsCb, debug_info);
733     dex_file.DecodeDebugPositionInfo(disk_code_item, GetPositionsCb, debug_info);
734   }
735   return new MethodItem(access_flags, method_id, code_item);
736 }
737 
CreateClassData(const DexFile & dex_file,const uint8_t * encoded_data,uint32_t offset)738 ClassData* Collections::CreateClassData(
739     const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
740   // Read the fields and methods defined by the class, resolving the circular reference from those
741   // to classes by setting class at the same time.
742   ClassData* class_data = class_datas_.GetExistingObject(offset);
743   if (class_data == nullptr && encoded_data != nullptr) {
744     ClassDataItemIterator cdii(dex_file, encoded_data);
745     // Static fields.
746     FieldItemVector* static_fields = new FieldItemVector();
747     for (; cdii.HasNextStaticField(); cdii.Next()) {
748       FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
749       uint32_t access_flags = cdii.GetRawMemberAccessFlags();
750       static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
751     }
752     // Instance fields.
753     FieldItemVector* instance_fields = new FieldItemVector();
754     for (; cdii.HasNextInstanceField(); cdii.Next()) {
755       FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
756       uint32_t access_flags = cdii.GetRawMemberAccessFlags();
757       instance_fields->push_back(
758           std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
759     }
760     // Direct methods.
761     MethodItemVector* direct_methods = new MethodItemVector();
762     for (; cdii.HasNextDirectMethod(); cdii.Next()) {
763       direct_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
764     }
765     // Virtual methods.
766     MethodItemVector* virtual_methods = new MethodItemVector();
767     for (; cdii.HasNextVirtualMethod(); cdii.Next()) {
768       virtual_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
769     }
770     class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
771     class_data->SetSize(cdii.EndDataPointer() - encoded_data);
772     class_datas_.AddItem(class_data, offset);
773   }
774   return class_data;
775 }
776 
CreateCallSitesAndMethodHandles(const DexFile & dex_file)777 void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
778   // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems.
779   const DexFile::MapList* map =
780       reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + MapListOffset());
781   for (uint32_t i = 0; i < map->size_; ++i) {
782     const DexFile::MapItem* item = map->list_ + i;
783     switch (item->type_) {
784       case DexFile::kDexTypeCallSiteIdItem:
785         SetCallSiteIdsOffset(item->offset_);
786         break;
787       case DexFile::kDexTypeMethodHandleItem:
788         SetMethodHandleItemsOffset(item->offset_);
789         break;
790       default:
791         break;
792     }
793   }
794   // Populate MethodHandleItems first (CallSiteIds may depend on them).
795   for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) {
796     CreateMethodHandleItem(dex_file, i);
797   }
798   // Populate CallSiteIds.
799   for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) {
800     CreateCallSiteId(dex_file, i);
801   }
802 }
803 
CreateCallSiteId(const DexFile & dex_file,uint32_t i)804 void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
805   const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i);
806   const uint8_t* disk_call_item_ptr = dex_file.Begin() + disk_call_site_id.data_off_;
807   EncodedArrayItem* call_site_item =
808       CreateEncodedArrayItem(disk_call_item_ptr, disk_call_site_id.data_off_);
809 
810   CallSiteId* call_site_id = new CallSiteId(call_site_item);
811   call_site_ids_.AddIndexedItem(call_site_id, CallSiteIdsOffset() + i * CallSiteId::ItemSize(), i);
812 }
813 
CreateMethodHandleItem(const DexFile & dex_file,uint32_t i)814 void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
815   const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i);
816   uint16_t index = disk_method_handle.field_or_method_idx_;
817   DexFile::MethodHandleType type =
818       static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_);
819   bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic ||
820                    type == DexFile::MethodHandleType::kInvokeInstance ||
821                    type == DexFile::MethodHandleType::kInvokeConstructor;
822   static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeConstructor,
823                 "Unexpected method handle types.");
824   IndexedItem* field_or_method_id;
825   if (is_invoke) {
826     field_or_method_id = GetMethodId(index);
827   } else {
828     field_or_method_id = GetFieldId(index);
829   }
830   MethodHandleItem* method_handle = new MethodHandleItem(type, field_or_method_id);
831   method_handle_items_.AddIndexedItem(
832       method_handle, MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(), i);
833 }
834 
HeaderOffset(const dex_ir::Collections & collections ATTRIBUTE_UNUSED)835 static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
836   return 0;
837 }
838 
HeaderSize(const dex_ir::Collections & collections ATTRIBUTE_UNUSED)839 static uint32_t HeaderSize(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
840   // Size is in elements, so there is only one header.
841   return 1;
842 }
843 
844 // The description of each dex file section type.
845 struct FileSectionDescriptor {
846  public:
847   std::string name;
848   uint16_t type;
849   // A function that when applied to a collection object, gives the size of the section.
850   std::function<uint32_t(const dex_ir::Collections&)> size_fn;
851   // A function that when applied to a collection object, gives the offset of the section.
852   std::function<uint32_t(const dex_ir::Collections&)> offset_fn;
853 };
854 
855 static const FileSectionDescriptor kFileSectionDescriptors[] = {
856   {
857     "Header",
858     DexFile::kDexTypeHeaderItem,
859     &HeaderSize,
860     &HeaderOffset,
861   }, {
862     "StringId",
863     DexFile::kDexTypeStringIdItem,
864     &dex_ir::Collections::StringIdsSize,
865     &dex_ir::Collections::StringIdsOffset
866   }, {
867     "TypeId",
868     DexFile::kDexTypeTypeIdItem,
869     &dex_ir::Collections::TypeIdsSize,
870     &dex_ir::Collections::TypeIdsOffset
871   }, {
872     "ProtoId",
873     DexFile::kDexTypeProtoIdItem,
874     &dex_ir::Collections::ProtoIdsSize,
875     &dex_ir::Collections::ProtoIdsOffset
876   }, {
877     "FieldId",
878     DexFile::kDexTypeFieldIdItem,
879     &dex_ir::Collections::FieldIdsSize,
880     &dex_ir::Collections::FieldIdsOffset
881   }, {
882     "MethodId",
883     DexFile::kDexTypeMethodIdItem,
884     &dex_ir::Collections::MethodIdsSize,
885     &dex_ir::Collections::MethodIdsOffset
886   }, {
887     "ClassDef",
888     DexFile::kDexTypeClassDefItem,
889     &dex_ir::Collections::ClassDefsSize,
890     &dex_ir::Collections::ClassDefsOffset
891   }, {
892     "CallSiteId",
893     DexFile::kDexTypeCallSiteIdItem,
894     &dex_ir::Collections::CallSiteIdsSize,
895     &dex_ir::Collections::CallSiteIdsOffset
896   }, {
897     "MethodHandle",
898     DexFile::kDexTypeMethodHandleItem,
899     &dex_ir::Collections::MethodHandleItemsSize,
900     &dex_ir::Collections::MethodHandleItemsOffset
901   }, {
902     "StringData",
903     DexFile::kDexTypeStringDataItem,
904     &dex_ir::Collections::StringDatasSize,
905     &dex_ir::Collections::StringDatasOffset
906   }, {
907     "TypeList",
908     DexFile::kDexTypeTypeList,
909     &dex_ir::Collections::TypeListsSize,
910     &dex_ir::Collections::TypeListsOffset
911   }, {
912     "EncArr",
913     DexFile::kDexTypeEncodedArrayItem,
914     &dex_ir::Collections::EncodedArrayItemsSize,
915     &dex_ir::Collections::EncodedArrayItemsOffset
916   }, {
917     "Annotation",
918     DexFile::kDexTypeAnnotationItem,
919     &dex_ir::Collections::AnnotationItemsSize,
920     &dex_ir::Collections::AnnotationItemsOffset
921   }, {
922     "AnnoSet",
923     DexFile::kDexTypeAnnotationSetItem,
924     &dex_ir::Collections::AnnotationSetItemsSize,
925     &dex_ir::Collections::AnnotationSetItemsOffset
926   }, {
927     "AnnoSetRL",
928     DexFile::kDexTypeAnnotationSetRefList,
929     &dex_ir::Collections::AnnotationSetRefListsSize,
930     &dex_ir::Collections::AnnotationSetRefListsOffset
931   }, {
932     "AnnoDir",
933     DexFile::kDexTypeAnnotationsDirectoryItem,
934     &dex_ir::Collections::AnnotationsDirectoryItemsSize,
935     &dex_ir::Collections::AnnotationsDirectoryItemsOffset
936   }, {
937     "DebugInfo",
938     DexFile::kDexTypeDebugInfoItem,
939     &dex_ir::Collections::DebugInfoItemsSize,
940     &dex_ir::Collections::DebugInfoItemsOffset
941   }, {
942     "CodeItem",
943     DexFile::kDexTypeCodeItem,
944     &dex_ir::Collections::CodeItemsSize,
945     &dex_ir::Collections::CodeItemsOffset
946   }, {
947     "ClassData",
948     DexFile::kDexTypeClassDataItem,
949     &dex_ir::Collections::ClassDatasSize,
950     &dex_ir::Collections::ClassDatasOffset
951   }
952 };
953 
GetSortedDexFileSections(dex_ir::Header * header,dex_ir::SortDirection direction)954 std::vector<dex_ir::DexFileSection> GetSortedDexFileSections(dex_ir::Header* header,
955                                                              dex_ir::SortDirection direction) {
956   const dex_ir::Collections& collections = header->GetCollections();
957   std::vector<dex_ir::DexFileSection> sorted_sections;
958   // Build the table that will map from offset to color
959   for (const FileSectionDescriptor& s : kFileSectionDescriptors) {
960     sorted_sections.push_back(dex_ir::DexFileSection(s.name,
961                                                      s.type,
962                                                      s.size_fn(collections),
963                                                      s.offset_fn(collections)));
964   }
965   // Sort by offset.
966   std::sort(sorted_sections.begin(),
967             sorted_sections.end(),
968             [=](dex_ir::DexFileSection& a, dex_ir::DexFileSection& b) {
969               if (direction == SortDirection::kSortDescending) {
970                 return a.offset > b.offset;
971               } else {
972                 return a.offset < b.offset;
973               }
974             });
975   return sorted_sections;
976 }
977 
978 }  // namespace dex_ir
979 }  // namespace art
980