blob: 0a59cc9ba2da57d39ca9262e8c415417ec690ad2 [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 Chartier3e0c5172017-11-12 12:58:40 -0800283 const uint32_t offset = *data - dex_file.Begin();
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);
443 const uint32_t offset = start_data - dex_file.Begin();
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
568CodeItem* Collections::CreateCodeItem(const DexFile& dex_file,
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800569 const DexFile::CodeItem& disk_code_item,
570 uint32_t offset,
571 uint32_t dex_method_index) {
572 CodeItemDebugInfoAccessor accessor(dex_file, &disk_code_item, dex_method_index);
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800573 const uint16_t registers_size = accessor.RegistersSize();
574 const uint16_t ins_size = accessor.InsSize();
575 const uint16_t outs_size = accessor.OutsSize();
576 const uint32_t tries_size = accessor.TriesSize();
Jeff Hao3ab96b42016-09-09 18:35:01 -0700577
578 // TODO: Calculate the size of the debug info.
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800579 const uint32_t debug_info_offset = accessor.DebugInfoOffset();
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +0000580 const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(debug_info_offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700581 DebugInfoItem* debug_info = nullptr;
582 if (debug_info_stream != nullptr) {
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +0000583 debug_info = debug_info_items_map_.GetExistingObject(debug_info_offset);
Mathieu Chartiera2973d72017-02-14 17:12:20 -0800584 if (debug_info == nullptr) {
585 uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream);
586 uint8_t* debug_info_buffer = new uint8_t[debug_info_size];
587 memcpy(debug_info_buffer, debug_info_stream, debug_info_size);
588 debug_info = new DebugInfoItem(debug_info_size, debug_info_buffer);
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +0000589 AddItem(debug_info_items_map_, debug_info_items_, debug_info, debug_info_offset);
Mathieu Chartiera2973d72017-02-14 17:12:20 -0800590 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700591 }
592
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800593 uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
Jeff Hao3ab96b42016-09-09 18:35:01 -0700594 uint16_t* insns = new uint16_t[insns_size];
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800595 memcpy(insns, accessor.Insns(), insns_size * sizeof(uint16_t));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700596
597 TryItemVector* tries = nullptr;
Jeff Haoa8621002016-10-04 18:13:44 +0000598 CatchHandlerVector* handler_list = nullptr;
Jeff Hao3ab96b42016-09-09 18:35:01 -0700599 if (tries_size > 0) {
600 tries = new TryItemVector();
Jeff Haoa8621002016-10-04 18:13:44 +0000601 handler_list = new CatchHandlerVector();
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800602 for (const DexFile::TryItem& disk_try_item : accessor.TryItems()) {
603 uint32_t start_addr = disk_try_item.start_addr_;
604 uint16_t insn_count = disk_try_item.insn_count_;
605 uint16_t handler_off = disk_try_item.handler_off_;
Jeff Haoa8621002016-10-04 18:13:44 +0000606 const CatchHandler* handlers = nullptr;
607 for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
608 if (handler_off == existing_handlers->GetListOffset()) {
609 handlers = existing_handlers.get();
Jeff Hao44652a32017-02-22 14:20:41 -0800610 break;
Jeff Haoa8621002016-10-04 18:13:44 +0000611 }
612 }
613 if (handlers == nullptr) {
614 bool catch_all = false;
615 TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
Mathieu Chartierdc578c72017-12-27 11:51:45 -0800616 for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) {
Andreas Gampea5b09a62016-11-17 15:21:22 -0800617 const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
618 const TypeId* type_id = GetTypeIdOrNullPtr(type_index.index_);
Jeff Haoa8621002016-10-04 18:13:44 +0000619 catch_all |= type_id == nullptr;
620 addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>(
621 new TypeAddrPair(type_id, it.GetHandlerAddress())));
622 }
623 handlers = new CatchHandler(catch_all, handler_off, addr_pairs);
624 handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700625 }
626 TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
627 tries->push_back(std::unique_ptr<const TryItem>(try_item));
628 }
Jeff Hao44652a32017-02-22 14:20:41 -0800629 // Manually walk catch handlers list and add any missing handlers unreferenced by try items.
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800630 const uint8_t* handlers_base = accessor.GetCatchHandlerData();
Jeff Hao44652a32017-02-22 14:20:41 -0800631 const uint8_t* handlers_data = handlers_base;
632 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data);
633 while (handlers_size > handler_list->size()) {
634 bool already_added = false;
635 uint16_t handler_off = handlers_data - handlers_base;
636 for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
637 if (handler_off == existing_handlers->GetListOffset()) {
638 already_added = true;
639 break;
640 }
641 }
642 int32_t size = DecodeSignedLeb128(&handlers_data);
Jeff Haoac462712017-03-02 10:59:43 -0800643 bool has_catch_all = size <= 0;
Jeff Hao44652a32017-02-22 14:20:41 -0800644 if (has_catch_all) {
645 size = -size;
646 }
Jeff Haoe17f5892017-02-23 16:14:04 -0800647 if (already_added) {
Jeff Hao44652a32017-02-22 14:20:41 -0800648 for (int32_t i = 0; i < size; i++) {
649 DecodeUnsignedLeb128(&handlers_data);
650 DecodeUnsignedLeb128(&handlers_data);
651 }
652 if (has_catch_all) {
653 DecodeUnsignedLeb128(&handlers_data);
654 }
655 continue;
656 }
657 TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
658 for (int32_t i = 0; i < size; i++) {
659 const TypeId* type_id = GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data));
660 uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
661 addr_pairs->push_back(
662 std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr)));
663 }
664 if (has_catch_all) {
665 uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
666 addr_pairs->push_back(
667 std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr)));
668 }
669 const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs);
670 handler_list->push_back(std::unique_ptr<const CatchHandler>(handler));
671 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700672 }
Jeff Hao44652a32017-02-22 14:20:41 -0800673
Mathieu Chartier6238c832018-01-04 09:55:13 -0800674 uint32_t size = dex_file.GetCodeItemSize(disk_code_item);
Jeff Haoa8621002016-10-04 18:13:44 +0000675 CodeItem* code_item = new CodeItem(
676 registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries, handler_list);
Jeff Haoea7c6292016-11-14 18:10:16 -0800677 code_item->SetSize(size);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800678 AddItem(code_items_map_, code_items_, code_item, offset);
David Sehrd1e44e22016-10-06 17:09:32 -0700679 // Add "fixup" references to types, strings, methods, and fields.
680 // This is temporary, as we will probably want more detailed parsing of the
681 // instructions here.
Vladimir Marko219cb902017-12-07 16:20:39 +0000682 std::vector<TypeId*> type_ids;
683 std::vector<StringId*> string_ids;
684 std::vector<MethodId*> method_ids;
685 std::vector<FieldId*> field_ids;
David Sehrd1e44e22016-10-06 17:09:32 -0700686 if (GetIdsFromByteCode(*this,
687 code_item,
Vladimir Marko219cb902017-12-07 16:20:39 +0000688 /*out*/ &type_ids,
689 /*out*/ &string_ids,
690 /*out*/ &method_ids,
691 /*out*/ &field_ids)) {
692 CodeFixups* fixups = new CodeFixups(std::move(type_ids),
693 std::move(string_ids),
694 std::move(method_ids),
695 std::move(field_ids));
David Sehrd1e44e22016-10-06 17:09:32 -0700696 code_item->SetCodeFixups(fixups);
697 }
698
Jeff Hao3ab96b42016-09-09 18:35:01 -0700699 return code_item;
700}
701
702MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
Jeff Hao9804e9e2017-06-15 14:04:51 -0700703 MethodId* method_id = GetMethodId(cdii.GetMemberIndex());
Jeff Hao3ab96b42016-09-09 18:35:01 -0700704 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
705 const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800706 CodeItem* code_item = code_items_map_.GetExistingObject(cdii.GetMethodCodeItemOffset());
Jeff Hao3ab96b42016-09-09 18:35:01 -0700707 DebugInfoItem* debug_info = nullptr;
708 if (disk_code_item != nullptr) {
Jeff Haod212d5b2017-04-26 12:09:06 -0700709 if (code_item == nullptr) {
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800710 code_item = CreateCodeItem(dex_file,
711 *disk_code_item,
712 cdii.GetMethodCodeItemOffset(),
713 cdii.GetMemberIndex());
Jeff Haod212d5b2017-04-26 12:09:06 -0700714 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700715 debug_info = code_item->DebugInfo();
716 }
Jeff Hao9804e9e2017-06-15 14:04:51 -0700717 return new MethodItem(access_flags, method_id, code_item);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700718}
719
720ClassData* Collections::CreateClassData(
721 const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
722 // Read the fields and methods defined by the class, resolving the circular reference from those
723 // to classes by setting class at the same time.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800724 ClassData* class_data = class_datas_map_.GetExistingObject(offset);
Mathieu Chartiera2973d72017-02-14 17:12:20 -0800725 if (class_data == nullptr && encoded_data != nullptr) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700726 ClassDataItemIterator cdii(dex_file, encoded_data);
727 // Static fields.
728 FieldItemVector* static_fields = new FieldItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700729 for (; cdii.HasNextStaticField(); cdii.Next()) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700730 FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
731 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
732 static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
733 }
734 // Instance fields.
735 FieldItemVector* instance_fields = new FieldItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700736 for (; cdii.HasNextInstanceField(); cdii.Next()) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700737 FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
738 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
739 instance_fields->push_back(
740 std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
741 }
742 // Direct methods.
743 MethodItemVector* direct_methods = new MethodItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700744 for (; cdii.HasNextDirectMethod(); cdii.Next()) {
745 direct_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700746 }
747 // Virtual methods.
748 MethodItemVector* virtual_methods = new MethodItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700749 for (; cdii.HasNextVirtualMethod(); cdii.Next()) {
750 virtual_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700751 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700752 class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
Jeff Haoea7c6292016-11-14 18:10:16 -0800753 class_data->SetSize(cdii.EndDataPointer() - encoded_data);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800754 AddItem(class_datas_map_, class_datas_, class_data, offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700755 }
756 return class_data;
757}
758
Jeff Hao5daee902017-04-27 18:00:38 -0700759void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
760 // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems.
761 const DexFile::MapList* map =
762 reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + MapListOffset());
763 for (uint32_t i = 0; i < map->size_; ++i) {
764 const DexFile::MapItem* item = map->list_ + i;
765 switch (item->type_) {
766 case DexFile::kDexTypeCallSiteIdItem:
767 SetCallSiteIdsOffset(item->offset_);
768 break;
769 case DexFile::kDexTypeMethodHandleItem:
770 SetMethodHandleItemsOffset(item->offset_);
771 break;
772 default:
773 break;
774 }
775 }
776 // Populate MethodHandleItems first (CallSiteIds may depend on them).
777 for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) {
778 CreateMethodHandleItem(dex_file, i);
779 }
780 // Populate CallSiteIds.
781 for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) {
782 CreateCallSiteId(dex_file, i);
783 }
784}
785
786void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
787 const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i);
788 const uint8_t* disk_call_item_ptr = dex_file.Begin() + disk_call_site_id.data_off_;
789 EncodedArrayItem* call_site_item =
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800790 CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_);
Jeff Hao5daee902017-04-27 18:00:38 -0700791
792 CallSiteId* call_site_id = new CallSiteId(call_site_item);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800793 AddIndexedItem(call_site_ids_, call_site_id, CallSiteIdsOffset() + i * CallSiteId::ItemSize(), i);
Jeff Hao5daee902017-04-27 18:00:38 -0700794}
795
796void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
797 const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i);
798 uint16_t index = disk_method_handle.field_or_method_idx_;
799 DexFile::MethodHandleType type =
800 static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_);
801 bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic ||
802 type == DexFile::MethodHandleType::kInvokeInstance ||
Orion Hodson631827d2017-04-10 14:53:47 +0100803 type == DexFile::MethodHandleType::kInvokeConstructor ||
804 type == DexFile::MethodHandleType::kInvokeDirect ||
805 type == DexFile::MethodHandleType::kInvokeInterface;
806 static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeInterface,
Jeff Hao5daee902017-04-27 18:00:38 -0700807 "Unexpected method handle types.");
808 IndexedItem* field_or_method_id;
809 if (is_invoke) {
810 field_or_method_id = GetMethodId(index);
811 } else {
812 field_or_method_id = GetFieldId(index);
813 }
814 MethodHandleItem* method_handle = new MethodHandleItem(type, field_or_method_id);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800815 AddIndexedItem(method_handle_items_,
816 method_handle,
817 MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(),
818 i);
819}
820
821void Collections::SortVectorsByMapOrder() {
822 string_datas_map_.SortVectorByMapOrder(string_datas_);
823 type_lists_map_.SortVectorByMapOrder(type_lists_);
824 encoded_array_items_map_.SortVectorByMapOrder(encoded_array_items_);
825 annotation_items_map_.SortVectorByMapOrder(annotation_items_);
826 annotation_set_items_map_.SortVectorByMapOrder(annotation_set_items_);
827 annotation_set_ref_lists_map_.SortVectorByMapOrder(annotation_set_ref_lists_);
828 annotations_directory_items_map_.SortVectorByMapOrder(annotations_directory_items_);
829 debug_info_items_map_.SortVectorByMapOrder(debug_info_items_);
830 code_items_map_.SortVectorByMapOrder(code_items_);
831 class_datas_map_.SortVectorByMapOrder(class_datas_);
Jeff Hao5daee902017-04-27 18:00:38 -0700832}
833
David Sehr9037a3a2017-03-30 17:50:24 -0700834static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
835 return 0;
836}
837
838static uint32_t HeaderSize(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
839 // Size is in elements, so there is only one header.
840 return 1;
841}
842
843// The description of each dex file section type.
844struct FileSectionDescriptor {
845 public:
846 std::string name;
847 uint16_t type;
848 // A function that when applied to a collection object, gives the size of the section.
849 std::function<uint32_t(const dex_ir::Collections&)> size_fn;
850 // A function that when applied to a collection object, gives the offset of the section.
851 std::function<uint32_t(const dex_ir::Collections&)> offset_fn;
852};
853
David Sehr7639cdc2017-04-15 10:06:21 -0700854static const FileSectionDescriptor kFileSectionDescriptors[] = {
David Sehr9037a3a2017-03-30 17:50:24 -0700855 {
856 "Header",
857 DexFile::kDexTypeHeaderItem,
858 &HeaderSize,
859 &HeaderOffset,
860 }, {
861 "StringId",
862 DexFile::kDexTypeStringIdItem,
863 &dex_ir::Collections::StringIdsSize,
864 &dex_ir::Collections::StringIdsOffset
865 }, {
866 "TypeId",
867 DexFile::kDexTypeTypeIdItem,
868 &dex_ir::Collections::TypeIdsSize,
869 &dex_ir::Collections::TypeIdsOffset
870 }, {
871 "ProtoId",
872 DexFile::kDexTypeProtoIdItem,
873 &dex_ir::Collections::ProtoIdsSize,
874 &dex_ir::Collections::ProtoIdsOffset
875 }, {
876 "FieldId",
877 DexFile::kDexTypeFieldIdItem,
878 &dex_ir::Collections::FieldIdsSize,
879 &dex_ir::Collections::FieldIdsOffset
880 }, {
881 "MethodId",
882 DexFile::kDexTypeMethodIdItem,
883 &dex_ir::Collections::MethodIdsSize,
884 &dex_ir::Collections::MethodIdsOffset
885 }, {
886 "ClassDef",
887 DexFile::kDexTypeClassDefItem,
888 &dex_ir::Collections::ClassDefsSize,
889 &dex_ir::Collections::ClassDefsOffset
890 }, {
Jeff Hao5daee902017-04-27 18:00:38 -0700891 "CallSiteId",
892 DexFile::kDexTypeCallSiteIdItem,
893 &dex_ir::Collections::CallSiteIdsSize,
894 &dex_ir::Collections::CallSiteIdsOffset
895 }, {
896 "MethodHandle",
897 DexFile::kDexTypeMethodHandleItem,
898 &dex_ir::Collections::MethodHandleItemsSize,
899 &dex_ir::Collections::MethodHandleItemsOffset
900 }, {
David Sehr9037a3a2017-03-30 17:50:24 -0700901 "StringData",
902 DexFile::kDexTypeStringDataItem,
903 &dex_ir::Collections::StringDatasSize,
904 &dex_ir::Collections::StringDatasOffset
905 }, {
906 "TypeList",
907 DexFile::kDexTypeTypeList,
908 &dex_ir::Collections::TypeListsSize,
909 &dex_ir::Collections::TypeListsOffset
910 }, {
911 "EncArr",
912 DexFile::kDexTypeEncodedArrayItem,
913 &dex_ir::Collections::EncodedArrayItemsSize,
914 &dex_ir::Collections::EncodedArrayItemsOffset
915 }, {
916 "Annotation",
917 DexFile::kDexTypeAnnotationItem,
918 &dex_ir::Collections::AnnotationItemsSize,
919 &dex_ir::Collections::AnnotationItemsOffset
920 }, {
921 "AnnoSet",
922 DexFile::kDexTypeAnnotationSetItem,
923 &dex_ir::Collections::AnnotationSetItemsSize,
924 &dex_ir::Collections::AnnotationSetItemsOffset
925 }, {
926 "AnnoSetRL",
927 DexFile::kDexTypeAnnotationSetRefList,
928 &dex_ir::Collections::AnnotationSetRefListsSize,
929 &dex_ir::Collections::AnnotationSetRefListsOffset
930 }, {
931 "AnnoDir",
932 DexFile::kDexTypeAnnotationsDirectoryItem,
933 &dex_ir::Collections::AnnotationsDirectoryItemsSize,
934 &dex_ir::Collections::AnnotationsDirectoryItemsOffset
935 }, {
936 "DebugInfo",
937 DexFile::kDexTypeDebugInfoItem,
938 &dex_ir::Collections::DebugInfoItemsSize,
939 &dex_ir::Collections::DebugInfoItemsOffset
940 }, {
941 "CodeItem",
942 DexFile::kDexTypeCodeItem,
943 &dex_ir::Collections::CodeItemsSize,
944 &dex_ir::Collections::CodeItemsOffset
945 }, {
946 "ClassData",
947 DexFile::kDexTypeClassDataItem,
948 &dex_ir::Collections::ClassDatasSize,
949 &dex_ir::Collections::ClassDatasOffset
950 }
951};
952
953std::vector<dex_ir::DexFileSection> GetSortedDexFileSections(dex_ir::Header* header,
954 dex_ir::SortDirection direction) {
955 const dex_ir::Collections& collections = header->GetCollections();
956 std::vector<dex_ir::DexFileSection> sorted_sections;
957 // Build the table that will map from offset to color
958 for (const FileSectionDescriptor& s : kFileSectionDescriptors) {
959 sorted_sections.push_back(dex_ir::DexFileSection(s.name,
960 s.type,
961 s.size_fn(collections),
962 s.offset_fn(collections)));
963 }
964 // Sort by offset.
965 std::sort(sorted_sections.begin(),
966 sorted_sections.end(),
967 [=](dex_ir::DexFileSection& a, dex_ir::DexFileSection& b) {
968 if (direction == SortDirection::kSortDescending) {
969 return a.offset > b.offset;
970 } else {
971 return a.offset < b.offset;
972 }
973 });
974 return sorted_sections;
975}
976
Jeff Hao3ab96b42016-09-09 18:35:01 -0700977} // namespace dex_ir
978} // namespace art