Home | History | Annotate | Download | only in dexlayout
      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