1959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle/* 2959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Copyright (C) 2014 The Android Open Source Project 3959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 4959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Licensed under the Apache License, Version 2.0 (the "License"); 5959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * you may not use this file except in compliance with the License. 6959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * You may obtain a copy of the License at 7959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 8959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * http://www.apache.org/licenses/LICENSE-2.0 9959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 10959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Unless required by applicable law or agreed to in writing, software 11959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * distributed under the License is distributed on an "AS IS" BASIS, 12959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * See the License for the specific language governing permissions and 14959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * limitations under the License. 15959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 16959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 17959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepackage dexfuzz.rawdex; 18959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 19959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.Log; 20959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 21959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.IOException; 22959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.ArrayList; 23959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.List; 24959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic class RawDexFile implements RawDexObject { 26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private OffsetTracker offsetTracker; 27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public HeaderItem header; 29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public MapList mapList; 31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Can be allocated after reading the header. 33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<StringIdItem> stringIds; 34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<TypeIdItem> typeIds; 35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<ProtoIdItem> protoIds; 36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<FieldIdItem> fieldIds; 37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<MethodIdItem> methodIds; 38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<ClassDefItem> classDefs; 39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Need to be allocated later (will be allocated in MapList.java) 41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<StringDataItem> stringDatas; 42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<ClassDataItem> classDatas; 43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<TypeList> typeLists; 44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<CodeItem> codeItems; 45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public DebugInfoItem debugInfoItem; 46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<AnnotationsDirectoryItem> annotationsDirectoryItems; 47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<AnnotationSetRefList> annotationSetRefLists; 48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<AnnotationSetItem> annotationSetItems; 49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<AnnotationItem> annotationItems; 50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<EncodedArrayItem> encodedArrayItems; 51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void read(DexRandomAccessFile file) throws IOException { 54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Get a reference to the OffsetTracker, so that IdCreator can use it. 55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle offsetTracker = file.getOffsetTracker(); 56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.seek(0); 58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Read header. 60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle (header = new HeaderItem()).read(file); 61959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // We can allocate all of these now. 63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle stringIds = new ArrayList<StringIdItem>(header.stringIdsSize); 64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle typeIds = new ArrayList<TypeIdItem>(header.typeIdsSize); 65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle protoIds = new ArrayList<ProtoIdItem>(header.protoIdsSize); 66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle fieldIds = new ArrayList<FieldIdItem>(header.fieldIdsSize); 67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle methodIds = new ArrayList<MethodIdItem>(header.methodIdsSize); 68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle classDefs = new ArrayList<ClassDefItem>(header.classDefsSize); 69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mapList = new MapList(this); 71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mapList.read(file); 72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.getOffsetTracker().associateOffsets(); 74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void write(DexRandomAccessFile file) throws IOException { 78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.seek(0); 79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // We read the header first, and then the map list, and then everything 81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // else. Therefore, when we get to the end of the header, tell OffsetTracker 82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // to skip past the map list offsets, and then when we get to the map list, 83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // tell OffsetTracker to skip back there, and then return to where it was previously. 84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Update the map items' sizes first 86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // - but only update the items that we expect to have changed size. 87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // ALSO update the header's table sizes! 88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (MapItem mapItem : mapList.mapItems) { 89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle switch (mapItem.type) { 90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_STRING_ID_ITEM: 91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != stringIds.size()) { 92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Updating StringIDs List size: " + stringIds.size()); 93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mapItem.size = stringIds.size(); 94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle header.stringIdsSize = stringIds.size(); 95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_STRING_DATA_ITEM: 98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != stringDatas.size()) { 99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Updating StringDatas List size: " + stringDatas.size()); 100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mapItem.size = stringDatas.size(); 101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_METHOD_ID_ITEM: 104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != methodIds.size()) { 105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Updating MethodIDs List size: " + methodIds.size()); 106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mapItem.size = methodIds.size(); 107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle header.methodIdsSize = methodIds.size(); 108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_FIELD_ID_ITEM: 111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != fieldIds.size()) { 112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Updating FieldIDs List size: " + fieldIds.size()); 113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mapItem.size = fieldIds.size(); 114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle header.fieldIdsSize = fieldIds.size(); 115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_PROTO_ID_ITEM: 118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != protoIds.size()) { 119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Updating ProtoIDs List size: " + protoIds.size()); 120959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mapItem.size = protoIds.size(); 121959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle header.protoIdsSize = protoIds.size(); 122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_TYPE_ID_ITEM: 125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != typeIds.size()) { 126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Updating TypeIDs List size: " + typeIds.size()); 127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mapItem.size = typeIds.size(); 128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle header.typeIdsSize = typeIds.size(); 129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_TYPE_LIST: 132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != typeLists.size()) { 133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Updating TypeLists List size: " + typeLists.size()); 134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mapItem.size = typeLists.size(); 135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle default: 138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Use the map list to write the file. 142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (MapItem mapItem : mapList.mapItems) { 143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle switch (mapItem.type) { 144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_HEADER_ITEM: 145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle header.write(file); 146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.getOffsetTracker().skipToAfterMapList(); 147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_STRING_ID_ITEM: 149959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != stringIds.size()) { 150959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 151959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches StringIDs table size " + stringIds.size()); 152959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 153959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (StringIdItem stringId : stringIds) { 154959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle stringId.write(file); 155959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 156959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 157959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_TYPE_ID_ITEM: 158959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != typeIds.size()) { 159959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 160959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches TypeIDs table size " + typeIds.size()); 161959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 162959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (TypeIdItem typeId : typeIds) { 163959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle typeId.write(file); 164959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 165959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 166959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_PROTO_ID_ITEM: 167959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != protoIds.size()) { 168959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 169959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches ProtoIDs table size " + protoIds.size()); 170959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 171959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (ProtoIdItem protoId : protoIds) { 172959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle protoId.write(file); 173959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 174959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 175959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_FIELD_ID_ITEM: 176959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != fieldIds.size()) { 177959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 178959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches FieldIDs table size " + fieldIds.size()); 179959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 180959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (FieldIdItem fieldId : fieldIds) { 181959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle fieldId.write(file); 182959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 183959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 184959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_METHOD_ID_ITEM: 185959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != methodIds.size()) { 186959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 187959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches MethodIDs table size " + methodIds.size()); 188959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 189959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (MethodIdItem methodId : methodIds) { 190959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle methodId.write(file); 191959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 192959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 193959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_CLASS_DEF_ITEM: 194959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != classDefs.size()) { 195959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 196959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches ClassDefs table size " + classDefs.size()); 197959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 198959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (ClassDefItem classDef : classDefs) { 199959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle classDef.write(file); 200959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 201959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 202959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_MAP_LIST: 203959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.getOffsetTracker().goBackToMapList(); 204959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mapList.write(file); 205959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.getOffsetTracker().goBackToPreviousPoint(); 206959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 207959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_TYPE_LIST: 208959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != typeLists.size()) { 209959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 210959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches TypeLists table size " + typeLists.size()); 211959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 212959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (TypeList typeList : typeLists) { 213959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle typeList.write(file); 214959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 215959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 216959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_ANNOTATION_SET_REF_LIST: 217959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != annotationSetRefLists.size()) { 218959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 219959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches AnnotationSetRefLists table size " 220959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + annotationSetRefLists.size()); 221959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 222959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (AnnotationSetRefList annotationSetRefList : annotationSetRefLists) { 223959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle annotationSetRefList.write(file); 224959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 225959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 226959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_ANNOTATION_SET_ITEM: 227959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != annotationSetItems.size()) { 228959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 229959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches AnnotationSetItems table size " 230959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + annotationSetItems.size()); 231959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 232959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (AnnotationSetItem annotationSetItem : annotationSetItems) { 233959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle annotationSetItem.write(file); 234959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 235959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 236959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_CLASS_DATA_ITEM: 237959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != classDatas.size()) { 238959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 239959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches ClassDataItems table size " + classDatas.size()); 240959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 241959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (ClassDataItem classData : classDatas) { 242959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle classData.write(file); 243959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 244959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 245959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_CODE_ITEM: 246959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != codeItems.size()) { 247959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 248959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches CodeItems table size " + codeItems.size()); 249959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 250959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (CodeItem codeItem : codeItems) { 251959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle codeItem.write(file); 252959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 253959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 254959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_STRING_DATA_ITEM: 255959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != stringDatas.size()) { 256959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 257959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches StringDataItems table size " 258959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + stringDatas.size()); 259959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 260959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (StringDataItem stringDataItem : stringDatas) { 261959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle stringDataItem.write(file); 262959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 263959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 264959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_DEBUG_INFO_ITEM: 265959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle debugInfoItem.write(file); 266959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 267959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_ANNOTATION_ITEM: 268959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != annotationItems.size()) { 269959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 270959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches AnnotationItems table size " 271959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + annotationItems.size()); 272959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 273959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (AnnotationItem annotationItem : annotationItems) { 274959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle annotationItem.write(file); 275959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 276959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 277959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_ENCODED_ARRAY_ITEM: 278959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != encodedArrayItems.size()) { 279959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 280959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches EncodedArrayItems table size " 281959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + encodedArrayItems.size()); 282959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 283959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (EncodedArrayItem encodedArrayItem : encodedArrayItems) { 284959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle encodedArrayItem.write(file); 285959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 286959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 287959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case MapItem.TYPE_ANNOTATIONS_DIRECTORY_ITEM: 288959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mapItem.size != annotationsDirectoryItems.size()) { 289959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("MapItem's size " + mapItem.size 290959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " no longer matches AnnotationDirectoryItems table size " 291959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + annotationsDirectoryItems.size()); 292959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 293959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (AnnotationsDirectoryItem annotationsDirectory : annotationsDirectoryItems) { 294959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle annotationsDirectory.write(file); 295959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 296959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 297959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle default: 298959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("Encountered unknown map item in map item list."); 299959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 300959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 301959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 302959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.getOffsetTracker().updateOffsets(file); 303959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 304959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 305959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 306959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Given a DexRandomAccessFile, calculate the correct adler32 checksum for it. 307959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 308959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private int calculateAdler32Checksum(DexRandomAccessFile file) throws IOException { 309959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Skip magic + checksum. 310959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.seek(12); 311959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int a = 1; 312959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b = 0; 313959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (file.getFilePointer() < file.length()) { 314959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle a = (a + file.readUnsignedByte()) % 65521; 315959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle b = (b + a) % 65521; 316959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 317959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return (b << 16) | a; 318959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 319959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 320959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 321959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Given a DexRandomAccessFile, update the file size, data size, and checksum. 322959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 323959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void updateHeader(DexRandomAccessFile file) throws IOException { 324959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // File size must be updated before checksum. 325959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int newFileSize = (int) file.length(); 326959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.seek(32); 327959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.writeUInt(newFileSize); 328959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 329959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Data size must be updated before checksum. 330959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int newDataSize = newFileSize - header.dataOff.getNewPositionOfItem(); 331959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.seek(104); 332959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.writeUInt(newDataSize); 333959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 334959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Now update the checksum. 335959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int newChecksum = calculateAdler32Checksum(file); 336959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.seek(8); 337959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.writeUInt(newChecksum); 338959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 339959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle header.fileSize = newFileSize; 340959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle header.dataSize = newDataSize; 341959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle header.checksum = newChecksum; 342959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 343959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 344959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 345959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * This should only be called from NewItemCreator. 346959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 347959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public OffsetTracker getOffsetTracker() { 348959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return offsetTracker; 349959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 350959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 351959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 352959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void incrementIndex(IndexUpdateKind kind, int insertedIdx) { 353959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (TypeIdItem typeId : typeIds) { 354959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle typeId.incrementIndex(kind, insertedIdx); 355959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 356959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (ProtoIdItem protoId : protoIds) { 357959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle protoId.incrementIndex(kind, insertedIdx); 358959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 359959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (FieldIdItem fieldId : fieldIds) { 360959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle fieldId.incrementIndex(kind, insertedIdx); 361959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 362959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (MethodIdItem methodId : methodIds) { 363959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle methodId.incrementIndex(kind, insertedIdx); 364959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 365959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (ClassDefItem classDef : classDefs) { 366959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle classDef.incrementIndex(kind, insertedIdx); 367959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 368959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (ClassDataItem classData : classDatas) { 369959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle classData.incrementIndex(kind, insertedIdx); 370959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 371959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (typeLists != null) { 372959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (TypeList typeList : typeLists) { 373959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle typeList.incrementIndex(kind, insertedIdx); 374959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 375959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 376959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (CodeItem codeItem : codeItems) { 377959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle codeItem.incrementIndex(kind, insertedIdx); 378959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 379959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (annotationsDirectoryItems != null) { 380959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (AnnotationsDirectoryItem annotationsDirectoryItem : annotationsDirectoryItems) { 381959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle annotationsDirectoryItem.incrementIndex(kind, insertedIdx); 382959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 383959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 384959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (annotationItems != null) { 385959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (AnnotationItem annotationItem : annotationItems) { 386959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle annotationItem.incrementIndex(kind, insertedIdx); 387959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 388959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 389959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 390959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle} 391