blob: b6718e36507afdf717747a40efc754c9f73ed414 [file] [log] [blame]
/*
* 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();
}
}