1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/* 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License. 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License. 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.dex.file; 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.dex.DexFormat; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.dex.DexOptions; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.Constant; 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstBaseMethodRef; 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstEnumRef; 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstFieldRef; 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstString; 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstType; 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.Type; 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.ByteArrayAnnotatedOutput; 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.ExceptionWithContext; 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.IOException; 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.OutputStream; 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.Writer; 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.security.DigestException; 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.security.MessageDigest; 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.security.NoSuchAlgorithmException; 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.zip.Adler32; 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport static com.android.dx.dex.file.MixedItemSection.SortType; 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Representation of an entire {@code .dex} (Dalvik EXecutable) 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * file, which itself consists of a set of Dalvik classes. 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class DexFile { 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** options controlling the creation of the file */ 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private DexOptions dexOptions; 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} word data section */ 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final MixedItemSection wordData; 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code non-null;} type lists section. This is word data, but separating 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * it from {@link #wordData} helps break what would otherwise be a 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * circular dependency between the that and {@link #protoIds}. 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final MixedItemSection typeLists; 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code non-null;} map section. The map needs to be in a section by itself 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * for the self-reference mechanics to work in a reasonably 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * straightforward way. See {@link MapItem#addMap} for more detail. 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final MixedItemSection map; 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} string data section */ 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final MixedItemSection stringData; 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} string identifiers section */ 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final StringIdsSection stringIds; 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} type identifiers section */ 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final TypeIdsSection typeIds; 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} prototype identifiers section */ 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final ProtoIdsSection protoIds; 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} field identifiers section */ 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final FieldIdsSection fieldIds; 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} method identifiers section */ 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final MethodIdsSection methodIds; 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} class definitions section */ 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final ClassDefsSection classDefs; 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} class data section */ 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final MixedItemSection classData; 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} byte data section */ 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final MixedItemSection byteData; 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} file header */ 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final HeaderSection header; 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code non-null;} array of sections in the order they will appear in the 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * final output file 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final Section[] sections; 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code >= -1;} total file size or {@code -1} if unknown */ 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private int fileSize; 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code >= 40;} maximum width of the file dump */ 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private int dumpWidth; 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. It is initially empty. 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public DexFile(DexOptions dexOptions) { 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.dexOptions = dexOptions; 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson header = new HeaderSection(this); 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson typeLists = new MixedItemSection(null, this, 4, SortType.NONE); 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson wordData = new MixedItemSection("word_data", this, 4, SortType.TYPE); 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson stringData = 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson new MixedItemSection("string_data", this, 1, SortType.INSTANCE); 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson classData = new MixedItemSection(null, this, 1, SortType.NONE); 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson byteData = new MixedItemSection("byte_data", this, 1, SortType.TYPE); 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson stringIds = new StringIdsSection(this); 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson typeIds = new TypeIdsSection(this); 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protoIds = new ProtoIdsSection(this); 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fieldIds = new FieldIdsSection(this); 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson methodIds = new MethodIdsSection(this); 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson classDefs = new ClassDefsSection(this); 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson map = new MixedItemSection("map", this, 4, SortType.NONE); 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * This is the list of sections in the order they appear in 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the final output. 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sections = new Section[] { 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson header, stringIds, typeIds, protoIds, fieldIds, methodIds, 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson classDefs, wordData, typeLists, stringData, byteData, 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson classData, map }; 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fileSize = -1; 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson dumpWidth = 79; 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns true if this dex doesn't contain any class defs. 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean isEmpty() { 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return classDefs.items().isEmpty(); 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the dex-creation options object. 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public DexOptions getDexOptions() { 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return dexOptions; 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Adds a class to this instance. It is illegal to attempt to add more 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * than one class with the same name. 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param clazz {@code non-null;} the class to add 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void add(ClassDefItem clazz) { 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson classDefs.add(clazz); 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the class definition with the given name, if any. 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param name {@code non-null;} the class name to look for 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code null-ok;} the class with the given name, or {@code null} 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * if there is no such class 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public ClassDefItem getClassOrNull(String name) { 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Type type = Type.internClassName(name); 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return (ClassDefItem) classDefs.get(new CstType(type)); 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (IllegalArgumentException ex) { 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Translate exception, per contract. 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Writes the contents of this instance as either a binary or a 185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * human-readable form, or both. 186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param out {@code null-ok;} where to write to 188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param humanOut {@code null-ok;} where to write human-oriented output to 189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param verbose whether to be verbose when writing human-oriented output 190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void writeTo(OutputStream out, Writer humanOut, boolean verbose) 192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throws IOException { 193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson boolean annotate = (humanOut != null); 194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ByteArrayAnnotatedOutput result = toDex0(annotate, verbose); 195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (out != null) { 197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.write(result.getArray()); 198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (annotate) { 201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson result.writeAnnotationsTo(humanOut); 202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns the contents of this instance as a {@code .dex} file, 207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * in {@code byte[]} form. 208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param humanOut {@code null-ok;} where to write human-oriented output to 210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param verbose whether to be verbose when writing human-oriented output 211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} a {@code .dex} file for this instance 212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public byte[] toDex(Writer humanOut, boolean verbose) 214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throws IOException { 215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson boolean annotate = (humanOut != null); 216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ByteArrayAnnotatedOutput result = toDex0(annotate, verbose); 217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (annotate) { 219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson result.writeAnnotationsTo(humanOut); 220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return result.getArray(); 223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Sets the maximum width of the human-oriented dump of the instance. 227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param dumpWidth {@code >= 40;} the width 229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void setDumpWidth(int dumpWidth) { 231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (dumpWidth < 40) { 232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalArgumentException("dumpWidth < 40"); 233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.dumpWidth = dumpWidth; 236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the total file size, if known. 240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the {@link HeaderSection} to set itself up properly.</p> 243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code >= 0;} the total file size 245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @throws RuntimeException thrown if the file size is not yet known 246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ int getFileSize() { 248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (fileSize < 0) { 249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("file size not yet known"); 250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return fileSize; 253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the string data section. 257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the various {@link Item} instances to add items to the 260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.</p> 261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the string data section 263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ MixedItemSection getStringData() { 265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return stringData; 266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the word data section. 270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the various {@link Item} instances to add items to the 273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.</p> 274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the word data section 276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ MixedItemSection getWordData() { 278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return wordData; 279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the type lists section. 283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the various {@link Item} instances to add items to the 286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.</p> 287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the word data section 289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ MixedItemSection getTypeLists() { 291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return typeLists; 292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the map section. 296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow the header section 298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * to query it.</p> 299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the map section 301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ MixedItemSection getMap() { 303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return map; 304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the string identifiers section. 308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the various {@link Item} instances to add items to the 311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.</p> 312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the string identifiers section 314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ StringIdsSection getStringIds() { 316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return stringIds; 317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the class definitions section. 321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the various {@link Item} instances to add items to the 324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.</p> 325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the class definitions section 327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ ClassDefsSection getClassDefs() { 329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return classDefs; 330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the class data section. 334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the various {@link Item} instances to add items to the 337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.</p> 338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the class data section 340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ MixedItemSection getClassData() { 342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return classData; 343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the type identifiers section. 347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the various {@link Item} instances to add items to the 350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.</p> 351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the class identifiers section 353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ TypeIdsSection getTypeIds() { 355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return typeIds; 356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the prototype identifiers section. 360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the various {@link Item} instances to add items to the 363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.</p> 364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the prototype identifiers section 366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ ProtoIdsSection getProtoIds() { 368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return protoIds; 369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the field identifiers section. 373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the various {@link Item} instances to add items to the 376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.</p> 377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the field identifiers section 379579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ FieldIdsSection getFieldIds() { 381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return fieldIds; 382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the method identifiers section. 386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the various {@link Item} instances to add items to the 389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.</p> 390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the method identifiers section 392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ MethodIdsSection getMethodIds() { 394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return methodIds; 395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the byte data section. 399579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 400579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow 401579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the various {@link Item} instances to add items to the 402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.</p> 403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 404579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the byte data section 405579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ MixedItemSection getByteData() { 407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return byteData; 408579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 409579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 410579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 411579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the first section of the file that is to be considered 412579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * part of the data section. 413579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 414579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow the header section 415579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * to query it.</p> 416579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 417579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the section 418579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 419579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ Section getFirstDataSection() { 420579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return wordData; 421579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 422579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 423579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 424579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the last section of the file that is to be considered 425579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * part of the data section. 426579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 427579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This is package-scope in order to allow the header section 428579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * to query it.</p> 429579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 430579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the section 431579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 432579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ Section getLastDataSection() { 433579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return map; 434579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 435579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 436579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 437579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Interns the given constant in the appropriate section of this 438579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance, or do nothing if the given constant isn't the sort 439579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * that should be interned. 440579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 441579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param cst {@code non-null;} constant to possibly intern 442579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 443579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ void internIfAppropriate(Constant cst) { 444579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (cst instanceof CstString) { 445579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson stringIds.intern((CstString) cst); 446579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if (cst instanceof CstType) { 447579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson typeIds.intern((CstType) cst); 448579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if (cst instanceof CstBaseMethodRef) { 449579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson methodIds.intern((CstBaseMethodRef) cst); 450579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if (cst instanceof CstFieldRef) { 451579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fieldIds.intern((CstFieldRef) cst); 452579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if (cst instanceof CstEnumRef) { 453579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fieldIds.intern(((CstEnumRef) cst).getFieldRef()); 454579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if (cst == null) { 455579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException("cst == null"); 456579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 457579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 458579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 459579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 460579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the {@link IndexedItem} corresponding to the given constant, 461579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * if it is a constant that has such a correspondence, or return 462579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null} if it isn't such a constant. This will throw 463579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * an exception if the given constant <i>should</i> have been found 464579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * but wasn't. 465579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 466579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param cst {@code non-null;} the constant to look up 467579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code null-ok;} its corresponding item, if it has a corresponding 468579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * item, or {@code null} if it's not that sort of constant 469579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 470579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /*package*/ IndexedItem findItemOrNull(Constant cst) { 471579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson IndexedItem item; 472579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 473579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (cst instanceof CstString) { 474579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return stringIds.get(cst); 475579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if (cst instanceof CstType) { 476579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return typeIds.get(cst); 477579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if (cst instanceof CstBaseMethodRef) { 478579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return methodIds.get(cst); 479579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if (cst instanceof CstFieldRef) { 480579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return fieldIds.get(cst); 481579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 482579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 483579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 484579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 485579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 486579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 487579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns the contents of this instance as a {@code .dex} file, 488579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * in a {@link ByteArrayAnnotatedOutput} instance. 489579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 490579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param annotate whether or not to keep annotations 491579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param verbose if annotating, whether to be verbose 492579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} a {@code .dex} file for this instance 493579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 494579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private ByteArrayAnnotatedOutput toDex0(boolean annotate, 495579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson boolean verbose) { 496579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 497579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * The following is ordered so that the prepare() calls which 498579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * add items happen before the calls to the sections that get 499579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * added to. 500579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 501579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 502579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson classDefs.prepare(); 503579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson classData.prepare(); 504579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson wordData.prepare(); 505579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson byteData.prepare(); 506579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson methodIds.prepare(); 507579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fieldIds.prepare(); 508579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protoIds.prepare(); 509579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson typeLists.prepare(); 510579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson typeIds.prepare(); 511579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson stringIds.prepare(); 512579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson stringData.prepare(); 513579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson header.prepare(); 514579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 515579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Place the sections within the file. 516579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 517579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int count = sections.length; 518579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int offset = 0; 519579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 520579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < count; i++) { 521579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Section one = sections[i]; 522579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int placedAt = one.setFileOffset(offset); 523579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (placedAt < offset) { 524579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("bogus placement for section " + i); 525579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 526579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 527579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 528579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (one == map) { 529579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 530579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Inform the map of all the sections, and add it 531579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * to the file. This can only be done after all 532579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the other items have been sorted and placed. 533579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 534579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MapItem.addMap(sections, map); 535579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson map.prepare(); 536579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 537579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 538579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (one instanceof MixedItemSection) { 539579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 540579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Place the items of a MixedItemSection that just 541579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * got placed. 542579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 543579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ((MixedItemSection) one).placeItems(); 544579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 545579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 546579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson offset = placedAt + one.writeSize(); 547579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (RuntimeException ex) { 548579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw ExceptionWithContext.withContext(ex, 549579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson "...while writing section " + i); 550579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 551579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 552579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 553579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Write out all the sections. 554579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 555579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fileSize = offset; 556579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson byte[] barr = new byte[fileSize]; 557579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(barr); 558579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 559579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (annotate) { 560579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.enableAnnotations(dumpWidth, verbose); 561579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 562579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 563579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < count; i++) { 564579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 565579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Section one = sections[i]; 566579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int zeroCount = one.getFileOffset() - out.getCursor(); 567579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (zeroCount < 0) { 568579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new ExceptionWithContext("excess write of " + 569579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson (-zeroCount)); 570579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 571579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.writeZeroes(one.getFileOffset() - out.getCursor()); 572579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson one.writeTo(out); 573579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (RuntimeException ex) { 574579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ExceptionWithContext ec; 575579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (ex instanceof ExceptionWithContext) { 576579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ec = (ExceptionWithContext) ex; 577579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 578579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ec = new ExceptionWithContext(ex); 579579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 580579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ec.addContext("...while writing section " + i); 581579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw ec; 582579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 583579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 584579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 585579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (out.getCursor() != fileSize) { 586579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("foreshortened write"); 587579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 588579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 589579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Perform final bookkeeping. 590579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 591579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson calcSignature(barr); 592579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson calcChecksum(barr); 593579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 594579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (annotate) { 595579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson wordData.writeIndexAnnotation(out, ItemType.TYPE_CODE_ITEM, 596579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson "\nmethod code index:\n\n"); 597579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson getStatistics().writeAnnotation(out); 598579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.finishAnnotating(); 599579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 600579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 601579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return out; 602579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 603579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 604579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 605579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Generates and returns statistics for all the items in the file. 606579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 607579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the statistics 608579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 609579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Statistics getStatistics() { 610579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Statistics stats = new Statistics(); 611579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 612579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (Section s : sections) { 613579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson stats.addAll(s); 614579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 615579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 616579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return stats; 617579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 618579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 619579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 620579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Calculates the signature for the {@code .dex} file in the 621579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * given array, and modify the array to contain it. 622579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 623579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param bytes {@code non-null;} the bytes of the file 624579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 625579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static void calcSignature(byte[] bytes) { 626579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MessageDigest md; 627579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 628579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 629579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson md = MessageDigest.getInstance("SHA-1"); 630579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (NoSuchAlgorithmException ex) { 631579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException(ex); 632579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 633579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 634579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson md.update(bytes, 32, bytes.length - 32); 635579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 636579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 637579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int amt = md.digest(bytes, 12, 20); 638579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (amt != 20) { 639579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("unexpected digest write: " + amt + 640579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson " bytes"); 641579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 642579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (DigestException ex) { 643579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException(ex); 644579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 645579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 646579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 647579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 648579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Calculates the checksum for the {@code .dex} file in the 649579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * given array, and modify the array to contain it. 650579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 651579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param bytes {@code non-null;} the bytes of the file 652579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 653579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static void calcChecksum(byte[] bytes) { 654579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Adler32 a32 = new Adler32(); 655579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 656579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson a32.update(bytes, 12, bytes.length - 12); 657579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 658579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int sum = (int) a32.getValue(); 659579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 660579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson bytes[8] = (byte) sum; 661579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson bytes[9] = (byte) (sum >> 8); 662579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson bytes[10] = (byte) (sum >> 16); 663579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson bytes[11] = (byte) (sum >> 24); 664579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 665579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 666