1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 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.dex.file.MixedItemSection.SortType; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Constant; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstBaseMethodRef; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstEnumRef; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstFieldRef; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstString; 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstType; 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstUtf8; 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.Type; 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.ByteArrayAnnotatedOutput; 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.ExceptionWithContext; 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.IOException; 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.OutputStream; 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.Writer; 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.security.DigestException; 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.security.MessageDigest; 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.security.NoSuchAlgorithmException; 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.zip.Adler32; 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Representation of an entire {@code .dex} (Dalvik EXecutable) 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * file, which itself consists of a set of Dalvik classes. 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class DexFile { 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} word data section */ 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final MixedItemSection wordData; 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code non-null;} type lists section. This is word data, but separating 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * it from {@link #wordData} helps break what would otherwise be a 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * circular dependency between the that and {@link #protoIds}. 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final MixedItemSection typeLists; 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code non-null;} map section. The map needs to be in a section by itself 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * for the self-reference mechanics to work in a reasonably 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * straightforward way. See {@link MapItem#addMap} for more detail. 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final MixedItemSection map; 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} string data section */ 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final MixedItemSection stringData; 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} string identifiers section */ 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final StringIdsSection stringIds; 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} type identifiers section */ 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final TypeIdsSection typeIds; 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} prototype identifiers section */ 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final ProtoIdsSection protoIds; 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} field identifiers section */ 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final FieldIdsSection fieldIds; 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} method identifiers section */ 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final MethodIdsSection methodIds; 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} class definitions section */ 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final ClassDefsSection classDefs; 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} class data section */ 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final MixedItemSection classData; 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} byte data section */ 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final MixedItemSection byteData; 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} file header */ 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final HeaderSection header; 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code non-null;} array of sections in the order they will appear in the 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * final output file 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final Section[] sections; 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= -1;} total file size or {@code -1} if unknown */ 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int fileSize; 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 40;} maximum width of the file dump */ 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int dumpWidth; 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. It is initially empty. 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public DexFile() { 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul header = new HeaderSection(this); 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul typeLists = new MixedItemSection(null, this, 4, SortType.NONE); 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul wordData = new MixedItemSection("word_data", this, 4, SortType.TYPE); 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul stringData = 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new MixedItemSection("string_data", this, 1, SortType.INSTANCE); 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul classData = new MixedItemSection(null, this, 1, SortType.NONE); 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul byteData = new MixedItemSection("byte_data", this, 1, SortType.TYPE); 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul stringIds = new StringIdsSection(this); 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul typeIds = new TypeIdsSection(this); 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protoIds = new ProtoIdsSection(this); 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul fieldIds = new FieldIdsSection(this); 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul methodIds = new MethodIdsSection(this); 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul classDefs = new ClassDefsSection(this); 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul map = new MixedItemSection("map", this, 4, SortType.NONE); 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * This is the list of sections in the order they appear in 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the final output. 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sections = new Section[] { 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul header, stringIds, typeIds, protoIds, fieldIds, methodIds, 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul classDefs, wordData, typeLists, stringData, byteData, 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul classData, map }; 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul fileSize = -1; 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul dumpWidth = 79; 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds a class to this instance. It is illegal to attempt to add more 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * than one class with the same name. 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param clazz {@code non-null;} the class to add 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void add(ClassDefItem clazz) { 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul classDefs.add(clazz); 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the class definition with the given name, if any. 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param name {@code non-null;} the class name to look for 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} the class with the given name, or {@code null} 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if there is no such class 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public ClassDefItem getClassOrNull(String name) { 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul try { 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type type = Type.internClassName(name); 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (ClassDefItem) classDefs.get(new CstType(type)); 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } catch (IllegalArgumentException ex) { 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Translate exception, per contract. 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writes the contents of this instance as either a binary or a 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * human-readable form, or both. 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code null-ok;} where to write to 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param humanOut {@code null-ok;} where to write human-oriented output to 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param verbose whether to be verbose when writing human-oriented output 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void writeTo(OutputStream out, Writer humanOut, boolean verbose) 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throws IOException { 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean annotate = (humanOut != null); 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ByteArrayAnnotatedOutput result = toDex0(annotate, verbose); 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (out != null) { 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.write(result.getArray()); 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotate) { 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.writeAnnotationsTo(humanOut); 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the contents of this instance as a {@code .dex} file, 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * in {@code byte[]} form. 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param humanOut {@code null-ok;} where to write human-oriented output to 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param verbose whether to be verbose when writing human-oriented output 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} a {@code .dex} file for this instance 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public byte[] toDex(Writer humanOut, boolean verbose) 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throws IOException { 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean annotate = (humanOut != null); 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ByteArrayAnnotatedOutput result = toDex0(annotate, verbose); 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotate) { 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.writeAnnotationsTo(humanOut); 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result.getArray(); 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Sets the maximum width of the human-oriented dump of the instance. 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param dumpWidth {@code >= 40;} the width 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void setDumpWidth(int dumpWidth) { 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (dumpWidth < 40) { 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("dumpWidth < 40"); 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.dumpWidth = dumpWidth; 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the total file size, if known. 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the {@link HeaderSection} to set itself up properly.</p> 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the total file size 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws RuntimeException thrown if the file size is not yet known 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ int getFileSize() { 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (fileSize < 0) { 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("file size not yet known"); 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return fileSize; 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the string data section. 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the various {@link Item} instances to add items to the 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance.</p> 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string data section 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ MixedItemSection getStringData() { 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return stringData; 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the word data section. 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the various {@link Item} instances to add items to the 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance.</p> 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the word data section 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ MixedItemSection getWordData() { 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return wordData; 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the type lists section. 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the various {@link Item} instances to add items to the 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance.</p> 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the word data section 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ MixedItemSection getTypeLists() { 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return typeLists; 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the map section. 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow the header section 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * to query it.</p> 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the map section 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ MixedItemSection getMap() { 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return map; 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the string identifiers section. 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the various {@link Item} instances to add items to the 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance.</p> 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string identifiers section 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ StringIdsSection getStringIds() { 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return stringIds; 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the class definitions section. 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the various {@link Item} instances to add items to the 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance.</p> 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the class definitions section 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ ClassDefsSection getClassDefs() { 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return classDefs; 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the class data section. 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the various {@link Item} instances to add items to the 316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance.</p> 317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the class data section 319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ MixedItemSection getClassData() { 321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return classData; 322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the type identifiers section. 326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the various {@link Item} instances to add items to the 329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance.</p> 330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the class identifiers section 332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ TypeIdsSection getTypeIds() { 334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return typeIds; 335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the prototype identifiers section. 339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the various {@link Item} instances to add items to the 342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance.</p> 343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the prototype identifiers section 345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ ProtoIdsSection getProtoIds() { 347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return protoIds; 348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the field identifiers section. 352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the various {@link Item} instances to add items to the 355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance.</p> 356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the field identifiers section 358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ FieldIdsSection getFieldIds() { 360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return fieldIds; 361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the method identifiers section. 365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the various {@link Item} instances to add items to the 368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance.</p> 369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the method identifiers section 371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ MethodIdsSection getMethodIds() { 373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return methodIds; 374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the byte data section. 378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow 380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the various {@link Item} instances to add items to the 381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance.</p> 382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the byte data section 384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ MixedItemSection getByteData() { 386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return byteData; 387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the first section of the file that is to be considered 391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * part of the data section. 392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow the header section 394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * to query it.</p> 395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the section 397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 398917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ Section getFirstDataSection() { 399917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return wordData; 400917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 401917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 402917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 403917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the last section of the file that is to be considered 404917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * part of the data section. 405917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 406917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <p>This is package-scope in order to allow the header section 407917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * to query it.</p> 408917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 409917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the section 410917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 411917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ Section getLastDataSection() { 412917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return map; 413917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 414917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 415917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 416917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Interns the given constant in the appropriate section of this 417917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance, or do nothing if the given constant isn't the sort 418917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * that should be interned. 419917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 420917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param cst {@code non-null;} constant to possibly intern 421917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 422917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ void internIfAppropriate(Constant cst) { 423917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (cst instanceof CstString) { 424917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul stringIds.intern((CstString) cst); 425917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (cst instanceof CstUtf8) { 426917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul stringIds.intern((CstUtf8) cst); 427917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (cst instanceof CstType) { 428917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul typeIds.intern((CstType) cst); 429917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (cst instanceof CstBaseMethodRef) { 430917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul methodIds.intern((CstBaseMethodRef) cst); 431917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (cst instanceof CstFieldRef) { 432917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul fieldIds.intern((CstFieldRef) cst); 433917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (cst instanceof CstEnumRef) { 434917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul fieldIds.intern(((CstEnumRef) cst).getFieldRef()); 435917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (cst == null) { 436917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("cst == null"); 437917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 438917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 439917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 440917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 441917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the {@link IndexedItem} corresponding to the given constant, 442917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if it is a constant that has such a correspondence, or return 443917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null} if it isn't such a constant. This will throw 444917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * an exception if the given constant <i>should</i> have been found 445917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * but wasn't. 446917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 447917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param cst {@code non-null;} the constant to look up 448917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} its corresponding item, if it has a corresponding 449917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * item, or {@code null} if it's not that sort of constant 450917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 451917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /*package*/ IndexedItem findItemOrNull(Constant cst) { 452917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul IndexedItem item; 453917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 454917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (cst instanceof CstString) { 455917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return stringIds.get(cst); 456917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (cst instanceof CstType) { 457917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return typeIds.get(cst); 458917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (cst instanceof CstBaseMethodRef) { 459917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return methodIds.get(cst); 460917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (cst instanceof CstFieldRef) { 461917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return fieldIds.get(cst); 462917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 463917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 464917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 465917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 466917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 467917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 468917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the contents of this instance as a {@code .dex} file, 469917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * in a {@link ByteArrayAnnotatedOutput} instance. 470917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 471917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param annotate whether or not to keep annotations 472917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param verbose if annotating, whether to be verbose 473917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} a {@code .dex} file for this instance 474917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 475917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private ByteArrayAnnotatedOutput toDex0(boolean annotate, 476917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean verbose) { 477917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 478917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * The following is ordered so that the prepare() calls which 479917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * add items happen before the calls to the sections that get 480917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * added to. 481917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 482917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 483917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul classDefs.prepare(); 484917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul classData.prepare(); 485917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul wordData.prepare(); 486917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul byteData.prepare(); 487917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul methodIds.prepare(); 488917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul fieldIds.prepare(); 489917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protoIds.prepare(); 490917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul typeLists.prepare(); 491917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul typeIds.prepare(); 492917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul stringIds.prepare(); 493917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul stringData.prepare(); 494917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul header.prepare(); 495917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 496917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Place the sections within the file. 497917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 498917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int count = sections.length; 499917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int offset = 0; 500917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 501917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < count; i++) { 502917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Section one = sections[i]; 503917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int placedAt = one.setFileOffset(offset); 504917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (placedAt < offset) { 505917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("bogus placement for section " + i); 506917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 507917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 508917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul try { 509917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (one == map) { 510917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 511917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Inform the map of all the sections, and add it 512917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * to the file. This can only be done after all 513917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the other items have been sorted and placed. 514917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 515917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul MapItem.addMap(sections, map); 516917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul map.prepare(); 517917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 518917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 519917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (one instanceof MixedItemSection) { 520917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 521917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Place the items of a MixedItemSection that just 522917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * got placed. 523917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 524917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ((MixedItemSection) one).placeItems(); 525917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 526917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 527917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul offset = placedAt + one.writeSize(); 528917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } catch (RuntimeException ex) { 529917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw ExceptionWithContext.withContext(ex, 530917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "...while writing section " + i); 531917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 532917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 533917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 534917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Write out all the sections. 535917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 536917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul fileSize = offset; 537917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul byte[] barr = new byte[fileSize]; 538917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(barr); 539917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 540917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotate) { 541917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.enableAnnotations(dumpWidth, verbose); 542917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 543917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 544917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < count; i++) { 545917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul try { 546917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Section one = sections[i]; 547917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int zeroCount = one.getFileOffset() - out.getCursor(); 548917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (zeroCount < 0) { 549917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new ExceptionWithContext("excess write of " + 550917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (-zeroCount)); 551917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 552917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.writeZeroes(one.getFileOffset() - out.getCursor()); 553917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul one.writeTo(out); 554917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } catch (RuntimeException ex) { 555917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ExceptionWithContext ec; 556917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (ex instanceof ExceptionWithContext) { 557917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ec = (ExceptionWithContext) ex; 558917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 559917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ec = new ExceptionWithContext(ex); 560917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 561917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ec.addContext("...while writing section " + i); 562917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw ec; 563917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 564917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 565917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 566917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (out.getCursor() != fileSize) { 567917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("foreshortened write"); 568917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 569917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 570917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Perform final bookkeeping. 571917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 572917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul calcSignature(barr); 573917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul calcChecksum(barr); 574917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 575917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (annotate) { 576917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul wordData.writeIndexAnnotation(out, ItemType.TYPE_CODE_ITEM, 577917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "\nmethod code index:\n\n"); 578917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul getStatistics().writeAnnotation(out); 579917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.finishAnnotating(); 580917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 581917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 582917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return out; 583917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 584917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 585917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 586917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Generates and returns statistics for all the items in the file. 587917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 588917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the statistics 589917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 590917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public Statistics getStatistics() { 591917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Statistics stats = new Statistics(); 592917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 593917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (Section s : sections) { 594917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul stats.addAll(s); 595917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 596917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 597917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return stats; 598917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 599917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 600917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 601917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Calculates the signature for the {@code .dex} file in the 602917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * given array, and modify the array to contain it. 603917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 604917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param bytes {@code non-null;} the bytes of the file 605917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 606917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static void calcSignature(byte[] bytes) { 607917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul MessageDigest md; 608917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 609917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul try { 610917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul md = MessageDigest.getInstance("SHA-1"); 611917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } catch (NoSuchAlgorithmException ex) { 612917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException(ex); 613917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 614917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 615917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul md.update(bytes, 32, bytes.length - 32); 616917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 617917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul try { 618917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int amt = md.digest(bytes, 12, 20); 619917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (amt != 20) { 620917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("unexpected digest write: " + amt + 621917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul " bytes"); 622917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 623917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } catch (DigestException ex) { 624917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException(ex); 625917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 626917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 627917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 628917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 629917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Calculates the checksum for the {@code .dex} file in the 630917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * given array, and modify the array to contain it. 631917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 632917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param bytes {@code non-null;} the bytes of the file 633917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 634917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static void calcChecksum(byte[] bytes) { 635917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Adler32 a32 = new Adler32(); 636917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 637917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul a32.update(bytes, 12, bytes.length - 12); 638917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 639917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sum = (int) a32.getValue(); 640917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 641917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul bytes[8] = (byte) sum; 642917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul bytes[9] = (byte) (sum >> 8); 643917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul bytes[10] = (byte) (sum >> 16); 644917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul bytes[11] = (byte) (sum >> 24); 645917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 646917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 647