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