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