blob: 7ffa38bfd4afa5bfb0817c84564fd317ea65181c [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) {
Jeff Haoea7c6292016-11-14 18:10:16 -0800107 DCHECK_LE(offset + length, mem_map_->Size());
108 memcpy(mem_map_->Begin() + offset, buffer, length);
109 return length;
Jeff Haoa8621002016-10-04 18:13:44 +0000110}
111
112size_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
118size_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
124size_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::kDexAnnotationString:
155 length = EncodeUIntValue(encoded_value->GetStringId()->GetIndex(), buffer);
156 break;
157 case DexFile::kDexAnnotationType:
158 length = EncodeUIntValue(encoded_value->GetTypeId()->GetIndex(), buffer);
159 break;
160 case DexFile::kDexAnnotationField:
161 case DexFile::kDexAnnotationEnum:
162 length = EncodeUIntValue(encoded_value->GetFieldId()->GetIndex(), buffer);
163 break;
164 case DexFile::kDexAnnotationMethod:
165 length = EncodeUIntValue(encoded_value->GetMethodId()->GetIndex(), buffer);
166 break;
167 case DexFile::kDexAnnotationArray:
168 offset += WriteEncodedValueHeader(type, 0, offset);
169 offset += WriteEncodedArray(encoded_value->GetEncodedArray()->GetEncodedValues(), offset);
170 return offset - original_offset;
171 case DexFile::kDexAnnotationAnnotation:
172 offset += WriteEncodedValueHeader(type, 0, offset);
173 offset += WriteEncodedAnnotation(encoded_value->GetEncodedAnnotation(), offset);
174 return offset - original_offset;
175 case DexFile::kDexAnnotationNull:
176 return WriteEncodedValueHeader(type, 0, offset);
177 case DexFile::kDexAnnotationBoolean:
178 return WriteEncodedValueHeader(type, encoded_value->GetBoolean() ? 1 : 0, offset);
179 default:
180 return 0;
181 }
182 offset += WriteEncodedValueHeader(type, length - 1, offset);
183 offset += Write(buffer + start, length, offset);
184 return offset - original_offset;
185}
186
187size_t DexWriter::WriteEncodedValueHeader(int8_t value_type, size_t value_arg, size_t offset) {
188 uint8_t buffer[1] = { static_cast<uint8_t>((value_arg << 5) | value_type) };
189 return Write(buffer, sizeof(uint8_t), offset);
190}
191
192size_t DexWriter::WriteEncodedArray(dex_ir::EncodedValueVector* values, size_t offset) {
193 size_t original_offset = offset;
194 offset += WriteUleb128(values->size(), offset);
195 for (std::unique_ptr<dex_ir::EncodedValue>& value : *values) {
196 offset += WriteEncodedValue(value.get(), offset);
197 }
198 return offset - original_offset;
199}
200
201size_t DexWriter::WriteEncodedAnnotation(dex_ir::EncodedAnnotation* annotation, size_t offset) {
202 size_t original_offset = offset;
203 offset += WriteUleb128(annotation->GetType()->GetIndex(), offset);
204 offset += WriteUleb128(annotation->GetAnnotationElements()->size(), offset);
205 for (std::unique_ptr<dex_ir::AnnotationElement>& annotation_element :
206 *annotation->GetAnnotationElements()) {
207 offset += WriteUleb128(annotation_element->GetName()->GetIndex(), offset);
208 offset += WriteEncodedValue(annotation_element->GetValue(), offset);
209 }
210 return offset - original_offset;
211}
212
213size_t DexWriter::WriteEncodedFields(dex_ir::FieldItemVector* fields, size_t offset) {
214 size_t original_offset = offset;
215 uint32_t prev_index = 0;
216 for (std::unique_ptr<dex_ir::FieldItem>& field : *fields) {
217 uint32_t index = field->GetFieldId()->GetIndex();
218 offset += WriteUleb128(index - prev_index, offset);
219 offset += WriteUleb128(field->GetAccessFlags(), offset);
220 prev_index = index;
221 }
222 return offset - original_offset;
223}
224
225size_t DexWriter::WriteEncodedMethods(dex_ir::MethodItemVector* methods, size_t offset) {
226 size_t original_offset = offset;
227 uint32_t prev_index = 0;
228 for (std::unique_ptr<dex_ir::MethodItem>& method : *methods) {
229 uint32_t index = method->GetMethodId()->GetIndex();
230 uint32_t code_off = method->GetCodeItem() == nullptr ? 0 : method->GetCodeItem()->GetOffset();
231 offset += WriteUleb128(index - prev_index, offset);
232 offset += WriteUleb128(method->GetAccessFlags(), offset);
233 offset += WriteUleb128(code_off, offset);
234 prev_index = index;
235 }
236 return offset - original_offset;
237}
238
239void DexWriter::WriteStrings() {
240 uint32_t string_data_off[1];
Jeff Haoea7c6292016-11-14 18:10:16 -0800241 for (std::unique_ptr<dex_ir::StringId>& string_id : header_->GetCollections().StringIds()) {
Jeff Haoa8621002016-10-04 18:13:44 +0000242 string_data_off[0] = string_id->DataItem()->GetOffset();
243 Write(string_data_off, string_id->GetSize(), string_id->GetOffset());
244 }
245
Jeff Haoea7c6292016-11-14 18:10:16 -0800246 for (auto& string_data_pair : header_->GetCollections().StringDatas()) {
247 std::unique_ptr<dex_ir::StringData>& string_data = string_data_pair.second;
Jeff Haoa8621002016-10-04 18:13:44 +0000248 uint32_t offset = string_data->GetOffset();
249 offset += WriteUleb128(CountModifiedUtf8Chars(string_data->Data()), offset);
250 Write(string_data->Data(), strlen(string_data->Data()), offset);
251 }
252}
253
254void DexWriter::WriteTypes() {
255 uint32_t descriptor_idx[1];
Jeff Haoea7c6292016-11-14 18:10:16 -0800256 for (std::unique_ptr<dex_ir::TypeId>& type_id : header_->GetCollections().TypeIds()) {
Jeff Haoa8621002016-10-04 18:13:44 +0000257 descriptor_idx[0] = type_id->GetStringId()->GetIndex();
258 Write(descriptor_idx, type_id->GetSize(), type_id->GetOffset());
259 }
260}
261
262void DexWriter::WriteTypeLists() {
263 uint32_t size[1];
264 uint16_t list[1];
Jeff Haoea7c6292016-11-14 18:10:16 -0800265 for (auto& type_list_pair : header_->GetCollections().TypeLists()) {
266 std::unique_ptr<dex_ir::TypeList>& type_list = type_list_pair.second;
Jeff Haoa8621002016-10-04 18:13:44 +0000267 size[0] = type_list->GetTypeList()->size();
268 uint32_t offset = type_list->GetOffset();
269 offset += Write(size, sizeof(uint32_t), offset);
270 for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) {
271 list[0] = type_id->GetIndex();
272 offset += Write(list, sizeof(uint16_t), offset);
273 }
274 }
275}
276
277void DexWriter::WriteProtos() {
278 uint32_t buffer[3];
Jeff Haoea7c6292016-11-14 18:10:16 -0800279 for (std::unique_ptr<dex_ir::ProtoId>& proto_id : header_->GetCollections().ProtoIds()) {
Jeff Haoa8621002016-10-04 18:13:44 +0000280 buffer[0] = proto_id->Shorty()->GetIndex();
281 buffer[1] = proto_id->ReturnType()->GetIndex();
282 buffer[2] = proto_id->Parameters() == nullptr ? 0 : proto_id->Parameters()->GetOffset();
283 Write(buffer, proto_id->GetSize(), proto_id->GetOffset());
284 }
285}
286
287void DexWriter::WriteFields() {
288 uint16_t buffer[4];
Jeff Haoea7c6292016-11-14 18:10:16 -0800289 for (std::unique_ptr<dex_ir::FieldId>& field_id : header_->GetCollections().FieldIds()) {
Jeff Haoa8621002016-10-04 18:13:44 +0000290 buffer[0] = field_id->Class()->GetIndex();
291 buffer[1] = field_id->Type()->GetIndex();
292 buffer[2] = field_id->Name()->GetIndex();
293 buffer[3] = field_id->Name()->GetIndex() >> 16;
294 Write(buffer, field_id->GetSize(), field_id->GetOffset());
295 }
296}
297
298void DexWriter::WriteMethods() {
299 uint16_t buffer[4];
Jeff Haoea7c6292016-11-14 18:10:16 -0800300 for (std::unique_ptr<dex_ir::MethodId>& method_id : header_->GetCollections().MethodIds()) {
Jeff Haoa8621002016-10-04 18:13:44 +0000301 buffer[0] = method_id->Class()->GetIndex();
302 buffer[1] = method_id->Proto()->GetIndex();
303 buffer[2] = method_id->Name()->GetIndex();
304 buffer[3] = method_id->Name()->GetIndex() >> 16;
305 Write(buffer, method_id->GetSize(), method_id->GetOffset());
306 }
307}
308
309void DexWriter::WriteEncodedArrays() {
Jeff Haoea7c6292016-11-14 18:10:16 -0800310 for (auto& encoded_array_pair : header_->GetCollections().EncodedArrayItems()) {
311 std::unique_ptr<dex_ir::EncodedArrayItem>& encoded_array = encoded_array_pair.second;
Jeff Haoa8621002016-10-04 18:13:44 +0000312 WriteEncodedArray(encoded_array->GetEncodedValues(), encoded_array->GetOffset());
313 }
314}
315
316void DexWriter::WriteAnnotations() {
317 uint8_t visibility[1];
Jeff Haoea7c6292016-11-14 18:10:16 -0800318 for (auto& annotation_pair : header_->GetCollections().AnnotationItems()) {
319 std::unique_ptr<dex_ir::AnnotationItem>& annotation = annotation_pair.second;
Jeff Haoa8621002016-10-04 18:13:44 +0000320 visibility[0] = annotation->GetVisibility();
321 size_t offset = annotation->GetOffset();
322 offset += Write(visibility, sizeof(uint8_t), offset);
323 WriteEncodedAnnotation(annotation->GetAnnotation(), offset);
324 }
325}
326
327void DexWriter::WriteAnnotationSets() {
328 uint32_t size[1];
329 uint32_t annotation_off[1];
Jeff Haoea7c6292016-11-14 18:10:16 -0800330 for (auto& annotation_set_pair : header_->GetCollections().AnnotationSetItems()) {
331 std::unique_ptr<dex_ir::AnnotationSetItem>& annotation_set = annotation_set_pair.second;
Jeff Haoa8621002016-10-04 18:13:44 +0000332 size[0] = annotation_set->GetItems()->size();
333 size_t offset = annotation_set->GetOffset();
334 offset += Write(size, sizeof(uint32_t), offset);
335 for (dex_ir::AnnotationItem* annotation : *annotation_set->GetItems()) {
336 annotation_off[0] = annotation->GetOffset();
337 offset += Write(annotation_off, sizeof(uint32_t), offset);
338 }
339 }
340}
341
342void DexWriter::WriteAnnotationSetRefs() {
343 uint32_t size[1];
344 uint32_t annotations_off[1];
Jeff Haoea7c6292016-11-14 18:10:16 -0800345 for (auto& anno_set_ref_pair : header_->GetCollections().AnnotationSetRefLists()) {
346 std::unique_ptr<dex_ir::AnnotationSetRefList>& annotation_set_ref = anno_set_ref_pair.second;
Jeff Haoa8621002016-10-04 18:13:44 +0000347 size[0] = annotation_set_ref->GetItems()->size();
348 size_t offset = annotation_set_ref->GetOffset();
349 offset += Write(size, sizeof(uint32_t), offset);
350 for (dex_ir::AnnotationSetItem* annotation_set : *annotation_set_ref->GetItems()) {
351 annotations_off[0] = annotation_set == nullptr ? 0 : annotation_set->GetOffset();
352 offset += Write(annotations_off, sizeof(uint32_t), offset);
353 }
354 }
355}
356
357void DexWriter::WriteAnnotationsDirectories() {
358 uint32_t directory_buffer[4];
359 uint32_t annotation_buffer[2];
Jeff Haoea7c6292016-11-14 18:10:16 -0800360 for (auto& annotations_directory_pair : header_->GetCollections().AnnotationsDirectoryItems()) {
361 std::unique_ptr<dex_ir::AnnotationsDirectoryItem>& annotations_directory =
362 annotations_directory_pair.second;
Jeff Haoa8621002016-10-04 18:13:44 +0000363 directory_buffer[0] = annotations_directory->GetClassAnnotation() == nullptr ? 0 :
364 annotations_directory->GetClassAnnotation()->GetOffset();
365 directory_buffer[1] = annotations_directory->GetFieldAnnotations() == nullptr ? 0 :
366 annotations_directory->GetFieldAnnotations()->size();
367 directory_buffer[2] = annotations_directory->GetMethodAnnotations() == nullptr ? 0 :
368 annotations_directory->GetMethodAnnotations()->size();
369 directory_buffer[3] = annotations_directory->GetParameterAnnotations() == nullptr ? 0 :
370 annotations_directory->GetParameterAnnotations()->size();
371 uint32_t offset = annotations_directory->GetOffset();
372 offset += Write(directory_buffer, 4 * sizeof(uint32_t), offset);
373 if (annotations_directory->GetFieldAnnotations() != nullptr) {
374 for (std::unique_ptr<dex_ir::FieldAnnotation>& field :
375 *annotations_directory->GetFieldAnnotations()) {
376 annotation_buffer[0] = field->GetFieldId()->GetIndex();
377 annotation_buffer[1] = field->GetAnnotationSetItem()->GetOffset();
378 offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
379 }
380 }
381 if (annotations_directory->GetMethodAnnotations() != nullptr) {
382 for (std::unique_ptr<dex_ir::MethodAnnotation>& method :
383 *annotations_directory->GetMethodAnnotations()) {
384 annotation_buffer[0] = method->GetMethodId()->GetIndex();
385 annotation_buffer[1] = method->GetAnnotationSetItem()->GetOffset();
386 offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
387 }
388 }
389 if (annotations_directory->GetParameterAnnotations() != nullptr) {
390 for (std::unique_ptr<dex_ir::ParameterAnnotation>& parameter :
391 *annotations_directory->GetParameterAnnotations()) {
392 annotation_buffer[0] = parameter->GetMethodId()->GetIndex();
393 annotation_buffer[1] = parameter->GetAnnotations()->GetOffset();
394 offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
395 }
396 }
397 }
398}
399
400void DexWriter::WriteDebugInfoItems() {
Jeff Haoea7c6292016-11-14 18:10:16 -0800401 for (auto& debug_info_pair : header_->GetCollections().DebugInfoItems()) {
402 std::unique_ptr<dex_ir::DebugInfoItem>& debug_info = debug_info_pair.second;
403 Write(debug_info->GetDebugInfo(), debug_info->GetDebugInfoSize(), debug_info->GetOffset());
Jeff Haoa8621002016-10-04 18:13:44 +0000404 }
405}
406
407void DexWriter::WriteCodeItems() {
408 uint16_t uint16_buffer[4];
409 uint32_t uint32_buffer[2];
Jeff Haoea7c6292016-11-14 18:10:16 -0800410 for (auto& code_item_pair : header_->GetCollections().CodeItems()) {
411 std::unique_ptr<dex_ir::CodeItem>& code_item = code_item_pair.second;
Jeff Haoa8621002016-10-04 18:13:44 +0000412 uint16_buffer[0] = code_item->RegistersSize();
413 uint16_buffer[1] = code_item->InsSize();
414 uint16_buffer[2] = code_item->OutsSize();
415 uint16_buffer[3] = code_item->TriesSize();
416 uint32_buffer[0] = code_item->DebugInfo() == nullptr ? 0 : code_item->DebugInfo()->GetOffset();
417 uint32_buffer[1] = code_item->InsnsSize();
418 size_t offset = code_item->GetOffset();
419 offset += Write(uint16_buffer, 4 * sizeof(uint16_t), offset);
420 offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset);
421 offset += Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t), offset);
422 if (code_item->TriesSize() != 0) {
423 if (code_item->InsnsSize() % 2 != 0) {
424 uint16_t padding[1] = { 0 };
425 offset += Write(padding, sizeof(uint16_t), offset);
426 }
427 uint32_t start_addr[1];
428 uint16_t insn_count_and_handler_off[2];
429 for (std::unique_ptr<const dex_ir::TryItem>& try_item : *code_item->Tries()) {
430 start_addr[0] = try_item->StartAddr();
431 insn_count_and_handler_off[0] = try_item->InsnCount();
432 insn_count_and_handler_off[1] = try_item->GetHandlers()->GetListOffset();
433 offset += Write(start_addr, sizeof(uint32_t), offset);
434 offset += Write(insn_count_and_handler_off, 2 * sizeof(uint16_t), offset);
435 }
436 // Leave offset pointing to the end of the try items.
437 WriteUleb128(code_item->Handlers()->size(), offset);
438 for (std::unique_ptr<const dex_ir::CatchHandler>& handlers : *code_item->Handlers()) {
439 size_t list_offset = offset + handlers->GetListOffset();
440 uint32_t size = handlers->HasCatchAll() ? (handlers->GetHandlers()->size() - 1) * -1 :
441 handlers->GetHandlers()->size();
442 list_offset += WriteSleb128(size, list_offset);
443 for (std::unique_ptr<const dex_ir::TypeAddrPair>& handler : *handlers->GetHandlers()) {
444 if (handler->GetTypeId() != nullptr) {
445 list_offset += WriteUleb128(handler->GetTypeId()->GetIndex(), list_offset);
446 }
447 list_offset += WriteUleb128(handler->GetAddress(), list_offset);
448 }
449 }
450 }
451 }
452}
453
454void DexWriter::WriteClasses() {
455 uint32_t class_def_buffer[8];
Jeff Haoea7c6292016-11-14 18:10:16 -0800456 for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) {
Jeff Haoa8621002016-10-04 18:13:44 +0000457 class_def_buffer[0] = class_def->ClassType()->GetIndex();
458 class_def_buffer[1] = class_def->GetAccessFlags();
459 class_def_buffer[2] = class_def->Superclass() == nullptr ? DexFile::kDexNoIndex :
460 class_def->Superclass()->GetIndex();
461 class_def_buffer[3] = class_def->InterfacesOffset();
462 class_def_buffer[4] = class_def->SourceFile() == nullptr ? DexFile::kDexNoIndex :
463 class_def->SourceFile()->GetIndex();
464 class_def_buffer[5] = class_def->Annotations() == nullptr ? 0 :
465 class_def->Annotations()->GetOffset();
466 class_def_buffer[6] = class_def->GetClassData() == nullptr ? 0 :
467 class_def->GetClassData()->GetOffset();
468 class_def_buffer[7] = class_def->StaticValues() == nullptr ? 0 :
469 class_def->StaticValues()->GetOffset();
470 size_t offset = class_def->GetOffset();
471 Write(class_def_buffer, class_def->GetSize(), offset);
472 }
473
Jeff Haoea7c6292016-11-14 18:10:16 -0800474 for (auto& class_data_pair : header_->GetCollections().ClassDatas()) {
475 std::unique_ptr<dex_ir::ClassData>& class_data = class_data_pair.second;
Jeff Haoa8621002016-10-04 18:13:44 +0000476 size_t offset = class_data->GetOffset();
477 offset += WriteUleb128(class_data->StaticFields()->size(), offset);
478 offset += WriteUleb128(class_data->InstanceFields()->size(), offset);
479 offset += WriteUleb128(class_data->DirectMethods()->size(), offset);
480 offset += WriteUleb128(class_data->VirtualMethods()->size(), offset);
481 offset += WriteEncodedFields(class_data->StaticFields(), offset);
482 offset += WriteEncodedFields(class_data->InstanceFields(), offset);
483 offset += WriteEncodedMethods(class_data->DirectMethods(), offset);
484 offset += WriteEncodedMethods(class_data->VirtualMethods(), offset);
485 }
486}
487
488struct MapItemContainer {
489 MapItemContainer(uint32_t type, uint32_t size, uint32_t offset)
490 : type_(type), size_(size), offset_(offset) { }
491
492 bool operator<(const MapItemContainer& other) const {
493 return offset_ > other.offset_;
494 }
495
496 uint32_t type_;
497 uint32_t size_;
498 uint32_t offset_;
499};
500
501void DexWriter::WriteMapItem() {
Jeff Haoea7c6292016-11-14 18:10:16 -0800502 dex_ir::Collections& collection = header_->GetCollections();
Jeff Haoa8621002016-10-04 18:13:44 +0000503 std::priority_queue<MapItemContainer> queue;
504
505 // Header and index section.
506 queue.push(MapItemContainer(DexFile::kDexTypeHeaderItem, 1, 0));
507 if (collection.StringIdsSize() != 0) {
508 queue.push(MapItemContainer(DexFile::kDexTypeStringIdItem, collection.StringIdsSize(),
509 collection.StringIdsOffset()));
510 }
511 if (collection.TypeIdsSize() != 0) {
512 queue.push(MapItemContainer(DexFile::kDexTypeTypeIdItem, collection.TypeIdsSize(),
513 collection.TypeIdsOffset()));
514 }
515 if (collection.ProtoIdsSize() != 0) {
516 queue.push(MapItemContainer(DexFile::kDexTypeProtoIdItem, collection.ProtoIdsSize(),
517 collection.ProtoIdsOffset()));
518 }
519 if (collection.FieldIdsSize() != 0) {
520 queue.push(MapItemContainer(DexFile::kDexTypeFieldIdItem, collection.FieldIdsSize(),
521 collection.FieldIdsOffset()));
522 }
523 if (collection.MethodIdsSize() != 0) {
524 queue.push(MapItemContainer(DexFile::kDexTypeMethodIdItem, collection.MethodIdsSize(),
525 collection.MethodIdsOffset()));
526 }
527 if (collection.ClassDefsSize() != 0) {
528 queue.push(MapItemContainer(DexFile::kDexTypeClassDefItem, collection.ClassDefsSize(),
529 collection.ClassDefsOffset()));
530 }
531
532 // Data section.
Jeff Haoea7c6292016-11-14 18:10:16 -0800533 queue.push(MapItemContainer(DexFile::kDexTypeMapList, 1, collection.MapListOffset()));
Jeff Haoa8621002016-10-04 18:13:44 +0000534 if (collection.TypeListsSize() != 0) {
535 queue.push(MapItemContainer(DexFile::kDexTypeTypeList, collection.TypeListsSize(),
536 collection.TypeListsOffset()));
537 }
538 if (collection.AnnotationSetRefListsSize() != 0) {
539 queue.push(MapItemContainer(DexFile::kDexTypeAnnotationSetRefList,
540 collection.AnnotationSetRefListsSize(), collection.AnnotationSetRefListsOffset()));
541 }
542 if (collection.AnnotationSetItemsSize() != 0) {
543 queue.push(MapItemContainer(DexFile::kDexTypeAnnotationSetItem,
544 collection.AnnotationSetItemsSize(), collection.AnnotationSetItemsOffset()));
545 }
546 if (collection.ClassDatasSize() != 0) {
547 queue.push(MapItemContainer(DexFile::kDexTypeClassDataItem, collection.ClassDatasSize(),
548 collection.ClassDatasOffset()));
549 }
550 if (collection.CodeItemsSize() != 0) {
551 queue.push(MapItemContainer(DexFile::kDexTypeCodeItem, collection.CodeItemsSize(),
552 collection.CodeItemsOffset()));
553 }
554 if (collection.StringDatasSize() != 0) {
555 queue.push(MapItemContainer(DexFile::kDexTypeStringDataItem, collection.StringDatasSize(),
556 collection.StringDatasOffset()));
557 }
558 if (collection.DebugInfoItemsSize() != 0) {
559 queue.push(MapItemContainer(DexFile::kDexTypeDebugInfoItem, collection.DebugInfoItemsSize(),
560 collection.DebugInfoItemsOffset()));
561 }
562 if (collection.AnnotationItemsSize() != 0) {
563 queue.push(MapItemContainer(DexFile::kDexTypeAnnotationItem, collection.AnnotationItemsSize(),
564 collection.AnnotationItemsOffset()));
565 }
566 if (collection.EncodedArrayItemsSize() != 0) {
567 queue.push(MapItemContainer(DexFile::kDexTypeEncodedArrayItem,
568 collection.EncodedArrayItemsSize(), collection.EncodedArrayItemsOffset()));
569 }
570 if (collection.AnnotationsDirectoryItemsSize() != 0) {
571 queue.push(MapItemContainer(DexFile::kDexTypeAnnotationsDirectoryItem,
572 collection.AnnotationsDirectoryItemsSize(), collection.AnnotationsDirectoryItemsOffset()));
573 }
574
Jeff Haoea7c6292016-11-14 18:10:16 -0800575 uint32_t offset = collection.MapListOffset();
Jeff Haoa8621002016-10-04 18:13:44 +0000576 uint16_t uint16_buffer[2];
577 uint32_t uint32_buffer[2];
578 uint16_buffer[1] = 0;
579 uint32_buffer[0] = queue.size();
580 offset += Write(uint32_buffer, sizeof(uint32_t), offset);
581 while (!queue.empty()) {
582 const MapItemContainer& map_item = queue.top();
583 uint16_buffer[0] = map_item.type_;
584 uint32_buffer[0] = map_item.size_;
585 uint32_buffer[1] = map_item.offset_;
586 offset += Write(uint16_buffer, 2 * sizeof(uint16_t), offset);
587 offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset);
588 queue.pop();
589 }
590}
591
592void DexWriter::WriteHeader() {
593 uint32_t buffer[20];
Jeff Haoea7c6292016-11-14 18:10:16 -0800594 dex_ir::Collections& collections = header_->GetCollections();
Jeff Haoa8621002016-10-04 18:13:44 +0000595 size_t offset = 0;
Jeff Haoea7c6292016-11-14 18:10:16 -0800596 offset += Write(header_->Magic(), 8 * sizeof(uint8_t), offset);
597 buffer[0] = header_->Checksum();
Jeff Haoa8621002016-10-04 18:13:44 +0000598 offset += Write(buffer, sizeof(uint32_t), offset);
Jeff Haoea7c6292016-11-14 18:10:16 -0800599 offset += Write(header_->Signature(), 20 * sizeof(uint8_t), offset);
600 uint32_t file_size = header_->FileSize();
Jeff Haoa8621002016-10-04 18:13:44 +0000601 buffer[0] = file_size;
Jeff Haoea7c6292016-11-14 18:10:16 -0800602 buffer[1] = header_->GetSize();
603 buffer[2] = header_->EndianTag();
604 buffer[3] = header_->LinkSize();
605 buffer[4] = header_->LinkOffset();
606 buffer[5] = collections.MapListOffset();
Jeff Haoa8621002016-10-04 18:13:44 +0000607 buffer[6] = collections.StringIdsSize();
608 buffer[7] = collections.StringIdsOffset();
609 buffer[8] = collections.TypeIdsSize();
610 buffer[9] = collections.TypeIdsOffset();
611 buffer[10] = collections.ProtoIdsSize();
612 buffer[11] = collections.ProtoIdsOffset();
613 buffer[12] = collections.FieldIdsSize();
614 buffer[13] = collections.FieldIdsOffset();
615 buffer[14] = collections.MethodIdsSize();
616 buffer[15] = collections.MethodIdsOffset();
617 uint32_t class_defs_size = collections.ClassDefsSize();
618 uint32_t class_defs_off = collections.ClassDefsOffset();
619 buffer[16] = class_defs_size;
620 buffer[17] = class_defs_off;
621 uint32_t data_off = class_defs_off + class_defs_size * dex_ir::ClassDef::ItemSize();
622 uint32_t data_size = file_size - data_off;
623 buffer[18] = data_size;
624 buffer[19] = data_off;
625 Write(buffer, 20 * sizeof(uint32_t), offset);
626}
627
Jeff Haoea7c6292016-11-14 18:10:16 -0800628void DexWriter::WriteMemMap() {
Jeff Haoa8621002016-10-04 18:13:44 +0000629 WriteStrings();
630 WriteTypes();
631 WriteTypeLists();
632 WriteProtos();
633 WriteFields();
634 WriteMethods();
635 WriteEncodedArrays();
636 WriteAnnotations();
637 WriteAnnotationSets();
638 WriteAnnotationSetRefs();
639 WriteAnnotationsDirectories();
640 WriteDebugInfoItems();
641 WriteCodeItems();
642 WriteClasses();
643 WriteMapItem();
644 WriteHeader();
645}
646
Jeff Haoea7c6292016-11-14 18:10:16 -0800647void DexWriter::Output(dex_ir::Header* header, MemMap* mem_map) {
648 DexWriter dex_writer(header, mem_map);
649 dex_writer.WriteMemMap();
Jeff Haoa8621002016-10-04 18:13:44 +0000650}
651
652} // namespace art