1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * Implementation file of the dexlayout utility. 17 * 18 * This is a tool to read dex files into an internal representation, 19 * reorganize the representation, and emit dex files with a better 20 * file layout. 21 */ 22 23 #include "dex_ir.h" 24 25 #include "dex/code_item_accessors-inl.h" 26 #include "dex/dex_file_exception_helpers.h" 27 #include "dex/dex_instruction-inl.h" 28 #include "dex_ir_builder.h" 29 30 namespace art { 31 namespace dex_ir { 32 33 static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) { 34 uint64_t value = 0; 35 for (uint32_t i = 0; i <= length; i++) { 36 value |= static_cast<uint64_t>(*(*data)++) << (i * 8); 37 } 38 if (sign_extend) { 39 int shift = (7 - length) * 8; 40 return (static_cast<int64_t>(value) << shift) >> shift; 41 } 42 return value; 43 } 44 45 static uint32_t GetDebugInfoStreamSize(const uint8_t* debug_info_stream) { 46 const uint8_t* stream = debug_info_stream; 47 DecodeUnsignedLeb128(&stream); // line_start 48 uint32_t parameters_size = DecodeUnsignedLeb128(&stream); 49 for (uint32_t i = 0; i < parameters_size; ++i) { 50 DecodeUnsignedLeb128P1(&stream); // Parameter name. 51 } 52 53 for (;;) { 54 uint8_t opcode = *stream++; 55 switch (opcode) { 56 case DexFile::DBG_END_SEQUENCE: 57 return stream - debug_info_stream; // end of stream. 58 case DexFile::DBG_ADVANCE_PC: 59 DecodeUnsignedLeb128(&stream); // addr_diff 60 break; 61 case DexFile::DBG_ADVANCE_LINE: 62 DecodeSignedLeb128(&stream); // line_diff 63 break; 64 case DexFile::DBG_START_LOCAL: 65 DecodeUnsignedLeb128(&stream); // register_num 66 DecodeUnsignedLeb128P1(&stream); // name_idx 67 DecodeUnsignedLeb128P1(&stream); // type_idx 68 break; 69 case DexFile::DBG_START_LOCAL_EXTENDED: 70 DecodeUnsignedLeb128(&stream); // register_num 71 DecodeUnsignedLeb128P1(&stream); // name_idx 72 DecodeUnsignedLeb128P1(&stream); // type_idx 73 DecodeUnsignedLeb128P1(&stream); // sig_idx 74 break; 75 case DexFile::DBG_END_LOCAL: 76 case DexFile::DBG_RESTART_LOCAL: 77 DecodeUnsignedLeb128(&stream); // register_num 78 break; 79 case DexFile::DBG_SET_PROLOGUE_END: 80 case DexFile::DBG_SET_EPILOGUE_BEGIN: 81 break; 82 case DexFile::DBG_SET_FILE: { 83 DecodeUnsignedLeb128P1(&stream); // name_idx 84 break; 85 } 86 default: { 87 break; 88 } 89 } 90 } 91 } 92 93 static 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: 111 case Instruction::k45cc: 112 case Instruction::k4rcc: 113 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: 141 case Instruction::kIndexMethodAndProtoRef: 142 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 */ 166 static 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; 173 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; 179 if (next.IsErrorState()) { 180 break; 181 } 182 has_id |= GetIdFromInstruction(collections, 183 &it.Inst(), 184 type_ids, 185 string_ids, 186 method_ids, 187 field_ids); 188 } // for 189 return has_id; 190 } 191 192 EncodedValue* Collections::ReadEncodedValue(const DexFile& dex_file, const uint8_t** data) { 193 const uint8_t encoded_value = *(*data)++; 194 const uint8_t type = encoded_value & 0x1f; 195 EncodedValue* item = new EncodedValue(type); 196 ReadEncodedValue(dex_file, data, type, encoded_value >> 5, item); 197 return item; 198 } 199 200 EncodedValue* Collections::ReadEncodedValue(const DexFile& dex_file, 201 const uint8_t** data, 202 uint8_t type, 203 uint8_t length) { 204 EncodedValue* item = new EncodedValue(type); 205 ReadEncodedValue(dex_file, data, type, length, item); 206 return item; 207 } 208 209 void Collections::ReadEncodedValue(const DexFile& dex_file, 210 const uint8_t** data, 211 uint8_t type, 212 uint8_t length, 213 EncodedValue* item) { 214 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 } 250 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 } 260 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(); 283 const uint32_t offset = *data - dex_file.DataBegin(); 284 const uint32_t size = DecodeUnsignedLeb128(data); 285 // Decode all elements. 286 for (uint32_t i = 0; i < size; i++) { 287 values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, data))); 288 } 289 EncodedArrayItem* array_item = new EncodedArrayItem(values); 290 if (eagerly_assign_offsets_) { 291 array_item->SetOffset(offset); 292 } 293 item->SetEncodedArray(array_item); 294 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>( 304 new AnnotationElement(GetStringId(name_index), ReadEncodedValue(dex_file, data)))); 305 } 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 319 void Collections::CreateStringId(const DexFile& dex_file, uint32_t i) { 320 const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i)); 321 StringData* string_data = new StringData(dex_file.GetStringData(disk_string_id)); 322 AddItem(string_datas_map_, string_datas_, string_data, disk_string_id.string_data_off_); 323 324 StringId* string_id = new StringId(string_data); 325 AddIndexedItem(string_ids_, string_id, StringIdsOffset() + i * StringId::ItemSize(), i); 326 } 327 328 void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) { 329 const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i)); 330 TypeId* type_id = new TypeId(GetStringId(disk_type_id.descriptor_idx_.index_)); 331 AddIndexedItem(type_ids_, type_id, TypeIdsOffset() + i * TypeId::ItemSize(), i); 332 } 333 334 void 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); 337 TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_); 338 339 ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_.index_), 340 GetTypeId(disk_proto_id.return_type_idx_.index_), 341 parameter_type_list); 342 AddIndexedItem(proto_ids_, proto_id, ProtoIdsOffset() + i * ProtoId::ItemSize(), i); 343 } 344 345 void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) { 346 const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i); 347 FieldId* field_id = new FieldId(GetTypeId(disk_field_id.class_idx_.index_), 348 GetTypeId(disk_field_id.type_idx_.index_), 349 GetStringId(disk_field_id.name_idx_.index_)); 350 AddIndexedItem(field_ids_, field_id, FieldIdsOffset() + i * FieldId::ItemSize(), i); 351 } 352 353 void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) { 354 const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i); 355 MethodId* method_id = new MethodId(GetTypeId(disk_method_id.class_idx_.index_), 356 GetProtoId(disk_method_id.proto_idx_), 357 GetStringId(disk_method_id.name_idx_.index_)); 358 AddIndexedItem(method_ids_, method_id, MethodIdsOffset() + i * MethodId::ItemSize(), i); 359 } 360 361 void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) { 362 const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i); 363 const TypeId* class_type = GetTypeId(disk_class_def.class_idx_.index_); 364 uint32_t access_flags = disk_class_def.access_flags_; 365 const TypeId* superclass = GetTypeIdOrNullPtr(disk_class_def.superclass_idx_.index_); 366 367 const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def); 368 TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_); 369 370 const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_.index_); 371 // 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 = 382 CreateEncodedArrayItem(dex_file, static_data, disk_class_def.static_values_off_); 383 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); 387 AddIndexedItem(class_defs_, class_def, ClassDefsOffset() + i * ClassDef::ItemSize(), i); 388 } 389 390 TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) { 391 if (dex_type_list == nullptr) { 392 return nullptr; 393 } 394 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); 403 } 404 return type_list; 405 } 406 407 EncodedArrayItem* Collections::CreateEncodedArrayItem(const DexFile& dex_file, 408 const uint8_t* static_data, 409 uint32_t offset) { 410 if (static_data == nullptr) { 411 return nullptr; 412 } 413 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); 423 } 424 return encoded_array_item; 425 } 426 427 void 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 440 AnnotationItem* 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.DataBegin(); 444 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); 453 } 454 return annotation_item; 455 } 456 457 458 AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file, 459 const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset) { 460 if (disk_annotations_item == nullptr || (disk_annotations_item->size_ == 0 && offset == 0)) { 461 return nullptr; 462 } 463 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); 474 } 475 annotation_set_item = new AnnotationSetItem(items); 476 AddItem(annotation_set_items_map_, annotation_set_items_, annotation_set_item, offset); 477 } 478 return annotation_set_item; 479 } 480 481 AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file, 482 const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) { 483 AnnotationsDirectoryItem* annotations_directory_item = 484 annotations_directory_items_map_.GetExistingObject(offset); 485 if (annotations_directory_item != nullptr) { 486 return annotations_directory_item; 487 } 488 const DexFile::AnnotationSetItem* class_set_item = 489 dex_file.GetClassAnnotationSet(disk_annotations_item); 490 AnnotationSetItem* class_annotation = nullptr; 491 if (class_set_item != nullptr) { 492 uint32_t item_offset = disk_annotations_item->class_annotations_off_; 493 class_annotation = CreateAnnotationSetItem(dex_file, class_set_item, item_offset); 494 } 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 = 506 CreateAnnotationSetItem(dex_file, field_set_item, annotation_set_offset); 507 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 = 522 CreateAnnotationSetItem(dex_file, method_set_item, annotation_set_offset); 523 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(¶meters[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. 541 annotations_directory_item = new AnnotationsDirectoryItem( 542 class_annotation, field_annotations, method_annotations, parameter_annotations); 543 AddItem(annotations_directory_items_map_, 544 annotations_directory_items_, 545 annotations_directory_item, 546 offset); 547 return annotations_directory_item; 548 } 549 550 ParameterAnnotation* Collections::GenerateParameterAnnotation( 551 const DexFile& dex_file, MethodId* method_id, 552 const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) { 553 AnnotationSetRefList* set_ref_list = annotation_set_ref_lists_map_.GetExistingObject(offset); 554 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_; 560 annotations->push_back(CreateAnnotationSetItem(dex_file, annotation_set_item, set_offset)); 561 } 562 set_ref_list = new AnnotationSetRefList(annotations); 563 AddItem(annotation_set_ref_lists_map_, annotation_set_ref_lists_, set_ref_list, offset); 564 } 565 return new ParameterAnnotation(method_id, set_ref_list); 566 } 567 568 CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file, 569 const DexFile::CodeItem* disk_code_item, 570 uint32_t offset, 571 uint32_t dex_method_index) { 572 if (disk_code_item == nullptr) { 573 return nullptr; 574 } 575 CodeItemDebugInfoAccessor accessor(dex_file, disk_code_item, dex_method_index); 576 const uint32_t debug_info_offset = accessor.DebugInfoOffset(); 577 578 // Create the offsets pair and dedupe based on it. 579 std::pair<uint32_t, uint32_t> offsets_pair(offset, debug_info_offset); 580 auto existing = code_items_map_.find(offsets_pair); 581 if (existing != code_items_map_.end()) { 582 return existing->second; 583 } 584 585 const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(debug_info_offset); 586 DebugInfoItem* debug_info = nullptr; 587 if (debug_info_stream != nullptr) { 588 debug_info = debug_info_items_map_.GetExistingObject(debug_info_offset); 589 if (debug_info == nullptr) { 590 uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream); 591 uint8_t* debug_info_buffer = new uint8_t[debug_info_size]; 592 memcpy(debug_info_buffer, debug_info_stream, debug_info_size); 593 debug_info = new DebugInfoItem(debug_info_size, debug_info_buffer); 594 AddItem(debug_info_items_map_, debug_info_items_, debug_info, debug_info_offset); 595 } 596 } 597 598 uint32_t insns_size = accessor.InsnsSizeInCodeUnits(); 599 uint16_t* insns = new uint16_t[insns_size]; 600 memcpy(insns, accessor.Insns(), insns_size * sizeof(uint16_t)); 601 602 TryItemVector* tries = nullptr; 603 CatchHandlerVector* handler_list = nullptr; 604 if (accessor.TriesSize() > 0) { 605 tries = new TryItemVector(); 606 handler_list = new CatchHandlerVector(); 607 for (const DexFile::TryItem& disk_try_item : accessor.TryItems()) { 608 uint32_t start_addr = disk_try_item.start_addr_; 609 uint16_t insn_count = disk_try_item.insn_count_; 610 uint16_t handler_off = disk_try_item.handler_off_; 611 const CatchHandler* handlers = nullptr; 612 for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) { 613 if (handler_off == existing_handlers->GetListOffset()) { 614 handlers = existing_handlers.get(); 615 break; 616 } 617 } 618 if (handlers == nullptr) { 619 bool catch_all = false; 620 TypeAddrPairVector* addr_pairs = new TypeAddrPairVector(); 621 for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) { 622 const dex::TypeIndex type_index = it.GetHandlerTypeIndex(); 623 const TypeId* type_id = GetTypeIdOrNullPtr(type_index.index_); 624 catch_all |= type_id == nullptr; 625 addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>( 626 new TypeAddrPair(type_id, it.GetHandlerAddress()))); 627 } 628 handlers = new CatchHandler(catch_all, handler_off, addr_pairs); 629 handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers)); 630 } 631 TryItem* try_item = new TryItem(start_addr, insn_count, handlers); 632 tries->push_back(std::unique_ptr<const TryItem>(try_item)); 633 } 634 // Manually walk catch handlers list and add any missing handlers unreferenced by try items. 635 const uint8_t* handlers_base = accessor.GetCatchHandlerData(); 636 const uint8_t* handlers_data = handlers_base; 637 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data); 638 while (handlers_size > handler_list->size()) { 639 bool already_added = false; 640 uint16_t handler_off = handlers_data - handlers_base; 641 for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) { 642 if (handler_off == existing_handlers->GetListOffset()) { 643 already_added = true; 644 break; 645 } 646 } 647 int32_t size = DecodeSignedLeb128(&handlers_data); 648 bool has_catch_all = size <= 0; 649 if (has_catch_all) { 650 size = -size; 651 } 652 if (already_added) { 653 for (int32_t i = 0; i < size; i++) { 654 DecodeUnsignedLeb128(&handlers_data); 655 DecodeUnsignedLeb128(&handlers_data); 656 } 657 if (has_catch_all) { 658 DecodeUnsignedLeb128(&handlers_data); 659 } 660 continue; 661 } 662 TypeAddrPairVector* addr_pairs = new TypeAddrPairVector(); 663 for (int32_t i = 0; i < size; i++) { 664 const TypeId* type_id = GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data)); 665 uint32_t addr = DecodeUnsignedLeb128(&handlers_data); 666 addr_pairs->push_back( 667 std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr))); 668 } 669 if (has_catch_all) { 670 uint32_t addr = DecodeUnsignedLeb128(&handlers_data); 671 addr_pairs->push_back( 672 std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr))); 673 } 674 const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs); 675 handler_list->push_back(std::unique_ptr<const CatchHandler>(handler)); 676 } 677 } 678 679 uint32_t size = dex_file.GetCodeItemSize(*disk_code_item); 680 CodeItem* code_item = new CodeItem(accessor.RegistersSize(), 681 accessor.InsSize(), 682 accessor.OutsSize(), 683 debug_info, 684 insns_size, 685 insns, 686 tries, 687 handler_list); 688 code_item->SetSize(size); 689 690 // Add the code item to the map. 691 DCHECK(!code_item->OffsetAssigned()); 692 if (eagerly_assign_offsets_) { 693 code_item->SetOffset(offset); 694 } 695 code_items_map_.emplace(offsets_pair, code_item); 696 code_items_.AddItem(code_item); 697 698 // Add "fixup" references to types, strings, methods, and fields. 699 // This is temporary, as we will probably want more detailed parsing of the 700 // instructions here. 701 std::vector<TypeId*> type_ids; 702 std::vector<StringId*> string_ids; 703 std::vector<MethodId*> method_ids; 704 std::vector<FieldId*> field_ids; 705 if (GetIdsFromByteCode(*this, 706 code_item, 707 /*out*/ &type_ids, 708 /*out*/ &string_ids, 709 /*out*/ &method_ids, 710 /*out*/ &field_ids)) { 711 CodeFixups* fixups = new CodeFixups(std::move(type_ids), 712 std::move(string_ids), 713 std::move(method_ids), 714 std::move(field_ids)); 715 code_item->SetCodeFixups(fixups); 716 } 717 718 return code_item; 719 } 720 721 MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) { 722 MethodId* method_id = GetMethodId(cdii.GetMemberIndex()); 723 uint32_t access_flags = cdii.GetRawMemberAccessFlags(); 724 const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem(); 725 // Temporary hack to prevent incorrectly deduping code items if they have the same offset since 726 // they may have different debug info streams. 727 CodeItem* code_item = DedupeOrCreateCodeItem(dex_file, 728 disk_code_item, 729 cdii.GetMethodCodeItemOffset(), 730 cdii.GetMemberIndex()); 731 return new MethodItem(access_flags, method_id, code_item); 732 } 733 734 ClassData* Collections::CreateClassData( 735 const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) { 736 // Read the fields and methods defined by the class, resolving the circular reference from those 737 // to classes by setting class at the same time. 738 ClassData* class_data = class_datas_map_.GetExistingObject(offset); 739 if (class_data == nullptr && encoded_data != nullptr) { 740 ClassDataItemIterator cdii(dex_file, encoded_data); 741 // Static fields. 742 FieldItemVector* static_fields = new FieldItemVector(); 743 for (; cdii.HasNextStaticField(); cdii.Next()) { 744 FieldId* field_item = GetFieldId(cdii.GetMemberIndex()); 745 uint32_t access_flags = cdii.GetRawMemberAccessFlags(); 746 static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item))); 747 } 748 // Instance fields. 749 FieldItemVector* instance_fields = new FieldItemVector(); 750 for (; cdii.HasNextInstanceField(); cdii.Next()) { 751 FieldId* field_item = GetFieldId(cdii.GetMemberIndex()); 752 uint32_t access_flags = cdii.GetRawMemberAccessFlags(); 753 instance_fields->push_back( 754 std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item))); 755 } 756 // Direct methods. 757 MethodItemVector* direct_methods = new MethodItemVector(); 758 for (; cdii.HasNextDirectMethod(); cdii.Next()) { 759 direct_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii))); 760 } 761 // Virtual methods. 762 MethodItemVector* virtual_methods = new MethodItemVector(); 763 for (; cdii.HasNextVirtualMethod(); cdii.Next()) { 764 virtual_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii))); 765 } 766 class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods); 767 class_data->SetSize(cdii.EndDataPointer() - encoded_data); 768 AddItem(class_datas_map_, class_datas_, class_data, offset); 769 } 770 return class_data; 771 } 772 773 void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) { 774 // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems. 775 const DexFile::MapList* map = dex_file.GetMapList(); 776 for (uint32_t i = 0; i < map->size_; ++i) { 777 const DexFile::MapItem* item = map->list_ + i; 778 switch (item->type_) { 779 case DexFile::kDexTypeCallSiteIdItem: 780 SetCallSiteIdsOffset(item->offset_); 781 break; 782 case DexFile::kDexTypeMethodHandleItem: 783 SetMethodHandleItemsOffset(item->offset_); 784 break; 785 default: 786 break; 787 } 788 } 789 // Populate MethodHandleItems first (CallSiteIds may depend on them). 790 for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) { 791 CreateMethodHandleItem(dex_file, i); 792 } 793 // Populate CallSiteIds. 794 for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) { 795 CreateCallSiteId(dex_file, i); 796 } 797 } 798 799 void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) { 800 const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i); 801 const uint8_t* disk_call_item_ptr = dex_file.DataBegin() + disk_call_site_id.data_off_; 802 EncodedArrayItem* call_site_item = 803 CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_); 804 805 CallSiteId* call_site_id = new CallSiteId(call_site_item); 806 AddIndexedItem(call_site_ids_, call_site_id, CallSiteIdsOffset() + i * CallSiteId::ItemSize(), i); 807 } 808 809 void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) { 810 const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i); 811 uint16_t index = disk_method_handle.field_or_method_idx_; 812 DexFile::MethodHandleType type = 813 static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_); 814 bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic || 815 type == DexFile::MethodHandleType::kInvokeInstance || 816 type == DexFile::MethodHandleType::kInvokeConstructor || 817 type == DexFile::MethodHandleType::kInvokeDirect || 818 type == DexFile::MethodHandleType::kInvokeInterface; 819 static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeInterface, 820 "Unexpected method handle types."); 821 IndexedItem* field_or_method_id; 822 if (is_invoke) { 823 field_or_method_id = GetMethodId(index); 824 } else { 825 field_or_method_id = GetFieldId(index); 826 } 827 MethodHandleItem* method_handle = new MethodHandleItem(type, field_or_method_id); 828 AddIndexedItem(method_handle_items_, 829 method_handle, 830 MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(), 831 i); 832 } 833 834 void Collections::SortVectorsByMapOrder() { 835 string_datas_.SortByMapOrder(string_datas_map_.Collection()); 836 type_lists_.SortByMapOrder(type_lists_map_.Collection()); 837 encoded_array_items_.SortByMapOrder(encoded_array_items_map_.Collection()); 838 annotation_items_.SortByMapOrder(annotation_items_map_.Collection()); 839 annotation_set_items_.SortByMapOrder(annotation_set_items_map_.Collection()); 840 annotation_set_ref_lists_.SortByMapOrder(annotation_set_ref_lists_map_.Collection()); 841 annotations_directory_items_.SortByMapOrder(annotations_directory_items_map_.Collection()); 842 debug_info_items_.SortByMapOrder(debug_info_items_map_.Collection()); 843 code_items_.SortByMapOrder(code_items_map_); 844 class_datas_.SortByMapOrder(class_datas_map_.Collection()); 845 } 846 847 static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) { 848 return 0; 849 } 850 851 static uint32_t HeaderSize(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) { 852 // Size is in elements, so there is only one header. 853 return 1; 854 } 855 856 // The description of each dex file section type. 857 struct FileSectionDescriptor { 858 public: 859 std::string name; 860 uint16_t type; 861 // A function that when applied to a collection object, gives the size of the section. 862 std::function<uint32_t(const dex_ir::Collections&)> size_fn; 863 // A function that when applied to a collection object, gives the offset of the section. 864 std::function<uint32_t(const dex_ir::Collections&)> offset_fn; 865 }; 866 867 static const FileSectionDescriptor kFileSectionDescriptors[] = { 868 { 869 "Header", 870 DexFile::kDexTypeHeaderItem, 871 &HeaderSize, 872 &HeaderOffset, 873 }, { 874 "StringId", 875 DexFile::kDexTypeStringIdItem, 876 &dex_ir::Collections::StringIdsSize, 877 &dex_ir::Collections::StringIdsOffset 878 }, { 879 "TypeId", 880 DexFile::kDexTypeTypeIdItem, 881 &dex_ir::Collections::TypeIdsSize, 882 &dex_ir::Collections::TypeIdsOffset 883 }, { 884 "ProtoId", 885 DexFile::kDexTypeProtoIdItem, 886 &dex_ir::Collections::ProtoIdsSize, 887 &dex_ir::Collections::ProtoIdsOffset 888 }, { 889 "FieldId", 890 DexFile::kDexTypeFieldIdItem, 891 &dex_ir::Collections::FieldIdsSize, 892 &dex_ir::Collections::FieldIdsOffset 893 }, { 894 "MethodId", 895 DexFile::kDexTypeMethodIdItem, 896 &dex_ir::Collections::MethodIdsSize, 897 &dex_ir::Collections::MethodIdsOffset 898 }, { 899 "ClassDef", 900 DexFile::kDexTypeClassDefItem, 901 &dex_ir::Collections::ClassDefsSize, 902 &dex_ir::Collections::ClassDefsOffset 903 }, { 904 "CallSiteId", 905 DexFile::kDexTypeCallSiteIdItem, 906 &dex_ir::Collections::CallSiteIdsSize, 907 &dex_ir::Collections::CallSiteIdsOffset 908 }, { 909 "MethodHandle", 910 DexFile::kDexTypeMethodHandleItem, 911 &dex_ir::Collections::MethodHandleItemsSize, 912 &dex_ir::Collections::MethodHandleItemsOffset 913 }, { 914 "StringData", 915 DexFile::kDexTypeStringDataItem, 916 &dex_ir::Collections::StringDatasSize, 917 &dex_ir::Collections::StringDatasOffset 918 }, { 919 "TypeList", 920 DexFile::kDexTypeTypeList, 921 &dex_ir::Collections::TypeListsSize, 922 &dex_ir::Collections::TypeListsOffset 923 }, { 924 "EncArr", 925 DexFile::kDexTypeEncodedArrayItem, 926 &dex_ir::Collections::EncodedArrayItemsSize, 927 &dex_ir::Collections::EncodedArrayItemsOffset 928 }, { 929 "Annotation", 930 DexFile::kDexTypeAnnotationItem, 931 &dex_ir::Collections::AnnotationItemsSize, 932 &dex_ir::Collections::AnnotationItemsOffset 933 }, { 934 "AnnoSet", 935 DexFile::kDexTypeAnnotationSetItem, 936 &dex_ir::Collections::AnnotationSetItemsSize, 937 &dex_ir::Collections::AnnotationSetItemsOffset 938 }, { 939 "AnnoSetRL", 940 DexFile::kDexTypeAnnotationSetRefList, 941 &dex_ir::Collections::AnnotationSetRefListsSize, 942 &dex_ir::Collections::AnnotationSetRefListsOffset 943 }, { 944 "AnnoDir", 945 DexFile::kDexTypeAnnotationsDirectoryItem, 946 &dex_ir::Collections::AnnotationsDirectoryItemsSize, 947 &dex_ir::Collections::AnnotationsDirectoryItemsOffset 948 }, { 949 "DebugInfo", 950 DexFile::kDexTypeDebugInfoItem, 951 &dex_ir::Collections::DebugInfoItemsSize, 952 &dex_ir::Collections::DebugInfoItemsOffset 953 }, { 954 "CodeItem", 955 DexFile::kDexTypeCodeItem, 956 &dex_ir::Collections::CodeItemsSize, 957 &dex_ir::Collections::CodeItemsOffset 958 }, { 959 "ClassData", 960 DexFile::kDexTypeClassDataItem, 961 &dex_ir::Collections::ClassDatasSize, 962 &dex_ir::Collections::ClassDatasOffset 963 } 964 }; 965 966 std::vector<dex_ir::DexFileSection> GetSortedDexFileSections(dex_ir::Header* header, 967 dex_ir::SortDirection direction) { 968 const dex_ir::Collections& collections = header->GetCollections(); 969 std::vector<dex_ir::DexFileSection> sorted_sections; 970 // Build the table that will map from offset to color 971 for (const FileSectionDescriptor& s : kFileSectionDescriptors) { 972 sorted_sections.push_back(dex_ir::DexFileSection(s.name, 973 s.type, 974 s.size_fn(collections), 975 s.offset_fn(collections))); 976 } 977 // Sort by offset. 978 std::sort(sorted_sections.begin(), 979 sorted_sections.end(), 980 [=](dex_ir::DexFileSection& a, dex_ir::DexFileSection& b) { 981 if (direction == SortDirection::kSortDescending) { 982 return a.offset > b.offset; 983 } else { 984 return a.offset < b.offset; 985 } 986 }); 987 return sorted_sections; 988 } 989 990 } // namespace dex_ir 991 } // namespace art 992