Home | History | Annotate | Download | only in rawdex
      1 /*
      2  * Copyright (C) 2014 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 
     17 package dexfuzz.rawdex;
     18 
     19 import dexfuzz.Log;
     20 
     21 import java.io.IOException;
     22 import java.util.ArrayList;
     23 import java.util.List;
     24 
     25 public class MapList implements RawDexObject {
     26 
     27   private RawDexFile rawDexFile;
     28 
     29   public int size;
     30   public List<MapItem> mapItems;
     31 
     32   public MapList(RawDexFile rawDexFile) {
     33     this.rawDexFile = rawDexFile;
     34   }
     35 
     36   @Override
     37   public void read(DexRandomAccessFile file) throws IOException {
     38     // Find the map list.
     39     file.seek(rawDexFile.header.mapOff.getOriginalOffset());
     40 
     41     file.getOffsetTracker().getNewOffsettable(file, this);
     42 
     43     // Get the number of entries.
     44     size = file.readUInt();
     45 
     46     // Allocate and populate the array.
     47     mapItems = new ArrayList<MapItem>(size);
     48     for (int i = 0; i < size; i++) {
     49       MapItem mapItem = new MapItem();
     50       mapItems.add(mapItem);
     51       mapItem.read(file);
     52     }
     53 
     54     file.getOffsetTracker().rememberPointAfterMapList();
     55 
     56     // NB: We track the current index into the MapList, so when we encounter the DebugInfoItem
     57     // MapItem, we know how to find the next MapItem, so we know how large the DebugInfo
     58     // area is, so we can copy it as a blob.
     59     int mapItemIdx = 0;
     60 
     61     // Iterate through the list, and create all the other data structures.
     62     for (MapItem mapItem : mapItems) {
     63       file.seek(mapItem.offset.getOriginalOffset());
     64       switch (mapItem.type) {
     65         case MapItem.TYPE_HEADER_ITEM:
     66           // Already read it; skip.
     67           break;
     68         case MapItem.TYPE_STRING_ID_ITEM:
     69           for (int i = 0; i < mapItem.size; i++) {
     70             StringIdItem newStringId = new StringIdItem();
     71             rawDexFile.stringIds.add(newStringId);
     72             newStringId.read(file);
     73           }
     74           break;
     75         case MapItem.TYPE_TYPE_ID_ITEM:
     76           for (int i = 0; i < mapItem.size; i++) {
     77             TypeIdItem newTypeId = new TypeIdItem();
     78             rawDexFile.typeIds.add(newTypeId);
     79             newTypeId.read(file);
     80           }
     81           break;
     82         case MapItem.TYPE_PROTO_ID_ITEM:
     83           for (int i = 0; i < mapItem.size; i++) {
     84             ProtoIdItem newProtoId = new ProtoIdItem();
     85             rawDexFile.protoIds.add(newProtoId);
     86             newProtoId.read(file);
     87           }
     88           break;
     89         case MapItem.TYPE_FIELD_ID_ITEM:
     90           for (int i = 0; i < mapItem.size; i++) {
     91             FieldIdItem newFieldId = new FieldIdItem();
     92             rawDexFile.fieldIds.add(newFieldId);
     93             newFieldId.read(file);
     94           }
     95           break;
     96         case MapItem.TYPE_METHOD_ID_ITEM:
     97           for (int i = 0; i < mapItem.size; i++) {
     98             MethodIdItem newMethodId = new MethodIdItem();
     99             rawDexFile.methodIds.add(newMethodId);
    100             newMethodId.read(file);
    101           }
    102           break;
    103         case MapItem.TYPE_CLASS_DEF_ITEM:
    104           for (int i = 0; i < mapItem.size; i++) {
    105             ClassDefItem newClassDef = new ClassDefItem();
    106             rawDexFile.classDefs.add(newClassDef);
    107             newClassDef.read(file);
    108           }
    109           break;
    110         case MapItem.TYPE_MAP_LIST:
    111           // Already read it; skip.
    112           break;
    113         case MapItem.TYPE_TYPE_LIST:
    114           rawDexFile.typeLists = new ArrayList<TypeList>(mapItem.size);
    115           for (int i = 0; i < mapItem.size; i++) {
    116             TypeList newTypeList = new TypeList();
    117             rawDexFile.typeLists.add(newTypeList);
    118             newTypeList.read(file);
    119           }
    120           break;
    121         case MapItem.TYPE_ANNOTATION_SET_REF_LIST:
    122           rawDexFile.annotationSetRefLists =
    123             new ArrayList<AnnotationSetRefList>(mapItem.size);
    124           for (int i = 0; i < mapItem.size; i++) {
    125             AnnotationSetRefList newAnnotationSetRefList = new AnnotationSetRefList();
    126             rawDexFile.annotationSetRefLists.add(newAnnotationSetRefList);
    127             newAnnotationSetRefList.read(file);
    128           }
    129           break;
    130         case MapItem.TYPE_ANNOTATION_SET_ITEM:
    131           rawDexFile.annotationSetItems = new ArrayList<AnnotationSetItem>(mapItem.size);
    132           for (int i = 0; i < mapItem.size; i++) {
    133             AnnotationSetItem newAnnotationSetItem = new AnnotationSetItem();
    134             rawDexFile.annotationSetItems.add(newAnnotationSetItem);
    135             newAnnotationSetItem.read(file);
    136           }
    137           break;
    138         case MapItem.TYPE_CLASS_DATA_ITEM:
    139           rawDexFile.classDatas = new ArrayList<ClassDataItem>(mapItem.size);
    140           for (int i = 0; i < mapItem.size; i++) {
    141             ClassDataItem newClassData = new ClassDataItem();
    142             rawDexFile.classDatas.add(newClassData);
    143             newClassData.read(file);
    144           }
    145           break;
    146         case MapItem.TYPE_CODE_ITEM:
    147           rawDexFile.codeItems = new ArrayList<CodeItem>(mapItem.size);
    148           for (int i = 0; i < mapItem.size; i++) {
    149             CodeItem newCodeItem = new CodeItem();
    150             rawDexFile.codeItems.add(newCodeItem);
    151             newCodeItem.read(file);
    152           }
    153           break;
    154         case MapItem.TYPE_STRING_DATA_ITEM:
    155           rawDexFile.stringDatas = new ArrayList<StringDataItem>(mapItem.size);
    156           for (int i = 0; i < mapItem.size; i++) {
    157             StringDataItem newStringData = new StringDataItem();
    158             rawDexFile.stringDatas.add(newStringData);
    159             newStringData.read(file);
    160           }
    161           break;
    162         case MapItem.TYPE_DEBUG_INFO_ITEM:
    163         {
    164           // We aren't interested in updating the debug data, so just read it as a blob.
    165           long start = mapItem.offset.getOriginalOffset();
    166           long end = 0;
    167           if (mapItemIdx + 1 == mapItems.size()) {
    168             end = file.length();
    169           } else {
    170             end = mapItems.get(mapItemIdx + 1).offset.getOriginalOffset();
    171           }
    172           long size = end - start;
    173           rawDexFile.debugInfoItem = new DebugInfoItem((int)size);
    174           rawDexFile.debugInfoItem.read(file);
    175           break;
    176         }
    177         case MapItem.TYPE_ANNOTATION_ITEM:
    178           rawDexFile.annotationItems = new ArrayList<AnnotationItem>(mapItem.size);
    179           for (int i = 0; i < mapItem.size; i++) {
    180             AnnotationItem newAnnotationItem = new AnnotationItem();
    181             rawDexFile.annotationItems.add(newAnnotationItem);
    182             newAnnotationItem.read(file);
    183           }
    184           break;
    185         case MapItem.TYPE_ENCODED_ARRAY_ITEM:
    186           rawDexFile.encodedArrayItems = new ArrayList<EncodedArrayItem>(mapItem.size);
    187           for (int i = 0; i < mapItem.size; i++) {
    188             EncodedArrayItem newEncodedArrayItem = new EncodedArrayItem();
    189             rawDexFile.encodedArrayItems.add(newEncodedArrayItem);
    190             newEncodedArrayItem.read(file);
    191           }
    192           break;
    193         case MapItem.TYPE_ANNOTATIONS_DIRECTORY_ITEM:
    194           rawDexFile.annotationsDirectoryItems =
    195           new ArrayList<AnnotationsDirectoryItem>(mapItem.size);
    196           for (int i = 0; i < mapItem.size; i++) {
    197             AnnotationsDirectoryItem newAnnotationsDirectoryItem = new AnnotationsDirectoryItem();
    198             rawDexFile.annotationsDirectoryItems.add(newAnnotationsDirectoryItem);
    199             newAnnotationsDirectoryItem.read(file);
    200           }
    201           break;
    202         default:
    203           Log.errorAndQuit("Encountered unknown map item when reading map item list.");
    204       }
    205       mapItemIdx++;
    206     }
    207   }
    208 
    209   @Override
    210   public void write(DexRandomAccessFile file) throws IOException {
    211     file.alignForwards(4);
    212     file.getOffsetTracker().updatePositionOfNextOffsettable(file);
    213     file.writeUInt(mapItems.size());
    214     for (MapItem mapItem : mapItems) {
    215       mapItem.write(file);
    216     }
    217   }
    218 
    219   @Override
    220   public void incrementIndex(IndexUpdateKind kind, int insertedIdx) {
    221     // Do nothing.
    222   }
    223 }
    224