| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package dexfuzz.rawdex; |
| |
| import dexfuzz.Log; |
| |
| public class Offset { |
| /** |
| * The absolute value of this offset as it was originally read. |
| */ |
| private int originalOffset; |
| |
| /** |
| * The Offsettable that this Offset points to. |
| */ |
| private Offsettable offsettable; |
| |
| /** |
| * The location of this Offset in the new file, ONLY SET IF the Offset |
| * couldn't be written because what it points to hasn't been written |
| * yet. |
| */ |
| private int outputLocation; |
| |
| /** |
| * Was the output location for this Offset set?. |
| */ |
| private boolean outputLocationSet; |
| |
| /** |
| * Does this Offset need to be written out using ULEB128?. |
| */ |
| private boolean useUleb128; |
| |
| /** |
| * Was this Offset created after reading, during mutation?. |
| */ |
| private boolean isNewOffset; |
| |
| /** |
| * Only one Offset should have this flag set, the MapItem that points |
| * to the HeaderItem. |
| */ |
| private boolean pointsAtHeader; |
| |
| /** |
| * If an Offset pointed at 0 (because it is not actually a valid Offset), |
| * and it's not pointing at the header, then this is set. |
| */ |
| private boolean pointsAtNull; |
| |
| public Offset(boolean header) { |
| pointsAtHeader = header; |
| } |
| |
| public RawDexObject getPointedToItem() { |
| return offsettable.getItem(); |
| } |
| |
| public boolean pointsToSomething() { |
| return offsettable != null; |
| } |
| |
| public boolean pointsAtNull() { |
| return pointsAtNull; |
| } |
| |
| public boolean pointsAtHeader() { |
| return pointsAtHeader; |
| } |
| |
| /** |
| * Returns true if this Offset points at the provided RawDexObject. |
| */ |
| public boolean pointsToThisItem(RawDexObject thisItem) { |
| if (!pointsToSomething()) { |
| return false; |
| } |
| return (offsettable.getItem().equals(thisItem)); |
| } |
| |
| /** |
| * Returns true if this Offset points at the provided Offsettable. |
| */ |
| public boolean pointsToThisOffsettable(Offsettable thisOffsettable) { |
| if (!pointsToSomething()) { |
| return false; |
| } |
| return (offsettable.equals(thisOffsettable)); |
| } |
| |
| /** |
| * Makes this Offset point at a new Offsettable. |
| */ |
| public void pointTo(Offsettable offsettableItem) { |
| if (offsettable != null) { |
| Log.debug("Updating what an Offset points to..."); |
| } |
| offsettable = offsettableItem; |
| } |
| |
| /** |
| * Call this to make an Offset that pointed at null before now point at something. |
| * An Offset may have previously pointed at null before... |
| * Example: if there are no fields referred to in a DEX file, then header.field_ids_off |
| * will point at null. We distinguish when Offsets point at null, and are not pointing |
| * at the header (only the header MapItem should do this) with a flag. Therefore, this |
| * method is needed to indicate that this Offset now points at something. |
| */ |
| public void unsetNullAndPointTo(Offsettable offsettableItem) { |
| pointsAtNull = false; |
| if (offsettable != null) { |
| Log.debug("Updating what an Offset points to..."); |
| } |
| offsettable = offsettableItem; |
| } |
| |
| public void pointToNew(Offsettable offsettableItem) { |
| offsettable = offsettableItem; |
| isNewOffset = true; |
| } |
| |
| public int getNewPositionOfItem() { |
| return offsettable.getNewPosition(); |
| } |
| |
| public boolean usesUleb128() { |
| return useUleb128; |
| } |
| |
| /** |
| * Mark this Offset as using the ULEB128 encoding. |
| */ |
| public void setUsesUleb128() { |
| if (useUleb128) { |
| throw new Error("Offset is already marked as using ULEB128!"); |
| } |
| useUleb128 = true; |
| } |
| |
| public boolean isNewOffset() { |
| return isNewOffset; |
| } |
| |
| public void setPointsAtNull() { |
| pointsAtNull = true; |
| } |
| |
| public void setOutputLocation(int loc) { |
| outputLocation = loc; |
| outputLocationSet = true; |
| } |
| |
| /** |
| * Get the location in the output DEX file where this offset has been written. |
| * (This is used when patching Offsets when the Offsettable position was not |
| * known at the time of writing out the Offset.) |
| */ |
| public int getOutputLocation() { |
| if (!outputLocationSet) { |
| throw new Error("Output location was not set yet!"); |
| } |
| return outputLocation; |
| } |
| |
| public void setOriginalOffset(int offset) { |
| originalOffset = offset; |
| } |
| |
| public int getOriginalOffset() { |
| return originalOffset; |
| } |
| |
| public boolean readyForWriting() { |
| return offsettable.readyForFinalOffsetToBeWritten(); |
| } |
| } |