NOTE: The builder holds the actual data, so it must live as long as the dex file.
| 82 | |
| 83 | // NOTE: The builder holds the actual data, so it must live as long as the dex file. |
| 84 | std::unique_ptr<const DexFile> Build(const std::string& dex_location) { |
| 85 | CHECK(dex_file_data_.empty()); |
| 86 | union { |
| 87 | uint8_t data[sizeof(DexFile::Header)]; |
| 88 | uint64_t force_alignment; |
| 89 | } header_data; |
| 90 | std::memset(header_data.data, 0, sizeof(header_data.data)); |
| 91 | DexFile::Header* header = reinterpret_cast<DexFile::Header*>(&header_data.data); |
| 92 | std::copy_n(StandardDexFile::kDexMagic, 4u, header->magic_); |
| 93 | std::copy_n(StandardDexFile::kDexMagicVersions[0], 4u, header->magic_ + 4u); |
| 94 | header->header_size_ = sizeof(DexFile::Header); |
| 95 | header->endian_tag_ = DexFile::kDexEndianConstant; |
| 96 | header->link_size_ = 0u; // Unused. |
| 97 | header->link_off_ = 0u; // Unused. |
| 98 | header->map_off_ = 0u; // Unused. TODO: This is wrong. Dex files created by this builder |
| 99 | // cannot be verified. b/26808512 |
| 100 | |
| 101 | uint32_t data_section_size = 0u; |
| 102 | |
| 103 | uint32_t string_ids_offset = sizeof(DexFile::Header); |
| 104 | uint32_t string_idx = 0u; |
| 105 | for (auto& entry : strings_) { |
| 106 | entry.second.idx = string_idx; |
| 107 | string_idx += 1u; |
| 108 | entry.second.data_offset = data_section_size; |
| 109 | data_section_size += entry.first.length() + 1u /* length */ + 1u /* null-terminator */; |
| 110 | } |
| 111 | header->string_ids_size_ = strings_.size(); |
| 112 | header->string_ids_off_ = strings_.empty() ? 0u : string_ids_offset; |
| 113 | |
| 114 | uint32_t type_ids_offset = string_ids_offset + strings_.size() * sizeof(DexFile::StringId); |
| 115 | uint32_t type_idx = 0u; |
| 116 | for (auto& entry : types_) { |
| 117 | entry.second = type_idx; |
| 118 | type_idx += 1u; |
| 119 | } |
| 120 | header->type_ids_size_ = types_.size(); |
| 121 | header->type_ids_off_ = types_.empty() ? 0u : type_ids_offset; |
| 122 | |
| 123 | uint32_t proto_ids_offset = type_ids_offset + types_.size() * sizeof(DexFile::TypeId); |
| 124 | uint32_t proto_idx = 0u; |
| 125 | for (auto& entry : protos_) { |
| 126 | entry.second.idx = proto_idx; |
| 127 | proto_idx += 1u; |
| 128 | size_t num_args = entry.first.args.size(); |
| 129 | if (num_args != 0u) { |
| 130 | entry.second.data_offset = RoundUp(data_section_size, 4u); |
| 131 | data_section_size = entry.second.data_offset + 4u + num_args * sizeof(DexFile::TypeItem); |
| 132 | } else { |
| 133 | entry.second.data_offset = 0u; |
| 134 | } |
| 135 | } |
| 136 | header->proto_ids_size_ = protos_.size(); |
| 137 | header->proto_ids_off_ = protos_.empty() ? 0u : proto_ids_offset; |
| 138 | |
| 139 | uint32_t field_ids_offset = proto_ids_offset + protos_.size() * sizeof(DexFile::ProtoId); |
| 140 | uint32_t field_idx = 0u; |
| 141 | for (auto& entry : fields_) { |