Home | History | Annotate | Download | only in rawdex
      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    */
     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 
     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    */
     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 
     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    */
     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    */
    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 
    114   public boolean readyForFinalOffsetToBeWritten() {
    115     return (originalPositionKnown && updated);
    116   }
    117 }
    118