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 Kylepublic class Offset { 22959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 23959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * The absolute value of this offset as it was originally read. 24959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private int originalOffset; 26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * The Offsettable that this Offset points to. 29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private Offsettable offsettable; 31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * The location of this Offset in the new file, ONLY SET IF the Offset 34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * couldn't be written because what it points to hasn't been written 35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * yet. 36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private int outputLocation; 38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Was the output location for this Offset set?. 41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private boolean outputLocationSet; 43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Does this Offset need to be written out using ULEB128?. 46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private boolean useUleb128; 48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Was this Offset created after reading, during mutation?. 51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private boolean isNewOffset; 53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Only one Offset should have this flag set, the MapItem that points 56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * to the HeaderItem. 57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private boolean pointsAtHeader; 59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 61959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * If an Offset pointed at 0 (because it is not actually a valid Offset), 62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * and it's not pointing at the header, then this is set. 63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private boolean pointsAtNull; 65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public Offset(boolean header) { 67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle pointsAtHeader = header; 68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public RawDexObject getPointedToItem() { 71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return offsettable.getItem(); 72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public boolean pointsToSomething() { 75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return offsettable != null; 76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public boolean pointsAtNull() { 79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return pointsAtNull; 80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public boolean pointsAtHeader() { 83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return pointsAtHeader; 84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Returns true if this Offset points at the provided RawDexObject. 88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public boolean pointsToThisItem(RawDexObject thisItem) { 90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (!pointsToSomething()) { 91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return (offsettable.getItem().equals(thisItem)); 94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Returns true if this Offset points at the provided Offsettable. 98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public boolean pointsToThisOffsettable(Offsettable thisOffsettable) { 100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (!pointsToSomething()) { 101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return (offsettable.equals(thisOffsettable)); 104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Makes this Offset point at a new Offsettable. 108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void pointTo(Offsettable offsettableItem) { 110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (offsettable != null) { 111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Updating what an Offset points to..."); 112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle offsettable = offsettableItem; 114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Call this to make an Offset that pointed at null before now point at something. 118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * An Offset may have previously pointed at null before... 119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Example: if there are no fields referred to in a DEX file, then header.field_ids_off 120959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * will point at null. We distinguish when Offsets point at null, and are not pointing 121959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * at the header (only the header MapItem should do this) with a flag. Therefore, this 122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * method is needed to indicate that this Offset now points at something. 123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void unsetNullAndPointTo(Offsettable offsettableItem) { 125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle pointsAtNull = false; 126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (offsettable != null) { 127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Updating what an Offset points to..."); 128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle offsettable = offsettableItem; 130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void pointToNew(Offsettable offsettableItem) { 133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle offsettable = offsettableItem; 134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle isNewOffset = true; 135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public int getNewPositionOfItem() { 138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return offsettable.getNewPosition(); 139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public boolean usesUleb128() { 142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return useUleb128; 143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Mark this Offset as using the ULEB128 encoding. 147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void setUsesUleb128() { 149959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (useUleb128) { 150959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle throw new Error("Offset is already marked as using ULEB128!"); 151959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 152959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useUleb128 = true; 153959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 154959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 155959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public boolean isNewOffset() { 156959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return isNewOffset; 157959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 158959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 159959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void setPointsAtNull() { 160959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle pointsAtNull = true; 161959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 162959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 163959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void setOutputLocation(int loc) { 164959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle outputLocation = loc; 165959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle outputLocationSet = true; 166959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 167959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 168959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 169959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Get the location in the output DEX file where this offset has been written. 170959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * (This is used when patching Offsets when the Offsettable position was not 171959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * known at the time of writing out the Offset.) 172959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 173959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public int getOutputLocation() { 174959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (!outputLocationSet) { 175959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle throw new Error("Output location was not set yet!"); 176959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 177959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return outputLocation; 178959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 179959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 180959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void setOriginalOffset(int offset) { 181959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle originalOffset = offset; 182959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 183959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 184959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public int getOriginalOffset() { 185959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return originalOffset; 186959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 187959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 188959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public boolean readyForWriting() { 189959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return offsettable.readyForFinalOffsetToBeWritten(); 190959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 191959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle} 192