Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2016 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 15 | */ |
| 16 | |
Andreas Gampe | e2abbc6 | 2017-09-15 11:59:26 -0700 | [diff] [blame] | 17 | #include "dex_writer.h" |
| 18 | |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 19 | #include <stdint.h> |
| 20 | |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 21 | #include <vector> |
| 22 | |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 23 | #include "compact_dex_writer.h" |
David Sehr | 9e734c7 | 2018-01-04 17:56:19 -0800 | [diff] [blame] | 24 | #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 Sehr | 0225f8e | 2018-01-31 08:52:24 +0000 | [diff] [blame] | 28 | #include "dex/utf.h" |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 29 | #include "dexlayout.h" |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 30 | |
| 31 | namespace art { |
| 32 | |
Mathieu Chartier | c3a22aa | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 33 | constexpr uint32_t DexWriter::kDataSectionAlignment; |
| 34 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 35 | static size_t EncodeIntValue(int32_t value, uint8_t* buffer) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 36 | 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 52 | static size_t EncodeUIntValue(uint32_t value, uint8_t* buffer) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 53 | 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 61 | static size_t EncodeLongValue(int64_t value, uint8_t* buffer) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 62 | 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 | |
| 78 | union FloatUnion { |
| 79 | float f_; |
| 80 | uint32_t i_; |
| 81 | }; |
| 82 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 83 | static size_t EncodeFloatValue(float value, uint8_t* buffer) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 84 | 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 | |
| 95 | union DoubleUnion { |
| 96 | double d_; |
| 97 | uint64_t l_; |
| 98 | }; |
| 99 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 100 | static size_t EncodeDoubleValue(double value, uint8_t* buffer) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 101 | 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 112 | DexWriter::DexWriter(DexLayout* dex_layout, bool compute_offsets) |
| 113 | : header_(dex_layout->GetHeader()), |
| 114 | dex_layout_(dex_layout), |
| 115 | compute_offsets_(compute_offsets) {} |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 116 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 117 | void DexWriter::WriteEncodedValue(Stream* stream, dex_ir::EncodedValue* encoded_value) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 118 | 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 Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 146 | 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 Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 152 | 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 166 | WriteEncodedValueHeader(stream, type, 0); |
| 167 | WriteEncodedArray(stream, encoded_value->GetEncodedArray()->GetEncodedValues()); |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 168 | return; |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 169 | case DexFile::kDexAnnotationAnnotation: |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 170 | WriteEncodedValueHeader(stream, type, 0); |
| 171 | WriteEncodedAnnotation(stream, encoded_value->GetEncodedAnnotation()); |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 172 | return; |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 173 | case DexFile::kDexAnnotationNull: |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 174 | WriteEncodedValueHeader(stream, type, 0); |
| 175 | return; |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 176 | case DexFile::kDexAnnotationBoolean: |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 177 | WriteEncodedValueHeader(stream, type, encoded_value->GetBoolean() ? 1 : 0); |
| 178 | return; |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 179 | default: |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 180 | return; |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 181 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 182 | WriteEncodedValueHeader(stream, type, length - 1); |
| 183 | stream->Write(buffer + start, length); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 184 | } |
| 185 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 186 | void DexWriter::WriteEncodedValueHeader(Stream* stream, int8_t value_type, size_t value_arg) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 187 | uint8_t buffer[1] = { static_cast<uint8_t>((value_arg << 5) | value_type) }; |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 188 | stream->Write(buffer, sizeof(uint8_t)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 189 | } |
| 190 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 191 | void DexWriter::WriteEncodedArray(Stream* stream, dex_ir::EncodedValueVector* values) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 192 | stream->WriteUleb128(values->size()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 193 | for (std::unique_ptr<dex_ir::EncodedValue>& value : *values) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 194 | WriteEncodedValue(stream, value.get()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 195 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 196 | } |
| 197 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 198 | void DexWriter::WriteEncodedAnnotation(Stream* stream, dex_ir::EncodedAnnotation* annotation) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 199 | stream->WriteUleb128(annotation->GetType()->GetIndex()); |
| 200 | stream->WriteUleb128(annotation->GetAnnotationElements()->size()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 201 | for (std::unique_ptr<dex_ir::AnnotationElement>& annotation_element : |
| 202 | *annotation->GetAnnotationElements()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 203 | stream->WriteUleb128(annotation_element->GetName()->GetIndex()); |
| 204 | WriteEncodedValue(stream, annotation_element->GetValue()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 205 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 206 | } |
| 207 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 208 | void DexWriter::WriteEncodedFields(Stream* stream, dex_ir::FieldItemVector* fields) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 209 | uint32_t prev_index = 0; |
David Sehr | d83437c | 2018-06-11 14:06:23 -0700 | [diff] [blame] | 210 | for (auto& field : *fields) { |
| 211 | uint32_t index = field.GetFieldId()->GetIndex(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 212 | stream->WriteUleb128(index - prev_index); |
David Sehr | d83437c | 2018-06-11 14:06:23 -0700 | [diff] [blame] | 213 | stream->WriteUleb128(field.GetAccessFlags()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 214 | prev_index = index; |
| 215 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 216 | } |
| 217 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 218 | void DexWriter::WriteEncodedMethods(Stream* stream, dex_ir::MethodItemVector* methods) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 219 | uint32_t prev_index = 0; |
David Sehr | d83437c | 2018-06-11 14:06:23 -0700 | [diff] [blame] | 220 | for (auto& method : *methods) { |
| 221 | uint32_t index = method.GetMethodId()->GetIndex(); |
| 222 | uint32_t code_off = method.GetCodeItem() == nullptr ? 0 : method.GetCodeItem()->GetOffset(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 223 | stream->WriteUleb128(index - prev_index); |
David Sehr | d83437c | 2018-06-11 14:06:23 -0700 | [diff] [blame] | 224 | stream->WriteUleb128(method.GetAccessFlags()); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 225 | stream->WriteUleb128(code_off); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 226 | prev_index = index; |
| 227 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 228 | } |
| 229 | |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 230 | // 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 Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 232 | void DexWriter::WriteStringIds(Stream* stream, bool reserve_only) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 233 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 234 | for (auto& string_id : header_->StringIds()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 235 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeStringIdItem)); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 236 | if (reserve_only) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 237 | stream->Skip(string_id->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 238 | } else { |
| 239 | uint32_t string_data_off = string_id->DataItem()->GetOffset(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 240 | stream->Write(&string_data_off, string_id->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 241 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 242 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 243 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 244 | header_->StringIds().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 245 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 246 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 247 | |
Mathieu Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 248 | void 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 Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 257 | void DexWriter::WriteStringDatas(Stream* stream) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 258 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 259 | for (auto& string_data : header_->StringDatas()) { |
Mathieu Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 260 | WriteStringData(stream, string_data.get()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 261 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 262 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 263 | header_->StringDatas().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 264 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 265 | } |
| 266 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 267 | void DexWriter::WriteTypeIds(Stream* stream) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 268 | uint32_t descriptor_idx[1]; |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 269 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 270 | for (auto& type_id : header_->TypeIds()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 271 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeTypeIdItem)); |
| 272 | ProcessOffset(stream, type_id.get()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 273 | descriptor_idx[0] = type_id->GetStringId()->GetIndex(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 274 | stream->Write(descriptor_idx, type_id->GetSize()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 275 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 276 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 277 | header_->TypeIds().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 278 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 279 | } |
| 280 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 281 | void DexWriter::WriteTypeLists(Stream* stream) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 282 | uint32_t size[1]; |
| 283 | uint16_t list[1]; |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 284 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 285 | for (auto& type_list : header_->TypeLists()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 286 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeTypeList)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 287 | size[0] = type_list->GetTypeList()->size(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 288 | ProcessOffset(stream, type_list.get()); |
| 289 | stream->Write(size, sizeof(uint32_t)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 290 | for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) { |
| 291 | list[0] = type_id->GetIndex(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 292 | stream->Write(list, sizeof(uint16_t)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 293 | } |
| 294 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 295 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 296 | header_->TypeLists().SetOffset(start); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 297 | } |
| 298 | } |
| 299 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 300 | void DexWriter::WriteProtoIds(Stream* stream, bool reserve_only) { |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 301 | uint32_t buffer[3]; |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 302 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 303 | for (auto& proto_id : header_->ProtoIds()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 304 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeProtoIdItem)); |
| 305 | ProcessOffset(stream, proto_id.get()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 306 | if (reserve_only) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 307 | stream->Skip(proto_id->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 308 | } 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 312 | stream->Write(buffer, proto_id->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 313 | } |
| 314 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 315 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 316 | header_->ProtoIds().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 317 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 318 | } |
| 319 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 320 | void DexWriter::WriteFieldIds(Stream* stream) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 321 | uint16_t buffer[4]; |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 322 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 323 | for (auto& field_id : header_->FieldIds()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 324 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeFieldIdItem)); |
| 325 | ProcessOffset(stream, field_id.get()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 326 | 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 330 | stream->Write(buffer, field_id->GetSize()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 331 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 332 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 333 | header_->FieldIds().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 334 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 335 | } |
| 336 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 337 | void DexWriter::WriteMethodIds(Stream* stream) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 338 | uint16_t buffer[4]; |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 339 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 340 | for (auto& method_id : header_->MethodIds()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 341 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeMethodIdItem)); |
| 342 | ProcessOffset(stream, method_id.get()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 343 | 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 347 | stream->Write(buffer, method_id->GetSize()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 348 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 349 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 350 | header_->MethodIds().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 351 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 352 | } |
| 353 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 354 | void DexWriter::WriteEncodedArrays(Stream* stream) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 355 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 356 | for (auto& encoded_array : header_->EncodedArrayItems()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 357 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeEncodedArrayItem)); |
| 358 | ProcessOffset(stream, encoded_array.get()); |
| 359 | WriteEncodedArray(stream, encoded_array->GetEncodedValues()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 360 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 361 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 362 | header_->EncodedArrayItems().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 363 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 364 | } |
| 365 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 366 | void DexWriter::WriteAnnotations(Stream* stream) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 367 | uint8_t visibility[1]; |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 368 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 369 | for (auto& annotation : header_->AnnotationItems()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 370 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationItem)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 371 | visibility[0] = annotation->GetVisibility(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 372 | ProcessOffset(stream, annotation.get()); |
| 373 | stream->Write(visibility, sizeof(uint8_t)); |
| 374 | WriteEncodedAnnotation(stream, annotation->GetAnnotation()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 375 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 376 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 377 | header_->AnnotationItems().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 378 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 379 | } |
| 380 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 381 | void DexWriter::WriteAnnotationSets(Stream* stream) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 382 | uint32_t size[1]; |
| 383 | uint32_t annotation_off[1]; |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 384 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 385 | for (auto& annotation_set : header_->AnnotationSetItems()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 386 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationSetItem)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 387 | size[0] = annotation_set->GetItems()->size(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 388 | ProcessOffset(stream, annotation_set.get()); |
| 389 | stream->Write(size, sizeof(uint32_t)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 390 | for (dex_ir::AnnotationItem* annotation : *annotation_set->GetItems()) { |
| 391 | annotation_off[0] = annotation->GetOffset(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 392 | stream->Write(annotation_off, sizeof(uint32_t)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 393 | } |
| 394 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 395 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 396 | header_->AnnotationSetItems().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 397 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 398 | } |
| 399 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 400 | void DexWriter::WriteAnnotationSetRefs(Stream* stream) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 401 | uint32_t size[1]; |
| 402 | uint32_t annotations_off[1]; |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 403 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 404 | for (auto& annotation_set_ref : header_->AnnotationSetRefLists()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 405 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationSetRefList)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 406 | size[0] = annotation_set_ref->GetItems()->size(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 407 | ProcessOffset(stream, annotation_set_ref.get()); |
| 408 | stream->Write(size, sizeof(uint32_t)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 409 | for (dex_ir::AnnotationSetItem* annotation_set : *annotation_set_ref->GetItems()) { |
| 410 | annotations_off[0] = annotation_set == nullptr ? 0 : annotation_set->GetOffset(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 411 | stream->Write(annotations_off, sizeof(uint32_t)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 412 | } |
| 413 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 414 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 415 | header_->AnnotationSetRefLists().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 416 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 417 | } |
| 418 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 419 | void DexWriter::WriteAnnotationsDirectories(Stream* stream) { |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 420 | uint32_t directory_buffer[4]; |
| 421 | uint32_t annotation_buffer[2]; |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 422 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 423 | for (auto& annotations_directory : header_->AnnotationsDirectoryItems()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 424 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationsDirectoryItem)); |
| 425 | ProcessOffset(stream, annotations_directory.get()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 426 | 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 434 | stream->Write(directory_buffer, 4 * sizeof(uint32_t)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 435 | 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 440 | stream->Write(annotation_buffer, 2 * sizeof(uint32_t)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 441 | } |
| 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 448 | stream->Write(annotation_buffer, 2 * sizeof(uint32_t)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 449 | } |
| 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 456 | stream->Write(annotation_buffer, 2 * sizeof(uint32_t)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 457 | } |
| 458 | } |
| 459 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 460 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 461 | header_->AnnotationsDirectoryItems().SetOffset(start); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 462 | } |
| 463 | } |
| 464 | |
Mathieu Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 465 | void 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 Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 471 | void DexWriter::WriteDebugInfoItems(Stream* stream) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 472 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 473 | for (auto& debug_info : header_->DebugInfoItems()) { |
Mathieu Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 474 | WriteDebugInfoItem(stream, debug_info.get()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 475 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 476 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 477 | header_->DebugInfoItems().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 478 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 479 | } |
| 480 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 481 | void DexWriter::WriteCodeItemPostInstructionData(Stream* stream, |
| 482 | dex_ir::CodeItem* code_item, |
| 483 | bool reserve_only) { |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 484 | if (code_item->TriesSize() != 0) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 485 | stream->AlignTo(DexFile::TryItem::kAlignment); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 486 | // 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 494 | stream->Write(&disk_try_item, sizeof(disk_try_item)); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 495 | } |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 496 | // Leave offset pointing to the end of the try items. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 497 | const size_t offset = stream->Tell(); |
| 498 | size_t max_offset = offset + stream->WriteUleb128(code_item->Handlers()->size()); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 499 | for (std::unique_ptr<const dex_ir::CatchHandler>& handlers : *code_item->Handlers()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 500 | stream->Seek(offset + handlers->GetListOffset()); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 501 | uint32_t size = handlers->HasCatchAll() ? (handlers->GetHandlers()->size() - 1) * -1 : |
| 502 | handlers->GetHandlers()->size(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 503 | stream->WriteSleb128(size); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 504 | for (std::unique_ptr<const dex_ir::TypeAddrPair>& handler : *handlers->GetHandlers()) { |
| 505 | if (handler->GetTypeId() != nullptr) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 506 | stream->WriteUleb128(handler->GetTypeId()->GetIndex()); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 507 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 508 | stream->WriteUleb128(handler->GetAddress()); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 509 | } |
| 510 | // TODO: Clean this up to write the handlers in address order. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 511 | max_offset = std::max(max_offset, stream->Tell()); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 512 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 513 | stream->Seek(max_offset); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 514 | } |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 515 | } |
| 516 | |
Mathieu Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 517 | void DexWriter::WriteCodeItem(Stream* stream, |
| 518 | dex_ir::CodeItem* code_item, |
| 519 | bool reserve_only) { |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 520 | DCHECK(code_item != nullptr); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 521 | const uint32_t start_offset = stream->Tell(); |
| 522 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeCodeItem)); |
| 523 | ProcessOffset(stream, code_item); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 524 | |
| 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 538 | stream->Write(&disk_code_item, OFFSETOF_MEMBER(StandardDexFile::CodeItem, insns_)); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 539 | // Write the instructions. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 540 | stream->Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t)); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 541 | // Write the post instruction data. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 542 | WriteCodeItemPostInstructionData(stream, code_item, reserve_only); |
| 543 | if (reserve_only) { |
| 544 | stream->Clear(start_offset, stream->Tell() - start_offset); |
| 545 | } |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 546 | } |
| 547 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 548 | void DexWriter::WriteCodeItems(Stream* stream, bool reserve_only) { |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 549 | 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 554 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 555 | for (auto& code_item : header_->CodeItems()) { |
Mathieu Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 556 | uint32_t start_offset = stream->Tell(); |
| 557 | WriteCodeItem(stream, code_item.get(), reserve_only); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 558 | // 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 Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 563 | start_offset, |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 564 | stream->Tell()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 565 | } |
| 566 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 567 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 568 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 569 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 570 | header_->CodeItems().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 571 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 572 | } |
| 573 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 574 | void DexWriter::WriteClassDefs(Stream* stream, bool reserve_only) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 575 | const uint32_t start = stream->Tell(); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 576 | uint32_t class_def_buffer[8]; |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 577 | for (auto& class_def : header_->ClassDefs()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 578 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeClassDefItem)); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 579 | if (reserve_only) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 580 | stream->Skip(class_def->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 581 | } 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 595 | stream->Write(class_def_buffer, class_def->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 596 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 597 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 598 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 599 | header_->ClassDefs().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 600 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 601 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 602 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 603 | void DexWriter::WriteClassDatas(Stream* stream) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 604 | const uint32_t start = stream->Tell(); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 605 | for (const std::unique_ptr<dex_ir::ClassData>& class_data : |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 606 | header_->ClassDatas()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 607 | 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 Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 617 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 618 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 619 | header_->ClassDatas().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 620 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 621 | } |
| 622 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 623 | void DexWriter::WriteCallSiteIds(Stream* stream, bool reserve_only) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 624 | const uint32_t start = stream->Tell(); |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 625 | uint32_t call_site_off[1]; |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 626 | for (auto& call_site_id : header_->CallSiteIds()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 627 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeCallSiteIdItem)); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 628 | if (reserve_only) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 629 | stream->Skip(call_site_id->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 630 | } else { |
| 631 | call_site_off[0] = call_site_id->CallSiteItem()->GetOffset(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 632 | stream->Write(call_site_off, call_site_id->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 633 | } |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 634 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 635 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 636 | header_->CallSiteIds().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 637 | } |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 638 | } |
| 639 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 640 | void DexWriter::WriteMethodHandles(Stream* stream) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 641 | const uint32_t start = stream->Tell(); |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 642 | uint16_t method_handle_buff[4]; |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 643 | for (auto& method_handle : header_->MethodHandleItems()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 644 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeMethodHandleItem)); |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 645 | 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 649 | stream->Write(method_handle_buff, method_handle->GetSize()); |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 650 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 651 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 652 | header_->MethodHandleItems().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 653 | } |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 654 | } |
| 655 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 656 | void DexWriter::WriteMapItems(Stream* stream, MapItemQueue* queue) { |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 657 | // All the sections should already have been added. |
Mathieu Chartier | 9b302bf | 2018-01-25 13:08:08 -0800 | [diff] [blame] | 658 | const uint32_t map_list_size = queue->size(); |
Mathieu Chartier | 9b302bf | 2018-01-25 13:08:08 -0800 | [diff] [blame] | 659 | stream->Write(&map_list_size, sizeof(map_list_size)); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 660 | while (!queue->empty()) { |
Mathieu Chartier | 9b302bf | 2018-01-25 13:08:08 -0800 | [diff] [blame] | 661 | 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 Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 668 | queue->pop(); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 669 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 670 | } |
| 671 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 672 | void DexWriter::GenerateAndWriteMapItems(Stream* stream) { |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 673 | MapItemQueue queue; |
| 674 | |
| 675 | // Header and index section. |
| 676 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeHeaderItem, 1, 0)); |
| 677 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 678 | header_->StringIds().Size(), |
| 679 | header_->StringIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 680 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 681 | header_->TypeIds().Size(), |
| 682 | header_->TypeIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 683 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeProtoIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 684 | header_->ProtoIds().Size(), |
| 685 | header_->ProtoIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 686 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeFieldIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 687 | header_->FieldIds().Size(), |
| 688 | header_->FieldIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 689 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 690 | header_->MethodIds().Size(), |
| 691 | header_->MethodIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 692 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDefItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 693 | header_->ClassDefs().Size(), |
| 694 | header_->ClassDefs().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 695 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCallSiteIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 696 | header_->CallSiteIds().Size(), |
| 697 | header_->CallSiteIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 698 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodHandleItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 699 | header_->MethodHandleItems().Size(), |
| 700 | header_->MethodHandleItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 701 | // Data section. |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 702 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMapList, 1, header_->MapListOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 703 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeList, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 704 | header_->TypeLists().Size(), |
| 705 | header_->TypeLists().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 706 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetRefList, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 707 | header_->AnnotationSetRefLists().Size(), |
| 708 | header_->AnnotationSetRefLists().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 709 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 710 | header_->AnnotationSetItems().Size(), |
| 711 | header_->AnnotationSetItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 712 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDataItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 713 | header_->ClassDatas().Size(), |
| 714 | header_->ClassDatas().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 715 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCodeItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 716 | header_->CodeItems().Size(), |
| 717 | header_->CodeItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 718 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringDataItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 719 | header_->StringDatas().Size(), |
| 720 | header_->StringDatas().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 721 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeDebugInfoItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 722 | header_->DebugInfoItems().Size(), |
| 723 | header_->DebugInfoItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 724 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 725 | header_->AnnotationItems().Size(), |
| 726 | header_->AnnotationItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 727 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeEncodedArrayItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 728 | header_->EncodedArrayItems().Size(), |
| 729 | header_->EncodedArrayItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 730 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationsDirectoryItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 731 | header_->AnnotationsDirectoryItems().Size(), |
| 732 | header_->AnnotationsDirectoryItems().GetOffset())); |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 733 | WriteMapItems(stream, &queue); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 734 | } |
| 735 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 736 | void DexWriter::WriteHeader(Stream* stream) { |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 737 | StandardDexFile::Header header; |
Mathieu Chartier | 21cf258 | 2018-01-08 17:09:48 -0800 | [diff] [blame] | 738 | 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 Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 748 | header.checksum_ = header_->Checksum(); |
| 749 | std::copy_n(header_->Signature(), DexFile::kSha1DigestSize, header.signature_); |
| 750 | header.file_size_ = header_->FileSize(); |
Mathieu Chartier | f6e3147 | 2017-12-28 13:32:08 -0800 | [diff] [blame] | 751 | header.header_size_ = GetHeaderSize(); |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 752 | header.endian_tag_ = header_->EndianTag(); |
| 753 | header.link_size_ = header_->LinkSize(); |
| 754 | header.link_off_ = header_->LinkOffset(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 755 | 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 Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 768 | header.data_size_ = header_->DataSize(); |
| 769 | header.data_off_ = header_->DataOffset(); |
| 770 | |
Mathieu Chartier | f6e3147 | 2017-12-28 13:32:08 -0800 | [diff] [blame] | 771 | CHECK_EQ(sizeof(header), GetHeaderSize()); |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 772 | static_assert(sizeof(header) == 0x70, "Size doesn't match dex spec"); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 773 | stream->Seek(0); |
| 774 | stream->Overwrite(reinterpret_cast<uint8_t*>(&header), sizeof(header)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 775 | } |
| 776 | |
Mathieu Chartier | f6e3147 | 2017-12-28 13:32:08 -0800 | [diff] [blame] | 777 | size_t DexWriter::GetHeaderSize() const { |
| 778 | return sizeof(StandardDexFile::Header); |
| 779 | } |
| 780 | |
Mathieu Chartier | 05f90d1 | 2018-02-07 13:47:17 -0800 | [diff] [blame] | 781 | bool DexWriter::Write(DexContainer* output, std::string* error_msg) { |
| 782 | DCHECK(error_msg != nullptr); |
| 783 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 784 | Stream stream_storage(output->GetMainSection()); |
| 785 | Stream* stream = &stream_storage; |
| 786 | |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 787 | // Starting offset is right after the header. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 788 | stream->Seek(GetHeaderSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 789 | |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 790 | // 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 792 | const uint32_t string_ids_offset = stream->Tell(); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 793 | WriteStringIds(stream, /*reserve_only=*/ true); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 794 | WriteTypeIds(stream); |
| 795 | const uint32_t proto_ids_offset = stream->Tell(); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 796 | WriteProtoIds(stream, /*reserve_only=*/ true); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 797 | WriteFieldIds(stream); |
| 798 | WriteMethodIds(stream); |
| 799 | const uint32_t class_defs_offset = stream->Tell(); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 800 | WriteClassDefs(stream, /*reserve_only=*/ true); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 801 | const uint32_t call_site_ids_offset = stream->Tell(); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 802 | WriteCallSiteIds(stream, /*reserve_only=*/ true); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 803 | WriteMethodHandles(stream); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 804 | |
| 805 | uint32_t data_offset_ = 0u; |
| 806 | if (compute_offsets_) { |
| 807 | // Data section. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 808 | stream->AlignTo(kDataSectionAlignment); |
| 809 | data_offset_ = stream->Tell(); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 810 | } |
| 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 Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 814 | const uint32_t code_items_offset = stream->Tell(); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 815 | WriteCodeItems(stream, /*reserve_only=*/ true); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 816 | // Write debug info section. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 817 | WriteDebugInfoItems(stream); |
| 818 | { |
| 819 | // Actually write code items since debug info offsets are calculated now. |
| 820 | Stream::ScopedSeek seek(stream, code_items_offset); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 821 | WriteCodeItems(stream, /*reserve_only=*/ false); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 822 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 823 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 824 | WriteEncodedArrays(stream); |
| 825 | WriteAnnotations(stream); |
| 826 | WriteAnnotationSets(stream); |
| 827 | WriteAnnotationSetRefs(stream); |
| 828 | WriteAnnotationsDirectories(stream); |
| 829 | WriteTypeLists(stream); |
| 830 | WriteClassDatas(stream); |
| 831 | WriteStringDatas(stream); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 832 | |
| 833 | // Write delayed id sections that depend on data sections. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 834 | { |
| 835 | Stream::ScopedSeek seek(stream, string_ids_offset); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 836 | WriteStringIds(stream, /*reserve_only=*/ false); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 837 | } |
| 838 | { |
| 839 | Stream::ScopedSeek seek(stream, proto_ids_offset); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 840 | WriteProtoIds(stream, /*reserve_only=*/ false); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 841 | } |
| 842 | { |
| 843 | Stream::ScopedSeek seek(stream, class_defs_offset); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 844 | WriteClassDefs(stream, /*reserve_only=*/ false); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 845 | } |
| 846 | { |
| 847 | Stream::ScopedSeek seek(stream, call_site_ids_offset); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 848 | WriteCallSiteIds(stream, /*reserve_only=*/ false); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 849 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 850 | |
| 851 | // Write the map list. |
| 852 | if (compute_offsets_) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 853 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeMapList)); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 854 | header_->SetMapListOffset(stream->Tell()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 855 | } else { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 856 | stream->Seek(header_->MapListOffset()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 857 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 858 | GenerateAndWriteMapItems(stream); |
| 859 | stream->AlignTo(kDataSectionAlignment); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 860 | |
| 861 | // Map items are included in the data section. |
| 862 | if (compute_offsets_) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 863 | header_->SetDataSize(stream->Tell() - data_offset_); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 864 | 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 Chartier | 2f36d2f | 2017-11-20 15:45:25 -0800 | [diff] [blame] | 872 | // Write link data if it exists. |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 873 | const std::vector<uint8_t>& link_data = header_->LinkData(); |
Mathieu Chartier | 2f36d2f | 2017-11-20 15:45:25 -0800 | [diff] [blame] | 874 | if (link_data.size() > 0) { |
| 875 | CHECK_EQ(header_->LinkSize(), static_cast<uint32_t>(link_data.size())); |
| 876 | if (compute_offsets_) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 877 | header_->SetLinkOffset(stream->Tell()); |
| 878 | } else { |
| 879 | stream->Seek(header_->LinkOffset()); |
Mathieu Chartier | 2f36d2f | 2017-11-20 15:45:25 -0800 | [diff] [blame] | 880 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 881 | stream->Write(&link_data[0], link_data.size()); |
Mathieu Chartier | 2f36d2f | 2017-11-20 15:45:25 -0800 | [diff] [blame] | 882 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 883 | |
| 884 | // Write header last. |
| 885 | if (compute_offsets_) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 886 | header_->SetFileSize(stream->Tell()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 887 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 888 | WriteHeader(stream); |
Mathieu Chartier | 2c4b084 | 2017-12-13 11:49:51 -0800 | [diff] [blame] | 889 | |
| 890 | if (dex_layout_->GetOptions().update_checksum_) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 891 | header_->SetChecksum(DexFile::CalculateChecksum(stream->Begin(), header_->FileSize())); |
Mathieu Chartier | 2c4b084 | 2017-12-13 11:49:51 -0800 | [diff] [blame] | 892 | // Rewrite the header with the calculated checksum. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 893 | WriteHeader(stream); |
Mathieu Chartier | 2c4b084 | 2017-12-13 11:49:51 -0800 | [diff] [blame] | 894 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 895 | |
| 896 | // Trim the map to make it sized as large as the dex file. |
| 897 | output->GetMainSection()->Resize(header_->FileSize()); |
Mathieu Chartier | 05f90d1 | 2018-02-07 13:47:17 -0800 | [diff] [blame] | 898 | return true; |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 899 | } |
| 900 | |
Mathieu Chartier | 05f90d1 | 2018-02-07 13:47:17 -0800 | [diff] [blame] | 901 | bool DexWriter::Output(DexLayout* dex_layout, |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 902 | std::unique_ptr<DexContainer>* container, |
Mathieu Chartier | 05f90d1 | 2018-02-07 13:47:17 -0800 | [diff] [blame] | 903 | bool compute_offsets, |
| 904 | std::string* error_msg) { |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 905 | CHECK(dex_layout != nullptr); |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 906 | std::unique_ptr<DexWriter> writer; |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 907 | 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 Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 910 | } else { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 911 | writer.reset(new DexWriter(dex_layout, compute_offsets)); |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 912 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 913 | DCHECK(container != nullptr); |
| 914 | if (*container == nullptr) { |
| 915 | *container = writer->CreateDexContainer(); |
| 916 | } |
Mathieu Chartier | 05f90d1 | 2018-02-07 13:47:17 -0800 | [diff] [blame] | 917 | return writer->Write(container->get(), error_msg); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 918 | } |
| 919 | |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 920 | void MapItemQueue::AddIfNotEmpty(const MapItem& item) { |
| 921 | if (item.size_ != 0) { |
| 922 | push(item); |
| 923 | } |
| 924 | } |
| 925 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 926 | void 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 | |
| 935 | std::unique_ptr<DexContainer> DexWriter::CreateDexContainer() const { |
| 936 | return std::unique_ptr<DexContainer>(new DexWriter::Container); |
| 937 | } |
| 938 | |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 939 | } // namespace art |