blob: c85bca0d92975333008b1e770c77de6b9c769c05 [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.
Jeff Haoa8621002016-10-04 18:13:44 +000015 */
16
Andreas Gampee2abbc62017-09-15 11:59:26 -070017#include "dex_writer.h"
18
Jeff Haoa8621002016-10-04 18:13:44 +000019#include <stdint.h>
20
Jeff Haoa8621002016-10-04 18:13:44 +000021#include <vector>
22
Mathieu Chartier603ccab2017-10-20 14:34:28 -070023#include "cdex/compact_dex_file.h"
Mathieu Chartierf95a75e2017-11-03 15:25:52 -070024#include "compact_dex_writer.h"
Mathieu Chartier3e0c5172017-11-12 12:58:40 -080025#include "dex_file_layout.h"
Andreas Gampee2abbc62017-09-15 11:59:26 -070026#include "dex_file_types.h"
Mathieu Chartier3e0c5172017-11-12 12:58:40 -080027#include "dexlayout.h"
Mathieu Chartier603ccab2017-10-20 14:34:28 -070028#include "standard_dex_file.h"
Jeff Haoa8621002016-10-04 18:13:44 +000029#include "utf.h"
30
31namespace art {
32
Mathieu Chartier3e0c5172017-11-12 12:58:40 -080033static constexpr uint32_t kDataSectionAlignment = sizeof(uint32_t) * 2;
34static constexpr uint32_t kDexSectionWordAlignment = 4;
35
36static constexpr uint32_t SectionAlignment(DexFile::MapItemType type) {
37 switch (type) {
38 case DexFile::kDexTypeClassDataItem:
39 case DexFile::kDexTypeStringDataItem:
40 case DexFile::kDexTypeDebugInfoItem:
41 case DexFile::kDexTypeAnnotationItem:
42 case DexFile::kDexTypeEncodedArrayItem:
43 return alignof(uint8_t);
44
45 default:
46 // All other sections are kDexAlignedSection.
47 return kDexSectionWordAlignment;
48 }
49}
50
51
Jeff Haoa8621002016-10-04 18:13:44 +000052size_t EncodeIntValue(int32_t value, uint8_t* buffer) {
53 size_t length = 0;
54 if (value >= 0) {
55 while (value > 0x7f) {
56 buffer[length++] = static_cast<uint8_t>(value);
57 value >>= 8;
58 }
59 } else {
60 while (value < -0x80) {
61 buffer[length++] = static_cast<uint8_t>(value);
62 value >>= 8;
63 }
64 }
65 buffer[length++] = static_cast<uint8_t>(value);
66 return length;
67}
68
69size_t EncodeUIntValue(uint32_t value, uint8_t* buffer) {
70 size_t length = 0;
71 do {
72 buffer[length++] = static_cast<uint8_t>(value);
73 value >>= 8;
74 } while (value != 0);
75 return length;
76}
77
78size_t EncodeLongValue(int64_t value, uint8_t* buffer) {
79 size_t length = 0;
80 if (value >= 0) {
81 while (value > 0x7f) {
82 buffer[length++] = static_cast<uint8_t>(value);
83 value >>= 8;
84 }
85 } else {
86 while (value < -0x80) {
87 buffer[length++] = static_cast<uint8_t>(value);
88 value >>= 8;
89 }
90 }
91 buffer[length++] = static_cast<uint8_t>(value);
92 return length;
93}
94
95union FloatUnion {
96 float f_;
97 uint32_t i_;
98};
99
100size_t EncodeFloatValue(float value, uint8_t* buffer) {
101 FloatUnion float_union;
102 float_union.f_ = value;
103 uint32_t int_value = float_union.i_;
104 size_t index = 3;
105 do {
106 buffer[index--] = int_value >> 24;
107 int_value <<= 8;
108 } while (int_value != 0);
109 return 3 - index;
110}
111
112union DoubleUnion {
113 double d_;
114 uint64_t l_;
115};
116
117size_t EncodeDoubleValue(double value, uint8_t* buffer) {
118 DoubleUnion double_union;
119 double_union.d_ = value;
120 uint64_t long_value = double_union.l_;
121 size_t index = 7;
122 do {
123 buffer[index--] = long_value >> 56;
124 long_value <<= 8;
125 } while (long_value != 0);
126 return 7 - index;
127}
128
129size_t DexWriter::Write(const void* buffer, size_t length, size_t offset) {
Jeff Haoea7c6292016-11-14 18:10:16 -0800130 DCHECK_LE(offset + length, mem_map_->Size());
131 memcpy(mem_map_->Begin() + offset, buffer, length);
132 return length;
Jeff Haoa8621002016-10-04 18:13:44 +0000133}
134
135size_t DexWriter::WriteSleb128(uint32_t value, size_t offset) {
136 uint8_t buffer[8];
137 EncodeSignedLeb128(buffer, value);
138 return Write(buffer, SignedLeb128Size(value), offset);
139}
140
141size_t DexWriter::WriteUleb128(uint32_t value, size_t offset) {
142 uint8_t buffer[8];
143 EncodeUnsignedLeb128(buffer, value);
144 return Write(buffer, UnsignedLeb128Size(value), offset);
145}
146
147size_t DexWriter::WriteEncodedValue(dex_ir::EncodedValue* encoded_value, size_t offset) {
148 size_t original_offset = offset;
149 size_t start = 0;
150 size_t length;
151 uint8_t buffer[8];
152 int8_t type = encoded_value->Type();
153 switch (type) {
154 case DexFile::kDexAnnotationByte:
155 length = EncodeIntValue(encoded_value->GetByte(), buffer);
156 break;
157 case DexFile::kDexAnnotationShort:
158 length = EncodeIntValue(encoded_value->GetShort(), buffer);
159 break;
160 case DexFile::kDexAnnotationChar:
161 length = EncodeUIntValue(encoded_value->GetChar(), buffer);
162 break;
163 case DexFile::kDexAnnotationInt:
164 length = EncodeIntValue(encoded_value->GetInt(), buffer);
165 break;
166 case DexFile::kDexAnnotationLong:
167 length = EncodeLongValue(encoded_value->GetLong(), buffer);
168 break;
169 case DexFile::kDexAnnotationFloat:
170 length = EncodeFloatValue(encoded_value->GetFloat(), buffer);
171 start = 4 - length;
172 break;
173 case DexFile::kDexAnnotationDouble:
174 length = EncodeDoubleValue(encoded_value->GetDouble(), buffer);
175 start = 8 - length;
176 break;
Jeff Hao5daee902017-04-27 18:00:38 -0700177 case DexFile::kDexAnnotationMethodType:
178 length = EncodeUIntValue(encoded_value->GetProtoId()->GetIndex(), buffer);
179 break;
180 case DexFile::kDexAnnotationMethodHandle:
181 length = EncodeUIntValue(encoded_value->GetMethodHandle()->GetIndex(), buffer);
182 break;
Jeff Haoa8621002016-10-04 18:13:44 +0000183 case DexFile::kDexAnnotationString:
184 length = EncodeUIntValue(encoded_value->GetStringId()->GetIndex(), buffer);
185 break;
186 case DexFile::kDexAnnotationType:
187 length = EncodeUIntValue(encoded_value->GetTypeId()->GetIndex(), buffer);
188 break;
189 case DexFile::kDexAnnotationField:
190 case DexFile::kDexAnnotationEnum:
191 length = EncodeUIntValue(encoded_value->GetFieldId()->GetIndex(), buffer);
192 break;
193 case DexFile::kDexAnnotationMethod:
194 length = EncodeUIntValue(encoded_value->GetMethodId()->GetIndex(), buffer);
195 break;
196 case DexFile::kDexAnnotationArray:
197 offset += WriteEncodedValueHeader(type, 0, offset);
198 offset += WriteEncodedArray(encoded_value->GetEncodedArray()->GetEncodedValues(), offset);
199 return offset - original_offset;
200 case DexFile::kDexAnnotationAnnotation:
201 offset += WriteEncodedValueHeader(type, 0, offset);
202 offset += WriteEncodedAnnotation(encoded_value->GetEncodedAnnotation(), offset);
203 return offset - original_offset;
204 case DexFile::kDexAnnotationNull:
205 return WriteEncodedValueHeader(type, 0, offset);
206 case DexFile::kDexAnnotationBoolean:
207 return WriteEncodedValueHeader(type, encoded_value->GetBoolean() ? 1 : 0, offset);
208 default:
209 return 0;
210 }
211 offset += WriteEncodedValueHeader(type, length - 1, offset);
212 offset += Write(buffer + start, length, offset);
213 return offset - original_offset;
214}
215
216size_t DexWriter::WriteEncodedValueHeader(int8_t value_type, size_t value_arg, size_t offset) {
217 uint8_t buffer[1] = { static_cast<uint8_t>((value_arg << 5) | value_type) };
218 return Write(buffer, sizeof(uint8_t), offset);
219}
220
221size_t DexWriter::WriteEncodedArray(dex_ir::EncodedValueVector* values, size_t offset) {
222 size_t original_offset = offset;
223 offset += WriteUleb128(values->size(), offset);
224 for (std::unique_ptr<dex_ir::EncodedValue>& value : *values) {
225 offset += WriteEncodedValue(value.get(), offset);
226 }
227 return offset - original_offset;
228}
229
230size_t DexWriter::WriteEncodedAnnotation(dex_ir::EncodedAnnotation* annotation, size_t offset) {
231 size_t original_offset = offset;
232 offset += WriteUleb128(annotation->GetType()->GetIndex(), offset);
233 offset += WriteUleb128(annotation->GetAnnotationElements()->size(), offset);
234 for (std::unique_ptr<dex_ir::AnnotationElement>& annotation_element :
235 *annotation->GetAnnotationElements()) {
236 offset += WriteUleb128(annotation_element->GetName()->GetIndex(), offset);
237 offset += WriteEncodedValue(annotation_element->GetValue(), offset);
238 }
239 return offset - original_offset;
240}
241
242size_t DexWriter::WriteEncodedFields(dex_ir::FieldItemVector* fields, size_t offset) {
243 size_t original_offset = offset;
244 uint32_t prev_index = 0;
245 for (std::unique_ptr<dex_ir::FieldItem>& field : *fields) {
246 uint32_t index = field->GetFieldId()->GetIndex();
247 offset += WriteUleb128(index - prev_index, offset);
248 offset += WriteUleb128(field->GetAccessFlags(), offset);
249 prev_index = index;
250 }
251 return offset - original_offset;
252}
253
254size_t DexWriter::WriteEncodedMethods(dex_ir::MethodItemVector* methods, size_t offset) {
255 size_t original_offset = offset;
256 uint32_t prev_index = 0;
257 for (std::unique_ptr<dex_ir::MethodItem>& method : *methods) {
258 uint32_t index = method->GetMethodId()->GetIndex();
259 uint32_t code_off = method->GetCodeItem() == nullptr ? 0 : method->GetCodeItem()->GetOffset();
260 offset += WriteUleb128(index - prev_index, offset);
261 offset += WriteUleb128(method->GetAccessFlags(), offset);
262 offset += WriteUleb128(code_off, offset);
263 prev_index = index;
264 }
265 return offset - original_offset;
266}
267
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800268// TODO: Refactor this to remove duplicated boiler plate. One way to do this is adding
269// function that takes a CollectionVector<T> and uses overloading.
270uint32_t DexWriter::WriteStringIds(uint32_t offset, bool reserve_only) {
271 const uint32_t start = offset;
Jeff Haoea7c6292016-11-14 18:10:16 -0800272 for (std::unique_ptr<dex_ir::StringId>& string_id : header_->GetCollections().StringIds()) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800273 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeStringIdItem));
274 if (reserve_only) {
275 offset += string_id->GetSize();
276 } else {
277 uint32_t string_data_off = string_id->DataItem()->GetOffset();
278 offset += Write(&string_data_off, string_id->GetSize(), offset);
279 }
Jeff Haoa8621002016-10-04 18:13:44 +0000280 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800281 if (compute_offsets_ && start != offset) {
282 header_->GetCollections().SetStringIdsOffset(start);
283 }
284 return offset - start;
285}
Jeff Haoa8621002016-10-04 18:13:44 +0000286
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800287uint32_t DexWriter::WriteStringDatas(uint32_t offset) {
288 const uint32_t start = offset;
289 for (std::unique_ptr<dex_ir::StringData>& string_data : header_->GetCollections().StringDatas()) {
290 ProcessOffset(&offset, string_data.get());
291 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeStringDataItem));
Jeff Haoa8621002016-10-04 18:13:44 +0000292 offset += WriteUleb128(CountModifiedUtf8Chars(string_data->Data()), offset);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800293 // Skip null terminator (already zeroed out, no need to write).
294 offset += Write(string_data->Data(), strlen(string_data->Data()), offset) + 1u;
Jeff Haoa8621002016-10-04 18:13:44 +0000295 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800296 if (compute_offsets_ && start != offset) {
297 header_->GetCollections().SetStringDatasOffset(start);
298 }
299 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000300}
301
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800302uint32_t DexWriter::WriteTypeIds(uint32_t offset) {
Jeff Haoa8621002016-10-04 18:13:44 +0000303 uint32_t descriptor_idx[1];
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800304 const uint32_t start = offset;
Jeff Haoea7c6292016-11-14 18:10:16 -0800305 for (std::unique_ptr<dex_ir::TypeId>& type_id : header_->GetCollections().TypeIds()) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800306 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeTypeIdItem));
307 ProcessOffset(&offset, type_id.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000308 descriptor_idx[0] = type_id->GetStringId()->GetIndex();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800309 offset += Write(descriptor_idx, type_id->GetSize(), offset);
Jeff Haoa8621002016-10-04 18:13:44 +0000310 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800311 if (compute_offsets_ && start != offset) {
312 header_->GetCollections().SetTypeIdsOffset(start);
313 }
314 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000315}
316
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800317uint32_t DexWriter::WriteTypeLists(uint32_t offset) {
Jeff Haoa8621002016-10-04 18:13:44 +0000318 uint32_t size[1];
319 uint16_t list[1];
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800320 const uint32_t start = offset;
321 for (std::unique_ptr<dex_ir::TypeList>& type_list : header_->GetCollections().TypeLists()) {
322 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeTypeList));
Jeff Haoa8621002016-10-04 18:13:44 +0000323 size[0] = type_list->GetTypeList()->size();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800324 ProcessOffset(&offset, type_list.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000325 offset += Write(size, sizeof(uint32_t), offset);
326 for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) {
327 list[0] = type_id->GetIndex();
328 offset += Write(list, sizeof(uint16_t), offset);
329 }
330 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800331 if (compute_offsets_ && start != offset) {
332 header_->GetCollections().SetTypeListsOffset(start);
Jeff Haoa8621002016-10-04 18:13:44 +0000333 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800334 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000335}
336
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800337uint32_t DexWriter::WriteProtoIds(uint32_t offset, bool reserve_only) {
338 uint32_t buffer[3];
339 const uint32_t start = offset;
340 for (std::unique_ptr<dex_ir::ProtoId>& proto_id : header_->GetCollections().ProtoIds()) {
341 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeProtoIdItem));
342 ProcessOffset(&offset, proto_id.get());
343 if (reserve_only) {
344 offset += proto_id->GetSize();
345 } else {
346 buffer[0] = proto_id->Shorty()->GetIndex();
347 buffer[1] = proto_id->ReturnType()->GetIndex();
348 buffer[2] = proto_id->Parameters() == nullptr ? 0 : proto_id->Parameters()->GetOffset();
349 offset += Write(buffer, proto_id->GetSize(), offset);
350 }
351 }
352 if (compute_offsets_ && start != offset) {
353 header_->GetCollections().SetProtoIdsOffset(start);
354 }
355 return offset - start;
356}
357
358uint32_t DexWriter::WriteFieldIds(uint32_t offset) {
Jeff Haoa8621002016-10-04 18:13:44 +0000359 uint16_t buffer[4];
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800360 const uint32_t start = offset;
Jeff Haoea7c6292016-11-14 18:10:16 -0800361 for (std::unique_ptr<dex_ir::FieldId>& field_id : header_->GetCollections().FieldIds()) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800362 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeFieldIdItem));
363 ProcessOffset(&offset, field_id.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000364 buffer[0] = field_id->Class()->GetIndex();
365 buffer[1] = field_id->Type()->GetIndex();
366 buffer[2] = field_id->Name()->GetIndex();
367 buffer[3] = field_id->Name()->GetIndex() >> 16;
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800368 offset += Write(buffer, field_id->GetSize(), offset);
Jeff Haoa8621002016-10-04 18:13:44 +0000369 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800370 if (compute_offsets_ && start != offset) {
371 header_->GetCollections().SetFieldIdsOffset(start);
372 }
373 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000374}
375
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800376uint32_t DexWriter::WriteMethodIds(uint32_t offset) {
Jeff Haoa8621002016-10-04 18:13:44 +0000377 uint16_t buffer[4];
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800378 const uint32_t start = offset;
Jeff Haoea7c6292016-11-14 18:10:16 -0800379 for (std::unique_ptr<dex_ir::MethodId>& method_id : header_->GetCollections().MethodIds()) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800380 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeMethodIdItem));
381 ProcessOffset(&offset, method_id.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000382 buffer[0] = method_id->Class()->GetIndex();
383 buffer[1] = method_id->Proto()->GetIndex();
384 buffer[2] = method_id->Name()->GetIndex();
385 buffer[3] = method_id->Name()->GetIndex() >> 16;
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800386 offset += Write(buffer, method_id->GetSize(), offset);
Jeff Haoa8621002016-10-04 18:13:44 +0000387 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800388 if (compute_offsets_ && start != offset) {
389 header_->GetCollections().SetMethodIdsOffset(start);
390 }
391 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000392}
393
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800394uint32_t DexWriter::WriteEncodedArrays(uint32_t offset) {
395 const uint32_t start = offset;
396 for (std::unique_ptr<dex_ir::EncodedArrayItem>& encoded_array :
397 header_->GetCollections().EncodedArrayItems()) {
398 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeEncodedArrayItem));
399 ProcessOffset(&offset, encoded_array.get());
400 offset += WriteEncodedArray(encoded_array->GetEncodedValues(), offset);
Jeff Haoa8621002016-10-04 18:13:44 +0000401 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800402 if (compute_offsets_ && start != offset) {
403 header_->GetCollections().SetEncodedArrayItemsOffset(start);
404 }
405 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000406}
407
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800408uint32_t DexWriter::WriteAnnotations(uint32_t offset) {
Jeff Haoa8621002016-10-04 18:13:44 +0000409 uint8_t visibility[1];
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800410 const uint32_t start = offset;
411 for (std::unique_ptr<dex_ir::AnnotationItem>& annotation :
412 header_->GetCollections().AnnotationItems()) {
413 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeAnnotationItem));
Jeff Haoa8621002016-10-04 18:13:44 +0000414 visibility[0] = annotation->GetVisibility();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800415 ProcessOffset(&offset, annotation.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000416 offset += Write(visibility, sizeof(uint8_t), offset);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800417 offset += WriteEncodedAnnotation(annotation->GetAnnotation(), offset);
Jeff Haoa8621002016-10-04 18:13:44 +0000418 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800419 if (compute_offsets_ && start != offset) {
420 header_->GetCollections().SetAnnotationItemsOffset(start);
421 }
422 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000423}
424
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800425uint32_t DexWriter::WriteAnnotationSets(uint32_t offset) {
Jeff Haoa8621002016-10-04 18:13:44 +0000426 uint32_t size[1];
427 uint32_t annotation_off[1];
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800428 const uint32_t start = offset;
429 for (std::unique_ptr<dex_ir::AnnotationSetItem>& annotation_set :
430 header_->GetCollections().AnnotationSetItems()) {
431 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeAnnotationSetItem));
Jeff Haoa8621002016-10-04 18:13:44 +0000432 size[0] = annotation_set->GetItems()->size();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800433 ProcessOffset(&offset, annotation_set.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000434 offset += Write(size, sizeof(uint32_t), offset);
435 for (dex_ir::AnnotationItem* annotation : *annotation_set->GetItems()) {
436 annotation_off[0] = annotation->GetOffset();
437 offset += Write(annotation_off, sizeof(uint32_t), offset);
438 }
439 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800440 if (compute_offsets_ && start != offset) {
441 header_->GetCollections().SetAnnotationSetItemsOffset(start);
442 }
443 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000444}
445
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800446uint32_t DexWriter::WriteAnnotationSetRefs(uint32_t offset) {
Jeff Haoa8621002016-10-04 18:13:44 +0000447 uint32_t size[1];
448 uint32_t annotations_off[1];
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800449 const uint32_t start = offset;
450 for (std::unique_ptr<dex_ir::AnnotationSetRefList>& annotation_set_ref :
451 header_->GetCollections().AnnotationSetRefLists()) {
452 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeAnnotationSetRefList));
Jeff Haoa8621002016-10-04 18:13:44 +0000453 size[0] = annotation_set_ref->GetItems()->size();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800454 ProcessOffset(&offset, annotation_set_ref.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000455 offset += Write(size, sizeof(uint32_t), offset);
456 for (dex_ir::AnnotationSetItem* annotation_set : *annotation_set_ref->GetItems()) {
457 annotations_off[0] = annotation_set == nullptr ? 0 : annotation_set->GetOffset();
458 offset += Write(annotations_off, sizeof(uint32_t), offset);
459 }
460 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800461 if (compute_offsets_ && start != offset) {
462 header_->GetCollections().SetAnnotationSetRefListsOffset(start);
463 }
464 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000465}
466
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800467uint32_t DexWriter::WriteAnnotationsDirectories(uint32_t offset) {
Jeff Haoa8621002016-10-04 18:13:44 +0000468 uint32_t directory_buffer[4];
469 uint32_t annotation_buffer[2];
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800470 const uint32_t start = offset;
471 for (std::unique_ptr<dex_ir::AnnotationsDirectoryItem>& annotations_directory :
472 header_->GetCollections().AnnotationsDirectoryItems()) {
473 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeAnnotationsDirectoryItem));
474 ProcessOffset(&offset, annotations_directory.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000475 directory_buffer[0] = annotations_directory->GetClassAnnotation() == nullptr ? 0 :
476 annotations_directory->GetClassAnnotation()->GetOffset();
477 directory_buffer[1] = annotations_directory->GetFieldAnnotations() == nullptr ? 0 :
478 annotations_directory->GetFieldAnnotations()->size();
479 directory_buffer[2] = annotations_directory->GetMethodAnnotations() == nullptr ? 0 :
480 annotations_directory->GetMethodAnnotations()->size();
481 directory_buffer[3] = annotations_directory->GetParameterAnnotations() == nullptr ? 0 :
482 annotations_directory->GetParameterAnnotations()->size();
Jeff Haoa8621002016-10-04 18:13:44 +0000483 offset += Write(directory_buffer, 4 * sizeof(uint32_t), offset);
484 if (annotations_directory->GetFieldAnnotations() != nullptr) {
485 for (std::unique_ptr<dex_ir::FieldAnnotation>& field :
486 *annotations_directory->GetFieldAnnotations()) {
487 annotation_buffer[0] = field->GetFieldId()->GetIndex();
488 annotation_buffer[1] = field->GetAnnotationSetItem()->GetOffset();
489 offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
490 }
491 }
492 if (annotations_directory->GetMethodAnnotations() != nullptr) {
493 for (std::unique_ptr<dex_ir::MethodAnnotation>& method :
494 *annotations_directory->GetMethodAnnotations()) {
495 annotation_buffer[0] = method->GetMethodId()->GetIndex();
496 annotation_buffer[1] = method->GetAnnotationSetItem()->GetOffset();
497 offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
498 }
499 }
500 if (annotations_directory->GetParameterAnnotations() != nullptr) {
501 for (std::unique_ptr<dex_ir::ParameterAnnotation>& parameter :
502 *annotations_directory->GetParameterAnnotations()) {
503 annotation_buffer[0] = parameter->GetMethodId()->GetIndex();
504 annotation_buffer[1] = parameter->GetAnnotations()->GetOffset();
505 offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
506 }
507 }
508 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800509 if (compute_offsets_ && start != offset) {
510 header_->GetCollections().SetAnnotationsDirectoryItemsOffset(start);
Jeff Haoa8621002016-10-04 18:13:44 +0000511 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800512 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000513}
514
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800515uint32_t DexWriter::WriteDebugInfoItems(uint32_t offset) {
516 const uint32_t start = offset;
517 for (std::unique_ptr<dex_ir::DebugInfoItem>& debug_info :
518 header_->GetCollections().DebugInfoItems()) {
519 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeDebugInfoItem));
520 ProcessOffset(&offset, debug_info.get());
521 offset += Write(debug_info->GetDebugInfo(), debug_info->GetDebugInfoSize(), offset);
522 }
523 if (compute_offsets_ && start != offset) {
524 header_->GetCollections().SetDebugInfoItemsOffset(start);
525 }
526 return offset - start;
527}
528
529uint32_t DexWriter::WriteCodeItems(uint32_t offset, bool reserve_only) {
530 DexLayoutSection* code_section = nullptr;
531 if (!reserve_only && dex_layout_ != nullptr) {
532 code_section = &dex_layout_->GetSections().sections_[static_cast<size_t>(
533 DexLayoutSections::SectionType::kSectionTypeCode)];
534 }
535 uint16_t uint16_buffer[4] = {};
536 uint32_t uint32_buffer[2] = {};
537 uint32_t start = offset;
538 for (auto& code_item : header_->GetCollections().CodeItems()) {
539 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeCodeItem));
540 ProcessOffset(&offset, code_item.get());
541 if (!reserve_only) {
542 uint16_buffer[0] = code_item->RegistersSize();
543 uint16_buffer[1] = code_item->InsSize();
544 uint16_buffer[2] = code_item->OutsSize();
545 uint16_buffer[3] = code_item->TriesSize();
546 uint32_buffer[0] = code_item->DebugInfo() == nullptr ? 0 :
547 code_item->DebugInfo()->GetOffset();
548 uint32_buffer[1] = code_item->InsnsSize();
549 // Only add the section hotness info once.
550 if (code_section != nullptr) {
551 auto it = dex_layout_->LayoutHotnessInfo().code_item_layout_.find(code_item.get());
552 if (it != dex_layout_->LayoutHotnessInfo().code_item_layout_.end()) {
553 code_section->parts_[static_cast<size_t>(it->second)].CombineSection(
554 code_item->GetOffset(), code_item->GetOffset() + code_item->GetSize());
555 }
556 }
557 }
Jeff Haoa8621002016-10-04 18:13:44 +0000558 offset += Write(uint16_buffer, 4 * sizeof(uint16_t), offset);
559 offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset);
560 offset += Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t), offset);
561 if (code_item->TriesSize() != 0) {
562 if (code_item->InsnsSize() % 2 != 0) {
563 uint16_t padding[1] = { 0 };
564 offset += Write(padding, sizeof(uint16_t), offset);
565 }
566 uint32_t start_addr[1];
567 uint16_t insn_count_and_handler_off[2];
568 for (std::unique_ptr<const dex_ir::TryItem>& try_item : *code_item->Tries()) {
569 start_addr[0] = try_item->StartAddr();
570 insn_count_and_handler_off[0] = try_item->InsnCount();
571 insn_count_and_handler_off[1] = try_item->GetHandlers()->GetListOffset();
572 offset += Write(start_addr, sizeof(uint32_t), offset);
573 offset += Write(insn_count_and_handler_off, 2 * sizeof(uint16_t), offset);
574 }
575 // Leave offset pointing to the end of the try items.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800576 UNUSED(WriteUleb128(code_item->Handlers()->size(), offset));
Jeff Haoa8621002016-10-04 18:13:44 +0000577 for (std::unique_ptr<const dex_ir::CatchHandler>& handlers : *code_item->Handlers()) {
578 size_t list_offset = offset + handlers->GetListOffset();
579 uint32_t size = handlers->HasCatchAll() ? (handlers->GetHandlers()->size() - 1) * -1 :
580 handlers->GetHandlers()->size();
581 list_offset += WriteSleb128(size, list_offset);
582 for (std::unique_ptr<const dex_ir::TypeAddrPair>& handler : *handlers->GetHandlers()) {
583 if (handler->GetTypeId() != nullptr) {
584 list_offset += WriteUleb128(handler->GetTypeId()->GetIndex(), list_offset);
585 }
586 list_offset += WriteUleb128(handler->GetAddress(), list_offset);
587 }
588 }
589 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800590 // TODO: Clean this up to properly calculate the size instead of assuming it doesn't change.
591 offset = code_item->GetOffset() + code_item->GetSize();
Jeff Haoa8621002016-10-04 18:13:44 +0000592 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800593
594 if (compute_offsets_ && start != offset) {
595 header_->GetCollections().SetCodeItemsOffset(start);
596 }
597 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000598}
599
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800600uint32_t DexWriter::WriteClassDefs(uint32_t offset, bool reserve_only) {
601 const uint32_t start = offset;
Jeff Haoa8621002016-10-04 18:13:44 +0000602 uint32_t class_def_buffer[8];
Jeff Haoea7c6292016-11-14 18:10:16 -0800603 for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800604 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeClassDefItem));
605 if (reserve_only) {
606 offset += class_def->GetSize();
607 } else {
608 class_def_buffer[0] = class_def->ClassType()->GetIndex();
609 class_def_buffer[1] = class_def->GetAccessFlags();
610 class_def_buffer[2] = class_def->Superclass() == nullptr ? dex::kDexNoIndex :
611 class_def->Superclass()->GetIndex();
612 class_def_buffer[3] = class_def->InterfacesOffset();
613 class_def_buffer[4] = class_def->SourceFile() == nullptr ? dex::kDexNoIndex :
614 class_def->SourceFile()->GetIndex();
615 class_def_buffer[5] = class_def->Annotations() == nullptr ? 0 :
616 class_def->Annotations()->GetOffset();
617 class_def_buffer[6] = class_def->GetClassData() == nullptr ? 0 :
618 class_def->GetClassData()->GetOffset();
619 class_def_buffer[7] = class_def->StaticValues() == nullptr ? 0 :
620 class_def->StaticValues()->GetOffset();
621 offset += Write(class_def_buffer, class_def->GetSize(), offset);
622 }
Jeff Haoa8621002016-10-04 18:13:44 +0000623 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800624 if (compute_offsets_ && start != offset) {
625 header_->GetCollections().SetClassDefsOffset(start);
626 }
627 return offset - start;
628}
Jeff Haoa8621002016-10-04 18:13:44 +0000629
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800630uint32_t DexWriter::WriteClassDatas(uint32_t offset) {
631 const uint32_t start = offset;
632 for (const std::unique_ptr<dex_ir::ClassData>& class_data :
633 header_->GetCollections().ClassDatas()) {
634 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeClassDataItem));
635 ProcessOffset(&offset, class_data.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000636 offset += WriteUleb128(class_data->StaticFields()->size(), offset);
637 offset += WriteUleb128(class_data->InstanceFields()->size(), offset);
638 offset += WriteUleb128(class_data->DirectMethods()->size(), offset);
639 offset += WriteUleb128(class_data->VirtualMethods()->size(), offset);
640 offset += WriteEncodedFields(class_data->StaticFields(), offset);
641 offset += WriteEncodedFields(class_data->InstanceFields(), offset);
642 offset += WriteEncodedMethods(class_data->DirectMethods(), offset);
643 offset += WriteEncodedMethods(class_data->VirtualMethods(), offset);
644 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800645 if (compute_offsets_ && start != offset) {
646 header_->GetCollections().SetClassDatasOffset(start);
647 }
648 return offset - start;
Jeff Haoa8621002016-10-04 18:13:44 +0000649}
650
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800651uint32_t DexWriter::WriteCallSiteIds(uint32_t offset, bool reserve_only) {
652 const uint32_t start = offset;
Jeff Hao5daee902017-04-27 18:00:38 -0700653 uint32_t call_site_off[1];
654 for (std::unique_ptr<dex_ir::CallSiteId>& call_site_id :
655 header_->GetCollections().CallSiteIds()) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800656 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeCallSiteIdItem));
657 if (reserve_only) {
658 offset += call_site_id->GetSize();
659 } else {
660 call_site_off[0] = call_site_id->CallSiteItem()->GetOffset();
661 offset += Write(call_site_off, call_site_id->GetSize(), offset);
662 }
Jeff Hao5daee902017-04-27 18:00:38 -0700663 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800664 if (compute_offsets_ && start != offset) {
665 header_->GetCollections().SetCallSiteIdsOffset(start);
666 }
667 return offset - start;
Jeff Hao5daee902017-04-27 18:00:38 -0700668}
669
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800670uint32_t DexWriter::WriteMethodHandles(uint32_t offset) {
671 const uint32_t start = offset;
Jeff Hao5daee902017-04-27 18:00:38 -0700672 uint16_t method_handle_buff[4];
673 for (std::unique_ptr<dex_ir::MethodHandleItem>& method_handle :
674 header_->GetCollections().MethodHandleItems()) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800675 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeMethodHandleItem));
Jeff Hao5daee902017-04-27 18:00:38 -0700676 method_handle_buff[0] = static_cast<uint16_t>(method_handle->GetMethodHandleType());
677 method_handle_buff[1] = 0; // unused.
678 method_handle_buff[2] = method_handle->GetFieldOrMethodId()->GetIndex();
679 method_handle_buff[3] = 0; // unused.
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800680 offset += Write(method_handle_buff, method_handle->GetSize(), offset);
Jeff Hao5daee902017-04-27 18:00:38 -0700681 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800682 if (compute_offsets_ && start != offset) {
683 header_->GetCollections().SetMethodHandleItemsOffset(start);
684 }
685 return offset - start;
Jeff Hao5daee902017-04-27 18:00:38 -0700686}
687
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800688uint32_t DexWriter::WriteMapItems(uint32_t offset, MapItemQueue* queue) {
689 // All the sections should already have been added.
Jeff Haoa8621002016-10-04 18:13:44 +0000690 uint16_t uint16_buffer[2];
691 uint32_t uint32_buffer[2];
692 uint16_buffer[1] = 0;
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800693 uint32_buffer[0] = queue->size();
694 const uint32_t start = offset;
Jeff Haoa8621002016-10-04 18:13:44 +0000695 offset += Write(uint32_buffer, sizeof(uint32_t), offset);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800696 while (!queue->empty()) {
697 const MapItem& map_item = queue->top();
Jeff Haoa8621002016-10-04 18:13:44 +0000698 uint16_buffer[0] = map_item.type_;
699 uint32_buffer[0] = map_item.size_;
700 uint32_buffer[1] = map_item.offset_;
701 offset += Write(uint16_buffer, 2 * sizeof(uint16_t), offset);
702 offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800703 queue->pop();
Jeff Haoa8621002016-10-04 18:13:44 +0000704 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800705 return offset - start;
706}
707
708uint32_t DexWriter::GenerateAndWriteMapItems(uint32_t offset) {
709 dex_ir::Collections& collection = header_->GetCollections();
710 MapItemQueue queue;
711
712 // Header and index section.
713 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeHeaderItem, 1, 0));
714 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringIdItem,
715 collection.StringIdsSize(),
716 collection.StringIdsOffset()));
717 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeIdItem,
718 collection.TypeIdsSize(),
719 collection.TypeIdsOffset()));
720 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeProtoIdItem,
721 collection.ProtoIdsSize(),
722 collection.ProtoIdsOffset()));
723 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeFieldIdItem,
724 collection.FieldIdsSize(),
725 collection.FieldIdsOffset()));
726 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodIdItem,
727 collection.MethodIdsSize(),
728 collection.MethodIdsOffset()));
729 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDefItem,
730 collection.ClassDefsSize(),
731 collection.ClassDefsOffset()));
732 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCallSiteIdItem,
733 collection.CallSiteIdsSize(),
734 collection.CallSiteIdsOffset()));
735 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodHandleItem,
736 collection.MethodHandleItemsSize(),
737 collection.MethodHandleItemsOffset()));
738 // Data section.
739 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMapList, 1, collection.MapListOffset()));
740 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeList,
741 collection.TypeListsSize(),
742 collection.TypeListsOffset()));
743 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetRefList,
744 collection.AnnotationSetRefListsSize(),
745 collection.AnnotationSetRefListsOffset()));
746 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetItem,
747 collection.AnnotationSetItemsSize(),
748 collection.AnnotationSetItemsOffset()));
749 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDataItem,
750 collection.ClassDatasSize(),
751 collection.ClassDatasOffset()));
752 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCodeItem,
753 collection.CodeItemsSize(),
754 collection.CodeItemsOffset()));
755 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringDataItem,
756 collection.StringDatasSize(),
757 collection.StringDatasOffset()));
758 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeDebugInfoItem,
759 collection.DebugInfoItemsSize(),
760 collection.DebugInfoItemsOffset()));
761 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationItem,
762 collection.AnnotationItemsSize(),
763 collection.AnnotationItemsOffset()));
764 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeEncodedArrayItem,
765 collection.EncodedArrayItemsSize(),
766 collection.EncodedArrayItemsOffset()));
767 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationsDirectoryItem,
768 collection.AnnotationsDirectoryItemsSize(),
769 collection.AnnotationsDirectoryItemsOffset()));
770
771 // Write the map items.
772 return WriteMapItems(offset, &queue);
Jeff Haoa8621002016-10-04 18:13:44 +0000773}
774
775void DexWriter::WriteHeader() {
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700776 StandardDexFile::Header header;
777 static constexpr size_t kMagicAndVersionLen =
778 StandardDexFile::kDexMagicSize + StandardDexFile::kDexVersionLen;
779 std::copy_n(header_->Magic(), kMagicAndVersionLen, header.magic_);
780 header.checksum_ = header_->Checksum();
781 std::copy_n(header_->Signature(), DexFile::kSha1DigestSize, header.signature_);
782 header.file_size_ = header_->FileSize();
783 header.header_size_ = header_->GetSize();
784 header.endian_tag_ = header_->EndianTag();
785 header.link_size_ = header_->LinkSize();
786 header.link_off_ = header_->LinkOffset();
787 const dex_ir::Collections& collections = header_->GetCollections();
788 header.map_off_ = collections.MapListOffset();
789 header.string_ids_size_ = collections.StringIdsSize();
790 header.string_ids_off_ = collections.StringIdsOffset();
791 header.type_ids_size_ = collections.TypeIdsSize();
792 header.type_ids_off_ = collections.TypeIdsOffset();
793 header.proto_ids_size_ = collections.ProtoIdsSize();
794 header.proto_ids_off_ = collections.ProtoIdsOffset();
795 header.field_ids_size_ = collections.FieldIdsSize();
796 header.field_ids_off_ = collections.FieldIdsOffset();
797 header.method_ids_size_ = collections.MethodIdsSize();
798 header.method_ids_off_ = collections.MethodIdsOffset();
799 header.class_defs_size_ = collections.ClassDefsSize();
800 header.class_defs_off_ = collections.ClassDefsOffset();
801 header.data_size_ = header_->DataSize();
802 header.data_off_ = header_->DataOffset();
803
804 static_assert(sizeof(header) == 0x70, "Size doesn't match dex spec");
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800805 UNUSED(Write(reinterpret_cast<uint8_t*>(&header), sizeof(header), 0u));
Jeff Haoa8621002016-10-04 18:13:44 +0000806}
807
Jeff Haoea7c6292016-11-14 18:10:16 -0800808void DexWriter::WriteMemMap() {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800809 // Starting offset is right after the header.
810 uint32_t offset = sizeof(StandardDexFile::Header);
811
812 dex_ir::Collections& collection = header_->GetCollections();
813
814 // Based on: https://source.android.com/devices/tech/dalvik/dex-format
815 // Since the offsets may not be calculated already, the writing must be done in the correct order.
816 const uint32_t string_ids_offset = offset;
817 offset += WriteStringIds(offset, /*reserve_only*/ true);
818 offset += WriteTypeIds(offset);
819 const uint32_t proto_ids_offset = offset;
820 offset += WriteProtoIds(offset, /*reserve_only*/ true);
821 offset += WriteFieldIds(offset);
822 offset += WriteMethodIds(offset);
823 const uint32_t class_defs_offset = offset;
824 offset += WriteClassDefs(offset, /*reserve_only*/ true);
825 const uint32_t call_site_ids_offset = offset;
826 offset += WriteCallSiteIds(offset, /*reserve_only*/ true);
827 offset += WriteMethodHandles(offset);
828
829 uint32_t data_offset_ = 0u;
830 if (compute_offsets_) {
831 // Data section.
832 offset = RoundUp(offset, kDataSectionAlignment);
833 data_offset_ = offset;
834 }
835
836 // Write code item first to minimize the space required for encoded methods.
837 // Reserve code item space since we need the debug offsets to actually write them.
838 const uint32_t code_items_offset = offset;
839 offset += WriteCodeItems(offset, /*reserve_only*/ true);
840 // Write debug info section.
841 offset += WriteDebugInfoItems(offset);
842 // Actually write code items since debug info offsets are calculated now.
843 WriteCodeItems(code_items_offset, /*reserve_only*/ false);
844
845 offset += WriteEncodedArrays(offset);
846 offset += WriteAnnotations(offset);
847 offset += WriteAnnotationSets(offset);
848 offset += WriteAnnotationSetRefs(offset);
849 offset += WriteAnnotationsDirectories(offset);
850 offset += WriteTypeLists(offset);
851 offset += WriteClassDatas(offset);
852 offset += WriteStringDatas(offset);
853
854 // Write delayed id sections that depend on data sections.
855 WriteStringIds(string_ids_offset, /*reserve_only*/ false);
856 WriteProtoIds(proto_ids_offset, /*reserve_only*/ false);
857 WriteClassDefs(class_defs_offset, /*reserve_only*/ false);
858 WriteCallSiteIds(call_site_ids_offset, /*reserve_only*/ false);
859
860 // Write the map list.
861 if (compute_offsets_) {
862 offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeMapList));
863 collection.SetMapListOffset(offset);
864 } else {
865 offset = collection.MapListOffset();
866 }
867 offset += GenerateAndWriteMapItems(offset);
868 offset = RoundUp(offset, kDataSectionAlignment);
869
870 // Map items are included in the data section.
871 if (compute_offsets_) {
872 header_->SetDataSize(offset - data_offset_);
873 if (header_->DataSize() != 0) {
874 // Offset must be zero when the size is zero.
875 header_->SetDataOffset(data_offset_);
876 } else {
877 header_->SetDataOffset(0u);
878 }
879 }
880
881 // TODO: Write link data?
882
883 // Write header last.
884 if (compute_offsets_) {
885 header_->SetFileSize(offset);
886 }
Jeff Haoa8621002016-10-04 18:13:44 +0000887 WriteHeader();
888}
889
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800890void DexWriter::Output(dex_ir::Header* header,
891 MemMap* mem_map,
892 DexLayout* dex_layout,
893 bool compute_offsets,
894 CompactDexLevel compact_dex_level) {
895 CHECK(dex_layout != nullptr);
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700896 std::unique_ptr<DexWriter> writer;
897 if (compact_dex_level != CompactDexLevel::kCompactDexLevelNone) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800898 writer.reset(new CompactDexWriter(header, mem_map, dex_layout, compact_dex_level));
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700899 } else {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800900 writer.reset(new DexWriter(header, mem_map, dex_layout, compute_offsets));
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700901 }
902 writer->WriteMemMap();
Jeff Haoa8621002016-10-04 18:13:44 +0000903}
904
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800905void MapItemQueue::AddIfNotEmpty(const MapItem& item) {
906 if (item.size_ != 0) {
907 push(item);
908 }
909}
910
Jeff Haoa8621002016-10-04 18:13:44 +0000911} // namespace art