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 Kyleimport dexfuzz.program.MutatableCode; 21959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 22959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.IOException; 23959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.LinkedList; 24959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.List; 25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic class CodeItem implements RawDexObject { 27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public short registersSize; 28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public short insSize; 29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public short outsSize; 30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public short triesSize; 31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public int debugInfoOff; // NB: this is a special case 32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public int insnsSize; 33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public List<Instruction> insns; 34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public TryItem[] tries; 35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public EncodedCatchHandlerList handlers; 36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private MutatableCode mutatableCode; 38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static class MethodMetaInfo { 40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public String methodName; 41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public boolean isStatic; 42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public String shorty; 43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public MethodMetaInfo meta = new MethodMetaInfo(); 46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void read(DexRandomAccessFile file) throws IOException { 49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.alignForwards(4); 50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.getOffsetTracker().getNewOffsettable(file, this); 51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle registersSize = file.readUShort(); 52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insSize = file.readUShort(); 53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle outsSize = file.readUShort(); 54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle triesSize = file.readUShort(); 55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle debugInfoOff = file.readUInt(); 56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insnsSize = file.readUInt(); 57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle populateInstructionList(file); 58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (triesSize > 0) { 59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((insnsSize % 2) != 0) { 60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Consume padding. 61959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.readUShort(); 62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle tries = new TryItem[triesSize]; 64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (int i = 0; i < triesSize; i++) { 65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle (tries[i] = new TryItem()).read(file); 66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle (handlers = new EncodedCatchHandlerList()).read(file); 68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private void populateInstructionList(DexRandomAccessFile file) throws IOException { 72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insns = new LinkedList<Instruction>(); 73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle long insnsOffset = file.getFilePointer(); 74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (insnsOffset != 0) { 75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle long finger = insnsOffset; 76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle long insnsEnd = insnsOffset + (2 * insnsSize); 77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (finger < insnsEnd) { 79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.seek(finger); 80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Instruction newInsn = new Instruction(); 81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle newInsn.read(file); 82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insns.add(newInsn); 83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle finger += (2 * newInsn.getSize()); 84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.seek(finger); 87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void write(DexRandomAccessFile file) throws IOException { 92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.alignForwards(4); 93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.getOffsetTracker().updatePositionOfNextOffsettable(file); 94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.writeUShort(registersSize); 95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.writeUShort(insSize); 96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.writeUShort(outsSize); 97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.writeUShort(triesSize); 98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // We do not support retaining debug info currently. 99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.writeUInt(0 /*debug_info_off*/); 100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.writeUInt(insnsSize); 101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (Instruction insn : insns) { 102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insn.write(file); 103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (triesSize > 0) { 105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((insnsSize % 2) != 0) { 106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // produce padding 107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle file.writeUShort((short) 0); 108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (TryItem tryItem : tries) { 110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle tryItem.write(file); 111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle handlers.write(file); 113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * CodeTranslator should call this to notify a CodeItem about its 118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * mutatable code, so it can always get the "latest" view of its 119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * instructions. 120959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 121959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void registerMutatableCode(MutatableCode mutatableCode) { 122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle this.mutatableCode = mutatableCode; 123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void incrementIndex(IndexUpdateKind kind, int insertedIdx) { 127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (kind == IndexUpdateKind.TYPE_ID && triesSize > 0) { 128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // EncodedCatchHandlerList (well, the EncodedTypeAddrPairs it owns) 129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // are only interested in TYPE_IDs. 130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle handlers.incrementIndex(kind, insertedIdx); 131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (kind == IndexUpdateKind.PROTO_ID) { 134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // The only kind we can't encounter in an instruction. 135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return; 136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle List<Instruction> insnsToIncrement = insns; 139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // If we have an associated MutatableCode, then it may have created some new insns 141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // that we won't know about yet, during the mutation phase. 142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // 143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Ask for the latest view of the insns. 144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mutatableCode != null) { 145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insnsToIncrement = mutatableCode.requestLatestInstructions(); 146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (Instruction insn : insnsToIncrement) { 149959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Opcode opcode = insn.info.opcode; 150959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle switch (kind) { 151959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case STRING_ID: 152959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (opcode == Opcode.CONST_STRING || opcode == Opcode.CONST_STRING_JUMBO) { 153959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // STRING@BBBB 154959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (insn.vregB >= insertedIdx) { 155959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insn.vregB++; 156959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 157959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 158959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 159959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case TYPE_ID: 160959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (opcode == Opcode.CONST_CLASS 161959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle || opcode == Opcode.CHECK_CAST 162959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle || opcode == Opcode.NEW_INSTANCE 163959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle || opcode == Opcode.FILLED_NEW_ARRAY 164959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle || opcode == Opcode.FILLED_NEW_ARRAY_RANGE) { 165959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // TYPE@BBBB 166959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (insn.vregB >= insertedIdx) { 167959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insn.vregB++; 168959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 169959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (opcode == Opcode.INSTANCE_OF || opcode == Opcode.NEW_ARRAY) { 170959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // TYPE@CCCC 171959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (insn.vregC >= insertedIdx) { 172959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insn.vregC++; 173959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 174959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 175959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 176959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case FIELD_ID: 177959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (Opcode.isBetween(opcode, Opcode.SGET, Opcode.SPUT_SHORT)) { 178959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // FIELD@BBBB 179959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (insn.vregB >= insertedIdx) { 180959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insn.vregB++; 181959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 182959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (Opcode.isBetween(opcode, Opcode.IGET, Opcode.IPUT_SHORT)) { 183959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // FIELD@CCCC 184959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (insn.vregC >= insertedIdx) { 185959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insn.vregC++; 186959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 187959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 188959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 189959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle case METHOD_ID: 190959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (Opcode.isBetween(opcode, Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_INTERFACE) 191959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle || Opcode.isBetween(opcode, 192959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Opcode.INVOKE_VIRTUAL_RANGE, Opcode.INVOKE_INTERFACE_RANGE)) { 193959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // METHOD@BBBB 194959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (insn.vregB >= insertedIdx) { 195959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle insn.vregB++; 196959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 197959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 198959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 199959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle default: 200959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("Unexpected IndexUpdateKind requested " 201959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + "in Instruction.incrementIndex()"); 202959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 203959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 204959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 205959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle} 206