| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package dexfuzz.rawdex; |
| |
| import dexfuzz.Log; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| public class MapList implements RawDexObject { |
| |
| private RawDexFile rawDexFile; |
| |
| public int size; |
| public List<MapItem> mapItems; |
| |
| public MapList(RawDexFile rawDexFile) { |
| this.rawDexFile = rawDexFile; |
| } |
| |
| @Override |
| public void read(DexRandomAccessFile file) throws IOException { |
| // Find the map list. |
| file.seek(rawDexFile.header.mapOff.getOriginalOffset()); |
| |
| file.getOffsetTracker().getNewOffsettable(file, this); |
| |
| // Get the number of entries. |
| size = file.readUInt(); |
| |
| // Allocate and populate the array. |
| mapItems = new ArrayList<MapItem>(size); |
| for (int i = 0; i < size; i++) { |
| MapItem mapItem = new MapItem(); |
| mapItems.add(mapItem); |
| mapItem.read(file); |
| } |
| |
| file.getOffsetTracker().rememberPointAfterMapList(); |
| |
| // NB: We track the current index into the MapList, so when we encounter the DebugInfoItem |
| // MapItem, we know how to find the next MapItem, so we know how large the DebugInfo |
| // area is, so we can copy it as a blob. |
| int mapItemIdx = 0; |
| |
| // Iterate through the list, and create all the other data structures. |
| for (MapItem mapItem : mapItems) { |
| file.seek(mapItem.offset.getOriginalOffset()); |
| switch (mapItem.type) { |
| case MapItem.TYPE_HEADER_ITEM: |
| // Already read it; skip. |
| break; |
| case MapItem.TYPE_STRING_ID_ITEM: |
| for (int i = 0; i < mapItem.size; i++) { |
| StringIdItem newStringId = new StringIdItem(); |
| rawDexFile.stringIds.add(newStringId); |
| newStringId.read(file); |
| } |
| break; |
| case MapItem.TYPE_TYPE_ID_ITEM: |
| for (int i = 0; i < mapItem.size; i++) { |
| TypeIdItem newTypeId = new TypeIdItem(); |
| rawDexFile.typeIds.add(newTypeId); |
| newTypeId.read(file); |
| } |
| break; |
| case MapItem.TYPE_PROTO_ID_ITEM: |
| for (int i = 0; i < mapItem.size; i++) { |
| ProtoIdItem newProtoId = new ProtoIdItem(); |
| rawDexFile.protoIds.add(newProtoId); |
| newProtoId.read(file); |
| } |
| break; |
| case MapItem.TYPE_FIELD_ID_ITEM: |
| for (int i = 0; i < mapItem.size; i++) { |
| FieldIdItem newFieldId = new FieldIdItem(); |
| rawDexFile.fieldIds.add(newFieldId); |
| newFieldId.read(file); |
| } |
| break; |
| case MapItem.TYPE_METHOD_ID_ITEM: |
| for (int i = 0; i < mapItem.size; i++) { |
| MethodIdItem newMethodId = new MethodIdItem(); |
| rawDexFile.methodIds.add(newMethodId); |
| newMethodId.read(file); |
| } |
| break; |
| case MapItem.TYPE_CLASS_DEF_ITEM: |
| for (int i = 0; i < mapItem.size; i++) { |
| ClassDefItem newClassDef = new ClassDefItem(); |
| rawDexFile.classDefs.add(newClassDef); |
| newClassDef.read(file); |
| } |
| break; |
| case MapItem.TYPE_MAP_LIST: |
| // Already read it; skip. |
| break; |
| case MapItem.TYPE_TYPE_LIST: |
| rawDexFile.typeLists = new ArrayList<TypeList>(mapItem.size); |
| for (int i = 0; i < mapItem.size; i++) { |
| TypeList newTypeList = new TypeList(); |
| rawDexFile.typeLists.add(newTypeList); |
| newTypeList.read(file); |
| } |
| break; |
| case MapItem.TYPE_ANNOTATION_SET_REF_LIST: |
| rawDexFile.annotationSetRefLists = |
| new ArrayList<AnnotationSetRefList>(mapItem.size); |
| for (int i = 0; i < mapItem.size; i++) { |
| AnnotationSetRefList newAnnotationSetRefList = new AnnotationSetRefList(); |
| rawDexFile.annotationSetRefLists.add(newAnnotationSetRefList); |
| newAnnotationSetRefList.read(file); |
| } |
| break; |
| case MapItem.TYPE_ANNOTATION_SET_ITEM: |
| rawDexFile.annotationSetItems = new ArrayList<AnnotationSetItem>(mapItem.size); |
| for (int i = 0; i < mapItem.size; i++) { |
| AnnotationSetItem newAnnotationSetItem = new AnnotationSetItem(); |
| rawDexFile.annotationSetItems.add(newAnnotationSetItem); |
| newAnnotationSetItem.read(file); |
| } |
| break; |
| case MapItem.TYPE_CLASS_DATA_ITEM: |
| rawDexFile.classDatas = new ArrayList<ClassDataItem>(mapItem.size); |
| for (int i = 0; i < mapItem.size; i++) { |
| ClassDataItem newClassData = new ClassDataItem(); |
| rawDexFile.classDatas.add(newClassData); |
| newClassData.read(file); |
| } |
| break; |
| case MapItem.TYPE_CODE_ITEM: |
| rawDexFile.codeItems = new ArrayList<CodeItem>(mapItem.size); |
| for (int i = 0; i < mapItem.size; i++) { |
| CodeItem newCodeItem = new CodeItem(); |
| rawDexFile.codeItems.add(newCodeItem); |
| newCodeItem.read(file); |
| } |
| break; |
| case MapItem.TYPE_STRING_DATA_ITEM: |
| rawDexFile.stringDatas = new ArrayList<StringDataItem>(mapItem.size); |
| for (int i = 0; i < mapItem.size; i++) { |
| StringDataItem newStringData = new StringDataItem(); |
| rawDexFile.stringDatas.add(newStringData); |
| newStringData.read(file); |
| } |
| break; |
| case MapItem.TYPE_DEBUG_INFO_ITEM: |
| { |
| // We aren't interested in updating the debug data, so just read it as a blob. |
| int start = mapItem.offset.getOriginalOffset(); |
| int end = mapItems.get(mapItemIdx + 1).offset.getOriginalOffset(); |
| int size = end - start; |
| rawDexFile.debugInfoItem = new DebugInfoItem(size); |
| rawDexFile.debugInfoItem.read(file); |
| break; |
| } |
| case MapItem.TYPE_ANNOTATION_ITEM: |
| rawDexFile.annotationItems = new ArrayList<AnnotationItem>(mapItem.size); |
| for (int i = 0; i < mapItem.size; i++) { |
| AnnotationItem newAnnotationItem = new AnnotationItem(); |
| rawDexFile.annotationItems.add(newAnnotationItem); |
| newAnnotationItem.read(file); |
| } |
| break; |
| case MapItem.TYPE_ENCODED_ARRAY_ITEM: |
| rawDexFile.encodedArrayItems = new ArrayList<EncodedArrayItem>(mapItem.size); |
| for (int i = 0; i < mapItem.size; i++) { |
| EncodedArrayItem newEncodedArrayItem = new EncodedArrayItem(); |
| rawDexFile.encodedArrayItems.add(newEncodedArrayItem); |
| newEncodedArrayItem.read(file); |
| } |
| break; |
| case MapItem.TYPE_ANNOTATIONS_DIRECTORY_ITEM: |
| rawDexFile.annotationsDirectoryItems = |
| new ArrayList<AnnotationsDirectoryItem>(mapItem.size); |
| for (int i = 0; i < mapItem.size; i++) { |
| AnnotationsDirectoryItem newAnnotationsDirectoryItem = new AnnotationsDirectoryItem(); |
| rawDexFile.annotationsDirectoryItems.add(newAnnotationsDirectoryItem); |
| newAnnotationsDirectoryItem.read(file); |
| } |
| break; |
| default: |
| Log.errorAndQuit("Encountered unknown map item when reading map item list."); |
| } |
| mapItemIdx++; |
| } |
| } |
| |
| @Override |
| public void write(DexRandomAccessFile file) throws IOException { |
| file.alignForwards(4); |
| file.getOffsetTracker().updatePositionOfNextOffsettable(file); |
| file.writeUInt(mapItems.size()); |
| for (MapItem mapItem : mapItems) { |
| mapItem.write(file); |
| } |
| } |
| |
| @Override |
| public void incrementIndex(IndexUpdateKind kind, int insertedIdx) { |
| // Do nothing. |
| } |
| } |