blob: 1525d537b7281f963117636cfcdc7fbfda26405a [file] [log] [blame]
Jeff Hao3ab96b42016-09-09 18:35:01 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * 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"
Mathieu Chartier808c7a52017-12-15 11:19:33 -080024
David Sehr9e734c72018-01-04 17:56:19 -080025#include "dex/code_item_accessors-inl.h"
26#include "dex/dex_file_exception_helpers.h"
27#include "dex/dex_instruction-inl.h"
Jeff Hao3ab96b42016-09-09 18:35:01 -070028#include "dex_ir_builder.h"
29
30namespace art {
31namespace dex_ir {
32
33static 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
Jeff Haoa8621002016-10-04 18:13:44 +000045static 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
David Sehrd1e44e22016-10-06 17:09:32 -070093static bool GetIdFromInstruction(Collections& collections,
94 const Instruction* dec_insn,
95 std::vector<TypeId*>* type_ids,
96 std::vector<StringId*>* string_ids,
97 std::vector<MethodId*>* method_ids,
98 std::vector<FieldId*>* field_ids) {
99 // Determine index and width of the string.
100 uint32_t index = 0;
101 switch (Instruction::FormatOf(dec_insn->Opcode())) {
102 // SOME NOT SUPPORTED:
103 // case Instruction::k20bc:
104 case Instruction::k21c:
105 case Instruction::k35c:
106 // case Instruction::k35ms:
107 case Instruction::k3rc:
108 // case Instruction::k3rms:
109 // case Instruction::k35mi:
110 // case Instruction::k3rmi:
Orion Hodsonb34bb192016-10-18 17:02:58 +0100111 case Instruction::k45cc:
112 case Instruction::k4rcc:
David Sehrd1e44e22016-10-06 17:09:32 -0700113 index = dec_insn->VRegB();
114 break;
115 case Instruction::k31c:
116 index = dec_insn->VRegB();
117 break;
118 case Instruction::k22c:
119 // case Instruction::k22cs:
120 index = dec_insn->VRegC();
121 break;
122 default:
123 break;
124 } // switch
125
126 // Determine index type, and add reference to the appropriate collection.
127 switch (Instruction::IndexTypeOf(dec_insn->Opcode())) {
128 case Instruction::kIndexTypeRef:
129 if (index < collections.TypeIdsSize()) {
130 type_ids->push_back(collections.GetTypeId(index));
131 return true;
132 }
133 break;
134 case Instruction::kIndexStringRef:
135 if (index < collections.StringIdsSize()) {
136 string_ids->push_back(collections.GetStringId(index));
137 return true;
138 }
139 break;
140 case Instruction::kIndexMethodRef:
Orion Hodsonb34bb192016-10-18 17:02:58 +0100141 case Instruction::kIndexMethodAndProtoRef:
David Sehrd1e44e22016-10-06 17:09:32 -0700142 if (index < collections.MethodIdsSize()) {
143 method_ids->push_back(collections.GetMethodId(index));
144 return true;
145 }
146 break;
147 case Instruction::kIndexFieldRef:
148 if (index < collections.FieldIdsSize()) {
149 field_ids->push_back(collections.GetFieldId(index));
150 return true;
151 }
152 break;
153 case Instruction::kIndexUnknown:
154 case Instruction::kIndexNone:
155 case Instruction::kIndexVtableOffset:
156 case Instruction::kIndexFieldOffset:
157 default:
158 break;
159 } // switch
160 return false;
161}
162
163/*
164 * Get all the types, strings, methods, and fields referred to from bytecode.
165 */
166static bool GetIdsFromByteCode(Collections& collections,
167 const CodeItem* code,
168 std::vector<TypeId*>* type_ids,
169 std::vector<StringId*>* string_ids,
170 std::vector<MethodId*>* method_ids,
171 std::vector<FieldId*>* field_ids) {
172 bool has_id = false;
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700173 IterationRange<DexInstructionIterator> instructions = code->Instructions();
174 SafeDexInstructionIterator it(instructions.begin(), instructions.end());
175 for (; !it.IsErrorState() && it < instructions.end(); ++it) {
176 // In case the instruction goes past the end of the code item, make sure to not process it.
177 SafeDexInstructionIterator next = it;
178 ++next;
Mathieu Chartier2b2bef22017-10-26 17:10:19 -0700179 if (next.IsErrorState()) {
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700180 break;
181 }
David Sehrd1e44e22016-10-06 17:09:32 -0700182 has_id |= GetIdFromInstruction(collections,
Mathieu Chartier2b2bef22017-10-26 17:10:19 -0700183 &it.Inst(),
David Sehrd1e44e22016-10-06 17:09:32 -0700184 type_ids,
185 string_ids,
186 method_ids,
187 field_ids);
David Sehrd1e44e22016-10-06 17:09:32 -0700188 } // for
189 return has_id;
190}
191
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800192EncodedValue* Collections::ReadEncodedValue(const DexFile& dex_file, const uint8_t** data) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700193 const uint8_t encoded_value = *(*data)++;
194 const uint8_t type = encoded_value & 0x1f;
195 EncodedValue* item = new EncodedValue(type);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800196 ReadEncodedValue(dex_file, data, type, encoded_value >> 5, item);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700197 return item;
198}
199
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800200EncodedValue* Collections::ReadEncodedValue(const DexFile& dex_file,
201 const uint8_t** data,
202 uint8_t type,
203 uint8_t length) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700204 EncodedValue* item = new EncodedValue(type);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800205 ReadEncodedValue(dex_file, data, type, length, item);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700206 return item;
207}
208
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800209void Collections::ReadEncodedValue(const DexFile& dex_file,
210 const uint8_t** data,
211 uint8_t type,
212 uint8_t length,
213 EncodedValue* item) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700214 switch (type) {
215 case DexFile::kDexAnnotationByte:
216 item->SetByte(static_cast<int8_t>(ReadVarWidth(data, length, false)));
217 break;
218 case DexFile::kDexAnnotationShort:
219 item->SetShort(static_cast<int16_t>(ReadVarWidth(data, length, true)));
220 break;
221 case DexFile::kDexAnnotationChar:
222 item->SetChar(static_cast<uint16_t>(ReadVarWidth(data, length, false)));
223 break;
224 case DexFile::kDexAnnotationInt:
225 item->SetInt(static_cast<int32_t>(ReadVarWidth(data, length, true)));
226 break;
227 case DexFile::kDexAnnotationLong:
228 item->SetLong(static_cast<int64_t>(ReadVarWidth(data, length, true)));
229 break;
230 case DexFile::kDexAnnotationFloat: {
231 // Fill on right.
232 union {
233 float f;
234 uint32_t data;
235 } conv;
236 conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
237 item->SetFloat(conv.f);
238 break;
239 }
240 case DexFile::kDexAnnotationDouble: {
241 // Fill on right.
242 union {
243 double d;
244 uint64_t data;
245 } conv;
246 conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
247 item->SetDouble(conv.d);
248 break;
249 }
Jeff Hao5daee902017-04-27 18:00:38 -0700250 case DexFile::kDexAnnotationMethodType: {
251 const uint32_t proto_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
252 item->SetProtoId(GetProtoId(proto_index));
253 break;
254 }
255 case DexFile::kDexAnnotationMethodHandle: {
256 const uint32_t method_handle_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
257 item->SetMethodHandle(GetMethodHandle(method_handle_index));
258 break;
259 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700260 case DexFile::kDexAnnotationString: {
261 const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
262 item->SetStringId(GetStringId(string_index));
263 break;
264 }
265 case DexFile::kDexAnnotationType: {
266 const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
267 item->SetTypeId(GetTypeId(string_index));
268 break;
269 }
270 case DexFile::kDexAnnotationField:
271 case DexFile::kDexAnnotationEnum: {
272 const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
273 item->SetFieldId(GetFieldId(field_index));
274 break;
275 }
276 case DexFile::kDexAnnotationMethod: {
277 const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
278 item->SetMethodId(GetMethodId(method_index));
279 break;
280 }
281 case DexFile::kDexAnnotationArray: {
282 EncodedValueVector* values = new EncodedValueVector();
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -0800283 const uint32_t offset = *data - dex_file.DataBegin();
Jeff Hao3ab96b42016-09-09 18:35:01 -0700284 const uint32_t size = DecodeUnsignedLeb128(data);
285 // Decode all elements.
286 for (uint32_t i = 0; i < size; i++) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800287 values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, data)));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700288 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800289 EncodedArrayItem* array_item = new EncodedArrayItem(values);
290 if (eagerly_assign_offsets_) {
291 array_item->SetOffset(offset);
292 }
293 item->SetEncodedArray(array_item);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700294 break;
295 }
296 case DexFile::kDexAnnotationAnnotation: {
297 AnnotationElementVector* elements = new AnnotationElementVector();
298 const uint32_t type_idx = DecodeUnsignedLeb128(data);
299 const uint32_t size = DecodeUnsignedLeb128(data);
300 // Decode all name=value pairs.
301 for (uint32_t i = 0; i < size; i++) {
302 const uint32_t name_index = DecodeUnsignedLeb128(data);
303 elements->push_back(std::unique_ptr<AnnotationElement>(
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800304 new AnnotationElement(GetStringId(name_index), ReadEncodedValue(dex_file, data))));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700305 }
306 item->SetEncodedAnnotation(new EncodedAnnotation(GetTypeId(type_idx), elements));
307 break;
308 }
309 case DexFile::kDexAnnotationNull:
310 break;
311 case DexFile::kDexAnnotationBoolean:
312 item->SetBoolean(length != 0);
313 break;
314 default:
315 break;
316 }
317}
318
319void Collections::CreateStringId(const DexFile& dex_file, uint32_t i) {
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800320 const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700321 StringData* string_data = new StringData(dex_file.GetStringData(disk_string_id));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800322 AddItem(string_datas_map_, string_datas_, string_data, disk_string_id.string_data_off_);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700323
324 StringId* string_id = new StringId(string_data);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800325 AddIndexedItem(string_ids_, string_id, StringIdsOffset() + i * StringId::ItemSize(), i);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700326}
327
328void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) {
Andreas Gampea5b09a62016-11-17 15:21:22 -0800329 const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i));
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800330 TypeId* type_id = new TypeId(GetStringId(disk_type_id.descriptor_idx_.index_));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800331 AddIndexedItem(type_ids_, type_id, TypeIdsOffset() + i * TypeId::ItemSize(), i);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700332}
333
334void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) {
335 const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i);
336 const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
Jeff Haoa8621002016-10-04 18:13:44 +0000337 TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700338
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800339 ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_.index_),
Andreas Gampea5b09a62016-11-17 15:21:22 -0800340 GetTypeId(disk_proto_id.return_type_idx_.index_),
Jeff Hao3ab96b42016-09-09 18:35:01 -0700341 parameter_type_list);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800342 AddIndexedItem(proto_ids_, proto_id, ProtoIdsOffset() + i * ProtoId::ItemSize(), i);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700343}
344
345void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) {
346 const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
Andreas Gampea5b09a62016-11-17 15:21:22 -0800347 FieldId* field_id = new FieldId(GetTypeId(disk_field_id.class_idx_.index_),
348 GetTypeId(disk_field_id.type_idx_.index_),
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800349 GetStringId(disk_field_id.name_idx_.index_));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800350 AddIndexedItem(field_ids_, field_id, FieldIdsOffset() + i * FieldId::ItemSize(), i);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700351}
352
353void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) {
354 const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
Andreas Gampea5b09a62016-11-17 15:21:22 -0800355 MethodId* method_id = new MethodId(GetTypeId(disk_method_id.class_idx_.index_),
Jeff Hao3ab96b42016-09-09 18:35:01 -0700356 GetProtoId(disk_method_id.proto_idx_),
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800357 GetStringId(disk_method_id.name_idx_.index_));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800358 AddIndexedItem(method_ids_, method_id, MethodIdsOffset() + i * MethodId::ItemSize(), i);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700359}
360
361void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) {
362 const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
Andreas Gampea5b09a62016-11-17 15:21:22 -0800363 const TypeId* class_type = GetTypeId(disk_class_def.class_idx_.index_);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700364 uint32_t access_flags = disk_class_def.access_flags_;
Andreas Gampea5b09a62016-11-17 15:21:22 -0800365 const TypeId* superclass = GetTypeIdOrNullPtr(disk_class_def.superclass_idx_.index_);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700366
367 const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
Jeff Haoa8621002016-10-04 18:13:44 +0000368 TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700369
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800370 const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_.index_);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700371 // Annotations.
372 AnnotationsDirectoryItem* annotations = nullptr;
373 const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
374 dex_file.GetAnnotationsDirectory(disk_class_def);
375 if (disk_annotations_directory_item != nullptr) {
376 annotations = CreateAnnotationsDirectoryItem(
377 dex_file, disk_annotations_directory_item, disk_class_def.annotations_off_);
378 }
379 // Static field initializers.
380 const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def);
381 EncodedArrayItem* static_values =
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800382 CreateEncodedArrayItem(dex_file, static_data, disk_class_def.static_values_off_);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700383 ClassData* class_data = CreateClassData(
384 dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_);
385 ClassDef* class_def = new ClassDef(class_type, access_flags, superclass, interfaces_type_list,
386 source_file, annotations, static_values, class_data);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800387 AddIndexedItem(class_defs_, class_def, ClassDefsOffset() + i * ClassDef::ItemSize(), i);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700388}
389
Jeff Haoa8621002016-10-04 18:13:44 +0000390TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) {
391 if (dex_type_list == nullptr) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700392 return nullptr;
393 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800394 TypeList* type_list = type_lists_map_.GetExistingObject(offset);
395 if (type_list == nullptr) {
396 TypeIdVector* type_vector = new TypeIdVector();
397 uint32_t size = dex_type_list->Size();
398 for (uint32_t index = 0; index < size; ++index) {
399 type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_.index_));
400 }
401 type_list = new TypeList(type_vector);
402 AddItem(type_lists_map_, type_lists_, type_list, offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700403 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800404 return type_list;
Jeff Hao3ab96b42016-09-09 18:35:01 -0700405}
406
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800407EncodedArrayItem* Collections::CreateEncodedArrayItem(const DexFile& dex_file,
408 const uint8_t* static_data,
409 uint32_t offset) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700410 if (static_data == nullptr) {
411 return nullptr;
412 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800413 EncodedArrayItem* encoded_array_item = encoded_array_items_map_.GetExistingObject(offset);
414 if (encoded_array_item == nullptr) {
415 uint32_t size = DecodeUnsignedLeb128(&static_data);
416 EncodedValueVector* values = new EncodedValueVector();
417 for (uint32_t i = 0; i < size; ++i) {
418 values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, &static_data)));
419 }
420 // TODO: Calculate the size of the encoded array.
421 encoded_array_item = new EncodedArrayItem(values);
422 AddItem(encoded_array_items_map_, encoded_array_items_, encoded_array_item, offset);
Jeff Haoa8621002016-10-04 18:13:44 +0000423 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700424 return encoded_array_item;
425}
426
Mathieu Chartier24066ec2017-10-21 16:01:08 -0700427void Collections::AddAnnotationsFromMapListSection(const DexFile& dex_file,
428 uint32_t start_offset,
429 uint32_t count) {
430 uint32_t current_offset = start_offset;
431 for (size_t i = 0; i < count; ++i) {
432 // Annotation that we didn't process already, add it to the set.
433 const DexFile::AnnotationItem* annotation = dex_file.GetAnnotationItemAtOffset(current_offset);
434 AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation);
435 DCHECK(annotation_item != nullptr);
436 current_offset += annotation_item->GetSize();
437 }
438}
439
440AnnotationItem* Collections::CreateAnnotationItem(const DexFile& dex_file,
441 const DexFile::AnnotationItem* annotation) {
442 const uint8_t* const start_data = reinterpret_cast<const uint8_t*>(annotation);
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -0800443 const uint32_t offset = start_data - dex_file.DataBegin();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800444 AnnotationItem* annotation_item = annotation_items_map_.GetExistingObject(offset);
445 if (annotation_item == nullptr) {
446 uint8_t visibility = annotation->visibility_;
447 const uint8_t* annotation_data = annotation->annotation_;
448 std::unique_ptr<EncodedValue> encoded_value(
449 ReadEncodedValue(dex_file, &annotation_data, DexFile::kDexAnnotationAnnotation, 0));
450 annotation_item = new AnnotationItem(visibility, encoded_value->ReleaseEncodedAnnotation());
451 annotation_item->SetSize(annotation_data - start_data);
452 AddItem(annotation_items_map_, annotation_items_, annotation_item, offset);
Jeff Haoa8621002016-10-04 18:13:44 +0000453 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700454 return annotation_item;
455}
456
457
458AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file,
Jeff Haobe9b44b2017-02-16 13:34:38 -0800459 const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset) {
460 if (disk_annotations_item == nullptr || (disk_annotations_item->size_ == 0 && offset == 0)) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700461 return nullptr;
462 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800463 AnnotationSetItem* annotation_set_item = annotation_set_items_map_.GetExistingObject(offset);
464 if (annotation_set_item == nullptr) {
465 std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
466 for (uint32_t i = 0; i < disk_annotations_item->size_; ++i) {
467 const DexFile::AnnotationItem* annotation =
468 dex_file.GetAnnotationItem(disk_annotations_item, i);
469 if (annotation == nullptr) {
470 continue;
471 }
472 AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation);
473 items->push_back(annotation_item);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700474 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800475 annotation_set_item = new AnnotationSetItem(items);
476 AddItem(annotation_set_items_map_, annotation_set_items_, annotation_set_item, offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700477 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700478 return annotation_set_item;
479}
480
481AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
482 const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800483 AnnotationsDirectoryItem* annotations_directory_item =
484 annotations_directory_items_map_.GetExistingObject(offset);
485 if (annotations_directory_item != nullptr) {
486 return annotations_directory_item;
Jeff Haoa8621002016-10-04 18:13:44 +0000487 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700488 const DexFile::AnnotationSetItem* class_set_item =
489 dex_file.GetClassAnnotationSet(disk_annotations_item);
490 AnnotationSetItem* class_annotation = nullptr;
491 if (class_set_item != nullptr) {
David Sehr7639cdc2017-04-15 10:06:21 -0700492 uint32_t item_offset = disk_annotations_item->class_annotations_off_;
493 class_annotation = CreateAnnotationSetItem(dex_file, class_set_item, item_offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700494 }
495 const DexFile::FieldAnnotationsItem* fields =
496 dex_file.GetFieldAnnotations(disk_annotations_item);
497 FieldAnnotationVector* field_annotations = nullptr;
498 if (fields != nullptr) {
499 field_annotations = new FieldAnnotationVector();
500 for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
501 FieldId* field_id = GetFieldId(fields[i].field_idx_);
502 const DexFile::AnnotationSetItem* field_set_item =
503 dex_file.GetFieldAnnotationSetItem(fields[i]);
504 uint32_t annotation_set_offset = fields[i].annotations_off_;
505 AnnotationSetItem* annotation_set_item =
Jeff Haobe9b44b2017-02-16 13:34:38 -0800506 CreateAnnotationSetItem(dex_file, field_set_item, annotation_set_offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700507 field_annotations->push_back(std::unique_ptr<FieldAnnotation>(
508 new FieldAnnotation(field_id, annotation_set_item)));
509 }
510 }
511 const DexFile::MethodAnnotationsItem* methods =
512 dex_file.GetMethodAnnotations(disk_annotations_item);
513 MethodAnnotationVector* method_annotations = nullptr;
514 if (methods != nullptr) {
515 method_annotations = new MethodAnnotationVector();
516 for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
517 MethodId* method_id = GetMethodId(methods[i].method_idx_);
518 const DexFile::AnnotationSetItem* method_set_item =
519 dex_file.GetMethodAnnotationSetItem(methods[i]);
520 uint32_t annotation_set_offset = methods[i].annotations_off_;
521 AnnotationSetItem* annotation_set_item =
Jeff Haobe9b44b2017-02-16 13:34:38 -0800522 CreateAnnotationSetItem(dex_file, method_set_item, annotation_set_offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700523 method_annotations->push_back(std::unique_ptr<MethodAnnotation>(
524 new MethodAnnotation(method_id, annotation_set_item)));
525 }
526 }
527 const DexFile::ParameterAnnotationsItem* parameters =
528 dex_file.GetParameterAnnotations(disk_annotations_item);
529 ParameterAnnotationVector* parameter_annotations = nullptr;
530 if (parameters != nullptr) {
531 parameter_annotations = new ParameterAnnotationVector();
532 for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
533 MethodId* method_id = GetMethodId(parameters[i].method_idx_);
534 const DexFile::AnnotationSetRefList* list =
535 dex_file.GetParameterAnnotationSetRefList(&parameters[i]);
536 parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
537 GenerateParameterAnnotation(dex_file, method_id, list, parameters[i].annotations_off_)));
538 }
539 }
540 // TODO: Calculate the size of the annotations directory.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800541annotations_directory_item = new AnnotationsDirectoryItem(
Jeff Hao3ab96b42016-09-09 18:35:01 -0700542 class_annotation, field_annotations, method_annotations, parameter_annotations);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800543 AddItem(annotations_directory_items_map_,
544 annotations_directory_items_,
545 annotations_directory_item,
546 offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700547 return annotations_directory_item;
548}
549
550ParameterAnnotation* Collections::GenerateParameterAnnotation(
551 const DexFile& dex_file, MethodId* method_id,
552 const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800553 AnnotationSetRefList* set_ref_list = annotation_set_ref_lists_map_.GetExistingObject(offset);
Jeff Haoa8621002016-10-04 18:13:44 +0000554 if (set_ref_list == nullptr) {
555 std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
556 for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
557 const DexFile::AnnotationSetItem* annotation_set_item =
558 dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
559 uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
Jeff Haobe9b44b2017-02-16 13:34:38 -0800560 annotations->push_back(CreateAnnotationSetItem(dex_file, annotation_set_item, set_offset));
Jeff Haoa8621002016-10-04 18:13:44 +0000561 }
562 set_ref_list = new AnnotationSetRefList(annotations);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800563 AddItem(annotation_set_ref_lists_map_, annotation_set_ref_lists_, set_ref_list, offset);
Jeff Haoa8621002016-10-04 18:13:44 +0000564 }
565 return new ParameterAnnotation(method_id, set_ref_list);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700566}
567
Mathieu Chartier66c9df12018-01-16 14:45:20 -0800568CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file,
569 const DexFile::CodeItem* disk_code_item,
570 uint32_t offset,
571 uint32_t dex_method_index) {
572 if (disk_code_item == nullptr) {
573 return nullptr;
574 }
575 CodeItemDebugInfoAccessor accessor(dex_file, disk_code_item, dex_method_index);
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800576 const uint32_t debug_info_offset = accessor.DebugInfoOffset();
Mathieu Chartier66c9df12018-01-16 14:45:20 -0800577
578 // Create the offsets pair and dedupe based on it.
579 std::pair<uint32_t, uint32_t> offsets_pair(offset, debug_info_offset);
580 auto existing = code_items_map_.find(offsets_pair);
581 if (existing != code_items_map_.end()) {
582 return existing->second;
583 }
584
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +0000585 const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(debug_info_offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700586 DebugInfoItem* debug_info = nullptr;
587 if (debug_info_stream != nullptr) {
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +0000588 debug_info = debug_info_items_map_.GetExistingObject(debug_info_offset);
Mathieu Chartiera2973d72017-02-14 17:12:20 -0800589 if (debug_info == nullptr) {
590 uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream);
591 uint8_t* debug_info_buffer = new uint8_t[debug_info_size];
592 memcpy(debug_info_buffer, debug_info_stream, debug_info_size);
593 debug_info = new DebugInfoItem(debug_info_size, debug_info_buffer);
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +0000594 AddItem(debug_info_items_map_, debug_info_items_, debug_info, debug_info_offset);
Mathieu Chartiera2973d72017-02-14 17:12:20 -0800595 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700596 }
597
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800598 uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
Jeff Hao3ab96b42016-09-09 18:35:01 -0700599 uint16_t* insns = new uint16_t[insns_size];
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800600 memcpy(insns, accessor.Insns(), insns_size * sizeof(uint16_t));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700601
602 TryItemVector* tries = nullptr;
Jeff Haoa8621002016-10-04 18:13:44 +0000603 CatchHandlerVector* handler_list = nullptr;
Mathieu Chartier66c9df12018-01-16 14:45:20 -0800604 if (accessor.TriesSize() > 0) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700605 tries = new TryItemVector();
Jeff Haoa8621002016-10-04 18:13:44 +0000606 handler_list = new CatchHandlerVector();
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800607 for (const DexFile::TryItem& disk_try_item : accessor.TryItems()) {
608 uint32_t start_addr = disk_try_item.start_addr_;
609 uint16_t insn_count = disk_try_item.insn_count_;
610 uint16_t handler_off = disk_try_item.handler_off_;
Jeff Haoa8621002016-10-04 18:13:44 +0000611 const CatchHandler* handlers = nullptr;
612 for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
613 if (handler_off == existing_handlers->GetListOffset()) {
614 handlers = existing_handlers.get();
Jeff Hao44652a32017-02-22 14:20:41 -0800615 break;
Jeff Haoa8621002016-10-04 18:13:44 +0000616 }
617 }
618 if (handlers == nullptr) {
619 bool catch_all = false;
620 TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
Mathieu Chartierdc578c72017-12-27 11:51:45 -0800621 for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) {
Andreas Gampea5b09a62016-11-17 15:21:22 -0800622 const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
623 const TypeId* type_id = GetTypeIdOrNullPtr(type_index.index_);
Jeff Haoa8621002016-10-04 18:13:44 +0000624 catch_all |= type_id == nullptr;
625 addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>(
626 new TypeAddrPair(type_id, it.GetHandlerAddress())));
627 }
628 handlers = new CatchHandler(catch_all, handler_off, addr_pairs);
629 handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700630 }
631 TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
632 tries->push_back(std::unique_ptr<const TryItem>(try_item));
633 }
Jeff Hao44652a32017-02-22 14:20:41 -0800634 // Manually walk catch handlers list and add any missing handlers unreferenced by try items.
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800635 const uint8_t* handlers_base = accessor.GetCatchHandlerData();
Jeff Hao44652a32017-02-22 14:20:41 -0800636 const uint8_t* handlers_data = handlers_base;
637 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data);
638 while (handlers_size > handler_list->size()) {
639 bool already_added = false;
640 uint16_t handler_off = handlers_data - handlers_base;
641 for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
642 if (handler_off == existing_handlers->GetListOffset()) {
643 already_added = true;
644 break;
645 }
646 }
647 int32_t size = DecodeSignedLeb128(&handlers_data);
Jeff Haoac462712017-03-02 10:59:43 -0800648 bool has_catch_all = size <= 0;
Jeff Hao44652a32017-02-22 14:20:41 -0800649 if (has_catch_all) {
650 size = -size;
651 }
Jeff Haoe17f5892017-02-23 16:14:04 -0800652 if (already_added) {
Jeff Hao44652a32017-02-22 14:20:41 -0800653 for (int32_t i = 0; i < size; i++) {
654 DecodeUnsignedLeb128(&handlers_data);
655 DecodeUnsignedLeb128(&handlers_data);
656 }
657 if (has_catch_all) {
658 DecodeUnsignedLeb128(&handlers_data);
659 }
660 continue;
661 }
662 TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
663 for (int32_t i = 0; i < size; i++) {
664 const TypeId* type_id = GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data));
665 uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
666 addr_pairs->push_back(
667 std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr)));
668 }
669 if (has_catch_all) {
670 uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
671 addr_pairs->push_back(
672 std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr)));
673 }
674 const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs);
675 handler_list->push_back(std::unique_ptr<const CatchHandler>(handler));
676 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700677 }
Jeff Hao44652a32017-02-22 14:20:41 -0800678
Mathieu Chartier66c9df12018-01-16 14:45:20 -0800679 uint32_t size = dex_file.GetCodeItemSize(*disk_code_item);
680 CodeItem* code_item = new CodeItem(accessor.RegistersSize(),
681 accessor.InsSize(),
682 accessor.OutsSize(),
683 debug_info,
684 insns_size,
685 insns,
686 tries,
687 handler_list);
Jeff Haoea7c6292016-11-14 18:10:16 -0800688 code_item->SetSize(size);
Mathieu Chartier66c9df12018-01-16 14:45:20 -0800689
690 // Add the code item to the map.
691 DCHECK(!code_item->OffsetAssigned());
692 if (eagerly_assign_offsets_) {
693 code_item->SetOffset(offset);
694 }
695 code_items_map_.emplace(offsets_pair, code_item);
696 code_items_.AddItem(code_item);
697
David Sehrd1e44e22016-10-06 17:09:32 -0700698 // Add "fixup" references to types, strings, methods, and fields.
699 // This is temporary, as we will probably want more detailed parsing of the
700 // instructions here.
Vladimir Marko219cb902017-12-07 16:20:39 +0000701 std::vector<TypeId*> type_ids;
702 std::vector<StringId*> string_ids;
703 std::vector<MethodId*> method_ids;
704 std::vector<FieldId*> field_ids;
David Sehrd1e44e22016-10-06 17:09:32 -0700705 if (GetIdsFromByteCode(*this,
706 code_item,
Vladimir Marko219cb902017-12-07 16:20:39 +0000707 /*out*/ &type_ids,
708 /*out*/ &string_ids,
709 /*out*/ &method_ids,
710 /*out*/ &field_ids)) {
711 CodeFixups* fixups = new CodeFixups(std::move(type_ids),
712 std::move(string_ids),
713 std::move(method_ids),
714 std::move(field_ids));
David Sehrd1e44e22016-10-06 17:09:32 -0700715 code_item->SetCodeFixups(fixups);
716 }
717
Jeff Hao3ab96b42016-09-09 18:35:01 -0700718 return code_item;
719}
720
721MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
Jeff Hao9804e9e2017-06-15 14:04:51 -0700722 MethodId* method_id = GetMethodId(cdii.GetMemberIndex());
Jeff Hao3ab96b42016-09-09 18:35:01 -0700723 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
724 const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
Mathieu Chartier66c9df12018-01-16 14:45:20 -0800725 // Temporary hack to prevent incorrectly deduping code items if they have the same offset since
726 // they may have different debug info streams.
727 CodeItem* code_item = DedupeOrCreateCodeItem(dex_file,
728 disk_code_item,
729 cdii.GetMethodCodeItemOffset(),
730 cdii.GetMemberIndex());
Jeff Hao9804e9e2017-06-15 14:04:51 -0700731 return new MethodItem(access_flags, method_id, code_item);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700732}
733
734ClassData* Collections::CreateClassData(
735 const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
736 // Read the fields and methods defined by the class, resolving the circular reference from those
737 // to classes by setting class at the same time.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800738 ClassData* class_data = class_datas_map_.GetExistingObject(offset);
Mathieu Chartiera2973d72017-02-14 17:12:20 -0800739 if (class_data == nullptr && encoded_data != nullptr) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700740 ClassDataItemIterator cdii(dex_file, encoded_data);
741 // Static fields.
742 FieldItemVector* static_fields = new FieldItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700743 for (; cdii.HasNextStaticField(); cdii.Next()) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700744 FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
745 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
746 static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
747 }
748 // Instance fields.
749 FieldItemVector* instance_fields = new FieldItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700750 for (; cdii.HasNextInstanceField(); cdii.Next()) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700751 FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
752 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
753 instance_fields->push_back(
754 std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
755 }
756 // Direct methods.
757 MethodItemVector* direct_methods = new MethodItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700758 for (; cdii.HasNextDirectMethod(); cdii.Next()) {
759 direct_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700760 }
761 // Virtual methods.
762 MethodItemVector* virtual_methods = new MethodItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700763 for (; cdii.HasNextVirtualMethod(); cdii.Next()) {
764 virtual_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700765 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700766 class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
Jeff Haoea7c6292016-11-14 18:10:16 -0800767 class_data->SetSize(cdii.EndDataPointer() - encoded_data);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800768 AddItem(class_datas_map_, class_datas_, class_data, offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700769 }
770 return class_data;
771}
772
Jeff Hao5daee902017-04-27 18:00:38 -0700773void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
774 // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems.
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -0800775 const DexFile::MapList* map = dex_file.GetMapList();
Jeff Hao5daee902017-04-27 18:00:38 -0700776 for (uint32_t i = 0; i < map->size_; ++i) {
777 const DexFile::MapItem* item = map->list_ + i;
778 switch (item->type_) {
779 case DexFile::kDexTypeCallSiteIdItem:
780 SetCallSiteIdsOffset(item->offset_);
781 break;
782 case DexFile::kDexTypeMethodHandleItem:
783 SetMethodHandleItemsOffset(item->offset_);
784 break;
785 default:
786 break;
787 }
788 }
789 // Populate MethodHandleItems first (CallSiteIds may depend on them).
790 for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) {
791 CreateMethodHandleItem(dex_file, i);
792 }
793 // Populate CallSiteIds.
794 for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) {
795 CreateCallSiteId(dex_file, i);
796 }
797}
798
799void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
800 const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i);
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -0800801 const uint8_t* disk_call_item_ptr = dex_file.DataBegin() + disk_call_site_id.data_off_;
Jeff Hao5daee902017-04-27 18:00:38 -0700802 EncodedArrayItem* call_site_item =
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800803 CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_);
Jeff Hao5daee902017-04-27 18:00:38 -0700804
805 CallSiteId* call_site_id = new CallSiteId(call_site_item);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800806 AddIndexedItem(call_site_ids_, call_site_id, CallSiteIdsOffset() + i * CallSiteId::ItemSize(), i);
Jeff Hao5daee902017-04-27 18:00:38 -0700807}
808
809void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
810 const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i);
811 uint16_t index = disk_method_handle.field_or_method_idx_;
812 DexFile::MethodHandleType type =
813 static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_);
814 bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic ||
815 type == DexFile::MethodHandleType::kInvokeInstance ||
Orion Hodson631827d2017-04-10 14:53:47 +0100816 type == DexFile::MethodHandleType::kInvokeConstructor ||
817 type == DexFile::MethodHandleType::kInvokeDirect ||
818 type == DexFile::MethodHandleType::kInvokeInterface;
819 static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeInterface,
Jeff Hao5daee902017-04-27 18:00:38 -0700820 "Unexpected method handle types.");
821 IndexedItem* field_or_method_id;
822 if (is_invoke) {
823 field_or_method_id = GetMethodId(index);
824 } else {
825 field_or_method_id = GetFieldId(index);
826 }
827 MethodHandleItem* method_handle = new MethodHandleItem(type, field_or_method_id);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800828 AddIndexedItem(method_handle_items_,
829 method_handle,
830 MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(),
831 i);
832}
833
834void Collections::SortVectorsByMapOrder() {
Mathieu Chartier66c9df12018-01-16 14:45:20 -0800835 string_datas_.SortByMapOrder(string_datas_map_.Collection());
836 type_lists_.SortByMapOrder(type_lists_map_.Collection());
837 encoded_array_items_.SortByMapOrder(encoded_array_items_map_.Collection());
838 annotation_items_.SortByMapOrder(annotation_items_map_.Collection());
839 annotation_set_items_.SortByMapOrder(annotation_set_items_map_.Collection());
840 annotation_set_ref_lists_.SortByMapOrder(annotation_set_ref_lists_map_.Collection());
841 annotations_directory_items_.SortByMapOrder(annotations_directory_items_map_.Collection());
842 debug_info_items_.SortByMapOrder(debug_info_items_map_.Collection());
843 code_items_.SortByMapOrder(code_items_map_);
844 class_datas_.SortByMapOrder(class_datas_map_.Collection());
Jeff Hao5daee902017-04-27 18:00:38 -0700845}
846
David Sehr9037a3a2017-03-30 17:50:24 -0700847static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
848 return 0;
849}
850
851static uint32_t HeaderSize(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
852 // Size is in elements, so there is only one header.
853 return 1;
854}
855
856// The description of each dex file section type.
857struct FileSectionDescriptor {
858 public:
859 std::string name;
860 uint16_t type;
861 // A function that when applied to a collection object, gives the size of the section.
862 std::function<uint32_t(const dex_ir::Collections&)> size_fn;
863 // A function that when applied to a collection object, gives the offset of the section.
864 std::function<uint32_t(const dex_ir::Collections&)> offset_fn;
865};
866
David Sehr7639cdc2017-04-15 10:06:21 -0700867static const FileSectionDescriptor kFileSectionDescriptors[] = {
David Sehr9037a3a2017-03-30 17:50:24 -0700868 {
869 "Header",
870 DexFile::kDexTypeHeaderItem,
871 &HeaderSize,
872 &HeaderOffset,
873 }, {
874 "StringId",
875 DexFile::kDexTypeStringIdItem,
876 &dex_ir::Collections::StringIdsSize,
877 &dex_ir::Collections::StringIdsOffset
878 }, {
879 "TypeId",
880 DexFile::kDexTypeTypeIdItem,
881 &dex_ir::Collections::TypeIdsSize,
882 &dex_ir::Collections::TypeIdsOffset
883 }, {
884 "ProtoId",
885 DexFile::kDexTypeProtoIdItem,
886 &dex_ir::Collections::ProtoIdsSize,
887 &dex_ir::Collections::ProtoIdsOffset
888 }, {
889 "FieldId",
890 DexFile::kDexTypeFieldIdItem,
891 &dex_ir::Collections::FieldIdsSize,
892 &dex_ir::Collections::FieldIdsOffset
893 }, {
894 "MethodId",
895 DexFile::kDexTypeMethodIdItem,
896 &dex_ir::Collections::MethodIdsSize,
897 &dex_ir::Collections::MethodIdsOffset
898 }, {
899 "ClassDef",
900 DexFile::kDexTypeClassDefItem,
901 &dex_ir::Collections::ClassDefsSize,
902 &dex_ir::Collections::ClassDefsOffset
903 }, {
Jeff Hao5daee902017-04-27 18:00:38 -0700904 "CallSiteId",
905 DexFile::kDexTypeCallSiteIdItem,
906 &dex_ir::Collections::CallSiteIdsSize,
907 &dex_ir::Collections::CallSiteIdsOffset
908 }, {
909 "MethodHandle",
910 DexFile::kDexTypeMethodHandleItem,
911 &dex_ir::Collections::MethodHandleItemsSize,
912 &dex_ir::Collections::MethodHandleItemsOffset
913 }, {
David Sehr9037a3a2017-03-30 17:50:24 -0700914 "StringData",
915 DexFile::kDexTypeStringDataItem,
916 &dex_ir::Collections::StringDatasSize,
917 &dex_ir::Collections::StringDatasOffset
918 }, {
919 "TypeList",
920 DexFile::kDexTypeTypeList,
921 &dex_ir::Collections::TypeListsSize,
922 &dex_ir::Collections::TypeListsOffset
923 }, {
924 "EncArr",
925 DexFile::kDexTypeEncodedArrayItem,
926 &dex_ir::Collections::EncodedArrayItemsSize,
927 &dex_ir::Collections::EncodedArrayItemsOffset
928 }, {
929 "Annotation",
930 DexFile::kDexTypeAnnotationItem,
931 &dex_ir::Collections::AnnotationItemsSize,
932 &dex_ir::Collections::AnnotationItemsOffset
933 }, {
934 "AnnoSet",
935 DexFile::kDexTypeAnnotationSetItem,
936 &dex_ir::Collections::AnnotationSetItemsSize,
937 &dex_ir::Collections::AnnotationSetItemsOffset
938 }, {
939 "AnnoSetRL",
940 DexFile::kDexTypeAnnotationSetRefList,
941 &dex_ir::Collections::AnnotationSetRefListsSize,
942 &dex_ir::Collections::AnnotationSetRefListsOffset
943 }, {
944 "AnnoDir",
945 DexFile::kDexTypeAnnotationsDirectoryItem,
946 &dex_ir::Collections::AnnotationsDirectoryItemsSize,
947 &dex_ir::Collections::AnnotationsDirectoryItemsOffset
948 }, {
949 "DebugInfo",
950 DexFile::kDexTypeDebugInfoItem,
951 &dex_ir::Collections::DebugInfoItemsSize,
952 &dex_ir::Collections::DebugInfoItemsOffset
953 }, {
954 "CodeItem",
955 DexFile::kDexTypeCodeItem,
956 &dex_ir::Collections::CodeItemsSize,
957 &dex_ir::Collections::CodeItemsOffset
958 }, {
959 "ClassData",
960 DexFile::kDexTypeClassDataItem,
961 &dex_ir::Collections::ClassDatasSize,
962 &dex_ir::Collections::ClassDatasOffset
963 }
964};
965
966std::vector<dex_ir::DexFileSection> GetSortedDexFileSections(dex_ir::Header* header,
967 dex_ir::SortDirection direction) {
968 const dex_ir::Collections& collections = header->GetCollections();
969 std::vector<dex_ir::DexFileSection> sorted_sections;
970 // Build the table that will map from offset to color
971 for (const FileSectionDescriptor& s : kFileSectionDescriptors) {
972 sorted_sections.push_back(dex_ir::DexFileSection(s.name,
973 s.type,
974 s.size_fn(collections),
975 s.offset_fn(collections)));
976 }
977 // Sort by offset.
978 std::sort(sorted_sections.begin(),
979 sorted_sections.end(),
980 [=](dex_ir::DexFileSection& a, dex_ir::DexFileSection& b) {
981 if (direction == SortDirection::kSortDescending) {
982 return a.offset > b.offset;
983 } else {
984 return a.offset < b.offset;
985 }
986 });
987 return sorted_sections;
988}
989
Jeff Hao3ab96b42016-09-09 18:35:01 -0700990} // namespace dex_ir
991} // namespace art