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