1c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko/* 2c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * Copyright (C) 2015 The Android Open Source Project 3c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * 4c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * Licensed under the Apache License, Version 2.0 (the "License"); 5c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * you may not use this file except in compliance with the License. 6c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * You may obtain a copy of the License at 7c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * 8c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * http://www.apache.org/licenses/LICENSE-2.0 9c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * 10c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * Unless required by applicable law or agreed to in writing, software 11c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * distributed under the License is distributed on an "AS IS" BASIS, 12c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * See the License for the specific language governing permissions and 14c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko * limitations under the License. 15c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko */ 16c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 17c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko#ifndef ART_COMPILER_UTILS_TEST_DEX_FILE_BUILDER_H_ 18c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko#define ART_COMPILER_UTILS_TEST_DEX_FILE_BUILDER_H_ 19c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 20c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko#include <cstring> 21c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko#include <set> 22c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko#include <map> 23c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko#include <vector> 24c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 2541b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko#include "base/bit_utils.h" 2641b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko#include "base/logging.h" 27c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko#include "dex_file.h" 28c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 29c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Markonamespace art { 30c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 31c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Markoclass TestDexFileBuilder { 32c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko public: 33c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko TestDexFileBuilder() 34c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko : strings_(), types_(), fields_(), protos_(), dex_file_data_() { 35c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 36c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 37c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko void AddString(const std::string& str) { 38c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(dex_file_data_.empty()); 39c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko auto it = strings_.emplace(str, IdxAndDataOffset()).first; 40c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_LT(it->first.length(), 128u); // Don't allow multi-byte length in uleb128. 41c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 42c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 43c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko void AddType(const std::string& descriptor) { 44c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(dex_file_data_.empty()); 45c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko AddString(descriptor); 46c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko types_.emplace(descriptor, 0u); 47c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 48c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 49c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko void AddField(const std::string& class_descriptor, const std::string& type, 50c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const std::string& name) { 51c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(dex_file_data_.empty()); 52c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko AddType(class_descriptor); 53c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko AddType(type); 54c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko AddString(name); 55c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko FieldKey key = { class_descriptor, type, name }; 56c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko fields_.emplace(key, 0u); 57c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 58c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 59c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko void AddMethod(const std::string& class_descriptor, const std::string& signature, 60c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const std::string& name) { 61c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(dex_file_data_.empty()); 62c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko AddType(class_descriptor); 63c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko AddString(name); 64c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 65c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko ProtoKey proto_key = CreateProtoKey(signature); 66c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko AddString(proto_key.shorty); 67c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko AddType(proto_key.return_type); 68c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (const auto& arg_type : proto_key.args) { 69c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko AddType(arg_type); 70c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 71c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko auto it = protos_.emplace(proto_key, IdxAndDataOffset()).first; 72c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const ProtoKey* proto = &it->first; // Valid as long as the element remains in protos_. 73c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 74c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko MethodKey method_key = { 75c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko class_descriptor, name, proto 76c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko }; 77c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko methods_.emplace(method_key, 0u); 78c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 79c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 80c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko // NOTE: The builder holds the actual data, so it must live as long as the dex file. 81c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::unique_ptr<const DexFile> Build(const std::string& dex_location) { 82c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(dex_file_data_.empty()); 83c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko union { 84c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint8_t data[sizeof(DexFile::Header)]; 85c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint64_t force_alignment; 86c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } header_data; 87c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::memset(header_data.data, 0, sizeof(header_data.data)); 88c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko DexFile::Header* header = reinterpret_cast<DexFile::Header*>(&header_data.data); 89c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::copy_n(DexFile::kDexMagic, 4u, header->magic_); 90c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::copy_n(DexFile::kDexMagicVersion, 4u, header->magic_ + 4u); 91c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->header_size_ = sizeof(header); 92c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->endian_tag_ = DexFile::kDexEndianConstant; 93c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->link_size_ = 0u; // Unused. 94c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->link_off_ = 0u; // Unused. 95c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->map_off_ = 0u; // Unused. 96c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 97c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t data_section_size = 0u; 98c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 99c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t string_ids_offset = sizeof(DexFile::Header); 100c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t string_idx = 0u; 101c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (auto& entry : strings_) { 102c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko entry.second.idx = string_idx; 103c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko string_idx += 1u; 104c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko entry.second.data_offset = data_section_size; 105c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko data_section_size += entry.first.length() + 1u /* length */ + 1u /* null-terminator */; 106c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 107c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->string_ids_size_ = strings_.size(); 108c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->string_ids_off_ = strings_.empty() ? 0u : string_ids_offset; 109c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 110c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t type_ids_offset = string_ids_offset + strings_.size() * sizeof(DexFile::StringId); 111c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t type_idx = 0u; 112c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (auto& entry : types_) { 113c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko entry.second = type_idx; 114c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko type_idx += 1u; 115c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 116c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->type_ids_size_ = types_.size(); 117c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->type_ids_off_ = types_.empty() ? 0u : type_ids_offset; 118c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 119c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t proto_ids_offset = type_ids_offset + types_.size() * sizeof(DexFile::TypeId); 120c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t proto_idx = 0u; 121c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (auto& entry : protos_) { 122c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko entry.second.idx = proto_idx; 123c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko proto_idx += 1u; 124c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko size_t num_args = entry.first.args.size(); 125c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko if (num_args != 0u) { 126c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko entry.second.data_offset = RoundUp(data_section_size, 4u); 127c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko data_section_size = entry.second.data_offset + 4u + num_args * sizeof(DexFile::TypeItem); 128c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } else { 129c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko entry.second.data_offset = 0u; 130c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 131c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 132c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->proto_ids_size_ = protos_.size(); 133c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->proto_ids_off_ = protos_.empty() ? 0u : proto_ids_offset; 134c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 135c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t field_ids_offset = proto_ids_offset + protos_.size() * sizeof(DexFile::ProtoId); 136c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t field_idx = 0u; 137c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (auto& entry : fields_) { 138c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko entry.second = field_idx; 139c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko field_idx += 1u; 140c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 141c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->field_ids_size_ = fields_.size(); 142c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->field_ids_off_ = fields_.empty() ? 0u : field_ids_offset; 143c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 144c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t method_ids_offset = field_ids_offset + fields_.size() * sizeof(DexFile::FieldId); 145c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t method_idx = 0u; 146c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (auto& entry : methods_) { 147c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko entry.second = method_idx; 148c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko method_idx += 1u; 149c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 150c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->method_ids_size_ = methods_.size(); 151c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->method_ids_off_ = methods_.empty() ? 0u : method_ids_offset; 152c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 153c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko // No class defs. 154c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->class_defs_size_ = 0u; 155c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->class_defs_off_ = 0u; 156c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 157c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t data_section_offset = method_ids_offset + methods_.size() * sizeof(DexFile::MethodId); 158c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->data_size_ = data_section_size; 159c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko header->data_off_ = (data_section_size != 0u) ? data_section_offset : 0u; 160c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 161c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t total_size = data_section_offset + data_section_size; 162c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 163c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko dex_file_data_.resize(total_size); 164c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::memcpy(&dex_file_data_[0], header_data.data, sizeof(DexFile::Header)); 165c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 166c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (const auto& entry : strings_) { 167c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_LT(entry.first.size(), 128u); 168c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t raw_offset = data_section_offset + entry.second.data_offset; 169c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko dex_file_data_[raw_offset] = static_cast<uint8_t>(entry.first.size()); 170c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::memcpy(&dex_file_data_[raw_offset + 1], entry.first.c_str(), entry.first.size() + 1); 171c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write32(string_ids_offset + entry.second.idx * sizeof(DexFile::StringId), raw_offset); 172c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 173c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 174c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (const auto& entry : types_) { 175c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write32(type_ids_offset + entry.second * sizeof(DexFile::TypeId), GetStringIdx(entry.first)); 176c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko ++type_idx; 177c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 178c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 179c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (const auto& entry : protos_) { 180c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko size_t num_args = entry.first.args.size(); 181c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t type_list_offset = 182c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko (num_args != 0u) ? data_section_offset + entry.second.data_offset : 0u; 183c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t raw_offset = proto_ids_offset + entry.second.idx * sizeof(DexFile::ProtoId); 184c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write32(raw_offset + 0u, GetStringIdx(entry.first.shorty)); 185c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write16(raw_offset + 4u, GetTypeIdx(entry.first.return_type)); 186c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write32(raw_offset + 8u, type_list_offset); 187c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko if (num_args != 0u) { 188c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_NE(entry.second.data_offset, 0u); 189c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write32(type_list_offset, num_args); 190c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (size_t i = 0; i != num_args; ++i) { 191c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write16(type_list_offset + 4u + i * sizeof(DexFile::TypeItem), 192c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko GetTypeIdx(entry.first.args[i])); 193c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 194c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 195c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 196c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 197c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (const auto& entry : fields_) { 198c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t raw_offset = field_ids_offset + entry.second * sizeof(DexFile::FieldId); 199c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write16(raw_offset + 0u, GetTypeIdx(entry.first.class_descriptor)); 200c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write16(raw_offset + 2u, GetTypeIdx(entry.first.type)); 201c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write32(raw_offset + 4u, GetStringIdx(entry.first.name)); 202c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 203c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 204c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (const auto& entry : methods_) { 205c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t raw_offset = method_ids_offset + entry.second * sizeof(DexFile::MethodId); 206c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write16(raw_offset + 0u, GetTypeIdx(entry.first.class_descriptor)); 207c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko auto it = protos_.find(*entry.first.proto); 208c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(it != protos_.end()); 209c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write16(raw_offset + 2u, it->second.idx); 210c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko Write32(raw_offset + 4u, GetStringIdx(entry.first.name)); 211c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 212c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 213c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko // Leave checksum and signature as zeros. 214c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 215c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::string error_msg; 216c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::unique_ptr<const DexFile> dex_file(DexFile::Open( 217c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko &dex_file_data_[0], dex_file_data_.size(), dex_location, 0u, nullptr, &error_msg)); 218c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(dex_file != nullptr) << error_msg; 219c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return std::move(dex_file); 220c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 221c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 222c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t GetStringIdx(const std::string& type) { 223c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko auto it = strings_.find(type); 224c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(it != strings_.end()); 225c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return it->second.idx; 226c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 227c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 228c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t GetTypeIdx(const std::string& type) { 229c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko auto it = types_.find(type); 230c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(it != types_.end()); 231c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return it->second; 232c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 233c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 234c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t GetFieldIdx(const std::string& class_descriptor, const std::string& type, 235c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const std::string& name) { 236c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko FieldKey key = { class_descriptor, type, name }; 237c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko auto it = fields_.find(key); 238c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(it != fields_.end()); 239c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return it->second; 240c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 241c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 242c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t GetMethodIdx(const std::string& class_descriptor, const std::string& signature, 243c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const std::string& name) { 244c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko ProtoKey proto_key = CreateProtoKey(signature); 245c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko MethodKey method_key = { class_descriptor, name, &proto_key }; 246c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko auto it = methods_.find(method_key); 247c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(it != methods_.end()); 248c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return it->second; 249c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 250c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 251c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko private: 252c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko struct IdxAndDataOffset { 253c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t idx; 254c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko uint32_t data_offset; 255c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko }; 256c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 257c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko struct FieldKey { 258c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const std::string class_descriptor; 259c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const std::string type; 260c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const std::string name; 261c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko }; 262c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko struct FieldKeyComparator { 263c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko bool operator()(const FieldKey& lhs, const FieldKey& rhs) const { 264c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko if (lhs.class_descriptor != rhs.class_descriptor) { 265c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return lhs.class_descriptor < rhs.class_descriptor; 266c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 267c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko if (lhs.name != rhs.name) { 268c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return lhs.name < rhs.name; 269c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 270c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return lhs.type < rhs.type; 271c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 272c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko }; 273c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 274c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko struct ProtoKey { 275c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::string shorty; 276c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::string return_type; 277c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::vector<std::string> args; 278c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko }; 279c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko struct ProtoKeyComparator { 280c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko bool operator()(const ProtoKey& lhs, const ProtoKey& rhs) const { 281c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko if (lhs.return_type != rhs.return_type) { 282c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return lhs.return_type < rhs.return_type; 283c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 284c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko size_t min_args = std::min(lhs.args.size(), rhs.args.size()); 285c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko for (size_t i = 0; i != min_args; ++i) { 286c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko if (lhs.args[i] != rhs.args[i]) { 287c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return lhs.args[i] < rhs.args[i]; 288c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 289c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 290c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return lhs.args.size() < rhs.args.size(); 291c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 292c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko }; 293c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 294c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko struct MethodKey { 295c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::string class_descriptor; 296c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::string name; 297c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const ProtoKey* proto; 298c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko }; 299c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko struct MethodKeyComparator { 300c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko bool operator()(const MethodKey& lhs, const MethodKey& rhs) const { 301c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko if (lhs.class_descriptor != rhs.class_descriptor) { 302c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return lhs.class_descriptor < rhs.class_descriptor; 303c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 304c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko if (lhs.name != rhs.name) { 305c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return lhs.name < rhs.name; 306c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 307c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return ProtoKeyComparator()(*lhs.proto, *rhs.proto); 308c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 309c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko }; 310c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 311c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko ProtoKey CreateProtoKey(const std::string& signature) { 312c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_EQ(signature[0], '('); 313c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const char* args = signature.c_str() + 1; 314c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const char* args_end = std::strchr(args, ')'); 315c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK(args_end != nullptr); 316c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const char* return_type = args_end + 1; 317c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 318c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko ProtoKey key = { 319c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::string() + ((*return_type == '[') ? 'L' : *return_type), 320c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return_type, 321c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::vector<std::string>() 322c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko }; 323c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko while (args != args_end) { 324c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko key.shorty += (*args == '[') ? 'L' : *args; 325c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko const char* arg_start = args; 326c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko while (*args == '[') { 327c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko ++args; 328c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 329c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko if (*args == 'L') { 330c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko do { 331c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko ++args; 332c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_NE(args, args_end); 333c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } while (*args != ';'); 334c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 335c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko ++args; 336c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko key.args.emplace_back(arg_start, args); 337c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 338c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko return key; 339c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 340c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 341c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko void Write32(size_t offset, uint32_t value) { 342c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_LE(offset + 4u, dex_file_data_.size()); 343c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_EQ(dex_file_data_[offset + 0], 0u); 344c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_EQ(dex_file_data_[offset + 1], 0u); 345c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_EQ(dex_file_data_[offset + 2], 0u); 346c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_EQ(dex_file_data_[offset + 3], 0u); 347c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko dex_file_data_[offset + 0] = static_cast<uint8_t>(value >> 0); 348c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko dex_file_data_[offset + 1] = static_cast<uint8_t>(value >> 8); 349c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko dex_file_data_[offset + 2] = static_cast<uint8_t>(value >> 16); 350c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko dex_file_data_[offset + 3] = static_cast<uint8_t>(value >> 24); 351c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 352c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 353c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko void Write16(size_t offset, uint32_t value) { 354c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_LE(value, 0xffffu); 355c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_LE(offset + 2u, dex_file_data_.size()); 356c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_EQ(dex_file_data_[offset + 0], 0u); 357c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko CHECK_EQ(dex_file_data_[offset + 1], 0u); 358c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko dex_file_data_[offset + 0] = static_cast<uint8_t>(value >> 0); 359c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko dex_file_data_[offset + 1] = static_cast<uint8_t>(value >> 8); 360c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko } 361c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 362c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::map<std::string, IdxAndDataOffset> strings_; 363c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::map<std::string, uint32_t> types_; 364c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::map<FieldKey, uint32_t, FieldKeyComparator> fields_; 365c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::map<ProtoKey, IdxAndDataOffset, ProtoKeyComparator> protos_; 366c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::map<MethodKey, uint32_t, MethodKeyComparator> methods_; 367c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 368c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko std::vector<uint8_t> dex_file_data_; 369c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko}; 370c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 371c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko} // namespace art 372c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko 373c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko#endif // ART_COMPILER_UTILS_TEST_DEX_FILE_BUILDER_H_ 374