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