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 | |
David Brazdil | 20c765f | 2018-10-27 21:45:15 +0000 | [diff] [blame] | 465 | void DexWriter::WriteHiddenapiClassData(Stream* stream) { |
| 466 | if (header_->HiddenapiClassDatas().Empty()) { |
| 467 | return; |
| 468 | } |
| 469 | DCHECK_EQ(header_->HiddenapiClassDatas().Size(), header_->ClassDefs().Size()); |
| 470 | |
| 471 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeHiddenapiClassData)); |
David Brazdil | 1783480 | 2019-01-21 19:46:46 +0000 | [diff] [blame] | 472 | ProcessOffset(stream, &header_->HiddenapiClassDatas()); |
David Brazdil | 20c765f | 2018-10-27 21:45:15 +0000 | [diff] [blame] | 473 | const uint32_t start = stream->Tell(); |
| 474 | |
| 475 | // Compute offsets for each class def and write the header. |
| 476 | // data_header[0]: total size of the section |
| 477 | // data_header[i + 1]: offset of class def[i] from the beginning of the section, |
| 478 | // or zero if no data |
| 479 | std::vector<uint32_t> data_header(header_->ClassDefs().Size() + 1, 0); |
| 480 | data_header[0] = sizeof(uint32_t) * (header_->ClassDefs().Size() + 1); |
| 481 | for (uint32_t i = 0; i < header_->ClassDefs().Size(); ++i) { |
| 482 | uint32_t item_size = header_->HiddenapiClassDatas()[i]->ItemSize(); |
| 483 | data_header[i + 1] = item_size == 0u ? 0 : data_header[0]; |
| 484 | data_header[0] += item_size; |
| 485 | } |
| 486 | stream->Write(data_header.data(), sizeof(uint32_t) * data_header.size()); |
| 487 | |
| 488 | // Write class data streams. |
| 489 | for (uint32_t i = 0; i < header_->ClassDefs().Size(); ++i) { |
| 490 | dex_ir::ClassDef* class_def = header_->ClassDefs()[i]; |
| 491 | const auto& item = header_->HiddenapiClassDatas()[i]; |
| 492 | DCHECK(item->GetClassDef() == class_def); |
| 493 | |
| 494 | if (data_header[i + 1] != 0u) { |
| 495 | dex_ir::ClassData* class_data = class_def->GetClassData(); |
| 496 | DCHECK(class_data != nullptr); |
| 497 | DCHECK_EQ(data_header[i + 1], stream->Tell() - start); |
| 498 | for (const dex_ir::FieldItem& field : *class_data->StaticFields()) { |
| 499 | stream->WriteUleb128(item->GetFlags(&field)); |
| 500 | } |
| 501 | for (const dex_ir::FieldItem& field : *class_data->InstanceFields()) { |
| 502 | stream->WriteUleb128(item->GetFlags(&field)); |
| 503 | } |
| 504 | for (const dex_ir::MethodItem& method : *class_data->DirectMethods()) { |
| 505 | stream->WriteUleb128(item->GetFlags(&method)); |
| 506 | } |
| 507 | for (const dex_ir::MethodItem& method : *class_data->VirtualMethods()) { |
| 508 | stream->WriteUleb128(item->GetFlags(&method)); |
| 509 | } |
| 510 | } |
| 511 | } |
| 512 | DCHECK_EQ(stream->Tell() - start, data_header[0]); |
| 513 | |
| 514 | if (compute_offsets_ && start != stream->Tell()) { |
| 515 | header_->HiddenapiClassDatas().SetOffset(start); |
| 516 | } |
| 517 | } |
| 518 | |
Mathieu Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 519 | void DexWriter::WriteDebugInfoItem(Stream* stream, dex_ir::DebugInfoItem* debug_info) { |
| 520 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeDebugInfoItem)); |
| 521 | ProcessOffset(stream, debug_info); |
| 522 | stream->Write(debug_info->GetDebugInfo(), debug_info->GetDebugInfoSize()); |
| 523 | } |
| 524 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 525 | void DexWriter::WriteDebugInfoItems(Stream* stream) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 526 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 527 | for (auto& debug_info : header_->DebugInfoItems()) { |
Mathieu Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 528 | WriteDebugInfoItem(stream, debug_info.get()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 529 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 530 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 531 | header_->DebugInfoItems().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 532 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 533 | } |
| 534 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 535 | void DexWriter::WriteCodeItemPostInstructionData(Stream* stream, |
| 536 | dex_ir::CodeItem* code_item, |
| 537 | bool reserve_only) { |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 538 | if (code_item->TriesSize() != 0) { |
Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 539 | stream->AlignTo(dex::TryItem::kAlignment); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 540 | // Write try items. |
| 541 | for (std::unique_ptr<const dex_ir::TryItem>& try_item : *code_item->Tries()) { |
Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 542 | dex::TryItem disk_try_item; |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 543 | if (!reserve_only) { |
| 544 | disk_try_item.start_addr_ = try_item->StartAddr(); |
| 545 | disk_try_item.insn_count_ = try_item->InsnCount(); |
| 546 | disk_try_item.handler_off_ = try_item->GetHandlers()->GetListOffset(); |
| 547 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 548 | stream->Write(&disk_try_item, sizeof(disk_try_item)); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 549 | } |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 550 | // Leave offset pointing to the end of the try items. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 551 | const size_t offset = stream->Tell(); |
| 552 | size_t max_offset = offset + stream->WriteUleb128(code_item->Handlers()->size()); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 553 | for (std::unique_ptr<const dex_ir::CatchHandler>& handlers : *code_item->Handlers()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 554 | stream->Seek(offset + handlers->GetListOffset()); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 555 | uint32_t size = handlers->HasCatchAll() ? (handlers->GetHandlers()->size() - 1) * -1 : |
| 556 | handlers->GetHandlers()->size(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 557 | stream->WriteSleb128(size); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 558 | for (std::unique_ptr<const dex_ir::TypeAddrPair>& handler : *handlers->GetHandlers()) { |
| 559 | if (handler->GetTypeId() != nullptr) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 560 | stream->WriteUleb128(handler->GetTypeId()->GetIndex()); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 561 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 562 | stream->WriteUleb128(handler->GetAddress()); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 563 | } |
| 564 | // TODO: Clean this up to write the handlers in address order. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 565 | max_offset = std::max(max_offset, stream->Tell()); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 566 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 567 | stream->Seek(max_offset); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 568 | } |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 569 | } |
| 570 | |
Mathieu Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 571 | void DexWriter::WriteCodeItem(Stream* stream, |
| 572 | dex_ir::CodeItem* code_item, |
| 573 | bool reserve_only) { |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 574 | DCHECK(code_item != nullptr); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 575 | const uint32_t start_offset = stream->Tell(); |
| 576 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeCodeItem)); |
| 577 | ProcessOffset(stream, code_item); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 578 | |
| 579 | StandardDexFile::CodeItem disk_code_item; |
| 580 | if (!reserve_only) { |
| 581 | disk_code_item.registers_size_ = code_item->RegistersSize(); |
| 582 | disk_code_item.ins_size_ = code_item->InsSize(); |
| 583 | disk_code_item.outs_size_ = code_item->OutsSize(); |
| 584 | disk_code_item.tries_size_ = code_item->TriesSize(); |
| 585 | disk_code_item.debug_info_off_ = code_item->DebugInfo() == nullptr |
| 586 | ? 0 |
| 587 | : code_item->DebugInfo()->GetOffset(); |
| 588 | disk_code_item.insns_size_in_code_units_ = code_item->InsnsSize(); |
| 589 | } |
| 590 | // Avoid using sizeof so that we don't write the fake instruction array at the end of the code |
| 591 | // item. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 592 | stream->Write(&disk_code_item, OFFSETOF_MEMBER(StandardDexFile::CodeItem, insns_)); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 593 | // Write the instructions. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 594 | stream->Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t)); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 595 | // Write the post instruction data. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 596 | WriteCodeItemPostInstructionData(stream, code_item, reserve_only); |
| 597 | if (reserve_only) { |
| 598 | stream->Clear(start_offset, stream->Tell() - start_offset); |
| 599 | } |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 600 | } |
| 601 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 602 | void DexWriter::WriteCodeItems(Stream* stream, bool reserve_only) { |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 603 | DexLayoutSection* code_section = nullptr; |
| 604 | if (!reserve_only && dex_layout_ != nullptr) { |
| 605 | code_section = &dex_layout_->GetSections().sections_[static_cast<size_t>( |
| 606 | DexLayoutSections::SectionType::kSectionTypeCode)]; |
| 607 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 608 | const uint32_t start = stream->Tell(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 609 | for (auto& code_item : header_->CodeItems()) { |
Mathieu Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 610 | uint32_t start_offset = stream->Tell(); |
| 611 | WriteCodeItem(stream, code_item.get(), reserve_only); |
Mathieu Chartier | 8892c6b | 2018-01-09 15:10:17 -0800 | [diff] [blame] | 612 | // Only add the section hotness info once. |
| 613 | if (!reserve_only && code_section != nullptr) { |
| 614 | auto it = dex_layout_->LayoutHotnessInfo().code_item_layout_.find(code_item.get()); |
| 615 | if (it != dex_layout_->LayoutHotnessInfo().code_item_layout_.end()) { |
| 616 | code_section->parts_[static_cast<size_t>(it->second)].CombineSection( |
Mathieu Chartier | b81ecad | 2018-01-23 22:08:26 -0800 | [diff] [blame] | 617 | start_offset, |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 618 | stream->Tell()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 619 | } |
| 620 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 621 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 622 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 623 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 624 | header_->CodeItems().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 625 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 626 | } |
| 627 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 628 | void DexWriter::WriteClassDefs(Stream* stream, bool reserve_only) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 629 | const uint32_t start = stream->Tell(); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 630 | uint32_t class_def_buffer[8]; |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 631 | for (auto& class_def : header_->ClassDefs()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 632 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeClassDefItem)); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 633 | if (reserve_only) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 634 | stream->Skip(class_def->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 635 | } else { |
| 636 | class_def_buffer[0] = class_def->ClassType()->GetIndex(); |
| 637 | class_def_buffer[1] = class_def->GetAccessFlags(); |
| 638 | class_def_buffer[2] = class_def->Superclass() == nullptr ? dex::kDexNoIndex : |
| 639 | class_def->Superclass()->GetIndex(); |
| 640 | class_def_buffer[3] = class_def->InterfacesOffset(); |
| 641 | class_def_buffer[4] = class_def->SourceFile() == nullptr ? dex::kDexNoIndex : |
| 642 | class_def->SourceFile()->GetIndex(); |
| 643 | class_def_buffer[5] = class_def->Annotations() == nullptr ? 0 : |
| 644 | class_def->Annotations()->GetOffset(); |
| 645 | class_def_buffer[6] = class_def->GetClassData() == nullptr ? 0 : |
| 646 | class_def->GetClassData()->GetOffset(); |
| 647 | class_def_buffer[7] = class_def->StaticValues() == nullptr ? 0 : |
| 648 | class_def->StaticValues()->GetOffset(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 649 | stream->Write(class_def_buffer, class_def->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 650 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 651 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 652 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 653 | header_->ClassDefs().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 654 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 655 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 656 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 657 | void DexWriter::WriteClassDatas(Stream* stream) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 658 | const uint32_t start = stream->Tell(); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 659 | for (const std::unique_ptr<dex_ir::ClassData>& class_data : |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 660 | header_->ClassDatas()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 661 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeClassDataItem)); |
| 662 | ProcessOffset(stream, class_data.get()); |
| 663 | stream->WriteUleb128(class_data->StaticFields()->size()); |
| 664 | stream->WriteUleb128(class_data->InstanceFields()->size()); |
| 665 | stream->WriteUleb128(class_data->DirectMethods()->size()); |
| 666 | stream->WriteUleb128(class_data->VirtualMethods()->size()); |
| 667 | WriteEncodedFields(stream, class_data->StaticFields()); |
| 668 | WriteEncodedFields(stream, class_data->InstanceFields()); |
| 669 | WriteEncodedMethods(stream, class_data->DirectMethods()); |
| 670 | WriteEncodedMethods(stream, class_data->VirtualMethods()); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 671 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 672 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 673 | header_->ClassDatas().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 674 | } |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 675 | } |
| 676 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 677 | void DexWriter::WriteCallSiteIds(Stream* stream, bool reserve_only) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 678 | const uint32_t start = stream->Tell(); |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 679 | uint32_t call_site_off[1]; |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 680 | for (auto& call_site_id : header_->CallSiteIds()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 681 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeCallSiteIdItem)); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 682 | if (reserve_only) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 683 | stream->Skip(call_site_id->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 684 | } else { |
| 685 | call_site_off[0] = call_site_id->CallSiteItem()->GetOffset(); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 686 | stream->Write(call_site_off, call_site_id->GetSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 687 | } |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 688 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 689 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 690 | header_->CallSiteIds().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 691 | } |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 692 | } |
| 693 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 694 | void DexWriter::WriteMethodHandles(Stream* stream) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 695 | const uint32_t start = stream->Tell(); |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 696 | uint16_t method_handle_buff[4]; |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 697 | for (auto& method_handle : header_->MethodHandleItems()) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 698 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeMethodHandleItem)); |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 699 | method_handle_buff[0] = static_cast<uint16_t>(method_handle->GetMethodHandleType()); |
| 700 | method_handle_buff[1] = 0; // unused. |
| 701 | method_handle_buff[2] = method_handle->GetFieldOrMethodId()->GetIndex(); |
| 702 | method_handle_buff[3] = 0; // unused. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 703 | stream->Write(method_handle_buff, method_handle->GetSize()); |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 704 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 705 | if (compute_offsets_ && start != stream->Tell()) { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 706 | header_->MethodHandleItems().SetOffset(start); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 707 | } |
Jeff Hao | 5daee90 | 2017-04-27 18:00:38 -0700 | [diff] [blame] | 708 | } |
| 709 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 710 | void DexWriter::WriteMapItems(Stream* stream, MapItemQueue* queue) { |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 711 | // All the sections should already have been added. |
Mathieu Chartier | 9b302bf | 2018-01-25 13:08:08 -0800 | [diff] [blame] | 712 | const uint32_t map_list_size = queue->size(); |
Mathieu Chartier | 9b302bf | 2018-01-25 13:08:08 -0800 | [diff] [blame] | 713 | stream->Write(&map_list_size, sizeof(map_list_size)); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 714 | while (!queue->empty()) { |
Mathieu Chartier | 9b302bf | 2018-01-25 13:08:08 -0800 | [diff] [blame] | 715 | const MapItem& item = queue->top(); |
Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 716 | dex::MapItem map_item; |
Mathieu Chartier | 9b302bf | 2018-01-25 13:08:08 -0800 | [diff] [blame] | 717 | map_item.type_ = item.type_; |
| 718 | map_item.size_ = item.size_; |
| 719 | map_item.offset_ = item.offset_; |
| 720 | map_item.unused_ = 0u; |
| 721 | stream->Write(&map_item, sizeof(map_item)); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 722 | queue->pop(); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 723 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 724 | } |
| 725 | |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 726 | void DexWriter::GenerateAndWriteMapItems(Stream* stream) { |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 727 | MapItemQueue queue; |
| 728 | |
| 729 | // Header and index section. |
| 730 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeHeaderItem, 1, 0)); |
| 731 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 732 | header_->StringIds().Size(), |
| 733 | header_->StringIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 734 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 735 | header_->TypeIds().Size(), |
| 736 | header_->TypeIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 737 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeProtoIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 738 | header_->ProtoIds().Size(), |
| 739 | header_->ProtoIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 740 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeFieldIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 741 | header_->FieldIds().Size(), |
| 742 | header_->FieldIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 743 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 744 | header_->MethodIds().Size(), |
| 745 | header_->MethodIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 746 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDefItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 747 | header_->ClassDefs().Size(), |
| 748 | header_->ClassDefs().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 749 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCallSiteIdItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 750 | header_->CallSiteIds().Size(), |
| 751 | header_->CallSiteIds().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 752 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodHandleItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 753 | header_->MethodHandleItems().Size(), |
| 754 | header_->MethodHandleItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 755 | // Data section. |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 756 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMapList, 1, header_->MapListOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 757 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeList, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 758 | header_->TypeLists().Size(), |
| 759 | header_->TypeLists().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 760 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetRefList, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 761 | header_->AnnotationSetRefLists().Size(), |
| 762 | header_->AnnotationSetRefLists().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 763 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 764 | header_->AnnotationSetItems().Size(), |
| 765 | header_->AnnotationSetItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 766 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDataItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 767 | header_->ClassDatas().Size(), |
| 768 | header_->ClassDatas().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 769 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCodeItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 770 | header_->CodeItems().Size(), |
| 771 | header_->CodeItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 772 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringDataItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 773 | header_->StringDatas().Size(), |
| 774 | header_->StringDatas().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 775 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeDebugInfoItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 776 | header_->DebugInfoItems().Size(), |
| 777 | header_->DebugInfoItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 778 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 779 | header_->AnnotationItems().Size(), |
| 780 | header_->AnnotationItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 781 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeEncodedArrayItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 782 | header_->EncodedArrayItems().Size(), |
| 783 | header_->EncodedArrayItems().GetOffset())); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 784 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationsDirectoryItem, |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 785 | header_->AnnotationsDirectoryItems().Size(), |
| 786 | header_->AnnotationsDirectoryItems().GetOffset())); |
David Brazdil | 20c765f | 2018-10-27 21:45:15 +0000 | [diff] [blame] | 787 | queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeHiddenapiClassData, |
| 788 | header_->HiddenapiClassDatas().Empty() ? 0u : 1u, |
| 789 | header_->HiddenapiClassDatas().GetOffset())); |
Mathieu Chartier | 5e49614 | 2018-01-27 13:11:14 -0800 | [diff] [blame] | 790 | WriteMapItems(stream, &queue); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 791 | } |
| 792 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 793 | void DexWriter::WriteHeader(Stream* stream) { |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 794 | StandardDexFile::Header header; |
Mathieu Chartier | 21cf258 | 2018-01-08 17:09:48 -0800 | [diff] [blame] | 795 | if (CompactDexFile::IsMagicValid(header_->Magic())) { |
| 796 | StandardDexFile::WriteMagic(header.magic_); |
Vladimir Marko | 1c993cd | 2020-05-28 09:30:06 +0000 | [diff] [blame] | 797 | if (header_->SupportDefaultMethods()) { |
| 798 | StandardDexFile::WriteCurrentVersion(header.magic_); |
| 799 | } else { |
| 800 | StandardDexFile::WriteVersionBeforeDefaultMethods(header.magic_); |
| 801 | } |
Mathieu Chartier | 21cf258 | 2018-01-08 17:09:48 -0800 | [diff] [blame] | 802 | } else { |
| 803 | // Standard dex -> standard dex, just reuse the same header. |
| 804 | static constexpr size_t kMagicAndVersionLen = |
| 805 | StandardDexFile::kDexMagicSize + StandardDexFile::kDexVersionLen; |
| 806 | std::copy_n(header_->Magic(), kMagicAndVersionLen, header.magic_); |
| 807 | } |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 808 | header.checksum_ = header_->Checksum(); |
| 809 | std::copy_n(header_->Signature(), DexFile::kSha1DigestSize, header.signature_); |
| 810 | header.file_size_ = header_->FileSize(); |
Mathieu Chartier | f6e3147 | 2017-12-28 13:32:08 -0800 | [diff] [blame] | 811 | header.header_size_ = GetHeaderSize(); |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 812 | header.endian_tag_ = header_->EndianTag(); |
| 813 | header.link_size_ = header_->LinkSize(); |
| 814 | header.link_off_ = header_->LinkOffset(); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 815 | header.map_off_ = header_->MapListOffset(); |
| 816 | header.string_ids_size_ = header_->StringIds().Size(); |
| 817 | header.string_ids_off_ = header_->StringIds().GetOffset(); |
| 818 | header.type_ids_size_ = header_->TypeIds().Size(); |
| 819 | header.type_ids_off_ = header_->TypeIds().GetOffset(); |
| 820 | header.proto_ids_size_ = header_->ProtoIds().Size(); |
| 821 | header.proto_ids_off_ = header_->ProtoIds().GetOffset(); |
| 822 | header.field_ids_size_ = header_->FieldIds().Size(); |
| 823 | header.field_ids_off_ = header_->FieldIds().GetOffset(); |
| 824 | header.method_ids_size_ = header_->MethodIds().Size(); |
| 825 | header.method_ids_off_ = header_->MethodIds().GetOffset(); |
| 826 | header.class_defs_size_ = header_->ClassDefs().Size(); |
| 827 | header.class_defs_off_ = header_->ClassDefs().GetOffset(); |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 828 | header.data_size_ = header_->DataSize(); |
| 829 | header.data_off_ = header_->DataOffset(); |
| 830 | |
Mathieu Chartier | f6e3147 | 2017-12-28 13:32:08 -0800 | [diff] [blame] | 831 | CHECK_EQ(sizeof(header), GetHeaderSize()); |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 832 | static_assert(sizeof(header) == 0x70, "Size doesn't match dex spec"); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 833 | stream->Seek(0); |
| 834 | stream->Overwrite(reinterpret_cast<uint8_t*>(&header), sizeof(header)); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 835 | } |
| 836 | |
Mathieu Chartier | f6e3147 | 2017-12-28 13:32:08 -0800 | [diff] [blame] | 837 | size_t DexWriter::GetHeaderSize() const { |
| 838 | return sizeof(StandardDexFile::Header); |
| 839 | } |
| 840 | |
Mathieu Chartier | 05f90d1 | 2018-02-07 13:47:17 -0800 | [diff] [blame] | 841 | bool DexWriter::Write(DexContainer* output, std::string* error_msg) { |
| 842 | DCHECK(error_msg != nullptr); |
| 843 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 844 | Stream stream_storage(output->GetMainSection()); |
| 845 | Stream* stream = &stream_storage; |
| 846 | |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 847 | // Starting offset is right after the header. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 848 | stream->Seek(GetHeaderSize()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 849 | |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 850 | // Based on: https://source.android.com/devices/tech/dalvik/dex-format |
| 851 | // 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] | 852 | const uint32_t string_ids_offset = stream->Tell(); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 853 | WriteStringIds(stream, /*reserve_only=*/ true); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 854 | WriteTypeIds(stream); |
| 855 | const uint32_t proto_ids_offset = stream->Tell(); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 856 | WriteProtoIds(stream, /*reserve_only=*/ true); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 857 | WriteFieldIds(stream); |
| 858 | WriteMethodIds(stream); |
| 859 | const uint32_t class_defs_offset = stream->Tell(); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 860 | WriteClassDefs(stream, /*reserve_only=*/ true); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 861 | const uint32_t call_site_ids_offset = stream->Tell(); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 862 | WriteCallSiteIds(stream, /*reserve_only=*/ true); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 863 | WriteMethodHandles(stream); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 864 | |
| 865 | uint32_t data_offset_ = 0u; |
| 866 | if (compute_offsets_) { |
| 867 | // Data section. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 868 | stream->AlignTo(kDataSectionAlignment); |
| 869 | data_offset_ = stream->Tell(); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 870 | } |
| 871 | |
| 872 | // Write code item first to minimize the space required for encoded methods. |
| 873 | // 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] | 874 | const uint32_t code_items_offset = stream->Tell(); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 875 | WriteCodeItems(stream, /*reserve_only=*/ true); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 876 | // Write debug info section. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 877 | WriteDebugInfoItems(stream); |
| 878 | { |
| 879 | // Actually write code items since debug info offsets are calculated now. |
| 880 | Stream::ScopedSeek seek(stream, code_items_offset); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 881 | WriteCodeItems(stream, /*reserve_only=*/ false); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 882 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 883 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 884 | WriteEncodedArrays(stream); |
| 885 | WriteAnnotations(stream); |
| 886 | WriteAnnotationSets(stream); |
| 887 | WriteAnnotationSetRefs(stream); |
| 888 | WriteAnnotationsDirectories(stream); |
| 889 | WriteTypeLists(stream); |
| 890 | WriteClassDatas(stream); |
| 891 | WriteStringDatas(stream); |
David Brazdil | 20c765f | 2018-10-27 21:45:15 +0000 | [diff] [blame] | 892 | WriteHiddenapiClassData(stream); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 893 | |
| 894 | // Write delayed id sections that depend on data sections. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 895 | { |
| 896 | Stream::ScopedSeek seek(stream, string_ids_offset); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 897 | WriteStringIds(stream, /*reserve_only=*/ false); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 898 | } |
| 899 | { |
| 900 | Stream::ScopedSeek seek(stream, proto_ids_offset); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 901 | WriteProtoIds(stream, /*reserve_only=*/ false); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 902 | } |
| 903 | { |
| 904 | Stream::ScopedSeek seek(stream, class_defs_offset); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 905 | WriteClassDefs(stream, /*reserve_only=*/ false); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 906 | } |
| 907 | { |
| 908 | Stream::ScopedSeek seek(stream, call_site_ids_offset); |
Andreas Gampe | 9b031f7 | 2018-10-04 11:03:34 -0700 | [diff] [blame] | 909 | WriteCallSiteIds(stream, /*reserve_only=*/ false); |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 910 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 911 | |
| 912 | // Write the map list. |
| 913 | if (compute_offsets_) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 914 | stream->AlignTo(SectionAlignment(DexFile::kDexTypeMapList)); |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 915 | header_->SetMapListOffset(stream->Tell()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 916 | } else { |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 917 | stream->Seek(header_->MapListOffset()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 918 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 919 | GenerateAndWriteMapItems(stream); |
| 920 | stream->AlignTo(kDataSectionAlignment); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 921 | |
| 922 | // Map items are included in the data section. |
| 923 | if (compute_offsets_) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 924 | header_->SetDataSize(stream->Tell() - data_offset_); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 925 | if (header_->DataSize() != 0) { |
| 926 | // Offset must be zero when the size is zero. |
| 927 | header_->SetDataOffset(data_offset_); |
| 928 | } else { |
| 929 | header_->SetDataOffset(0u); |
| 930 | } |
| 931 | } |
| 932 | |
Mathieu Chartier | 2f36d2f | 2017-11-20 15:45:25 -0800 | [diff] [blame] | 933 | // Write link data if it exists. |
David Sehr | 2b5a38f | 2018-06-14 15:13:04 -0700 | [diff] [blame] | 934 | const std::vector<uint8_t>& link_data = header_->LinkData(); |
Mathieu Chartier | 2f36d2f | 2017-11-20 15:45:25 -0800 | [diff] [blame] | 935 | if (link_data.size() > 0) { |
| 936 | CHECK_EQ(header_->LinkSize(), static_cast<uint32_t>(link_data.size())); |
| 937 | if (compute_offsets_) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 938 | header_->SetLinkOffset(stream->Tell()); |
| 939 | } else { |
| 940 | stream->Seek(header_->LinkOffset()); |
Mathieu Chartier | 2f36d2f | 2017-11-20 15:45:25 -0800 | [diff] [blame] | 941 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 942 | stream->Write(&link_data[0], link_data.size()); |
Mathieu Chartier | 2f36d2f | 2017-11-20 15:45:25 -0800 | [diff] [blame] | 943 | } |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 944 | |
| 945 | // Write header last. |
| 946 | if (compute_offsets_) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 947 | header_->SetFileSize(stream->Tell()); |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 948 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 949 | WriteHeader(stream); |
Mathieu Chartier | 2c4b084 | 2017-12-13 11:49:51 -0800 | [diff] [blame] | 950 | |
| 951 | if (dex_layout_->GetOptions().update_checksum_) { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 952 | header_->SetChecksum(DexFile::CalculateChecksum(stream->Begin(), header_->FileSize())); |
Mathieu Chartier | 2c4b084 | 2017-12-13 11:49:51 -0800 | [diff] [blame] | 953 | // Rewrite the header with the calculated checksum. |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 954 | WriteHeader(stream); |
Mathieu Chartier | 2c4b084 | 2017-12-13 11:49:51 -0800 | [diff] [blame] | 955 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 956 | |
| 957 | // Trim the map to make it sized as large as the dex file. |
| 958 | output->GetMainSection()->Resize(header_->FileSize()); |
Mathieu Chartier | 05f90d1 | 2018-02-07 13:47:17 -0800 | [diff] [blame] | 959 | return true; |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 960 | } |
| 961 | |
Mathieu Chartier | 05f90d1 | 2018-02-07 13:47:17 -0800 | [diff] [blame] | 962 | bool DexWriter::Output(DexLayout* dex_layout, |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 963 | std::unique_ptr<DexContainer>* container, |
Mathieu Chartier | 05f90d1 | 2018-02-07 13:47:17 -0800 | [diff] [blame] | 964 | bool compute_offsets, |
| 965 | std::string* error_msg) { |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 966 | CHECK(dex_layout != nullptr); |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 967 | std::unique_ptr<DexWriter> writer; |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 968 | if (dex_layout->GetOptions().compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone) { |
| 969 | CHECK(compute_offsets) << "Compact dex requires computing offsets"; |
| 970 | writer.reset(new CompactDexWriter(dex_layout)); |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 971 | } else { |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 972 | writer.reset(new DexWriter(dex_layout, compute_offsets)); |
Mathieu Chartier | f95a75e | 2017-11-03 15:25:52 -0700 | [diff] [blame] | 973 | } |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 974 | DCHECK(container != nullptr); |
| 975 | if (*container == nullptr) { |
| 976 | *container = writer->CreateDexContainer(); |
| 977 | } |
Mathieu Chartier | 05f90d1 | 2018-02-07 13:47:17 -0800 | [diff] [blame] | 978 | return writer->Write(container->get(), error_msg); |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 979 | } |
| 980 | |
Mathieu Chartier | 3e0c517 | 2017-11-12 12:58:40 -0800 | [diff] [blame] | 981 | void MapItemQueue::AddIfNotEmpty(const MapItem& item) { |
| 982 | if (item.size_ != 0) { |
| 983 | push(item); |
| 984 | } |
| 985 | } |
| 986 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 987 | void DexWriter::ProcessOffset(Stream* stream, dex_ir::Item* item) { |
| 988 | if (compute_offsets_) { |
| 989 | item->SetOffset(stream->Tell()); |
| 990 | } else { |
| 991 | // Not computing offsets, just use the one in the item. |
| 992 | stream->Seek(item->GetOffset()); |
| 993 | } |
| 994 | } |
| 995 | |
David Brazdil | 1783480 | 2019-01-21 19:46:46 +0000 | [diff] [blame] | 996 | void DexWriter::ProcessOffset(Stream* stream, dex_ir::CollectionBase* item) { |
| 997 | if (compute_offsets_) { |
| 998 | item->SetOffset(stream->Tell()); |
| 999 | } else { |
| 1000 | // Not computing offsets, just use the one in the item. |
| 1001 | stream->Seek(item->GetOffset()); |
| 1002 | } |
| 1003 | } |
| 1004 | |
Mathieu Chartier | e6b6ff8 | 2018-01-19 18:58:34 -0800 | [diff] [blame] | 1005 | std::unique_ptr<DexContainer> DexWriter::CreateDexContainer() const { |
| 1006 | return std::unique_ptr<DexContainer>(new DexWriter::Container); |
| 1007 | } |
| 1008 | |
Jeff Hao | a862100 | 2016-10-04 18:13:44 +0000 | [diff] [blame] | 1009 | } // namespace art |