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. 15 * 16 * Header file of an in-memory representation of DEX files. 17 */ 18 19 #include <stdint.h> 20 #include <vector> 21 22 #include "dex_ir_builder.h" 23 #include "dexlayout.h" 24 25 namespace art { 26 namespace dex_ir { 27 28 static void CheckAndSetRemainingOffsets(const DexFile& dex_file, 29 Collections* collections, 30 const Options& options); 31 32 Header* DexIrBuilder(const DexFile& dex_file, 33 bool eagerly_assign_offsets, 34 const Options& options) { 35 const DexFile::Header& disk_header = dex_file.GetHeader(); 36 Header* header = new Header(disk_header.magic_, 37 disk_header.checksum_, 38 disk_header.signature_, 39 disk_header.endian_tag_, 40 disk_header.file_size_, 41 disk_header.header_size_, 42 disk_header.link_size_, 43 disk_header.link_off_, 44 disk_header.data_size_, 45 disk_header.data_off_, 46 dex_file.SupportsDefaultMethods()); 47 Collections& collections = header->GetCollections(); 48 collections.SetEagerlyAssignOffsets(eagerly_assign_offsets); 49 // Walk the rest of the header fields. 50 // StringId table. 51 collections.SetStringIdsOffset(disk_header.string_ids_off_); 52 for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) { 53 collections.CreateStringId(dex_file, i); 54 } 55 // TypeId table. 56 collections.SetTypeIdsOffset(disk_header.type_ids_off_); 57 for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) { 58 collections.CreateTypeId(dex_file, i); 59 } 60 // ProtoId table. 61 collections.SetProtoIdsOffset(disk_header.proto_ids_off_); 62 for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) { 63 collections.CreateProtoId(dex_file, i); 64 } 65 // FieldId table. 66 collections.SetFieldIdsOffset(disk_header.field_ids_off_); 67 for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) { 68 collections.CreateFieldId(dex_file, i); 69 } 70 // MethodId table. 71 collections.SetMethodIdsOffset(disk_header.method_ids_off_); 72 for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) { 73 collections.CreateMethodId(dex_file, i); 74 } 75 // ClassDef table. 76 collections.SetClassDefsOffset(disk_header.class_defs_off_); 77 for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) { 78 if (!options.class_filter_.empty()) { 79 // If the filter is enabled (not empty), filter out classes that don't have a matching 80 // descriptor. 81 const DexFile::ClassDef& class_def = dex_file.GetClassDef(i); 82 const char* descriptor = dex_file.GetClassDescriptor(class_def); 83 if (options.class_filter_.find(descriptor) == options.class_filter_.end()) { 84 continue; 85 } 86 } 87 collections.CreateClassDef(dex_file, i); 88 } 89 // MapItem. 90 collections.SetMapListOffset(disk_header.map_off_); 91 // CallSiteIds and MethodHandleItems. 92 collections.CreateCallSitesAndMethodHandles(dex_file); 93 CheckAndSetRemainingOffsets(dex_file, &collections, options); 94 95 // Sort the vectors by the map order (same order as the file). 96 collections.SortVectorsByMapOrder(); 97 98 // Load the link data if it exists. 99 collections.SetLinkData(std::vector<uint8_t>( 100 dex_file.DataBegin() + dex_file.GetHeader().link_off_, 101 dex_file.DataBegin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_)); 102 103 return header; 104 } 105 106 static void CheckAndSetRemainingOffsets(const DexFile& dex_file, 107 Collections* collections, 108 const Options& options) { 109 const DexFile::Header& disk_header = dex_file.GetHeader(); 110 // Read MapItems and validate/set remaining offsets. 111 const DexFile::MapList* map = dex_file.GetMapList(); 112 const uint32_t count = map->size_; 113 for (uint32_t i = 0; i < count; ++i) { 114 const DexFile::MapItem* item = map->list_ + i; 115 switch (item->type_) { 116 case DexFile::kDexTypeHeaderItem: 117 CHECK_EQ(item->size_, 1u); 118 CHECK_EQ(item->offset_, 0u); 119 break; 120 case DexFile::kDexTypeStringIdItem: 121 CHECK_EQ(item->size_, collections->StringIdsSize()); 122 CHECK_EQ(item->offset_, collections->StringIdsOffset()); 123 break; 124 case DexFile::kDexTypeTypeIdItem: 125 CHECK_EQ(item->size_, collections->TypeIdsSize()); 126 CHECK_EQ(item->offset_, collections->TypeIdsOffset()); 127 break; 128 case DexFile::kDexTypeProtoIdItem: 129 CHECK_EQ(item->size_, collections->ProtoIdsSize()); 130 CHECK_EQ(item->offset_, collections->ProtoIdsOffset()); 131 break; 132 case DexFile::kDexTypeFieldIdItem: 133 CHECK_EQ(item->size_, collections->FieldIdsSize()); 134 CHECK_EQ(item->offset_, collections->FieldIdsOffset()); 135 break; 136 case DexFile::kDexTypeMethodIdItem: 137 CHECK_EQ(item->size_, collections->MethodIdsSize()); 138 CHECK_EQ(item->offset_, collections->MethodIdsOffset()); 139 break; 140 case DexFile::kDexTypeClassDefItem: 141 if (options.class_filter_.empty()) { 142 // The filter may have removed some classes, this will get fixed up during writing. 143 CHECK_EQ(item->size_, collections->ClassDefsSize()); 144 } 145 CHECK_EQ(item->offset_, collections->ClassDefsOffset()); 146 break; 147 case DexFile::kDexTypeCallSiteIdItem: 148 CHECK_EQ(item->size_, collections->CallSiteIdsSize()); 149 CHECK_EQ(item->offset_, collections->CallSiteIdsOffset()); 150 break; 151 case DexFile::kDexTypeMethodHandleItem: 152 CHECK_EQ(item->size_, collections->MethodHandleItemsSize()); 153 CHECK_EQ(item->offset_, collections->MethodHandleItemsOffset()); 154 break; 155 case DexFile::kDexTypeMapList: 156 CHECK_EQ(item->size_, 1u); 157 CHECK_EQ(item->offset_, disk_header.map_off_); 158 break; 159 case DexFile::kDexTypeTypeList: 160 collections->SetTypeListsOffset(item->offset_); 161 break; 162 case DexFile::kDexTypeAnnotationSetRefList: 163 collections->SetAnnotationSetRefListsOffset(item->offset_); 164 break; 165 case DexFile::kDexTypeAnnotationSetItem: 166 collections->SetAnnotationSetItemsOffset(item->offset_); 167 break; 168 case DexFile::kDexTypeClassDataItem: 169 collections->SetClassDatasOffset(item->offset_); 170 break; 171 case DexFile::kDexTypeCodeItem: 172 collections->SetCodeItemsOffset(item->offset_); 173 break; 174 case DexFile::kDexTypeStringDataItem: 175 collections->SetStringDatasOffset(item->offset_); 176 break; 177 case DexFile::kDexTypeDebugInfoItem: 178 collections->SetDebugInfoItemsOffset(item->offset_); 179 break; 180 case DexFile::kDexTypeAnnotationItem: 181 collections->SetAnnotationItemsOffset(item->offset_); 182 collections->AddAnnotationsFromMapListSection(dex_file, item->offset_, item->size_); 183 break; 184 case DexFile::kDexTypeEncodedArrayItem: 185 collections->SetEncodedArrayItemsOffset(item->offset_); 186 break; 187 case DexFile::kDexTypeAnnotationsDirectoryItem: 188 collections->SetAnnotationsDirectoryItemsOffset(item->offset_); 189 break; 190 default: 191 LOG(ERROR) << "Unknown map list item type."; 192 } 193 } 194 } 195 196 } // namespace dex_ir 197 } // namespace art 198