1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.dex.file;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.DalvCode;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.DalvInsnList;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.LocalList;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.PositionList;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstMethodRef;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstType;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstUtf8;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.AnnotatedOutput;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ExceptionWithContext;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.PrintWriter;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class DebugInfoItem extends OffsettedItem {
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** the required alignment for instances of this class */
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int ALIGNMENT = 1;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final boolean ENABLE_ENCODER_SELF_CHECK = false;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** non-null; the code this item represents */
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final DalvCode code;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[] encoded;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final boolean isStatic;
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final CstMethodRef ref;
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public DebugInfoItem(DalvCode code, boolean isStatic, CstMethodRef ref) {
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // We don't know the write size yet.
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super (ALIGNMENT, -1);
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (code == null) {
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("code == null");
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.code = code;
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.isStatic = isStatic;
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.ref = ref;
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ItemType itemType() {
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return ItemType.TYPE_DEBUG_INFO_ITEM;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void addContents(DexFile file) {
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // No contents to add.
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void place0(Section addedTo, int offset) {
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Encode the data and note the size.
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            encoded = encode(addedTo.getFile(), null, null, null, false);
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setWriteSize(encoded.length);
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (RuntimeException ex) {
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw ExceptionWithContext.withContext(ex,
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "...while placing debug info for " + ref.toHuman());
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toHuman() {
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new RuntimeException("unsupported");
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes annotations for the elements of this list, as
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * zero-length. This is meant to be used for dumping this instance
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * directly after a code dump (with the real local list actually
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * existing elsewhere in the output).
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file non-null; the file to use for referencing other sections
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param out non-null; where to annotate to
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param prefix null-ok; prefix to attach to each line of output
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void annotateTo(DexFile file, AnnotatedOutput out, String prefix) {
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        encode(file, prefix, null, out, false);
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Does a human-friendly dump of this instance.
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param out non-null; where to dump
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param prefix non-null; prefix to attach to each line of output
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void debugPrint(PrintWriter out, String prefix) {
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        encode(null, prefix, out, null, false);
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void writeTo0(DexFile file, AnnotatedOutput out) {
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (out.annotates()) {
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Re-run the encoder to generate the annotations,
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * but write the bits from the original encode
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.annotate(offsetString() + " debug info");
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            encode(file, null, null, out, true);
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.write(encoded);
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Performs debug info encoding.
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file null-ok; file to refer to during encoding
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param prefix null-ok; prefix to attach to each line of output
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param debugPrint null-ok; if specified, an alternate output for
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * annotations
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param out null-ok; if specified, where annotations should go
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param consume whether to claim to have consumed output for
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <code>out</code>
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return non-null; the encoded array
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[] encode(DexFile file, String prefix, PrintWriter debugPrint,
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            AnnotatedOutput out, boolean consume) {
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] result = encode0(file, prefix, debugPrint, out, consume);
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ENABLE_ENCODER_SELF_CHECK && (file != null)) {
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                DebugInfoDecoder.validateEncode(result, file, ref, code,
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        isStatic);
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } catch (RuntimeException ex) {
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Reconvert, annotating to System.err.
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                encode0(file, "", new PrintWriter(System.err, true), null,
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        false);
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw ex;
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper for {@link #encode} to do most of the work.
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file null-ok; file to refer to during encoding
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param prefix null-ok; prefix to attach to each line of output
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param debugPrint null-ok; if specified, an alternate output for
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * annotations
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param out null-ok; if specified, where annotations should go
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param consume whether to claim to have consumed output for
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <code>out</code>
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return non-null; the encoded array
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[] encode0(DexFile file, String prefix, PrintWriter debugPrint,
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            AnnotatedOutput out, boolean consume) {
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        PositionList positions = code.getPositions();
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LocalList locals = code.getLocals();
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DalvInsnList insns = code.getInsns();
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int codeSize = insns.codeSize();
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int regSize = insns.getRegistersSize();
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DebugInfoEncoder encoder =
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            new DebugInfoEncoder(positions, locals,
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    file, codeSize, regSize, isStatic, ref);
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] result;
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((debugPrint == null) && (out == null)) {
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result = encoder.convert();
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result = encoder.convertAndAnnotate(prefix, debugPrint, out,
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    consume);
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
197