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 * Implementation file of the dexlayout utility. 17 * 18 * This is a tool to read dex files into an internal representation, 19 * reorganize the representation, and emit dex files with a better 20 * file layout. 21 */ 22 23 #include "dex_ir.h" 24 25 #include "dex/code_item_accessors-inl.h" 26 #include "dex/dex_file_exception_helpers.h" 27 #include "dex/dex_instruction-inl.h" 28 #include "dex_ir_builder.h" 29 30 namespace art { 31 namespace dex_ir { 32 33 static uint32_t HeaderOffset(const dex_ir::Header* header ATTRIBUTE_UNUSED) { 34 return 0; 35 } 36 37 static uint32_t HeaderSize(const dex_ir::Header* header ATTRIBUTE_UNUSED) { 38 // Size is in elements, so there is only one header. 39 return 1; 40 } 41 42 // The description of each dex file section type. 43 struct FileSectionDescriptor { 44 public: 45 std::string name; 46 uint16_t type; 47 // A function that when applied to a collection object, gives the size of the section. 48 std::function<uint32_t(dex_ir::Header*)> size_fn; 49 // A function that when applied to a collection object, gives the offset of the section. 50 std::function<uint32_t(dex_ir::Header*)> offset_fn; 51 }; 52 53 static const FileSectionDescriptor kFileSectionDescriptors[] = { 54 { 55 "Header", 56 DexFile::kDexTypeHeaderItem, 57 &HeaderSize, 58 &HeaderOffset, 59 }, { 60 "StringId", 61 DexFile::kDexTypeStringIdItem, 62 [](const dex_ir::Header* h) { return h->StringIds().Size(); }, 63 [](const dex_ir::Header* h) { return h->StringIds().GetOffset(); } 64 }, { 65 "TypeId", 66 DexFile::kDexTypeTypeIdItem, 67 [](const dex_ir::Header* h) { return h->TypeIds().Size(); }, 68 [](const dex_ir::Header* h) { return h->TypeIds().GetOffset(); } 69 }, { 70 "ProtoId", 71 DexFile::kDexTypeProtoIdItem, 72 [](const dex_ir::Header* h) { return h->ProtoIds().Size(); }, 73 [](const dex_ir::Header* h) { return h->ProtoIds().GetOffset(); } 74 }, { 75 "FieldId", 76 DexFile::kDexTypeFieldIdItem, 77 [](const dex_ir::Header* h) { return h->FieldIds().Size(); }, 78 [](const dex_ir::Header* h) { return h->FieldIds().GetOffset(); } 79 }, { 80 "MethodId", 81 DexFile::kDexTypeMethodIdItem, 82 [](const dex_ir::Header* h) { return h->MethodIds().Size(); }, 83 [](const dex_ir::Header* h) { return h->MethodIds().GetOffset(); } 84 }, { 85 "ClassDef", 86 DexFile::kDexTypeClassDefItem, 87 [](const dex_ir::Header* h) { return h->ClassDefs().Size(); }, 88 [](const dex_ir::Header* h) { return h->ClassDefs().GetOffset(); } 89 }, { 90 "CallSiteId", 91 DexFile::kDexTypeCallSiteIdItem, 92 [](const dex_ir::Header* h) { return h->CallSiteIds().Size(); }, 93 [](const dex_ir::Header* h) { return h->CallSiteIds().GetOffset(); } 94 }, { 95 "MethodHandle", 96 DexFile::kDexTypeMethodHandleItem, 97 [](const dex_ir::Header* h) { return h->MethodHandleItems().Size(); }, 98 [](const dex_ir::Header* h) { return h->MethodHandleItems().GetOffset(); } 99 }, { 100 "StringData", 101 DexFile::kDexTypeStringDataItem, 102 [](const dex_ir::Header* h) { return h->StringDatas().Size(); }, 103 [](const dex_ir::Header* h) { return h->StringDatas().GetOffset(); } 104 }, { 105 "TypeList", 106 DexFile::kDexTypeTypeList, 107 [](const dex_ir::Header* h) { return h->TypeLists().Size(); }, 108 [](const dex_ir::Header* h) { return h->TypeLists().GetOffset(); } 109 }, { 110 "EncArr", 111 DexFile::kDexTypeEncodedArrayItem, 112 [](const dex_ir::Header* h) { return h->EncodedArrayItems().Size(); }, 113 [](const dex_ir::Header* h) { return h->EncodedArrayItems().GetOffset(); } 114 }, { 115 "Annotation", 116 DexFile::kDexTypeAnnotationItem, 117 [](const dex_ir::Header* h) { return h->AnnotationItems().Size(); }, 118 [](const dex_ir::Header* h) { return h->AnnotationItems().GetOffset(); } 119 }, { 120 "AnnoSet", 121 DexFile::kDexTypeAnnotationSetItem, 122 [](const dex_ir::Header* h) { return h->AnnotationSetItems().Size(); }, 123 [](const dex_ir::Header* h) { return h->AnnotationSetItems().GetOffset(); } 124 }, { 125 "AnnoSetRL", 126 DexFile::kDexTypeAnnotationSetRefList, 127 [](const dex_ir::Header* h) { return h->AnnotationSetRefLists().Size(); }, 128 [](const dex_ir::Header* h) { return h->AnnotationSetRefLists().GetOffset(); } 129 }, { 130 "AnnoDir", 131 DexFile::kDexTypeAnnotationsDirectoryItem, 132 [](const dex_ir::Header* h) { return h->AnnotationsDirectoryItems().Size(); }, 133 [](const dex_ir::Header* h) { return h->AnnotationsDirectoryItems().GetOffset(); } 134 }, { 135 "DebugInfo", 136 DexFile::kDexTypeDebugInfoItem, 137 [](const dex_ir::Header* h) { return h->DebugInfoItems().Size(); }, 138 [](const dex_ir::Header* h) { return h->DebugInfoItems().GetOffset(); } 139 }, { 140 "CodeItem", 141 DexFile::kDexTypeCodeItem, 142 [](const dex_ir::Header* h) { return h->CodeItems().Size(); }, 143 [](const dex_ir::Header* h) { return h->CodeItems().GetOffset(); } 144 }, { 145 "ClassData", 146 DexFile::kDexTypeClassDataItem, 147 [](const dex_ir::Header* h) { return h->ClassDatas().Size(); }, 148 [](const dex_ir::Header* h) { return h->ClassDatas().GetOffset(); } 149 } 150 }; 151 152 std::vector<dex_ir::DexFileSection> GetSortedDexFileSections(dex_ir::Header* header, 153 dex_ir::SortDirection direction) { 154 std::vector<dex_ir::DexFileSection> sorted_sections; 155 // Build the table that will map from offset to color 156 for (const FileSectionDescriptor& s : kFileSectionDescriptors) { 157 sorted_sections.push_back(dex_ir::DexFileSection(s.name, 158 s.type, 159 s.size_fn(header), 160 s.offset_fn(header))); 161 } 162 // Sort by offset. 163 std::sort(sorted_sections.begin(), 164 sorted_sections.end(), 165 [=](dex_ir::DexFileSection& a, dex_ir::DexFileSection& b) { 166 if (direction == SortDirection::kSortDescending) { 167 return a.offset > b.offset; 168 } else { 169 return a.offset < b.offset; 170 } 171 }); 172 return sorted_sections; 173 } 174 175 } // namespace dex_ir 176 } // namespace art 177