1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2008 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.file; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Constant; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstArray; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstLiteralBits; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstType; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Zeroes; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput; 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.ByteArrayAnnotatedOutput; 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.Hex; 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.Writers; 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.PrintWriter; 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.Writer; 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.ArrayList; 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.Arrays; 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.Collections; 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.List; 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.HashMap; 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Representation of all the parts of a Dalvik class that are generally 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * "inflated" into an in-memory representation at runtime. Instances of 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * this class are represented in a compact streamable form in a 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code dex} file, as opposed to a random-access form. 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class ClassDataItem extends OffsettedItem { 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} what class this data is for, just for listing generation */ 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final CstType thisClass; 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} list of static fields */ 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final ArrayList<EncodedField> staticFields; 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} list of initial values for static fields */ 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final HashMap<EncodedField, Constant> staticValues; 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} list of instance fields */ 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final ArrayList<EncodedField> instanceFields; 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} list of direct methods */ 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final ArrayList<EncodedMethod> directMethods; 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} list of virtual methods */ 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final ArrayList<EncodedMethod> virtualMethods; 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code null-ok;} static initializer list; set in {@link #addContents} */ 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private CstArray staticValuesConstant; 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null-ok;} encoded form, ready for writing to a file; set during 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #place0} 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private byte[] encodedForm; 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. Its sets of members are initially 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * empty. 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param thisClass {@code non-null;} what class this data is for, just 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * for listing generation 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public ClassDataItem(CstType thisClass) { 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super(1, -1); 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (thisClass == null) { 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("thisClass == null"); 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.thisClass = thisClass; 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.staticFields = new ArrayList<EncodedField>(20); 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.staticValues = new HashMap<EncodedField, Constant>(40); 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.instanceFields = new ArrayList<EncodedField>(20); 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.directMethods = new ArrayList<EncodedMethod>(20); 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.virtualMethods = new ArrayList<EncodedMethod>(20); 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.staticValuesConstant = null; 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public ItemType itemType() { 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return ItemType.TYPE_CLASS_DATA_ITEM; 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String toHuman() { 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return toString(); 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns whether this instance is empty. 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} if this instance is empty or 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code false} if at least one element has been added to it 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean isEmpty() { 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return staticFields.isEmpty() && instanceFields.isEmpty() 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && directMethods.isEmpty() && virtualMethods.isEmpty(); 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds a static field. 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param field {@code non-null;} the field to add 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param value {@code null-ok;} initial value for the field, if any 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void addStaticField(EncodedField field, Constant value) { 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (field == null) { 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("field == null"); 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (staticValuesConstant != null) { 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new UnsupportedOperationException( 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "static fields already sorted"); 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul staticFields.add(field); 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul staticValues.put(field, value); 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds an instance field. 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param field {@code non-null;} the field to add 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void addInstanceField(EncodedField field) { 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (field == null) { 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("field == null"); 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul instanceFields.add(field); 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds a direct ({@code static} and/or {@code private}) method. 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param method {@code non-null;} the method to add 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void addDirectMethod(EncodedMethod method) { 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (method == null) { 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("method == null"); 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul directMethods.add(method); 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds a virtual method. 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param method {@code non-null;} the method to add 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void addVirtualMethod(EncodedMethod method) { 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (method == null) { 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("method == null"); 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul virtualMethods.add(method); 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets all the methods in this class. The returned list is not linked 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * in any way to the underlying lists contained in this instance, but 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the objects contained in the list are shared. 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} list of all methods 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public ArrayList<EncodedMethod> getMethods() { 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = directMethods.size() + virtualMethods.size(); 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ArrayList<EncodedMethod> result = new ArrayList<EncodedMethod>(sz); 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.addAll(directMethods); 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.addAll(virtualMethods); 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Prints out the contents of this instance, in a debugging-friendly 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * way. 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to output to 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param verbose whether to be verbose with the output 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void debugPrint(Writer out, boolean verbose) { 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul PrintWriter pw = Writers.printWriterFor(out); 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = staticFields.size(); 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul pw.println(" sfields[" + i + "]: " + staticFields.get(i)); 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sz = instanceFields.size(); 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul pw.println(" ifields[" + i + "]: " + instanceFields.get(i)); 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sz = directMethods.size(); 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul pw.println(" dmeths[" + i + "]:"); 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul directMethods.get(i).debugPrint(pw, verbose); 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sz = virtualMethods.size(); 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul pw.println(" vmeths[" + i + "]:"); 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul virtualMethods.get(i).debugPrint(pw, verbose); 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void addContents(DexFile file) { 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!staticFields.isEmpty()) { 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul getStaticValuesConstant(); // Force the fields to be sorted. 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (EncodedField field : staticFields) { 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul field.addContents(file); 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!instanceFields.isEmpty()) { 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Collections.sort(instanceFields); 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (EncodedField field : instanceFields) { 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul field.addContents(file); 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!directMethods.isEmpty()) { 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Collections.sort(directMethods); 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (EncodedMethod method : directMethods) { 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul method.addContents(file); 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!virtualMethods.isEmpty()) { 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Collections.sort(virtualMethods); 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (EncodedMethod method : virtualMethods) { 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul method.addContents(file); 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets a {@link CstArray} corresponding to {@link #staticValues} if 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * it contains any non-zero non-{@code null} values. 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} the corresponding constant or {@code null} if 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * there are no values to encode 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public CstArray getStaticValuesConstant() { 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((staticValuesConstant == null) && (staticFields.size() != 0)) { 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul staticValuesConstant = makeStaticValuesConstant(); 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return staticValuesConstant; 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets a {@link CstArray} corresponding to {@link #staticValues} if 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * it contains any non-zero non-{@code null} values. 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} the corresponding constant or {@code null} if 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * there are no values to encode 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private CstArray makeStaticValuesConstant() { 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // First sort the statics into their final order. 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Collections.sort(staticFields); 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Get the size of staticValues minus any trailing zeros/nulls (both 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * nulls per se as well as instances of CstKnownNull). 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int size = staticFields.size(); 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul while (size > 0) { 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul EncodedField field = staticFields.get(size - 1); 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Constant cst = staticValues.get(field); 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (cst instanceof CstLiteralBits) { 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Note: CstKnownNull extends CstLiteralBits. 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (((CstLiteralBits) cst).getLongBits() != 0) { 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (cst != null) { 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul size--; 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (size == 0) { 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // There is something worth encoding, so build up a result. 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CstArray.List list = new CstArray.List(size); 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < size; i++) { 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul EncodedField field = staticFields.get(i); 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Constant cst = staticValues.get(field); 315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (cst == null) { 316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul cst = Zeroes.zeroFor(field.getRef().getType()); 317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul list.set(i, cst); 319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul list.setImmutable(); 321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return new CstArray(list); 323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected void place0(Section addedTo, int offset) { 328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Encode the data and note the size. 329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(); 331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul encodeOutput(addedTo.getFile(), out); 333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul encodedForm = out.toByteArray(); 334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul setWriteSize(encodedForm.length); 335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writes out the encoded form of this instance. 339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param file {@code non-null;} file this instance is part of 341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void encodeOutput(DexFile file, AnnotatedOutput out) { 344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean annotates = out.annotates(); 345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotates) { 347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.annotate(0, offsetString() + " class data for " + 348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul thisClass.toHuman()); 349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul encodeSize(file, out, "static_fields", staticFields.size()); 352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul encodeSize(file, out, "instance_fields", instanceFields.size()); 353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul encodeSize(file, out, "direct_methods", directMethods.size()); 354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul encodeSize(file, out, "virtual_methods", virtualMethods.size()); 355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul encodeList(file, out, "static_fields", staticFields); 357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul encodeList(file, out, "instance_fields", instanceFields); 358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul encodeList(file, out, "direct_methods", directMethods); 359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul encodeList(file, out, "virtual_methods", virtualMethods); 360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotates) { 362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.endAnnotation(); 363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper for {@link #encodeOutput}, which writes out the given 368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * size value, annotating it as well (if annotations are enabled). 369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param file {@code non-null;} file this instance is part of 371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param label {@code non-null;} the label for the purposes of annotation 373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param size {@code >= 0;} the size to write 374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static void encodeSize(DexFile file, AnnotatedOutput out, 376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String label, int size) { 377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (out.annotates()) { 378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.annotate(String.format(" %-21s %08x", label + "_size:", 379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul size)); 380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeUnsignedLeb128(size); 383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper for {@link #encodeOutput}, which writes out the given 387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * list. It also annotates the items (if any and if annotations 388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * are enabled). 389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param file {@code non-null;} file this instance is part of 391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param label {@code non-null;} the label for the purposes of annotation 393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param list {@code non-null;} the list in question 394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static void encodeList(DexFile file, AnnotatedOutput out, 396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String label, ArrayList<? extends EncodedMember> list) { 397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int size = list.size(); 398917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int lastIndex = 0; 399917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 400917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (size == 0) { 401917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return; 402917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 403917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 404917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (out.annotates()) { 405917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.annotate(0, " " + label + ":"); 406917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 407917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 408917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < size; i++) { 409917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul lastIndex = list.get(i).encode(file, out, lastIndex, i); 410917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 411917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 412917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 413917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 414917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 415917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void writeTo0(DexFile file, AnnotatedOutput out) { 416917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean annotates = out.annotates(); 417917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 418917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotates) { 419917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 420917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * The output is to be annotated, so redo the work previously 421917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * done by place0(), except this time annotations will actually 422917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * get emitted. 423917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 424917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul encodeOutput(file, out); 425917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 426917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.write(encodedForm); 427917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 428917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 429917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 430