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 import dexfuzz.Log;
     20 
     21 public class Offset {
     22   /**
     23    * The absolute value of this offset as it was originally read.
     24    */
     25   private int originalOffset;
     26 
     27   /**
     28    * The Offsettable that this Offset points to.
     29    */
     30   private Offsettable offsettable;
     31 
     32   /**
     33    * The location of this Offset in the new file, ONLY SET IF the Offset
     34    * couldn't be written because what it points to hasn't been written
     35    * yet.
     36    */
     37   private int outputLocation;
     38 
     39   /**
     40    * Was the output location for this Offset set?.
     41    */
     42   private boolean outputLocationSet;
     43 
     44   /**
     45    * Does this Offset need to be written out using ULEB128?.
     46    */
     47   private boolean useUleb128;
     48 
     49   /**
     50    * Was this Offset created after reading, during mutation?.
     51    */
     52   private boolean isNewOffset;
     53 
     54   /**
     55    * Only one Offset should have this flag set, the MapItem that points
     56    * to the HeaderItem.
     57    */
     58   private boolean pointsAtHeader;
     59 
     60   /**
     61    * If an Offset pointed at 0 (because it is not actually a valid Offset),
     62    * and it's not pointing at the header, then this is set.
     63    */
     64   private boolean pointsAtNull;
     65 
     66   public Offset(boolean header) {
     67     pointsAtHeader = header;
     68   }
     69 
     70   public RawDexObject getPointedToItem() {
     71     return offsettable.getItem();
     72   }
     73 
     74   public boolean pointsToSomething() {
     75     return offsettable != null;
     76   }
     77 
     78   public boolean pointsAtNull() {
     79     return pointsAtNull;
     80   }
     81 
     82   public boolean pointsAtHeader() {
     83     return pointsAtHeader;
     84   }
     85 
     86   /**
     87    * Returns true if this Offset points at the provided RawDexObject.
     88    */
     89   public boolean pointsToThisItem(RawDexObject thisItem) {
     90     if (!pointsToSomething()) {
     91       return false;
     92     }
     93     return (offsettable.getItem().equals(thisItem));
     94   }
     95 
     96   /**
     97    * Returns true if this Offset points at the provided Offsettable.
     98    */
     99   public boolean pointsToThisOffsettable(Offsettable thisOffsettable) {
    100     if (!pointsToSomething()) {
    101       return false;
    102     }
    103     return (offsettable.equals(thisOffsettable));
    104   }
    105 
    106   /**
    107    * Makes this Offset point at a new Offsettable.
    108    */
    109   public void pointTo(Offsettable offsettableItem) {
    110     if (offsettable != null) {
    111       Log.debug("Updating what an Offset points to...");
    112     }
    113     offsettable = offsettableItem;
    114   }
    115 
    116   /**
    117    * Call this to make an Offset that pointed at null before now point at something.
    118    * An Offset may have previously pointed at null before...
    119    * Example: if there are no fields referred to in a DEX file, then header.field_ids_off
    120    * will point at null. We distinguish when Offsets point at null, and are not pointing
    121    * at the header (only the header MapItem should do this) with a flag. Therefore, this
    122    * method is needed to indicate that this Offset now points at something.
    123    */
    124   public void unsetNullAndPointTo(Offsettable offsettableItem) {
    125     pointsAtNull = false;
    126     if (offsettable != null) {
    127       Log.debug("Updating what an Offset points to...");
    128     }
    129     offsettable = offsettableItem;
    130   }
    131 
    132   public void pointToNew(Offsettable offsettableItem) {
    133     offsettable = offsettableItem;
    134     isNewOffset = true;
    135   }
    136 
    137   public int getNewPositionOfItem() {
    138     return offsettable.getNewPosition();
    139   }
    140 
    141   public boolean usesUleb128() {
    142     return useUleb128;
    143   }
    144 
    145   /**
    146    * Mark this Offset as using the ULEB128 encoding.
    147    */
    148   public void setUsesUleb128() {
    149     if (useUleb128) {
    150       throw new Error("Offset is already marked as using ULEB128!");
    151     }
    152     useUleb128 = true;
    153   }
    154 
    155   public boolean isNewOffset() {
    156     return isNewOffset;
    157   }
    158 
    159   public void setPointsAtNull() {
    160     pointsAtNull = true;
    161   }
    162 
    163   public void setOutputLocation(int loc) {
    164     outputLocation = loc;
    165     outputLocationSet = true;
    166   }
    167 
    168   /**
    169    * Get the location in the output DEX file where this offset has been written.
    170    * (This is used when patching Offsets when the Offsettable position was not
    171    * known at the time of writing out the Offset.)
    172    */
    173   public int getOutputLocation() {
    174     if (!outputLocationSet) {
    175       throw new Error("Output location was not set yet!");
    176     }
    177     return outputLocation;
    178   }
    179 
    180   public void setOriginalOffset(int offset) {
    181     originalOffset = offset;
    182   }
    183 
    184   public int getOriginalOffset() {
    185     return originalOffset;
    186   }
    187 
    188   public boolean readyForWriting() {
    189     return offsettable.readyForFinalOffsetToBeWritten();
    190   }
    191 }
    192