blob: 365171b855d089b9180c2bf9ff9174d331504b1a [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 Chartierf95a75e2017-11-03 15:25:52 -070023#include "compact_dex_writer.h"
David Sehr9e734c72018-01-04 17:56:19 -080024#include "dex/compact_dex_file.h"
25#include "dex/dex_file_layout.h"
26#include "dex/dex_file_types.h"
27#include "dex/standard_dex_file.h"
David Sehr0225f8e2018-01-31 08:52:24 +000028#include "dex/utf.h"
Mathieu Chartier3e0c5172017-11-12 12:58:40 -080029#include "dexlayout.h"
Jeff Haoa8621002016-10-04 18:13:44 +000030
31namespace art {
32
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -080033constexpr uint32_t DexWriter::kDataSectionAlignment;
34
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -080035static size_t EncodeIntValue(int32_t value, uint8_t* buffer) {
Jeff Haoa8621002016-10-04 18:13:44 +000036 size_t length = 0;
37 if (value >= 0) {
38 while (value > 0x7f) {
39 buffer[length++] = static_cast<uint8_t>(value);
40 value >>= 8;
41 }
42 } else {
43 while (value < -0x80) {
44 buffer[length++] = static_cast<uint8_t>(value);
45 value >>= 8;
46 }
47 }
48 buffer[length++] = static_cast<uint8_t>(value);
49 return length;
50}
51
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -080052static size_t EncodeUIntValue(uint32_t value, uint8_t* buffer) {
Jeff Haoa8621002016-10-04 18:13:44 +000053 size_t length = 0;
54 do {
55 buffer[length++] = static_cast<uint8_t>(value);
56 value >>= 8;
57 } while (value != 0);
58 return length;
59}
60
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -080061static size_t EncodeLongValue(int64_t value, uint8_t* buffer) {
Jeff Haoa8621002016-10-04 18:13:44 +000062 size_t length = 0;
63 if (value >= 0) {
64 while (value > 0x7f) {
65 buffer[length++] = static_cast<uint8_t>(value);
66 value >>= 8;
67 }
68 } else {
69 while (value < -0x80) {
70 buffer[length++] = static_cast<uint8_t>(value);
71 value >>= 8;
72 }
73 }
74 buffer[length++] = static_cast<uint8_t>(value);
75 return length;
76}
77
78union FloatUnion {
79 float f_;
80 uint32_t i_;
81};
82
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -080083static size_t EncodeFloatValue(float value, uint8_t* buffer) {
Jeff Haoa8621002016-10-04 18:13:44 +000084 FloatUnion float_union;
85 float_union.f_ = value;
86 uint32_t int_value = float_union.i_;
87 size_t index = 3;
88 do {
89 buffer[index--] = int_value >> 24;
90 int_value <<= 8;
91 } while (int_value != 0);
92 return 3 - index;
93}
94
95union DoubleUnion {
96 double d_;
97 uint64_t l_;
98};
99
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800100static size_t EncodeDoubleValue(double value, uint8_t* buffer) {
Jeff Haoa8621002016-10-04 18:13:44 +0000101 DoubleUnion double_union;
102 double_union.d_ = value;
103 uint64_t long_value = double_union.l_;
104 size_t index = 7;
105 do {
106 buffer[index--] = long_value >> 56;
107 long_value <<= 8;
108 } while (long_value != 0);
109 return 7 - index;
110}
111
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800112DexWriter::DexWriter(DexLayout* dex_layout, bool compute_offsets)
113 : header_(dex_layout->GetHeader()),
114 dex_layout_(dex_layout),
115 compute_offsets_(compute_offsets) {}
Jeff Haoa8621002016-10-04 18:13:44 +0000116
Mathieu Chartier5e496142018-01-27 13:11:14 -0800117void DexWriter::WriteEncodedValue(Stream* stream, dex_ir::EncodedValue* encoded_value) {
Jeff Haoa8621002016-10-04 18:13:44 +0000118 size_t start = 0;
119 size_t length;
120 uint8_t buffer[8];
121 int8_t type = encoded_value->Type();
122 switch (type) {
123 case DexFile::kDexAnnotationByte:
124 length = EncodeIntValue(encoded_value->GetByte(), buffer);
125 break;
126 case DexFile::kDexAnnotationShort:
127 length = EncodeIntValue(encoded_value->GetShort(), buffer);
128 break;
129 case DexFile::kDexAnnotationChar:
130 length = EncodeUIntValue(encoded_value->GetChar(), buffer);
131 break;
132 case DexFile::kDexAnnotationInt:
133 length = EncodeIntValue(encoded_value->GetInt(), buffer);
134 break;
135 case DexFile::kDexAnnotationLong:
136 length = EncodeLongValue(encoded_value->GetLong(), buffer);
137 break;
138 case DexFile::kDexAnnotationFloat:
139 length = EncodeFloatValue(encoded_value->GetFloat(), buffer);
140 start = 4 - length;
141 break;
142 case DexFile::kDexAnnotationDouble:
143 length = EncodeDoubleValue(encoded_value->GetDouble(), buffer);
144 start = 8 - length;
145 break;
Jeff Hao5daee902017-04-27 18:00:38 -0700146 case DexFile::kDexAnnotationMethodType:
147 length = EncodeUIntValue(encoded_value->GetProtoId()->GetIndex(), buffer);
148 break;
149 case DexFile::kDexAnnotationMethodHandle:
150 length = EncodeUIntValue(encoded_value->GetMethodHandle()->GetIndex(), buffer);
151 break;
Jeff Haoa8621002016-10-04 18:13:44 +0000152 case DexFile::kDexAnnotationString:
153 length = EncodeUIntValue(encoded_value->GetStringId()->GetIndex(), buffer);
154 break;
155 case DexFile::kDexAnnotationType:
156 length = EncodeUIntValue(encoded_value->GetTypeId()->GetIndex(), buffer);
157 break;
158 case DexFile::kDexAnnotationField:
159 case DexFile::kDexAnnotationEnum:
160 length = EncodeUIntValue(encoded_value->GetFieldId()->GetIndex(), buffer);
161 break;
162 case DexFile::kDexAnnotationMethod:
163 length = EncodeUIntValue(encoded_value->GetMethodId()->GetIndex(), buffer);
164 break;
165 case DexFile::kDexAnnotationArray:
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800166 WriteEncodedValueHeader(stream, type, 0);
167 WriteEncodedArray(stream, encoded_value->GetEncodedArray()->GetEncodedValues());
Mathieu Chartier5e496142018-01-27 13:11:14 -0800168 return;
Jeff Haoa8621002016-10-04 18:13:44 +0000169 case DexFile::kDexAnnotationAnnotation:
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800170 WriteEncodedValueHeader(stream, type, 0);
171 WriteEncodedAnnotation(stream, encoded_value->GetEncodedAnnotation());
Mathieu Chartier5e496142018-01-27 13:11:14 -0800172 return;
Jeff Haoa8621002016-10-04 18:13:44 +0000173 case DexFile::kDexAnnotationNull:
Mathieu Chartier5e496142018-01-27 13:11:14 -0800174 WriteEncodedValueHeader(stream, type, 0);
175 return;
Jeff Haoa8621002016-10-04 18:13:44 +0000176 case DexFile::kDexAnnotationBoolean:
Mathieu Chartier5e496142018-01-27 13:11:14 -0800177 WriteEncodedValueHeader(stream, type, encoded_value->GetBoolean() ? 1 : 0);
178 return;
Jeff Haoa8621002016-10-04 18:13:44 +0000179 default:
Mathieu Chartier5e496142018-01-27 13:11:14 -0800180 return;
Jeff Haoa8621002016-10-04 18:13:44 +0000181 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800182 WriteEncodedValueHeader(stream, type, length - 1);
183 stream->Write(buffer + start, length);
Jeff Haoa8621002016-10-04 18:13:44 +0000184}
185
Mathieu Chartier5e496142018-01-27 13:11:14 -0800186void DexWriter::WriteEncodedValueHeader(Stream* stream, int8_t value_type, size_t value_arg) {
Jeff Haoa8621002016-10-04 18:13:44 +0000187 uint8_t buffer[1] = { static_cast<uint8_t>((value_arg << 5) | value_type) };
Mathieu Chartier5e496142018-01-27 13:11:14 -0800188 stream->Write(buffer, sizeof(uint8_t));
Jeff Haoa8621002016-10-04 18:13:44 +0000189}
190
Mathieu Chartier5e496142018-01-27 13:11:14 -0800191void DexWriter::WriteEncodedArray(Stream* stream, dex_ir::EncodedValueVector* values) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800192 stream->WriteUleb128(values->size());
Jeff Haoa8621002016-10-04 18:13:44 +0000193 for (std::unique_ptr<dex_ir::EncodedValue>& value : *values) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800194 WriteEncodedValue(stream, value.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000195 }
Jeff Haoa8621002016-10-04 18:13:44 +0000196}
197
Mathieu Chartier5e496142018-01-27 13:11:14 -0800198void DexWriter::WriteEncodedAnnotation(Stream* stream, dex_ir::EncodedAnnotation* annotation) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800199 stream->WriteUleb128(annotation->GetType()->GetIndex());
200 stream->WriteUleb128(annotation->GetAnnotationElements()->size());
Jeff Haoa8621002016-10-04 18:13:44 +0000201 for (std::unique_ptr<dex_ir::AnnotationElement>& annotation_element :
202 *annotation->GetAnnotationElements()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800203 stream->WriteUleb128(annotation_element->GetName()->GetIndex());
204 WriteEncodedValue(stream, annotation_element->GetValue());
Jeff Haoa8621002016-10-04 18:13:44 +0000205 }
Jeff Haoa8621002016-10-04 18:13:44 +0000206}
207
Mathieu Chartier5e496142018-01-27 13:11:14 -0800208void DexWriter::WriteEncodedFields(Stream* stream, dex_ir::FieldItemVector* fields) {
Jeff Haoa8621002016-10-04 18:13:44 +0000209 uint32_t prev_index = 0;
David Sehrd83437c2018-06-11 14:06:23 -0700210 for (auto& field : *fields) {
211 uint32_t index = field.GetFieldId()->GetIndex();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800212 stream->WriteUleb128(index - prev_index);
David Sehrd83437c2018-06-11 14:06:23 -0700213 stream->WriteUleb128(field.GetAccessFlags());
Jeff Haoa8621002016-10-04 18:13:44 +0000214 prev_index = index;
215 }
Jeff Haoa8621002016-10-04 18:13:44 +0000216}
217
Mathieu Chartier5e496142018-01-27 13:11:14 -0800218void DexWriter::WriteEncodedMethods(Stream* stream, dex_ir::MethodItemVector* methods) {
Jeff Haoa8621002016-10-04 18:13:44 +0000219 uint32_t prev_index = 0;
David Sehrd83437c2018-06-11 14:06:23 -0700220 for (auto& method : *methods) {
221 uint32_t index = method.GetMethodId()->GetIndex();
222 uint32_t code_off = method.GetCodeItem() == nullptr ? 0 : method.GetCodeItem()->GetOffset();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800223 stream->WriteUleb128(index - prev_index);
David Sehrd83437c2018-06-11 14:06:23 -0700224 stream->WriteUleb128(method.GetAccessFlags());
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800225 stream->WriteUleb128(code_off);
Jeff Haoa8621002016-10-04 18:13:44 +0000226 prev_index = index;
227 }
Jeff Haoa8621002016-10-04 18:13:44 +0000228}
229
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800230// TODO: Refactor this to remove duplicated boiler plate. One way to do this is adding
231// function that takes a CollectionVector<T> and uses overloading.
Mathieu Chartier5e496142018-01-27 13:11:14 -0800232void DexWriter::WriteStringIds(Stream* stream, bool reserve_only) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800233 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700234 for (auto& string_id : header_->StringIds()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800235 stream->AlignTo(SectionAlignment(DexFile::kDexTypeStringIdItem));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800236 if (reserve_only) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800237 stream->Skip(string_id->GetSize());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800238 } else {
239 uint32_t string_data_off = string_id->DataItem()->GetOffset();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800240 stream->Write(&string_data_off, string_id->GetSize());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800241 }
Jeff Haoa8621002016-10-04 18:13:44 +0000242 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800243 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700244 header_->StringIds().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800245 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800246}
Jeff Haoa8621002016-10-04 18:13:44 +0000247
Mathieu Chartierb81ecad2018-01-23 22:08:26 -0800248void DexWriter::WriteStringData(Stream* stream, dex_ir::StringData* string_data) {
249 ProcessOffset(stream, string_data);
250 stream->AlignTo(SectionAlignment(DexFile::kDexTypeStringDataItem));
251 stream->WriteUleb128(CountModifiedUtf8Chars(string_data->Data()));
252 stream->Write(string_data->Data(), strlen(string_data->Data()));
253 // Skip null terminator (already zeroed out, no need to write).
254 stream->Skip(1);
255}
256
Mathieu Chartier5e496142018-01-27 13:11:14 -0800257void DexWriter::WriteStringDatas(Stream* stream) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800258 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700259 for (auto& string_data : header_->StringDatas()) {
Mathieu Chartierb81ecad2018-01-23 22:08:26 -0800260 WriteStringData(stream, string_data.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000261 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800262 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700263 header_->StringDatas().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800264 }
Jeff Haoa8621002016-10-04 18:13:44 +0000265}
266
Mathieu Chartier5e496142018-01-27 13:11:14 -0800267void DexWriter::WriteTypeIds(Stream* stream) {
Jeff Haoa8621002016-10-04 18:13:44 +0000268 uint32_t descriptor_idx[1];
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800269 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700270 for (auto& type_id : header_->TypeIds()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800271 stream->AlignTo(SectionAlignment(DexFile::kDexTypeTypeIdItem));
272 ProcessOffset(stream, type_id.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000273 descriptor_idx[0] = type_id->GetStringId()->GetIndex();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800274 stream->Write(descriptor_idx, type_id->GetSize());
Jeff Haoa8621002016-10-04 18:13:44 +0000275 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800276 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700277 header_->TypeIds().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800278 }
Jeff Haoa8621002016-10-04 18:13:44 +0000279}
280
Mathieu Chartier5e496142018-01-27 13:11:14 -0800281void DexWriter::WriteTypeLists(Stream* stream) {
Jeff Haoa8621002016-10-04 18:13:44 +0000282 uint32_t size[1];
283 uint16_t list[1];
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800284 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700285 for (auto& type_list : header_->TypeLists()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800286 stream->AlignTo(SectionAlignment(DexFile::kDexTypeTypeList));
Jeff Haoa8621002016-10-04 18:13:44 +0000287 size[0] = type_list->GetTypeList()->size();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800288 ProcessOffset(stream, type_list.get());
289 stream->Write(size, sizeof(uint32_t));
Jeff Haoa8621002016-10-04 18:13:44 +0000290 for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) {
291 list[0] = type_id->GetIndex();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800292 stream->Write(list, sizeof(uint16_t));
Jeff Haoa8621002016-10-04 18:13:44 +0000293 }
294 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800295 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700296 header_->TypeLists().SetOffset(start);
Jeff Haoa8621002016-10-04 18:13:44 +0000297 }
298}
299
Mathieu Chartier5e496142018-01-27 13:11:14 -0800300void DexWriter::WriteProtoIds(Stream* stream, bool reserve_only) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800301 uint32_t buffer[3];
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800302 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700303 for (auto& proto_id : header_->ProtoIds()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800304 stream->AlignTo(SectionAlignment(DexFile::kDexTypeProtoIdItem));
305 ProcessOffset(stream, proto_id.get());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800306 if (reserve_only) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800307 stream->Skip(proto_id->GetSize());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800308 } else {
309 buffer[0] = proto_id->Shorty()->GetIndex();
310 buffer[1] = proto_id->ReturnType()->GetIndex();
311 buffer[2] = proto_id->Parameters() == nullptr ? 0 : proto_id->Parameters()->GetOffset();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800312 stream->Write(buffer, proto_id->GetSize());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800313 }
314 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800315 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700316 header_->ProtoIds().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800317 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800318}
319
Mathieu Chartier5e496142018-01-27 13:11:14 -0800320void DexWriter::WriteFieldIds(Stream* stream) {
Jeff Haoa8621002016-10-04 18:13:44 +0000321 uint16_t buffer[4];
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800322 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700323 for (auto& field_id : header_->FieldIds()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800324 stream->AlignTo(SectionAlignment(DexFile::kDexTypeFieldIdItem));
325 ProcessOffset(stream, field_id.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000326 buffer[0] = field_id->Class()->GetIndex();
327 buffer[1] = field_id->Type()->GetIndex();
328 buffer[2] = field_id->Name()->GetIndex();
329 buffer[3] = field_id->Name()->GetIndex() >> 16;
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800330 stream->Write(buffer, field_id->GetSize());
Jeff Haoa8621002016-10-04 18:13:44 +0000331 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800332 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700333 header_->FieldIds().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800334 }
Jeff Haoa8621002016-10-04 18:13:44 +0000335}
336
Mathieu Chartier5e496142018-01-27 13:11:14 -0800337void DexWriter::WriteMethodIds(Stream* stream) {
Jeff Haoa8621002016-10-04 18:13:44 +0000338 uint16_t buffer[4];
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800339 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700340 for (auto& method_id : header_->MethodIds()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800341 stream->AlignTo(SectionAlignment(DexFile::kDexTypeMethodIdItem));
342 ProcessOffset(stream, method_id.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000343 buffer[0] = method_id->Class()->GetIndex();
344 buffer[1] = method_id->Proto()->GetIndex();
345 buffer[2] = method_id->Name()->GetIndex();
346 buffer[3] = method_id->Name()->GetIndex() >> 16;
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800347 stream->Write(buffer, method_id->GetSize());
Jeff Haoa8621002016-10-04 18:13:44 +0000348 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800349 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700350 header_->MethodIds().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800351 }
Jeff Haoa8621002016-10-04 18:13:44 +0000352}
353
Mathieu Chartier5e496142018-01-27 13:11:14 -0800354void DexWriter::WriteEncodedArrays(Stream* stream) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800355 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700356 for (auto& encoded_array : header_->EncodedArrayItems()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800357 stream->AlignTo(SectionAlignment(DexFile::kDexTypeEncodedArrayItem));
358 ProcessOffset(stream, encoded_array.get());
359 WriteEncodedArray(stream, encoded_array->GetEncodedValues());
Jeff Haoa8621002016-10-04 18:13:44 +0000360 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800361 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700362 header_->EncodedArrayItems().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800363 }
Jeff Haoa8621002016-10-04 18:13:44 +0000364}
365
Mathieu Chartier5e496142018-01-27 13:11:14 -0800366void DexWriter::WriteAnnotations(Stream* stream) {
Jeff Haoa8621002016-10-04 18:13:44 +0000367 uint8_t visibility[1];
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800368 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700369 for (auto& annotation : header_->AnnotationItems()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800370 stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationItem));
Jeff Haoa8621002016-10-04 18:13:44 +0000371 visibility[0] = annotation->GetVisibility();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800372 ProcessOffset(stream, annotation.get());
373 stream->Write(visibility, sizeof(uint8_t));
374 WriteEncodedAnnotation(stream, annotation->GetAnnotation());
Jeff Haoa8621002016-10-04 18:13:44 +0000375 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800376 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700377 header_->AnnotationItems().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800378 }
Jeff Haoa8621002016-10-04 18:13:44 +0000379}
380
Mathieu Chartier5e496142018-01-27 13:11:14 -0800381void DexWriter::WriteAnnotationSets(Stream* stream) {
Jeff Haoa8621002016-10-04 18:13:44 +0000382 uint32_t size[1];
383 uint32_t annotation_off[1];
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800384 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700385 for (auto& annotation_set : header_->AnnotationSetItems()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800386 stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationSetItem));
Jeff Haoa8621002016-10-04 18:13:44 +0000387 size[0] = annotation_set->GetItems()->size();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800388 ProcessOffset(stream, annotation_set.get());
389 stream->Write(size, sizeof(uint32_t));
Jeff Haoa8621002016-10-04 18:13:44 +0000390 for (dex_ir::AnnotationItem* annotation : *annotation_set->GetItems()) {
391 annotation_off[0] = annotation->GetOffset();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800392 stream->Write(annotation_off, sizeof(uint32_t));
Jeff Haoa8621002016-10-04 18:13:44 +0000393 }
394 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800395 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700396 header_->AnnotationSetItems().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800397 }
Jeff Haoa8621002016-10-04 18:13:44 +0000398}
399
Mathieu Chartier5e496142018-01-27 13:11:14 -0800400void DexWriter::WriteAnnotationSetRefs(Stream* stream) {
Jeff Haoa8621002016-10-04 18:13:44 +0000401 uint32_t size[1];
402 uint32_t annotations_off[1];
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800403 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700404 for (auto& annotation_set_ref : header_->AnnotationSetRefLists()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800405 stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationSetRefList));
Jeff Haoa8621002016-10-04 18:13:44 +0000406 size[0] = annotation_set_ref->GetItems()->size();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800407 ProcessOffset(stream, annotation_set_ref.get());
408 stream->Write(size, sizeof(uint32_t));
Jeff Haoa8621002016-10-04 18:13:44 +0000409 for (dex_ir::AnnotationSetItem* annotation_set : *annotation_set_ref->GetItems()) {
410 annotations_off[0] = annotation_set == nullptr ? 0 : annotation_set->GetOffset();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800411 stream->Write(annotations_off, sizeof(uint32_t));
Jeff Haoa8621002016-10-04 18:13:44 +0000412 }
413 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800414 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700415 header_->AnnotationSetRefLists().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800416 }
Jeff Haoa8621002016-10-04 18:13:44 +0000417}
418
Mathieu Chartier5e496142018-01-27 13:11:14 -0800419void DexWriter::WriteAnnotationsDirectories(Stream* stream) {
Jeff Haoa8621002016-10-04 18:13:44 +0000420 uint32_t directory_buffer[4];
421 uint32_t annotation_buffer[2];
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800422 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700423 for (auto& annotations_directory : header_->AnnotationsDirectoryItems()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800424 stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationsDirectoryItem));
425 ProcessOffset(stream, annotations_directory.get());
Jeff Haoa8621002016-10-04 18:13:44 +0000426 directory_buffer[0] = annotations_directory->GetClassAnnotation() == nullptr ? 0 :
427 annotations_directory->GetClassAnnotation()->GetOffset();
428 directory_buffer[1] = annotations_directory->GetFieldAnnotations() == nullptr ? 0 :
429 annotations_directory->GetFieldAnnotations()->size();
430 directory_buffer[2] = annotations_directory->GetMethodAnnotations() == nullptr ? 0 :
431 annotations_directory->GetMethodAnnotations()->size();
432 directory_buffer[3] = annotations_directory->GetParameterAnnotations() == nullptr ? 0 :
433 annotations_directory->GetParameterAnnotations()->size();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800434 stream->Write(directory_buffer, 4 * sizeof(uint32_t));
Jeff Haoa8621002016-10-04 18:13:44 +0000435 if (annotations_directory->GetFieldAnnotations() != nullptr) {
436 for (std::unique_ptr<dex_ir::FieldAnnotation>& field :
437 *annotations_directory->GetFieldAnnotations()) {
438 annotation_buffer[0] = field->GetFieldId()->GetIndex();
439 annotation_buffer[1] = field->GetAnnotationSetItem()->GetOffset();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800440 stream->Write(annotation_buffer, 2 * sizeof(uint32_t));
Jeff Haoa8621002016-10-04 18:13:44 +0000441 }
442 }
443 if (annotations_directory->GetMethodAnnotations() != nullptr) {
444 for (std::unique_ptr<dex_ir::MethodAnnotation>& method :
445 *annotations_directory->GetMethodAnnotations()) {
446 annotation_buffer[0] = method->GetMethodId()->GetIndex();
447 annotation_buffer[1] = method->GetAnnotationSetItem()->GetOffset();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800448 stream->Write(annotation_buffer, 2 * sizeof(uint32_t));
Jeff Haoa8621002016-10-04 18:13:44 +0000449 }
450 }
451 if (annotations_directory->GetParameterAnnotations() != nullptr) {
452 for (std::unique_ptr<dex_ir::ParameterAnnotation>& parameter :
453 *annotations_directory->GetParameterAnnotations()) {
454 annotation_buffer[0] = parameter->GetMethodId()->GetIndex();
455 annotation_buffer[1] = parameter->GetAnnotations()->GetOffset();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800456 stream->Write(annotation_buffer, 2 * sizeof(uint32_t));
Jeff Haoa8621002016-10-04 18:13:44 +0000457 }
458 }
459 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800460 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700461 header_->AnnotationsDirectoryItems().SetOffset(start);
Jeff Haoa8621002016-10-04 18:13:44 +0000462 }
463}
464
Mathieu Chartierb81ecad2018-01-23 22:08:26 -0800465void DexWriter::WriteDebugInfoItem(Stream* stream, dex_ir::DebugInfoItem* debug_info) {
466 stream->AlignTo(SectionAlignment(DexFile::kDexTypeDebugInfoItem));
467 ProcessOffset(stream, debug_info);
468 stream->Write(debug_info->GetDebugInfo(), debug_info->GetDebugInfoSize());
469}
470
Mathieu Chartier5e496142018-01-27 13:11:14 -0800471void DexWriter::WriteDebugInfoItems(Stream* stream) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800472 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700473 for (auto& debug_info : header_->DebugInfoItems()) {
Mathieu Chartierb81ecad2018-01-23 22:08:26 -0800474 WriteDebugInfoItem(stream, debug_info.get());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800475 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800476 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700477 header_->DebugInfoItems().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800478 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800479}
480
Mathieu Chartier5e496142018-01-27 13:11:14 -0800481void DexWriter::WriteCodeItemPostInstructionData(Stream* stream,
482 dex_ir::CodeItem* code_item,
483 bool reserve_only) {
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800484 if (code_item->TriesSize() != 0) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800485 stream->AlignTo(DexFile::TryItem::kAlignment);
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800486 // Write try items.
487 for (std::unique_ptr<const dex_ir::TryItem>& try_item : *code_item->Tries()) {
488 DexFile::TryItem disk_try_item;
489 if (!reserve_only) {
490 disk_try_item.start_addr_ = try_item->StartAddr();
491 disk_try_item.insn_count_ = try_item->InsnCount();
492 disk_try_item.handler_off_ = try_item->GetHandlers()->GetListOffset();
493 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800494 stream->Write(&disk_try_item, sizeof(disk_try_item));
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800495 }
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800496 // Leave offset pointing to the end of the try items.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800497 const size_t offset = stream->Tell();
498 size_t max_offset = offset + stream->WriteUleb128(code_item->Handlers()->size());
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800499 for (std::unique_ptr<const dex_ir::CatchHandler>& handlers : *code_item->Handlers()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800500 stream->Seek(offset + handlers->GetListOffset());
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800501 uint32_t size = handlers->HasCatchAll() ? (handlers->GetHandlers()->size() - 1) * -1 :
502 handlers->GetHandlers()->size();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800503 stream->WriteSleb128(size);
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800504 for (std::unique_ptr<const dex_ir::TypeAddrPair>& handler : *handlers->GetHandlers()) {
505 if (handler->GetTypeId() != nullptr) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800506 stream->WriteUleb128(handler->GetTypeId()->GetIndex());
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800507 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800508 stream->WriteUleb128(handler->GetAddress());
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800509 }
510 // TODO: Clean this up to write the handlers in address order.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800511 max_offset = std::max(max_offset, stream->Tell());
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800512 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800513 stream->Seek(max_offset);
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800514 }
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800515}
516
Mathieu Chartierb81ecad2018-01-23 22:08:26 -0800517void DexWriter::WriteCodeItem(Stream* stream,
518 dex_ir::CodeItem* code_item,
519 bool reserve_only) {
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800520 DCHECK(code_item != nullptr);
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800521 const uint32_t start_offset = stream->Tell();
522 stream->AlignTo(SectionAlignment(DexFile::kDexTypeCodeItem));
523 ProcessOffset(stream, code_item);
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800524
525 StandardDexFile::CodeItem disk_code_item;
526 if (!reserve_only) {
527 disk_code_item.registers_size_ = code_item->RegistersSize();
528 disk_code_item.ins_size_ = code_item->InsSize();
529 disk_code_item.outs_size_ = code_item->OutsSize();
530 disk_code_item.tries_size_ = code_item->TriesSize();
531 disk_code_item.debug_info_off_ = code_item->DebugInfo() == nullptr
532 ? 0
533 : code_item->DebugInfo()->GetOffset();
534 disk_code_item.insns_size_in_code_units_ = code_item->InsnsSize();
535 }
536 // Avoid using sizeof so that we don't write the fake instruction array at the end of the code
537 // item.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800538 stream->Write(&disk_code_item, OFFSETOF_MEMBER(StandardDexFile::CodeItem, insns_));
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800539 // Write the instructions.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800540 stream->Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t));
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800541 // Write the post instruction data.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800542 WriteCodeItemPostInstructionData(stream, code_item, reserve_only);
543 if (reserve_only) {
544 stream->Clear(start_offset, stream->Tell() - start_offset);
545 }
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800546}
547
Mathieu Chartier5e496142018-01-27 13:11:14 -0800548void DexWriter::WriteCodeItems(Stream* stream, bool reserve_only) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800549 DexLayoutSection* code_section = nullptr;
550 if (!reserve_only && dex_layout_ != nullptr) {
551 code_section = &dex_layout_->GetSections().sections_[static_cast<size_t>(
552 DexLayoutSections::SectionType::kSectionTypeCode)];
553 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800554 const uint32_t start = stream->Tell();
David Sehr2b5a38f2018-06-14 15:13:04 -0700555 for (auto& code_item : header_->CodeItems()) {
Mathieu Chartierb81ecad2018-01-23 22:08:26 -0800556 uint32_t start_offset = stream->Tell();
557 WriteCodeItem(stream, code_item.get(), reserve_only);
Mathieu Chartier8892c6b2018-01-09 15:10:17 -0800558 // Only add the section hotness info once.
559 if (!reserve_only && code_section != nullptr) {
560 auto it = dex_layout_->LayoutHotnessInfo().code_item_layout_.find(code_item.get());
561 if (it != dex_layout_->LayoutHotnessInfo().code_item_layout_.end()) {
562 code_section->parts_[static_cast<size_t>(it->second)].CombineSection(
Mathieu Chartierb81ecad2018-01-23 22:08:26 -0800563 start_offset,
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800564 stream->Tell());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800565 }
566 }
Jeff Haoa8621002016-10-04 18:13:44 +0000567 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800568
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800569 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700570 header_->CodeItems().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800571 }
Jeff Haoa8621002016-10-04 18:13:44 +0000572}
573
Mathieu Chartier5e496142018-01-27 13:11:14 -0800574void DexWriter::WriteClassDefs(Stream* stream, bool reserve_only) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800575 const uint32_t start = stream->Tell();
Jeff Haoa8621002016-10-04 18:13:44 +0000576 uint32_t class_def_buffer[8];
David Sehr2b5a38f2018-06-14 15:13:04 -0700577 for (auto& class_def : header_->ClassDefs()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800578 stream->AlignTo(SectionAlignment(DexFile::kDexTypeClassDefItem));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800579 if (reserve_only) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800580 stream->Skip(class_def->GetSize());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800581 } else {
582 class_def_buffer[0] = class_def->ClassType()->GetIndex();
583 class_def_buffer[1] = class_def->GetAccessFlags();
584 class_def_buffer[2] = class_def->Superclass() == nullptr ? dex::kDexNoIndex :
585 class_def->Superclass()->GetIndex();
586 class_def_buffer[3] = class_def->InterfacesOffset();
587 class_def_buffer[4] = class_def->SourceFile() == nullptr ? dex::kDexNoIndex :
588 class_def->SourceFile()->GetIndex();
589 class_def_buffer[5] = class_def->Annotations() == nullptr ? 0 :
590 class_def->Annotations()->GetOffset();
591 class_def_buffer[6] = class_def->GetClassData() == nullptr ? 0 :
592 class_def->GetClassData()->GetOffset();
593 class_def_buffer[7] = class_def->StaticValues() == nullptr ? 0 :
594 class_def->StaticValues()->GetOffset();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800595 stream->Write(class_def_buffer, class_def->GetSize());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800596 }
Jeff Haoa8621002016-10-04 18:13:44 +0000597 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800598 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700599 header_->ClassDefs().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800600 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800601}
Jeff Haoa8621002016-10-04 18:13:44 +0000602
Mathieu Chartier5e496142018-01-27 13:11:14 -0800603void DexWriter::WriteClassDatas(Stream* stream) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800604 const uint32_t start = stream->Tell();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800605 for (const std::unique_ptr<dex_ir::ClassData>& class_data :
David Sehr2b5a38f2018-06-14 15:13:04 -0700606 header_->ClassDatas()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800607 stream->AlignTo(SectionAlignment(DexFile::kDexTypeClassDataItem));
608 ProcessOffset(stream, class_data.get());
609 stream->WriteUleb128(class_data->StaticFields()->size());
610 stream->WriteUleb128(class_data->InstanceFields()->size());
611 stream->WriteUleb128(class_data->DirectMethods()->size());
612 stream->WriteUleb128(class_data->VirtualMethods()->size());
613 WriteEncodedFields(stream, class_data->StaticFields());
614 WriteEncodedFields(stream, class_data->InstanceFields());
615 WriteEncodedMethods(stream, class_data->DirectMethods());
616 WriteEncodedMethods(stream, class_data->VirtualMethods());
Jeff Haoa8621002016-10-04 18:13:44 +0000617 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800618 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700619 header_->ClassDatas().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800620 }
Jeff Haoa8621002016-10-04 18:13:44 +0000621}
622
Mathieu Chartier5e496142018-01-27 13:11:14 -0800623void DexWriter::WriteCallSiteIds(Stream* stream, bool reserve_only) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800624 const uint32_t start = stream->Tell();
Jeff Hao5daee902017-04-27 18:00:38 -0700625 uint32_t call_site_off[1];
David Sehr2b5a38f2018-06-14 15:13:04 -0700626 for (auto& call_site_id : header_->CallSiteIds()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800627 stream->AlignTo(SectionAlignment(DexFile::kDexTypeCallSiteIdItem));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800628 if (reserve_only) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800629 stream->Skip(call_site_id->GetSize());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800630 } else {
631 call_site_off[0] = call_site_id->CallSiteItem()->GetOffset();
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800632 stream->Write(call_site_off, call_site_id->GetSize());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800633 }
Jeff Hao5daee902017-04-27 18:00:38 -0700634 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800635 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700636 header_->CallSiteIds().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800637 }
Jeff Hao5daee902017-04-27 18:00:38 -0700638}
639
Mathieu Chartier5e496142018-01-27 13:11:14 -0800640void DexWriter::WriteMethodHandles(Stream* stream) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800641 const uint32_t start = stream->Tell();
Jeff Hao5daee902017-04-27 18:00:38 -0700642 uint16_t method_handle_buff[4];
David Sehr2b5a38f2018-06-14 15:13:04 -0700643 for (auto& method_handle : header_->MethodHandleItems()) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800644 stream->AlignTo(SectionAlignment(DexFile::kDexTypeMethodHandleItem));
Jeff Hao5daee902017-04-27 18:00:38 -0700645 method_handle_buff[0] = static_cast<uint16_t>(method_handle->GetMethodHandleType());
646 method_handle_buff[1] = 0; // unused.
647 method_handle_buff[2] = method_handle->GetFieldOrMethodId()->GetIndex();
648 method_handle_buff[3] = 0; // unused.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800649 stream->Write(method_handle_buff, method_handle->GetSize());
Jeff Hao5daee902017-04-27 18:00:38 -0700650 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800651 if (compute_offsets_ && start != stream->Tell()) {
David Sehr2b5a38f2018-06-14 15:13:04 -0700652 header_->MethodHandleItems().SetOffset(start);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800653 }
Jeff Hao5daee902017-04-27 18:00:38 -0700654}
655
Mathieu Chartier5e496142018-01-27 13:11:14 -0800656void DexWriter::WriteMapItems(Stream* stream, MapItemQueue* queue) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800657 // All the sections should already have been added.
Mathieu Chartier9b302bf2018-01-25 13:08:08 -0800658 const uint32_t map_list_size = queue->size();
Mathieu Chartier9b302bf2018-01-25 13:08:08 -0800659 stream->Write(&map_list_size, sizeof(map_list_size));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800660 while (!queue->empty()) {
Mathieu Chartier9b302bf2018-01-25 13:08:08 -0800661 const MapItem& item = queue->top();
662 DexFile::MapItem map_item;
663 map_item.type_ = item.type_;
664 map_item.size_ = item.size_;
665 map_item.offset_ = item.offset_;
666 map_item.unused_ = 0u;
667 stream->Write(&map_item, sizeof(map_item));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800668 queue->pop();
Jeff Haoa8621002016-10-04 18:13:44 +0000669 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800670}
671
Mathieu Chartier5e496142018-01-27 13:11:14 -0800672void DexWriter::GenerateAndWriteMapItems(Stream* stream) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800673 MapItemQueue queue;
674
675 // Header and index section.
676 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeHeaderItem, 1, 0));
677 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringIdItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700678 header_->StringIds().Size(),
679 header_->StringIds().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800680 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeIdItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700681 header_->TypeIds().Size(),
682 header_->TypeIds().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800683 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeProtoIdItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700684 header_->ProtoIds().Size(),
685 header_->ProtoIds().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800686 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeFieldIdItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700687 header_->FieldIds().Size(),
688 header_->FieldIds().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800689 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodIdItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700690 header_->MethodIds().Size(),
691 header_->MethodIds().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800692 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDefItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700693 header_->ClassDefs().Size(),
694 header_->ClassDefs().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800695 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCallSiteIdItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700696 header_->CallSiteIds().Size(),
697 header_->CallSiteIds().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800698 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodHandleItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700699 header_->MethodHandleItems().Size(),
700 header_->MethodHandleItems().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800701 // Data section.
David Sehr2b5a38f2018-06-14 15:13:04 -0700702 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMapList, 1, header_->MapListOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800703 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeList,
David Sehr2b5a38f2018-06-14 15:13:04 -0700704 header_->TypeLists().Size(),
705 header_->TypeLists().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800706 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetRefList,
David Sehr2b5a38f2018-06-14 15:13:04 -0700707 header_->AnnotationSetRefLists().Size(),
708 header_->AnnotationSetRefLists().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800709 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700710 header_->AnnotationSetItems().Size(),
711 header_->AnnotationSetItems().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800712 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDataItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700713 header_->ClassDatas().Size(),
714 header_->ClassDatas().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800715 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCodeItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700716 header_->CodeItems().Size(),
717 header_->CodeItems().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800718 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringDataItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700719 header_->StringDatas().Size(),
720 header_->StringDatas().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800721 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeDebugInfoItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700722 header_->DebugInfoItems().Size(),
723 header_->DebugInfoItems().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800724 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700725 header_->AnnotationItems().Size(),
726 header_->AnnotationItems().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800727 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeEncodedArrayItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700728 header_->EncodedArrayItems().Size(),
729 header_->EncodedArrayItems().GetOffset()));
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800730 queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationsDirectoryItem,
David Sehr2b5a38f2018-06-14 15:13:04 -0700731 header_->AnnotationsDirectoryItems().Size(),
732 header_->AnnotationsDirectoryItems().GetOffset()));
Mathieu Chartier5e496142018-01-27 13:11:14 -0800733 WriteMapItems(stream, &queue);
Jeff Haoa8621002016-10-04 18:13:44 +0000734}
735
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800736void DexWriter::WriteHeader(Stream* stream) {
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700737 StandardDexFile::Header header;
Mathieu Chartier21cf2582018-01-08 17:09:48 -0800738 if (CompactDexFile::IsMagicValid(header_->Magic())) {
739 StandardDexFile::WriteMagic(header.magic_);
740 // TODO: Should we write older versions based on the feature flags?
741 StandardDexFile::WriteCurrentVersion(header.magic_);
742 } else {
743 // Standard dex -> standard dex, just reuse the same header.
744 static constexpr size_t kMagicAndVersionLen =
745 StandardDexFile::kDexMagicSize + StandardDexFile::kDexVersionLen;
746 std::copy_n(header_->Magic(), kMagicAndVersionLen, header.magic_);
747 }
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700748 header.checksum_ = header_->Checksum();
749 std::copy_n(header_->Signature(), DexFile::kSha1DigestSize, header.signature_);
750 header.file_size_ = header_->FileSize();
Mathieu Chartierf6e31472017-12-28 13:32:08 -0800751 header.header_size_ = GetHeaderSize();
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700752 header.endian_tag_ = header_->EndianTag();
753 header.link_size_ = header_->LinkSize();
754 header.link_off_ = header_->LinkOffset();
David Sehr2b5a38f2018-06-14 15:13:04 -0700755 header.map_off_ = header_->MapListOffset();
756 header.string_ids_size_ = header_->StringIds().Size();
757 header.string_ids_off_ = header_->StringIds().GetOffset();
758 header.type_ids_size_ = header_->TypeIds().Size();
759 header.type_ids_off_ = header_->TypeIds().GetOffset();
760 header.proto_ids_size_ = header_->ProtoIds().Size();
761 header.proto_ids_off_ = header_->ProtoIds().GetOffset();
762 header.field_ids_size_ = header_->FieldIds().Size();
763 header.field_ids_off_ = header_->FieldIds().GetOffset();
764 header.method_ids_size_ = header_->MethodIds().Size();
765 header.method_ids_off_ = header_->MethodIds().GetOffset();
766 header.class_defs_size_ = header_->ClassDefs().Size();
767 header.class_defs_off_ = header_->ClassDefs().GetOffset();
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700768 header.data_size_ = header_->DataSize();
769 header.data_off_ = header_->DataOffset();
770
Mathieu Chartierf6e31472017-12-28 13:32:08 -0800771 CHECK_EQ(sizeof(header), GetHeaderSize());
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700772 static_assert(sizeof(header) == 0x70, "Size doesn't match dex spec");
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800773 stream->Seek(0);
774 stream->Overwrite(reinterpret_cast<uint8_t*>(&header), sizeof(header));
Jeff Haoa8621002016-10-04 18:13:44 +0000775}
776
Mathieu Chartierf6e31472017-12-28 13:32:08 -0800777size_t DexWriter::GetHeaderSize() const {
778 return sizeof(StandardDexFile::Header);
779}
780
Mathieu Chartier05f90d12018-02-07 13:47:17 -0800781bool DexWriter::Write(DexContainer* output, std::string* error_msg) {
782 DCHECK(error_msg != nullptr);
783
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800784 Stream stream_storage(output->GetMainSection());
785 Stream* stream = &stream_storage;
786
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800787 // Starting offset is right after the header.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800788 stream->Seek(GetHeaderSize());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800789
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800790 // Based on: https://source.android.com/devices/tech/dalvik/dex-format
791 // Since the offsets may not be calculated already, the writing must be done in the correct order.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800792 const uint32_t string_ids_offset = stream->Tell();
Andreas Gampe9b031f72018-10-04 11:03:34 -0700793 WriteStringIds(stream, /*reserve_only=*/ true);
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800794 WriteTypeIds(stream);
795 const uint32_t proto_ids_offset = stream->Tell();
Andreas Gampe9b031f72018-10-04 11:03:34 -0700796 WriteProtoIds(stream, /*reserve_only=*/ true);
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800797 WriteFieldIds(stream);
798 WriteMethodIds(stream);
799 const uint32_t class_defs_offset = stream->Tell();
Andreas Gampe9b031f72018-10-04 11:03:34 -0700800 WriteClassDefs(stream, /*reserve_only=*/ true);
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800801 const uint32_t call_site_ids_offset = stream->Tell();
Andreas Gampe9b031f72018-10-04 11:03:34 -0700802 WriteCallSiteIds(stream, /*reserve_only=*/ true);
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800803 WriteMethodHandles(stream);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800804
805 uint32_t data_offset_ = 0u;
806 if (compute_offsets_) {
807 // Data section.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800808 stream->AlignTo(kDataSectionAlignment);
809 data_offset_ = stream->Tell();
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800810 }
811
812 // Write code item first to minimize the space required for encoded methods.
813 // Reserve code item space since we need the debug offsets to actually write them.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800814 const uint32_t code_items_offset = stream->Tell();
Andreas Gampe9b031f72018-10-04 11:03:34 -0700815 WriteCodeItems(stream, /*reserve_only=*/ true);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800816 // Write debug info section.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800817 WriteDebugInfoItems(stream);
818 {
819 // Actually write code items since debug info offsets are calculated now.
820 Stream::ScopedSeek seek(stream, code_items_offset);
Andreas Gampe9b031f72018-10-04 11:03:34 -0700821 WriteCodeItems(stream, /*reserve_only=*/ false);
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800822 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800823
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800824 WriteEncodedArrays(stream);
825 WriteAnnotations(stream);
826 WriteAnnotationSets(stream);
827 WriteAnnotationSetRefs(stream);
828 WriteAnnotationsDirectories(stream);
829 WriteTypeLists(stream);
830 WriteClassDatas(stream);
831 WriteStringDatas(stream);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800832
833 // Write delayed id sections that depend on data sections.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800834 {
835 Stream::ScopedSeek seek(stream, string_ids_offset);
Andreas Gampe9b031f72018-10-04 11:03:34 -0700836 WriteStringIds(stream, /*reserve_only=*/ false);
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800837 }
838 {
839 Stream::ScopedSeek seek(stream, proto_ids_offset);
Andreas Gampe9b031f72018-10-04 11:03:34 -0700840 WriteProtoIds(stream, /*reserve_only=*/ false);
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800841 }
842 {
843 Stream::ScopedSeek seek(stream, class_defs_offset);
Andreas Gampe9b031f72018-10-04 11:03:34 -0700844 WriteClassDefs(stream, /*reserve_only=*/ false);
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800845 }
846 {
847 Stream::ScopedSeek seek(stream, call_site_ids_offset);
Andreas Gampe9b031f72018-10-04 11:03:34 -0700848 WriteCallSiteIds(stream, /*reserve_only=*/ false);
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800849 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800850
851 // Write the map list.
852 if (compute_offsets_) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800853 stream->AlignTo(SectionAlignment(DexFile::kDexTypeMapList));
David Sehr2b5a38f2018-06-14 15:13:04 -0700854 header_->SetMapListOffset(stream->Tell());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800855 } else {
David Sehr2b5a38f2018-06-14 15:13:04 -0700856 stream->Seek(header_->MapListOffset());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800857 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800858 GenerateAndWriteMapItems(stream);
859 stream->AlignTo(kDataSectionAlignment);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800860
861 // Map items are included in the data section.
862 if (compute_offsets_) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800863 header_->SetDataSize(stream->Tell() - data_offset_);
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800864 if (header_->DataSize() != 0) {
865 // Offset must be zero when the size is zero.
866 header_->SetDataOffset(data_offset_);
867 } else {
868 header_->SetDataOffset(0u);
869 }
870 }
871
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -0800872 // Write link data if it exists.
David Sehr2b5a38f2018-06-14 15:13:04 -0700873 const std::vector<uint8_t>& link_data = header_->LinkData();
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -0800874 if (link_data.size() > 0) {
875 CHECK_EQ(header_->LinkSize(), static_cast<uint32_t>(link_data.size()));
876 if (compute_offsets_) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800877 header_->SetLinkOffset(stream->Tell());
878 } else {
879 stream->Seek(header_->LinkOffset());
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -0800880 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800881 stream->Write(&link_data[0], link_data.size());
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -0800882 }
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800883
884 // Write header last.
885 if (compute_offsets_) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800886 header_->SetFileSize(stream->Tell());
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800887 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800888 WriteHeader(stream);
Mathieu Chartier2c4b0842017-12-13 11:49:51 -0800889
890 if (dex_layout_->GetOptions().update_checksum_) {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800891 header_->SetChecksum(DexFile::CalculateChecksum(stream->Begin(), header_->FileSize()));
Mathieu Chartier2c4b0842017-12-13 11:49:51 -0800892 // Rewrite the header with the calculated checksum.
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800893 WriteHeader(stream);
Mathieu Chartier2c4b0842017-12-13 11:49:51 -0800894 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800895
896 // Trim the map to make it sized as large as the dex file.
897 output->GetMainSection()->Resize(header_->FileSize());
Mathieu Chartier05f90d12018-02-07 13:47:17 -0800898 return true;
Jeff Haoa8621002016-10-04 18:13:44 +0000899}
900
Mathieu Chartier05f90d12018-02-07 13:47:17 -0800901bool DexWriter::Output(DexLayout* dex_layout,
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800902 std::unique_ptr<DexContainer>* container,
Mathieu Chartier05f90d12018-02-07 13:47:17 -0800903 bool compute_offsets,
904 std::string* error_msg) {
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800905 CHECK(dex_layout != nullptr);
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700906 std::unique_ptr<DexWriter> writer;
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800907 if (dex_layout->GetOptions().compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone) {
908 CHECK(compute_offsets) << "Compact dex requires computing offsets";
909 writer.reset(new CompactDexWriter(dex_layout));
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700910 } else {
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800911 writer.reset(new DexWriter(dex_layout, compute_offsets));
Mathieu Chartierf95a75e2017-11-03 15:25:52 -0700912 }
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800913 DCHECK(container != nullptr);
914 if (*container == nullptr) {
915 *container = writer->CreateDexContainer();
916 }
Mathieu Chartier05f90d12018-02-07 13:47:17 -0800917 return writer->Write(container->get(), error_msg);
Jeff Haoa8621002016-10-04 18:13:44 +0000918}
919
Mathieu Chartier3e0c5172017-11-12 12:58:40 -0800920void MapItemQueue::AddIfNotEmpty(const MapItem& item) {
921 if (item.size_ != 0) {
922 push(item);
923 }
924}
925
Mathieu Chartiere6b6ff82018-01-19 18:58:34 -0800926void DexWriter::ProcessOffset(Stream* stream, dex_ir::Item* item) {
927 if (compute_offsets_) {
928 item->SetOffset(stream->Tell());
929 } else {
930 // Not computing offsets, just use the one in the item.
931 stream->Seek(item->GetOffset());
932 }
933}
934
935std::unique_ptr<DexContainer> DexWriter::CreateDexContainer() const {
936 return std::unique_ptr<DexContainer>(new DexWriter::Container);
937}
938
Jeff Haoa8621002016-10-04 18:13:44 +0000939} // namespace art