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 Kyle/**
20959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Tracks the original and updated positions of a RawDexObject when it is
21959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * parsed in from a DEX file, and written out to a mutated DEX file.
22959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */
23959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic class Offsettable {
24959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * The position of this Offsettable's item when it was read in.
26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private int originalPosition;
28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Set as we write out any Offsettable, so the Offset knows what its
31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * new value should be.
32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private int newPosition;
34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * The actual Item this Offsettable contains.
37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private RawDexObject item;
39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   *  Set either when getOriginalPosition() is called by the OffsetTracker
42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   *  to put the location in the offsettable map, so when Offsets are being
43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   *  associated, they know which Offsettable to point at.
44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   *  Or when an Offsettable is created that is marked as new, so we don't
45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   *  need to know its original position, because an Offset will be directly
46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   *  associated with it.
47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private boolean originalPositionKnown;
49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Set when we calculate the new position of this Offsettable as the file is
52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * being output.
53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private boolean updated;
55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Only the OffsetTracker should be able to create a new Offsettable.
58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public Offsettable(RawDexObject item, boolean isNew) {
60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    this.item = item;
61959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (isNew) {
62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // We no longer care about the original position of the Offsettable, because
63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // we are at the stage where we manually point Offsets at Offsettables, and
64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // don't need to use the OffsetTracker's offsettable map.
65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // So just lie and say we know it now.
66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      originalPositionKnown = true;
67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public RawDexObject getItem() {
71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return item;
72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Gets the offset from the beginning of the file to the RawDexObject this Offsettable
76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * contains, when the file was originally read.
77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Called when we're associating Offsets with Offsettables using the OffsetTracker's
78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * offsettable map.
79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public int getOriginalPosition() {
81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (!originalPositionKnown) {
82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      throw new Error("Cannot get the original position of an Offsettable when not yet set.");
83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return originalPosition;
85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public void setOriginalPosition(int pos) {
88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    originalPosition = pos;
89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    originalPositionKnown = true;
90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Get the new position of this Offsettable, once it's been written out to the output file.
94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public int getNewPosition() {
96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (!updated) {
97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      throw new Error("Cannot request new position before it has been set!");
98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return newPosition;
100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Record the new position of this Offsettable, as it is written out to the output file.
104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public void setNewPosition(int pos) {
106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (!updated) {
107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      newPosition = pos;
108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      updated = true;
109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else {
110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      throw new Error("Cannot update an Offsettable twice!");
111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public boolean readyForFinalOffsetToBeWritten() {
115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return (originalPositionKnown && updated);
116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle}
118