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
EncodeIntValue(int32_t value,uint8_t * buffer)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
EncodeUIntValue(uint32_t value,uint8_t * buffer)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
EncodeLongValue(int64_t value,uint8_t * buffer)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
EncodeFloatValue(float value,uint8_t * buffer)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
EncodeDoubleValue(double value,uint8_t * buffer)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
Write(const void * buffer,size_t length,size_t offset)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
WriteSleb128(uint32_t value,size_t offset)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
WriteUleb128(uint32_t value,size_t offset)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
WriteEncodedValue(dex_ir::EncodedValue * encoded_value,size_t offset)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
WriteEncodedValueHeader(int8_t value_type,size_t value_arg,size_t offset)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
WriteEncodedArray(dex_ir::EncodedValueVector * values,size_t offset)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
WriteEncodedAnnotation(dex_ir::EncodedAnnotation * annotation,size_t offset)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
WriteEncodedFields(dex_ir::FieldItemVector * fields,size_t offset)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
WriteEncodedMethods(dex_ir::MethodItemVector * methods,size_t offset)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
WriteStrings()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
WriteTypes()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
WriteTypeLists()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
WriteProtos()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
WriteFields()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
WriteMethods()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
WriteEncodedArrays()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
WriteAnnotations()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
WriteAnnotationSets()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
WriteAnnotationSetRefs()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
WriteAnnotationsDirectories()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
WriteDebugInfoItems()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
WriteCodeItems()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
WriteClasses()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
WriteCallSites()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
WriteMethodHandles()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 {
MapItemContainerart::MapItemContainer516 MapItemContainer(uint32_t type, uint32_t size, uint32_t offset)
517 : type_(type), size_(size), offset_(offset) { }
518
operator <art::MapItemContainer519 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
WriteMapItem()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
WriteHeader()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
WriteMemMap()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
Output(dex_ir::Header * header,MemMap * mem_map)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