blob: 2191ea601f7d2941201d69ed125e46b656ec1132 [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,
569 const DexFile::CodeItem& disk_code_item, uint32_t offset) {
Mathieu Chartier698ebbc2018-01-05 11:00:42 -0800570 CodeItemDebugInfoAccessor accessor(dex_file, &disk_code_item);
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800571 const uint16_t registers_size = accessor.RegistersSize();
572 const uint16_t ins_size = accessor.InsSize();
573 const uint16_t outs_size = accessor.OutsSize();
574 const uint32_t tries_size = accessor.TriesSize();
Jeff Hao3ab96b42016-09-09 18:35:01 -0700575
576 // TODO: Calculate the size of the debug info.
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800577 const uint32_t debug_info_offset = accessor.DebugInfoOffset();
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +0000578 const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(debug_info_offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700579 DebugInfoItem* debug_info = nullptr;
580 if (debug_info_stream != nullptr) {
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +0000581 debug_info = debug_info_items_map_.GetExistingObject(debug_info_offset);
Mathieu Chartiera2973d72017-02-14 17:12:20 -0800582 if (debug_info == nullptr) {
583 uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream);
584 uint8_t* debug_info_buffer = new uint8_t[debug_info_size];
585 memcpy(debug_info_buffer, debug_info_stream, debug_info_size);
586 debug_info = new DebugInfoItem(debug_info_size, debug_info_buffer);
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +0000587 AddItem(debug_info_items_map_, debug_info_items_, debug_info, debug_info_offset);
Mathieu Chartiera2973d72017-02-14 17:12:20 -0800588 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700589 }
590
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800591 uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
Jeff Hao3ab96b42016-09-09 18:35:01 -0700592 uint16_t* insns = new uint16_t[insns_size];
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800593 memcpy(insns, accessor.Insns(), insns_size * sizeof(uint16_t));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700594
595 TryItemVector* tries = nullptr;
Jeff Haoa8621002016-10-04 18:13:44 +0000596 CatchHandlerVector* handler_list = nullptr;
Jeff Hao3ab96b42016-09-09 18:35:01 -0700597 if (tries_size > 0) {
598 tries = new TryItemVector();
Jeff Haoa8621002016-10-04 18:13:44 +0000599 handler_list = new CatchHandlerVector();
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800600 for (const DexFile::TryItem& disk_try_item : accessor.TryItems()) {
601 uint32_t start_addr = disk_try_item.start_addr_;
602 uint16_t insn_count = disk_try_item.insn_count_;
603 uint16_t handler_off = disk_try_item.handler_off_;
Jeff Haoa8621002016-10-04 18:13:44 +0000604 const CatchHandler* handlers = nullptr;
605 for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
606 if (handler_off == existing_handlers->GetListOffset()) {
607 handlers = existing_handlers.get();
Jeff Hao44652a32017-02-22 14:20:41 -0800608 break;
Jeff Haoa8621002016-10-04 18:13:44 +0000609 }
610 }
611 if (handlers == nullptr) {
612 bool catch_all = false;
613 TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
Mathieu Chartierdc578c72017-12-27 11:51:45 -0800614 for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) {
Andreas Gampea5b09a62016-11-17 15:21:22 -0800615 const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
616 const TypeId* type_id = GetTypeIdOrNullPtr(type_index.index_);
Jeff Haoa8621002016-10-04 18:13:44 +0000617 catch_all |= type_id == nullptr;
618 addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>(
619 new TypeAddrPair(type_id, it.GetHandlerAddress())));
620 }
621 handlers = new CatchHandler(catch_all, handler_off, addr_pairs);
622 handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700623 }
624 TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
625 tries->push_back(std::unique_ptr<const TryItem>(try_item));
626 }
Jeff Hao44652a32017-02-22 14:20:41 -0800627 // Manually walk catch handlers list and add any missing handlers unreferenced by try items.
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800628 const uint8_t* handlers_base = accessor.GetCatchHandlerData();
Jeff Hao44652a32017-02-22 14:20:41 -0800629 const uint8_t* handlers_data = handlers_base;
630 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data);
631 while (handlers_size > handler_list->size()) {
632 bool already_added = false;
633 uint16_t handler_off = handlers_data - handlers_base;
634 for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
635 if (handler_off == existing_handlers->GetListOffset()) {
636 already_added = true;
637 break;
638 }
639 }
640 int32_t size = DecodeSignedLeb128(&handlers_data);
Jeff Haoac462712017-03-02 10:59:43 -0800641 bool has_catch_all = size <= 0;
Jeff Hao44652a32017-02-22 14:20:41 -0800642 if (has_catch_all) {
643 size = -size;
644 }
Jeff Haoe17f5892017-02-23 16:14:04 -0800645 if (already_added) {
Jeff Hao44652a32017-02-22 14:20:41 -0800646 for (int32_t i = 0; i < size; i++) {
647 DecodeUnsignedLeb128(&handlers_data);
648 DecodeUnsignedLeb128(&handlers_data);
649 }
650 if (has_catch_all) {
651 DecodeUnsignedLeb128(&handlers_data);
652 }
653 continue;
654 }
655 TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
656 for (int32_t i = 0; i < size; i++) {
657 const TypeId* type_id = GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data));
658 uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
659 addr_pairs->push_back(
660 std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr)));
661 }
662 if (has_catch_all) {
663 uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
664 addr_pairs->push_back(
665 std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr)));
666 }
667 const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs);
668 handler_list->push_back(std::unique_ptr<const CatchHandler>(handler));
669 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700670 }
Jeff Hao44652a32017-02-22 14:20:41 -0800671
Mathieu Chartier6238c832018-01-04 09:55:13 -0800672 uint32_t size = dex_file.GetCodeItemSize(disk_code_item);
Jeff Haoa8621002016-10-04 18:13:44 +0000673 CodeItem* code_item = new CodeItem(
674 registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries, handler_list);
Jeff Haoea7c6292016-11-14 18:10:16 -0800675 code_item->SetSize(size);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800676 AddItem(code_items_map_, code_items_, code_item, offset);
David Sehrd1e44e22016-10-06 17:09:32 -0700677 // Add "fixup" references to types, strings, methods, and fields.
678 // This is temporary, as we will probably want more detailed parsing of the
679 // instructions here.
Vladimir Marko219cb902017-12-07 16:20:39 +0000680 std::vector<TypeId*> type_ids;
681 std::vector<StringId*> string_ids;
682 std::vector<MethodId*> method_ids;
683 std::vector<FieldId*> field_ids;
David Sehrd1e44e22016-10-06 17:09:32 -0700684 if (GetIdsFromByteCode(*this,
685 code_item,
Vladimir Marko219cb902017-12-07 16:20:39 +0000686 /*out*/ &type_ids,
687 /*out*/ &string_ids,
688 /*out*/ &method_ids,
689 /*out*/ &field_ids)) {
690 CodeFixups* fixups = new CodeFixups(std::move(type_ids),
691 std::move(string_ids),
692 std::move(method_ids),
693 std::move(field_ids));
David Sehrd1e44e22016-10-06 17:09:32 -0700694 code_item->SetCodeFixups(fixups);
695 }
696
Jeff Hao3ab96b42016-09-09 18:35:01 -0700697 return code_item;
698}
699
700MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
Jeff Hao9804e9e2017-06-15 14:04:51 -0700701 MethodId* method_id = GetMethodId(cdii.GetMemberIndex());
Jeff Hao3ab96b42016-09-09 18:35:01 -0700702 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
703 const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800704 CodeItem* code_item = code_items_map_.GetExistingObject(cdii.GetMethodCodeItemOffset());
Jeff Hao3ab96b42016-09-09 18:35:01 -0700705 DebugInfoItem* debug_info = nullptr;
706 if (disk_code_item != nullptr) {
Jeff Haod212d5b2017-04-26 12:09:06 -0700707 if (code_item == nullptr) {
708 code_item = CreateCodeItem(dex_file, *disk_code_item, cdii.GetMethodCodeItemOffset());
709 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700710 debug_info = code_item->DebugInfo();
711 }
Jeff Hao9804e9e2017-06-15 14:04:51 -0700712 return new MethodItem(access_flags, method_id, code_item);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700713}
714
715ClassData* Collections::CreateClassData(
716 const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
717 // Read the fields and methods defined by the class, resolving the circular reference from those
718 // to classes by setting class at the same time.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800719 ClassData* class_data = class_datas_map_.GetExistingObject(offset);
Mathieu Chartiera2973d72017-02-14 17:12:20 -0800720 if (class_data == nullptr && encoded_data != nullptr) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700721 ClassDataItemIterator cdii(dex_file, encoded_data);
722 // Static fields.
723 FieldItemVector* static_fields = new FieldItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700724 for (; cdii.HasNextStaticField(); cdii.Next()) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700725 FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
726 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
727 static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
728 }
729 // Instance fields.
730 FieldItemVector* instance_fields = new FieldItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700731 for (; cdii.HasNextInstanceField(); cdii.Next()) {
Jeff Hao3ab96b42016-09-09 18:35:01 -0700732 FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
733 uint32_t access_flags = cdii.GetRawMemberAccessFlags();
734 instance_fields->push_back(
735 std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
736 }
737 // Direct methods.
738 MethodItemVector* direct_methods = new MethodItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700739 for (; cdii.HasNextDirectMethod(); cdii.Next()) {
740 direct_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700741 }
742 // Virtual methods.
743 MethodItemVector* virtual_methods = new MethodItemVector();
Jeff Hao9804e9e2017-06-15 14:04:51 -0700744 for (; cdii.HasNextVirtualMethod(); cdii.Next()) {
745 virtual_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
Jeff Hao3ab96b42016-09-09 18:35:01 -0700746 }
Jeff Hao3ab96b42016-09-09 18:35:01 -0700747 class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
Jeff Haoea7c6292016-11-14 18:10:16 -0800748 class_data->SetSize(cdii.EndDataPointer() - encoded_data);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800749 AddItem(class_datas_map_, class_datas_, class_data, offset);
Jeff Hao3ab96b42016-09-09 18:35:01 -0700750 }
751 return class_data;
752}
753
Jeff Hao5daee902017-04-27 18:00:38 -0700754void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
755 // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems.
756 const DexFile::MapList* map =
757 reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + MapListOffset());
758 for (uint32_t i = 0; i < map->size_; ++i) {
759 const DexFile::MapItem* item = map->list_ + i;
760 switch (item->type_) {
761 case DexFile::kDexTypeCallSiteIdItem:
762 SetCallSiteIdsOffset(item->offset_);
763 break;
764 case DexFile::kDexTypeMethodHandleItem:
765 SetMethodHandleItemsOffset(item->offset_);
766 break;
767 default:
768 break;
769 }
770 }
771 // Populate MethodHandleItems first (CallSiteIds may depend on them).
772 for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) {
773 CreateMethodHandleItem(dex_file, i);
774 }
775 // Populate CallSiteIds.
776 for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) {
777 CreateCallSiteId(dex_file, i);
778 }
779}
780
781void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
782 const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i);
783 const uint8_t* disk_call_item_ptr = dex_file.Begin() + disk_call_site_id.data_off_;
784 EncodedArrayItem* call_site_item =
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800785 CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_);
Jeff Hao5daee902017-04-27 18:00:38 -0700786
787 CallSiteId* call_site_id = new CallSiteId(call_site_item);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800788 AddIndexedItem(call_site_ids_, call_site_id, CallSiteIdsOffset() + i * CallSiteId::ItemSize(), i);
Jeff Hao5daee902017-04-27 18:00:38 -0700789}
790
791void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
792 const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i);
793 uint16_t index = disk_method_handle.field_or_method_idx_;
794 DexFile::MethodHandleType type =
795 static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_);
796 bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic ||
797 type == DexFile::MethodHandleType::kInvokeInstance ||
Orion Hodson631827d2017-04-10 14:53:47 +0100798 type == DexFile::MethodHandleType::kInvokeConstructor ||
799 type == DexFile::MethodHandleType::kInvokeDirect ||
800 type == DexFile::MethodHandleType::kInvokeInterface;
801 static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeInterface,
Jeff Hao5daee902017-04-27 18:00:38 -0700802 "Unexpected method handle types.");
803 IndexedItem* field_or_method_id;
804 if (is_invoke) {
805 field_or_method_id = GetMethodId(index);
806 } else {
807 field_or_method_id = GetFieldId(index);
808 }
809 MethodHandleItem* method_handle = new MethodHandleItem(type, field_or_method_id);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800810 AddIndexedItem(method_handle_items_,
811 method_handle,
812 MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(),
813 i);
814}
815
816void Collections::SortVectorsByMapOrder() {
817 string_datas_map_.SortVectorByMapOrder(string_datas_);
818 type_lists_map_.SortVectorByMapOrder(type_lists_);
819 encoded_array_items_map_.SortVectorByMapOrder(encoded_array_items_);
820 annotation_items_map_.SortVectorByMapOrder(annotation_items_);
821 annotation_set_items_map_.SortVectorByMapOrder(annotation_set_items_);
822 annotation_set_ref_lists_map_.SortVectorByMapOrder(annotation_set_ref_lists_);
823 annotations_directory_items_map_.SortVectorByMapOrder(annotations_directory_items_);
824 debug_info_items_map_.SortVectorByMapOrder(debug_info_items_);
825 code_items_map_.SortVectorByMapOrder(code_items_);
826 class_datas_map_.SortVectorByMapOrder(class_datas_);
Jeff Hao5daee902017-04-27 18:00:38 -0700827}
828
David Sehr9037a3a2017-03-30 17:50:24 -0700829static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
830 return 0;
831}
832
833static uint32_t HeaderSize(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
834 // Size is in elements, so there is only one header.
835 return 1;
836}
837
838// The description of each dex file section type.
839struct FileSectionDescriptor {
840 public:
841 std::string name;
842 uint16_t type;
843 // A function that when applied to a collection object, gives the size of the section.
844 std::function<uint32_t(const dex_ir::Collections&)> size_fn;
845 // A function that when applied to a collection object, gives the offset of the section.
846 std::function<uint32_t(const dex_ir::Collections&)> offset_fn;
847};
848
David Sehr7639cdc2017-04-15 10:06:21 -0700849static const FileSectionDescriptor kFileSectionDescriptors[] = {
David Sehr9037a3a2017-03-30 17:50:24 -0700850 {
851 "Header",
852 DexFile::kDexTypeHeaderItem,
853 &HeaderSize,
854 &HeaderOffset,
855 }, {
856 "StringId",
857 DexFile::kDexTypeStringIdItem,
858 &dex_ir::Collections::StringIdsSize,
859 &dex_ir::Collections::StringIdsOffset
860 }, {
861 "TypeId",
862 DexFile::kDexTypeTypeIdItem,
863 &dex_ir::Collections::TypeIdsSize,
864 &dex_ir::Collections::TypeIdsOffset
865 }, {
866 "ProtoId",
867 DexFile::kDexTypeProtoIdItem,
868 &dex_ir::Collections::ProtoIdsSize,
869 &dex_ir::Collections::ProtoIdsOffset
870 }, {
871 "FieldId",
872 DexFile::kDexTypeFieldIdItem,
873 &dex_ir::Collections::FieldIdsSize,
874 &dex_ir::Collections::FieldIdsOffset
875 }, {
876 "MethodId",
877 DexFile::kDexTypeMethodIdItem,
878 &dex_ir::Collections::MethodIdsSize,
879 &dex_ir::Collections::MethodIdsOffset
880 }, {
881 "ClassDef",
882 DexFile::kDexTypeClassDefItem,
883 &dex_ir::Collections::ClassDefsSize,
884 &dex_ir::Collections::ClassDefsOffset
885 }, {
Jeff Hao5daee902017-04-27 18:00:38 -0700886 "CallSiteId",
887 DexFile::kDexTypeCallSiteIdItem,
888 &dex_ir::Collections::CallSiteIdsSize,
889 &dex_ir::Collections::CallSiteIdsOffset
890 }, {
891 "MethodHandle",
892 DexFile::kDexTypeMethodHandleItem,
893 &dex_ir::Collections::MethodHandleItemsSize,
894 &dex_ir::Collections::MethodHandleItemsOffset
895 }, {
David Sehr9037a3a2017-03-30 17:50:24 -0700896 "StringData",
897 DexFile::kDexTypeStringDataItem,
898 &dex_ir::Collections::StringDatasSize,
899 &dex_ir::Collections::StringDatasOffset
900 }, {
901 "TypeList",
902 DexFile::kDexTypeTypeList,
903 &dex_ir::Collections::TypeListsSize,
904 &dex_ir::Collections::TypeListsOffset
905 }, {
906 "EncArr",
907 DexFile::kDexTypeEncodedArrayItem,
908 &dex_ir::Collections::EncodedArrayItemsSize,
909 &dex_ir::Collections::EncodedArrayItemsOffset
910 }, {
911 "Annotation",
912 DexFile::kDexTypeAnnotationItem,
913 &dex_ir::Collections::AnnotationItemsSize,
914 &dex_ir::Collections::AnnotationItemsOffset
915 }, {
916 "AnnoSet",
917 DexFile::kDexTypeAnnotationSetItem,
918 &dex_ir::Collections::AnnotationSetItemsSize,
919 &dex_ir::Collections::AnnotationSetItemsOffset
920 }, {
921 "AnnoSetRL",
922 DexFile::kDexTypeAnnotationSetRefList,
923 &dex_ir::Collections::AnnotationSetRefListsSize,
924 &dex_ir::Collections::AnnotationSetRefListsOffset
925 }, {
926 "AnnoDir",
927 DexFile::kDexTypeAnnotationsDirectoryItem,
928 &dex_ir::Collections::AnnotationsDirectoryItemsSize,
929 &dex_ir::Collections::AnnotationsDirectoryItemsOffset
930 }, {
931 "DebugInfo",
932 DexFile::kDexTypeDebugInfoItem,
933 &dex_ir::Collections::DebugInfoItemsSize,
934 &dex_ir::Collections::DebugInfoItemsOffset
935 }, {
936 "CodeItem",
937 DexFile::kDexTypeCodeItem,
938 &dex_ir::Collections::CodeItemsSize,
939 &dex_ir::Collections::CodeItemsOffset
940 }, {
941 "ClassData",
942 DexFile::kDexTypeClassDataItem,
943 &dex_ir::Collections::ClassDatasSize,
944 &dex_ir::Collections::ClassDatasOffset
945 }
946};
947
948std::vector<dex_ir::DexFileSection> GetSortedDexFileSections(dex_ir::Header* header,
949 dex_ir::SortDirection direction) {
950 const dex_ir::Collections& collections = header->GetCollections();
951 std::vector<dex_ir::DexFileSection> sorted_sections;
952 // Build the table that will map from offset to color
953 for (const FileSectionDescriptor& s : kFileSectionDescriptors) {
954 sorted_sections.push_back(dex_ir::DexFileSection(s.name,
955 s.type,
956 s.size_fn(collections),
957 s.offset_fn(collections)));
958 }
959 // Sort by offset.
960 std::sort(sorted_sections.begin(),
961 sorted_sections.end(),
962 [=](dex_ir::DexFileSection& a, dex_ir::DexFileSection& b) {
963 if (direction == SortDirection::kSortDescending) {
964 return a.offset > b.offset;
965 } else {
966 return a.offset < b.offset;
967 }
968 });
969 return sorted_sections;
970}
971
Jeff Hao3ab96b42016-09-09 18:35:01 -0700972} // namespace dex_ir
973} // namespace art