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 /** 20 * Tracks the original and updated positions of a RawDexObject when it is 21 * parsed in from a DEX file, and written out to a mutated DEX file. 22 */ 23 public class Offsettable { 24 /** 25 * The position of this Offsettable's item when it was read in. 26 */ 27 private int originalPosition; 28 29 /** 30 * Set as we write out any Offsettable, so the Offset knows what its 31 * new value should be. 32 */ 33 private int newPosition; 34 35 /** 36 * The actual Item this Offsettable contains. 37 */ 38 private RawDexObject item; 39 40 /** 41 * Set either when getOriginalPosition() is called by the OffsetTracker 42 * to put the location in the offsettable map, so when Offsets are being 43 * associated, they know which Offsettable to point at. 44 * Or when an Offsettable is created that is marked as new, so we don't 45 * need to know its original position, because an Offset will be directly 46 * associated with it. 47 */ 48 private boolean originalPositionKnown; 49 50 /** 51 * Set when we calculate the new position of this Offsettable as the file is 52 * being output. 53 */ 54 private boolean updated; 55 56 /** 57 * Only the OffsetTracker should be able to create a new Offsettable. 58 */ Offsettable(RawDexObject item, boolean isNew)59 public Offsettable(RawDexObject item, boolean isNew) { 60 this.item = item; 61 if (isNew) { 62 // We no longer care about the original position of the Offsettable, because 63 // we are at the stage where we manually point Offsets at Offsettables, and 64 // don't need to use the OffsetTracker's offsettable map. 65 // So just lie and say we know it now. 66 originalPositionKnown = true; 67 } 68 } 69 getItem()70 public RawDexObject getItem() { 71 return item; 72 } 73 74 /** 75 * Gets the offset from the beginning of the file to the RawDexObject this Offsettable 76 * contains, when the file was originally read. 77 * Called when we're associating Offsets with Offsettables using the OffsetTracker's 78 * offsettable map. 79 */ getOriginalPosition()80 public int getOriginalPosition() { 81 if (!originalPositionKnown) { 82 throw new Error("Cannot get the original position of an Offsettable when not yet set."); 83 } 84 return originalPosition; 85 } 86 setOriginalPosition(int pos)87 public void setOriginalPosition(int pos) { 88 originalPosition = pos; 89 originalPositionKnown = true; 90 } 91 92 /** 93 * Get the new position of this Offsettable, once it's been written out to the output file. 94 */ getNewPosition()95 public int getNewPosition() { 96 if (!updated) { 97 throw new Error("Cannot request new position before it has been set!"); 98 } 99 return newPosition; 100 } 101 102 /** 103 * Record the new position of this Offsettable, as it is written out to the output file. 104 */ setNewPosition(int pos)105 public void setNewPosition(int pos) { 106 if (!updated) { 107 newPosition = pos; 108 updated = true; 109 } else { 110 throw new Error("Cannot update an Offsettable twice!"); 111 } 112 } 113 readyForFinalOffsetToBeWritten()114 public boolean readyForFinalOffsetToBeWritten() { 115 return (originalPositionKnown && updated); 116 } 117 } 118