1959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle/*
2959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Copyright (C) 2014 The Android Open Source Project
3959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle *
4959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Licensed under the Apache License, Version 2.0 (the "License");
5959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * you may not use this file except in compliance with the License.
6959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * You may obtain a copy of the License at
7959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle *
8959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle *      http://www.apache.org/licenses/LICENSE-2.0
9959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle *
10959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Unless required by applicable law or agreed to in writing, software
11959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * distributed under the License is distributed on an "AS IS" BASIS,
12959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * See the License for the specific language governing permissions and
14959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * limitations under the License.
15959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */
16959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
17959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepackage dexfuzz.rawdex;
18959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
19959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.Log;
20959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
21959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic class Offset {
22959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
23959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * The absolute value of this offset as it was originally read.
24959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private int originalOffset;
26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * The Offsettable that this Offset points to.
29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private Offsettable offsettable;
31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * The location of this Offset in the new file, ONLY SET IF the Offset
34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * couldn't be written because what it points to hasn't been written
35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * yet.
36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private int outputLocation;
38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Was the output location for this Offset set?.
41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private boolean outputLocationSet;
43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Does this Offset need to be written out using ULEB128?.
46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private boolean useUleb128;
48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Was this Offset created after reading, during mutation?.
51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private boolean isNewOffset;
53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Only one Offset should have this flag set, the MapItem that points
56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * to the HeaderItem.
57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private boolean pointsAtHeader;
59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
61959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * If an Offset pointed at 0 (because it is not actually a valid Offset),
62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * and it's not pointing at the header, then this is set.
63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private boolean pointsAtNull;
65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public Offset(boolean header) {
67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    pointsAtHeader = header;
68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public RawDexObject getPointedToItem() {
71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return offsettable.getItem();
72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public boolean pointsToSomething() {
75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return offsettable != null;
76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public boolean pointsAtNull() {
79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return pointsAtNull;
80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public boolean pointsAtHeader() {
83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return pointsAtHeader;
84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Returns true if this Offset points at the provided RawDexObject.
88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public boolean pointsToThisItem(RawDexObject thisItem) {
90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (!pointsToSomething()) {
91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      return false;
92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return (offsettable.getItem().equals(thisItem));
94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Returns true if this Offset points at the provided Offsettable.
98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public boolean pointsToThisOffsettable(Offsettable thisOffsettable) {
100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (!pointsToSomething()) {
101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      return false;
102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return (offsettable.equals(thisOffsettable));
104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Makes this Offset point at a new Offsettable.
108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public void pointTo(Offsettable offsettableItem) {
110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (offsettable != null) {
111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      Log.debug("Updating what an Offset points to...");
112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    offsettable = offsettableItem;
114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Call this to make an Offset that pointed at null before now point at something.
118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * An Offset may have previously pointed at null before...
119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Example: if there are no fields referred to in a DEX file, then header.field_ids_off
120959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * will point at null. We distinguish when Offsets point at null, and are not pointing
121959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * at the header (only the header MapItem should do this) with a flag. Therefore, this
122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * method is needed to indicate that this Offset now points at something.
123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public void unsetNullAndPointTo(Offsettable offsettableItem) {
125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    pointsAtNull = false;
126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (offsettable != null) {
127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      Log.debug("Updating what an Offset points to...");
128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    offsettable = offsettableItem;
130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public void pointToNew(Offsettable offsettableItem) {
133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    offsettable = offsettableItem;
134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    isNewOffset = true;
135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public int getNewPositionOfItem() {
138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return offsettable.getNewPosition();
139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public boolean usesUleb128() {
142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return useUleb128;
143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Mark this Offset as using the ULEB128 encoding.
147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public void setUsesUleb128() {
149959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (useUleb128) {
150959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      throw new Error("Offset is already marked as using ULEB128!");
151959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
152959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    useUleb128 = true;
153959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
154959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
155959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public boolean isNewOffset() {
156959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return isNewOffset;
157959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
158959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
159959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public void setPointsAtNull() {
160959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    pointsAtNull = true;
161959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
162959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
163959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public void setOutputLocation(int loc) {
164959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    outputLocation = loc;
165959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    outputLocationSet = true;
166959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
167959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
168959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
169959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Get the location in the output DEX file where this offset has been written.
170959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * (This is used when patching Offsets when the Offsettable position was not
171959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * known at the time of writing out the Offset.)
172959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
173959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public int getOutputLocation() {
174959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (!outputLocationSet) {
175959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      throw new Error("Output location was not set yet!");
176959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
177959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return outputLocation;
178959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
179959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
180959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public void setOriginalOffset(int offset) {
181959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    originalOffset = offset;
182959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
183959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
184959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public int getOriginalOffset() {
185959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return originalOffset;
186959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
187959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
188959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public boolean readyForWriting() {
189959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return offsettable.readyForFinalOffsetToBeWritten();
190959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
191959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle}
192