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 * Header file of an in-memory representation of DEX files. 17 */ 18 19 #include <stdint.h> 20 21 #include <queue> 22 #include <vector> 23 24 #include "dex_writer.h" 25 #include "utf.h" 26 27 namespace art { 28 29 size_t EncodeIntValue(int32_t value, uint8_t* buffer) { 30 size_t length = 0; 31 if (value >= 0) { 32 while (value > 0x7f) { 33 buffer[length++] = static_cast<uint8_t>(value); 34 value >>= 8; 35 } 36 } else { 37 while (value < -0x80) { 38 buffer[length++] = static_cast<uint8_t>(value); 39 value >>= 8; 40 } 41 } 42 buffer[length++] = static_cast<uint8_t>(value); 43 return length; 44 } 45 46 size_t EncodeUIntValue(uint32_t value, uint8_t* buffer) { 47 size_t length = 0; 48 do { 49 buffer[length++] = static_cast<uint8_t>(value); 50 value >>= 8; 51 } while (value != 0); 52 return length; 53 } 54 55 size_t EncodeLongValue(int64_t value, uint8_t* buffer) { 56 size_t length = 0; 57 if (value >= 0) { 58 while (value > 0x7f) { 59 buffer[length++] = static_cast<uint8_t>(value); 60 value >>= 8; 61 } 62 } else { 63 while (value < -0x80) { 64 buffer[length++] = static_cast<uint8_t>(value); 65 value >>= 8; 66 } 67 } 68 buffer[length++] = static_cast<uint8_t>(value); 69 return length; 70 } 71 72 union FloatUnion { 73 float f_; 74 uint32_t i_; 75 }; 76 77 size_t EncodeFloatValue(float value, uint8_t* buffer) { 78 FloatUnion float_union; 79 float_union.f_ = value; 80 uint32_t int_value = float_union.i_; 81 size_t index = 3; 82 do { 83 buffer[index--] = int_value >> 24; 84 int_value <<= 8; 85 } while (int_value != 0); 86 return 3 - index; 87 } 88 89 union DoubleUnion { 90 double d_; 91 uint64_t l_; 92 }; 93 94 size_t EncodeDoubleValue(double value, uint8_t* buffer) { 95 DoubleUnion double_union; 96 double_union.d_ = value; 97 uint64_t long_value = double_union.l_; 98 size_t index = 7; 99 do { 100 buffer[index--] = long_value >> 56; 101 long_value <<= 8; 102 } while (long_value != 0); 103 return 7 - index; 104 } 105 106 size_t DexWriter::Write(const void* buffer, size_t length, size_t offset) { 107 DCHECK_LE(offset + length, mem_map_->Size()); 108 memcpy(mem_map_->Begin() + offset, buffer, length); 109 return length; 110 } 111 112 size_t DexWriter::WriteSleb128(uint32_t value, size_t offset) { 113 uint8_t buffer[8]; 114 EncodeSignedLeb128(buffer, value); 115 return Write(buffer, SignedLeb128Size(value), offset); 116 } 117 118 size_t DexWriter::WriteUleb128(uint32_t value, size_t offset) { 119 uint8_t buffer[8]; 120 EncodeUnsignedLeb128(buffer, value); 121 return Write(buffer, UnsignedLeb128Size(value), offset); 122 } 123 124 size_t DexWriter::WriteEncodedValue(dex_ir::EncodedValue* encoded_value, size_t offset) { 125 size_t original_offset = offset; 126 size_t start = 0; 127 size_t length; 128 uint8_t buffer[8]; 129 int8_t type = encoded_value->Type(); 130 switch (type) { 131 case DexFile::kDexAnnotationByte: 132 length = EncodeIntValue(encoded_value->GetByte(), buffer); 133 break; 134 case DexFile::kDexAnnotationShort: 135 length = EncodeIntValue(encoded_value->GetShort(), buffer); 136 break; 137 case DexFile::kDexAnnotationChar: 138 length = EncodeUIntValue(encoded_value->GetChar(), buffer); 139 break; 140 case DexFile::kDexAnnotationInt: 141 length = EncodeIntValue(encoded_value->GetInt(), buffer); 142 break; 143 case DexFile::kDexAnnotationLong: 144 length = EncodeLongValue(encoded_value->GetLong(), buffer); 145 break; 146 case DexFile::kDexAnnotationFloat: 147 length = EncodeFloatValue(encoded_value->GetFloat(), buffer); 148 start = 4 - length; 149 break; 150 case DexFile::kDexAnnotationDouble: 151 length = EncodeDoubleValue(encoded_value->GetDouble(), buffer); 152 start = 8 - length; 153 break; 154 case DexFile::kDexAnnotationMethodType: 155 length = EncodeUIntValue(encoded_value->GetProtoId()->GetIndex(), buffer); 156 break; 157 case DexFile::kDexAnnotationMethodHandle: 158 length = EncodeUIntValue(encoded_value->GetMethodHandle()->GetIndex(), buffer); 159 break; 160 case DexFile::kDexAnnotationString: 161 length = EncodeUIntValue(encoded_value->GetStringId()->GetIndex(), buffer); 162 break; 163 case DexFile::kDexAnnotationType: 164 length = EncodeUIntValue(encoded_value->GetTypeId()->GetIndex(), buffer); 165 break; 166 case DexFile::kDexAnnotationField: 167 case DexFile::kDexAnnotationEnum: 168 length = EncodeUIntValue(encoded_value->GetFieldId()->GetIndex(), buffer); 169 break; 170 case DexFile::kDexAnnotationMethod: 171 length = EncodeUIntValue(encoded_value->GetMethodId()->GetIndex(), buffer); 172 break; 173 case DexFile::kDexAnnotationArray: 174 offset += WriteEncodedValueHeader(type, 0, offset); 175 offset += WriteEncodedArray(encoded_value->GetEncodedArray()->GetEncodedValues(), offset); 176 return offset - original_offset; 177 case DexFile::kDexAnnotationAnnotation: 178 offset += WriteEncodedValueHeader(type, 0, offset); 179 offset += WriteEncodedAnnotation(encoded_value->GetEncodedAnnotation(), offset); 180 return offset - original_offset; 181 case DexFile::kDexAnnotationNull: 182 return WriteEncodedValueHeader(type, 0, offset); 183 case DexFile::kDexAnnotationBoolean: 184 return WriteEncodedValueHeader(type, encoded_value->GetBoolean() ? 1 : 0, offset); 185 default: 186 return 0; 187 } 188 offset += WriteEncodedValueHeader(type, length - 1, offset); 189 offset += Write(buffer + start, length, offset); 190 return offset - original_offset; 191 } 192 193 size_t DexWriter::WriteEncodedValueHeader(int8_t value_type, size_t value_arg, size_t offset) { 194 uint8_t buffer[1] = { static_cast<uint8_t>((value_arg << 5) | value_type) }; 195 return Write(buffer, sizeof(uint8_t), offset); 196 } 197 198 size_t DexWriter::WriteEncodedArray(dex_ir::EncodedValueVector* values, size_t offset) { 199 size_t original_offset = offset; 200 offset += WriteUleb128(values->size(), offset); 201 for (std::unique_ptr<dex_ir::EncodedValue>& value : *values) { 202 offset += WriteEncodedValue(value.get(), offset); 203 } 204 return offset - original_offset; 205 } 206 207 size_t DexWriter::WriteEncodedAnnotation(dex_ir::EncodedAnnotation* annotation, size_t offset) { 208 size_t original_offset = offset; 209 offset += WriteUleb128(annotation->GetType()->GetIndex(), offset); 210 offset += WriteUleb128(annotation->GetAnnotationElements()->size(), offset); 211 for (std::unique_ptr<dex_ir::AnnotationElement>& annotation_element : 212 *annotation->GetAnnotationElements()) { 213 offset += WriteUleb128(annotation_element->GetName()->GetIndex(), offset); 214 offset += WriteEncodedValue(annotation_element->GetValue(), offset); 215 } 216 return offset - original_offset; 217 } 218 219 size_t DexWriter::WriteEncodedFields(dex_ir::FieldItemVector* fields, size_t offset) { 220 size_t original_offset = offset; 221 uint32_t prev_index = 0; 222 for (std::unique_ptr<dex_ir::FieldItem>& field : *fields) { 223 uint32_t index = field->GetFieldId()->GetIndex(); 224 offset += WriteUleb128(index - prev_index, offset); 225 offset += WriteUleb128(field->GetAccessFlags(), offset); 226 prev_index = index; 227 } 228 return offset - original_offset; 229 } 230 231 size_t DexWriter::WriteEncodedMethods(dex_ir::MethodItemVector* methods, size_t offset) { 232 size_t original_offset = offset; 233 uint32_t prev_index = 0; 234 for (std::unique_ptr<dex_ir::MethodItem>& method : *methods) { 235 uint32_t index = method->GetMethodId()->GetIndex(); 236 uint32_t code_off = method->GetCodeItem() == nullptr ? 0 : method->GetCodeItem()->GetOffset(); 237 offset += WriteUleb128(index - prev_index, offset); 238 offset += WriteUleb128(method->GetAccessFlags(), offset); 239 offset += WriteUleb128(code_off, offset); 240 prev_index = index; 241 } 242 return offset - original_offset; 243 } 244 245 void DexWriter::WriteStrings() { 246 uint32_t string_data_off[1]; 247 for (std::unique_ptr<dex_ir::StringId>& string_id : header_->GetCollections().StringIds()) { 248 string_data_off[0] = string_id->DataItem()->GetOffset(); 249 Write(string_data_off, string_id->GetSize(), string_id->GetOffset()); 250 } 251 252 for (auto& string_data_pair : header_->GetCollections().StringDatas()) { 253 std::unique_ptr<dex_ir::StringData>& string_data = string_data_pair.second; 254 uint32_t offset = string_data->GetOffset(); 255 offset += WriteUleb128(CountModifiedUtf8Chars(string_data->Data()), offset); 256 Write(string_data->Data(), strlen(string_data->Data()), offset); 257 } 258 } 259 260 void DexWriter::WriteTypes() { 261 uint32_t descriptor_idx[1]; 262 for (std::unique_ptr<dex_ir::TypeId>& type_id : header_->GetCollections().TypeIds()) { 263 descriptor_idx[0] = type_id->GetStringId()->GetIndex(); 264 Write(descriptor_idx, type_id->GetSize(), type_id->GetOffset()); 265 } 266 } 267 268 void DexWriter::WriteTypeLists() { 269 uint32_t size[1]; 270 uint16_t list[1]; 271 for (auto& type_list_pair : header_->GetCollections().TypeLists()) { 272 std::unique_ptr<dex_ir::TypeList>& type_list = type_list_pair.second; 273 size[0] = type_list->GetTypeList()->size(); 274 uint32_t offset = type_list->GetOffset(); 275 offset += Write(size, sizeof(uint32_t), offset); 276 for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) { 277 list[0] = type_id->GetIndex(); 278 offset += Write(list, sizeof(uint16_t), offset); 279 } 280 } 281 } 282 283 void DexWriter::WriteProtos() { 284 uint32_t buffer[3]; 285 for (std::unique_ptr<dex_ir::ProtoId>& proto_id : header_->GetCollections().ProtoIds()) { 286 buffer[0] = proto_id->Shorty()->GetIndex(); 287 buffer[1] = proto_id->ReturnType()->GetIndex(); 288 buffer[2] = proto_id->Parameters() == nullptr ? 0 : proto_id->Parameters()->GetOffset(); 289 Write(buffer, proto_id->GetSize(), proto_id->GetOffset()); 290 } 291 } 292 293 void DexWriter::WriteFields() { 294 uint16_t buffer[4]; 295 for (std::unique_ptr<dex_ir::FieldId>& field_id : header_->GetCollections().FieldIds()) { 296 buffer[0] = field_id->Class()->GetIndex(); 297 buffer[1] = field_id->Type()->GetIndex(); 298 buffer[2] = field_id->Name()->GetIndex(); 299 buffer[3] = field_id->Name()->GetIndex() >> 16; 300 Write(buffer, field_id->GetSize(), field_id->GetOffset()); 301 } 302 } 303 304 void DexWriter::WriteMethods() { 305 uint16_t buffer[4]; 306 for (std::unique_ptr<dex_ir::MethodId>& method_id : header_->GetCollections().MethodIds()) { 307 buffer[0] = method_id->Class()->GetIndex(); 308 buffer[1] = method_id->Proto()->GetIndex(); 309 buffer[2] = method_id->Name()->GetIndex(); 310 buffer[3] = method_id->Name()->GetIndex() >> 16; 311 Write(buffer, method_id->GetSize(), method_id->GetOffset()); 312 } 313 } 314 315 void DexWriter::WriteEncodedArrays() { 316 for (auto& encoded_array_pair : header_->GetCollections().EncodedArrayItems()) { 317 std::unique_ptr<dex_ir::EncodedArrayItem>& encoded_array = encoded_array_pair.second; 318 WriteEncodedArray(encoded_array->GetEncodedValues(), encoded_array->GetOffset()); 319 } 320 } 321 322 void DexWriter::WriteAnnotations() { 323 uint8_t visibility[1]; 324 for (auto& annotation_pair : header_->GetCollections().AnnotationItems()) { 325 std::unique_ptr<dex_ir::AnnotationItem>& annotation = annotation_pair.second; 326 visibility[0] = annotation->GetVisibility(); 327 size_t offset = annotation->GetOffset(); 328 offset += Write(visibility, sizeof(uint8_t), offset); 329 WriteEncodedAnnotation(annotation->GetAnnotation(), offset); 330 } 331 } 332 333 void DexWriter::WriteAnnotationSets() { 334 uint32_t size[1]; 335 uint32_t annotation_off[1]; 336 for (auto& annotation_set_pair : header_->GetCollections().AnnotationSetItems()) { 337 std::unique_ptr<dex_ir::AnnotationSetItem>& annotation_set = annotation_set_pair.second; 338 size[0] = annotation_set->GetItems()->size(); 339 size_t offset = annotation_set->GetOffset(); 340 offset += Write(size, sizeof(uint32_t), offset); 341 for (dex_ir::AnnotationItem* annotation : *annotation_set->GetItems()) { 342 annotation_off[0] = annotation->GetOffset(); 343 offset += Write(annotation_off, sizeof(uint32_t), offset); 344 } 345 } 346 } 347 348 void DexWriter::WriteAnnotationSetRefs() { 349 uint32_t size[1]; 350 uint32_t annotations_off[1]; 351 for (auto& anno_set_ref_pair : header_->GetCollections().AnnotationSetRefLists()) { 352 std::unique_ptr<dex_ir::AnnotationSetRefList>& annotation_set_ref = anno_set_ref_pair.second; 353 size[0] = annotation_set_ref->GetItems()->size(); 354 size_t offset = annotation_set_ref->GetOffset(); 355 offset += Write(size, sizeof(uint32_t), offset); 356 for (dex_ir::AnnotationSetItem* annotation_set : *annotation_set_ref->GetItems()) { 357 annotations_off[0] = annotation_set == nullptr ? 0 : annotation_set->GetOffset(); 358 offset += Write(annotations_off, sizeof(uint32_t), offset); 359 } 360 } 361 } 362 363 void DexWriter::WriteAnnotationsDirectories() { 364 uint32_t directory_buffer[4]; 365 uint32_t annotation_buffer[2]; 366 for (auto& annotations_directory_pair : header_->GetCollections().AnnotationsDirectoryItems()) { 367 std::unique_ptr<dex_ir::AnnotationsDirectoryItem>& annotations_directory = 368 annotations_directory_pair.second; 369 directory_buffer[0] = annotations_directory->GetClassAnnotation() == nullptr ? 0 : 370 annotations_directory->GetClassAnnotation()->GetOffset(); 371 directory_buffer[1] = annotations_directory->GetFieldAnnotations() == nullptr ? 0 : 372 annotations_directory->GetFieldAnnotations()->size(); 373 directory_buffer[2] = annotations_directory->GetMethodAnnotations() == nullptr ? 0 : 374 annotations_directory->GetMethodAnnotations()->size(); 375 directory_buffer[3] = annotations_directory->GetParameterAnnotations() == nullptr ? 0 : 376 annotations_directory->GetParameterAnnotations()->size(); 377 uint32_t offset = annotations_directory->GetOffset(); 378 offset += Write(directory_buffer, 4 * sizeof(uint32_t), offset); 379 if (annotations_directory->GetFieldAnnotations() != nullptr) { 380 for (std::unique_ptr<dex_ir::FieldAnnotation>& field : 381 *annotations_directory->GetFieldAnnotations()) { 382 annotation_buffer[0] = field->GetFieldId()->GetIndex(); 383 annotation_buffer[1] = field->GetAnnotationSetItem()->GetOffset(); 384 offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset); 385 } 386 } 387 if (annotations_directory->GetMethodAnnotations() != nullptr) { 388 for (std::unique_ptr<dex_ir::MethodAnnotation>& method : 389 *annotations_directory->GetMethodAnnotations()) { 390 annotation_buffer[0] = method->GetMethodId()->GetIndex(); 391 annotation_buffer[1] = method->GetAnnotationSetItem()->GetOffset(); 392 offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset); 393 } 394 } 395 if (annotations_directory->GetParameterAnnotations() != nullptr) { 396 for (std::unique_ptr<dex_ir::ParameterAnnotation>& parameter : 397 *annotations_directory->GetParameterAnnotations()) { 398 annotation_buffer[0] = parameter->GetMethodId()->GetIndex(); 399 annotation_buffer[1] = parameter->GetAnnotations()->GetOffset(); 400 offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset); 401 } 402 } 403 } 404 } 405 406 void DexWriter::WriteDebugInfoItems() { 407 for (auto& debug_info_pair : header_->GetCollections().DebugInfoItems()) { 408 std::unique_ptr<dex_ir::DebugInfoItem>& debug_info = debug_info_pair.second; 409 Write(debug_info->GetDebugInfo(), debug_info->GetDebugInfoSize(), debug_info->GetOffset()); 410 } 411 } 412 413 void DexWriter::WriteCodeItems() { 414 uint16_t uint16_buffer[4]; 415 uint32_t uint32_buffer[2]; 416 for (auto& code_item_pair : header_->GetCollections().CodeItems()) { 417 std::unique_ptr<dex_ir::CodeItem>& code_item = code_item_pair.second; 418 uint16_buffer[0] = code_item->RegistersSize(); 419 uint16_buffer[1] = code_item->InsSize(); 420 uint16_buffer[2] = code_item->OutsSize(); 421 uint16_buffer[3] = code_item->TriesSize(); 422 uint32_buffer[0] = code_item->DebugInfo() == nullptr ? 0 : code_item->DebugInfo()->GetOffset(); 423 uint32_buffer[1] = code_item->InsnsSize(); 424 size_t offset = code_item->GetOffset(); 425 offset += Write(uint16_buffer, 4 * sizeof(uint16_t), offset); 426 offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset); 427 offset += Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t), offset); 428 if (code_item->TriesSize() != 0) { 429 if (code_item->InsnsSize() % 2 != 0) { 430 uint16_t padding[1] = { 0 }; 431 offset += Write(padding, sizeof(uint16_t), offset); 432 } 433 uint32_t start_addr[1]; 434 uint16_t insn_count_and_handler_off[2]; 435 for (std::unique_ptr<const dex_ir::TryItem>& try_item : *code_item->Tries()) { 436 start_addr[0] = try_item->StartAddr(); 437 insn_count_and_handler_off[0] = try_item->InsnCount(); 438 insn_count_and_handler_off[1] = try_item->GetHandlers()->GetListOffset(); 439 offset += Write(start_addr, sizeof(uint32_t), offset); 440 offset += Write(insn_count_and_handler_off, 2 * sizeof(uint16_t), offset); 441 } 442 // Leave offset pointing to the end of the try items. 443 WriteUleb128(code_item->Handlers()->size(), offset); 444 for (std::unique_ptr<const dex_ir::CatchHandler>& handlers : *code_item->Handlers()) { 445 size_t list_offset = offset + handlers->GetListOffset(); 446 uint32_t size = handlers->HasCatchAll() ? (handlers->GetHandlers()->size() - 1) * -1 : 447 handlers->GetHandlers()->size(); 448 list_offset += WriteSleb128(size, list_offset); 449 for (std::unique_ptr<const dex_ir::TypeAddrPair>& handler : *handlers->GetHandlers()) { 450 if (handler->GetTypeId() != nullptr) { 451 list_offset += WriteUleb128(handler->GetTypeId()->GetIndex(), list_offset); 452 } 453 list_offset += WriteUleb128(handler->GetAddress(), list_offset); 454 } 455 } 456 } 457 } 458 } 459 460 void DexWriter::WriteClasses() { 461 uint32_t class_def_buffer[8]; 462 for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) { 463 class_def_buffer[0] = class_def->ClassType()->GetIndex(); 464 class_def_buffer[1] = class_def->GetAccessFlags(); 465 class_def_buffer[2] = class_def->Superclass() == nullptr ? DexFile::kDexNoIndex : 466 class_def->Superclass()->GetIndex(); 467 class_def_buffer[3] = class_def->InterfacesOffset(); 468 class_def_buffer[4] = class_def->SourceFile() == nullptr ? DexFile::kDexNoIndex : 469 class_def->SourceFile()->GetIndex(); 470 class_def_buffer[5] = class_def->Annotations() == nullptr ? 0 : 471 class_def->Annotations()->GetOffset(); 472 class_def_buffer[6] = class_def->GetClassData() == nullptr ? 0 : 473 class_def->GetClassData()->GetOffset(); 474 class_def_buffer[7] = class_def->StaticValues() == nullptr ? 0 : 475 class_def->StaticValues()->GetOffset(); 476 size_t offset = class_def->GetOffset(); 477 Write(class_def_buffer, class_def->GetSize(), offset); 478 } 479 480 for (auto& class_data_pair : header_->GetCollections().ClassDatas()) { 481 std::unique_ptr<dex_ir::ClassData>& class_data = class_data_pair.second; 482 size_t offset = class_data->GetOffset(); 483 offset += WriteUleb128(class_data->StaticFields()->size(), offset); 484 offset += WriteUleb128(class_data->InstanceFields()->size(), offset); 485 offset += WriteUleb128(class_data->DirectMethods()->size(), offset); 486 offset += WriteUleb128(class_data->VirtualMethods()->size(), offset); 487 offset += WriteEncodedFields(class_data->StaticFields(), offset); 488 offset += WriteEncodedFields(class_data->InstanceFields(), offset); 489 offset += WriteEncodedMethods(class_data->DirectMethods(), offset); 490 offset += WriteEncodedMethods(class_data->VirtualMethods(), offset); 491 } 492 } 493 494 void DexWriter::WriteCallSites() { 495 uint32_t call_site_off[1]; 496 for (std::unique_ptr<dex_ir::CallSiteId>& call_site_id : 497 header_->GetCollections().CallSiteIds()) { 498 call_site_off[0] = call_site_id->CallSiteItem()->GetOffset(); 499 Write(call_site_off, call_site_id->GetSize(), call_site_id->GetOffset()); 500 } 501 } 502 503 void DexWriter::WriteMethodHandles() { 504 uint16_t method_handle_buff[4]; 505 for (std::unique_ptr<dex_ir::MethodHandleItem>& method_handle : 506 header_->GetCollections().MethodHandleItems()) { 507 method_handle_buff[0] = static_cast<uint16_t>(method_handle->GetMethodHandleType()); 508 method_handle_buff[1] = 0; // unused. 509 method_handle_buff[2] = method_handle->GetFieldOrMethodId()->GetIndex(); 510 method_handle_buff[3] = 0; // unused. 511 Write(method_handle_buff, method_handle->GetSize(), method_handle->GetOffset()); 512 } 513 } 514 515 struct MapItemContainer { 516 MapItemContainer(uint32_t type, uint32_t size, uint32_t offset) 517 : type_(type), size_(size), offset_(offset) { } 518 519 bool operator<(const MapItemContainer& other) const { 520 return offset_ > other.offset_; 521 } 522 523 uint32_t type_; 524 uint32_t size_; 525 uint32_t offset_; 526 }; 527 528 void DexWriter::WriteMapItem() { 529 dex_ir::Collections& collection = header_->GetCollections(); 530 std::priority_queue<MapItemContainer> queue; 531 532 // Header and index section. 533 queue.push(MapItemContainer(DexFile::kDexTypeHeaderItem, 1, 0)); 534 if (collection.StringIdsSize() != 0) { 535 queue.push(MapItemContainer(DexFile::kDexTypeStringIdItem, collection.StringIdsSize(), 536 collection.StringIdsOffset())); 537 } 538 if (collection.TypeIdsSize() != 0) { 539 queue.push(MapItemContainer(DexFile::kDexTypeTypeIdItem, collection.TypeIdsSize(), 540 collection.TypeIdsOffset())); 541 } 542 if (collection.ProtoIdsSize() != 0) { 543 queue.push(MapItemContainer(DexFile::kDexTypeProtoIdItem, collection.ProtoIdsSize(), 544 collection.ProtoIdsOffset())); 545 } 546 if (collection.FieldIdsSize() != 0) { 547 queue.push(MapItemContainer(DexFile::kDexTypeFieldIdItem, collection.FieldIdsSize(), 548 collection.FieldIdsOffset())); 549 } 550 if (collection.MethodIdsSize() != 0) { 551 queue.push(MapItemContainer(DexFile::kDexTypeMethodIdItem, collection.MethodIdsSize(), 552 collection.MethodIdsOffset())); 553 } 554 if (collection.ClassDefsSize() != 0) { 555 queue.push(MapItemContainer(DexFile::kDexTypeClassDefItem, collection.ClassDefsSize(), 556 collection.ClassDefsOffset())); 557 } 558 if (collection.CallSiteIdsSize() != 0) { 559 queue.push(MapItemContainer(DexFile::kDexTypeCallSiteIdItem, collection.CallSiteIdsSize(), 560 collection.CallSiteIdsOffset())); 561 } 562 if (collection.MethodHandleItemsSize() != 0) { 563 queue.push(MapItemContainer(DexFile::kDexTypeMethodHandleItem, 564 collection.MethodHandleItemsSize(), collection.MethodHandleItemsOffset())); 565 } 566 567 // Data section. 568 queue.push(MapItemContainer(DexFile::kDexTypeMapList, 1, collection.MapListOffset())); 569 if (collection.TypeListsSize() != 0) { 570 queue.push(MapItemContainer(DexFile::kDexTypeTypeList, collection.TypeListsSize(), 571 collection.TypeListsOffset())); 572 } 573 if (collection.AnnotationSetRefListsSize() != 0) { 574 queue.push(MapItemContainer(DexFile::kDexTypeAnnotationSetRefList, 575 collection.AnnotationSetRefListsSize(), collection.AnnotationSetRefListsOffset())); 576 } 577 if (collection.AnnotationSetItemsSize() != 0) { 578 queue.push(MapItemContainer(DexFile::kDexTypeAnnotationSetItem, 579 collection.AnnotationSetItemsSize(), collection.AnnotationSetItemsOffset())); 580 } 581 if (collection.ClassDatasSize() != 0) { 582 queue.push(MapItemContainer(DexFile::kDexTypeClassDataItem, collection.ClassDatasSize(), 583 collection.ClassDatasOffset())); 584 } 585 if (collection.CodeItemsSize() != 0) { 586 queue.push(MapItemContainer(DexFile::kDexTypeCodeItem, collection.CodeItemsSize(), 587 collection.CodeItemsOffset())); 588 } 589 if (collection.StringDatasSize() != 0) { 590 queue.push(MapItemContainer(DexFile::kDexTypeStringDataItem, collection.StringDatasSize(), 591 collection.StringDatasOffset())); 592 } 593 if (collection.DebugInfoItemsSize() != 0) { 594 queue.push(MapItemContainer(DexFile::kDexTypeDebugInfoItem, collection.DebugInfoItemsSize(), 595 collection.DebugInfoItemsOffset())); 596 } 597 if (collection.AnnotationItemsSize() != 0) { 598 queue.push(MapItemContainer(DexFile::kDexTypeAnnotationItem, collection.AnnotationItemsSize(), 599 collection.AnnotationItemsOffset())); 600 } 601 if (collection.EncodedArrayItemsSize() != 0) { 602 queue.push(MapItemContainer(DexFile::kDexTypeEncodedArrayItem, 603 collection.EncodedArrayItemsSize(), collection.EncodedArrayItemsOffset())); 604 } 605 if (collection.AnnotationsDirectoryItemsSize() != 0) { 606 queue.push(MapItemContainer(DexFile::kDexTypeAnnotationsDirectoryItem, 607 collection.AnnotationsDirectoryItemsSize(), collection.AnnotationsDirectoryItemsOffset())); 608 } 609 610 uint32_t offset = collection.MapListOffset(); 611 uint16_t uint16_buffer[2]; 612 uint32_t uint32_buffer[2]; 613 uint16_buffer[1] = 0; 614 uint32_buffer[0] = queue.size(); 615 offset += Write(uint32_buffer, sizeof(uint32_t), offset); 616 while (!queue.empty()) { 617 const MapItemContainer& map_item = queue.top(); 618 uint16_buffer[0] = map_item.type_; 619 uint32_buffer[0] = map_item.size_; 620 uint32_buffer[1] = map_item.offset_; 621 offset += Write(uint16_buffer, 2 * sizeof(uint16_t), offset); 622 offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset); 623 queue.pop(); 624 } 625 } 626 627 void DexWriter::WriteHeader() { 628 uint32_t buffer[20]; 629 dex_ir::Collections& collections = header_->GetCollections(); 630 size_t offset = 0; 631 offset += Write(header_->Magic(), 8 * sizeof(uint8_t), offset); 632 buffer[0] = header_->Checksum(); 633 offset += Write(buffer, sizeof(uint32_t), offset); 634 offset += Write(header_->Signature(), 20 * sizeof(uint8_t), offset); 635 uint32_t file_size = header_->FileSize(); 636 buffer[0] = file_size; 637 buffer[1] = header_->GetSize(); 638 buffer[2] = header_->EndianTag(); 639 buffer[3] = header_->LinkSize(); 640 buffer[4] = header_->LinkOffset(); 641 buffer[5] = collections.MapListOffset(); 642 buffer[6] = collections.StringIdsSize(); 643 buffer[7] = collections.StringIdsOffset(); 644 buffer[8] = collections.TypeIdsSize(); 645 buffer[9] = collections.TypeIdsOffset(); 646 buffer[10] = collections.ProtoIdsSize(); 647 buffer[11] = collections.ProtoIdsOffset(); 648 buffer[12] = collections.FieldIdsSize(); 649 buffer[13] = collections.FieldIdsOffset(); 650 buffer[14] = collections.MethodIdsSize(); 651 buffer[15] = collections.MethodIdsOffset(); 652 uint32_t class_defs_size = collections.ClassDefsSize(); 653 uint32_t class_defs_off = collections.ClassDefsOffset(); 654 buffer[16] = class_defs_size; 655 buffer[17] = class_defs_off; 656 buffer[18] = header_->DataSize(); 657 buffer[19] = header_->DataOffset(); 658 Write(buffer, 20 * sizeof(uint32_t), offset); 659 } 660 661 void DexWriter::WriteMemMap() { 662 WriteStrings(); 663 WriteTypes(); 664 WriteTypeLists(); 665 WriteProtos(); 666 WriteFields(); 667 WriteMethods(); 668 WriteEncodedArrays(); 669 WriteAnnotations(); 670 WriteAnnotationSets(); 671 WriteAnnotationSetRefs(); 672 WriteAnnotationsDirectories(); 673 WriteDebugInfoItems(); 674 WriteCodeItems(); 675 WriteClasses(); 676 WriteCallSites(); 677 WriteMethodHandles(); 678 WriteMapItem(); 679 WriteHeader(); 680 } 681 682 void DexWriter::Output(dex_ir::Header* header, MemMap* mem_map) { 683 DexWriter dex_writer(header, mem_map); 684 dex_writer.WriteMemMap(); 685 } 686 687 } // namespace art 688