DebugInfoDecoder.java revision bd3dba4346223593ac6033a3d2a7d8ec6f20738b
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.CstUtf8;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Prototype;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.StdTypeList;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
28bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.util.ByteArrayByteInput;
29bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.util.ByteInput;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ExceptionWithContext;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
32081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilsonimport com.android.dx.util.Leb128Utils;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.List;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport static com.android.dx.dex.file.DebugInfoConstants.*;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * A decoder for the dex debug info state machine format.
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This code exists mostly as a reference implementation and test for
4299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * for the {@code DebugInfoEncoder}
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class DebugInfoDecoder {
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** encoded debug info */
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final byte[] encoded;
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** positions decoded */
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final ArrayList<PositionEntry> positions;
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** locals decoded */
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final ArrayList<LocalEntry> locals;
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** size of code block in code units */
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int codesize;
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** indexed by register, the last local variable live in a reg */
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final LocalEntry[] lastEntryForReg;
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** method descriptor of method this debug info is for */
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final Prototype desc;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** true if method is static */
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final boolean isStatic;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** dex file this debug info will be stored in */
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final DexFile file;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * register size, in register units, of the register space
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * used by this method
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int regSize;
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** current decoding state: line number */
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int line = 1;
77de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** current decoding state: bytecode address */
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int address = 0;
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** string index of the string "this" */
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int thisStringIdx;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param encoded encoded debug info
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param codesize size of code block in code units
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param regSize register size, in register units, of the register space
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * used by this method
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param isStatic true if method is static
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ref method descriptor of method this debug info is for
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file dex file this debug info will be stored in
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DebugInfoDecoder(byte[] encoded, int codesize, int regSize,
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean isStatic, CstMethodRef ref, DexFile file) {
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (encoded == null) {
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("encoded == null");
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.encoded = encoded;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.isStatic = isStatic;
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.desc = ref.getPrototype();
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.file = file;
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.regSize = regSize;
106de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        positions = new ArrayList<PositionEntry>();
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        locals = new ArrayList<LocalEntry>();
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.codesize = codesize;
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lastEntryForReg = new LocalEntry[regSize];
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int idx = -1;
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            idx = file.getStringIds().indexOf(new CstUtf8("this"));
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IllegalArgumentException ex) {
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Silently tolerate not finding "this". It just means that
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * no method has local variable info that looks like
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * a standard instance method.
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        thisStringIdx = idx;
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * An entry in the resulting postions table
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static private class PositionEntry {
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** bytecode address */
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int address;
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** line number */
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int line;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public PositionEntry(int address, int line) {
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.address = address;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.line = line;
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * An entry in the resulting locals table
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static private class LocalEntry {
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** address of event */
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int address;
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** {@code true} iff it's a local start */
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public boolean isStart;
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** register number */
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int reg;
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** index of name in strings table */
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int nameIndex;
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** index of type in types table */
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int typeIndex;
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** index of type signature in strings table */
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int signatureIndex;
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public LocalEntry(int address, boolean isStart, int reg, int nameIndex,
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int typeIndex, int signatureIndex) {
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.address        = address;
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.isStart        = isStart;
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.reg            = reg;
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.nameIndex      = nameIndex;
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.typeIndex      = typeIndex;
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.signatureIndex = signatureIndex;
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public String toString() {
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return String.format("[%x %s v%d %04x %04x %04x]",
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    address, isStart ? "start" : "end", reg,
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    nameIndex, typeIndex, signatureIndex);
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the decoded positions list.
18499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Valid after calling {@code decode}.
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return positions list in ascending address order.
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public List<PositionEntry> getPositionList() {
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return positions;
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the decoded locals list, in ascending start-address order.
19499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Valid after calling {@code decode}.
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return locals list in ascending address order.
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public List<LocalEntry> getLocals() {
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return locals;
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Decodes the debug info sequence.
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void decode() {
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            decode0();
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (Exception ex) {
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw ExceptionWithContext.withContext(ex,
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "...while decoding debug info");
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Reads a string index. String indicies are offset by 1, and a 0 value
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the stream (-1 as returned by this method) means "null"
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return index into file's string ids table, -1 means null
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
221bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson    private int readStringIndex(ByteInput bs) throws IOException {
222081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson        int offsetIndex = Leb128Utils.readUnsignedLeb128(bs);
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return offsetIndex - 1;
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the register that begins the method's parameter range (including
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the 'this' parameter for non-static methods). The range continues until
23099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code regSize}
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return register as noted above.
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int getParamBase() {
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return regSize
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                - desc.getParameterTypes().getWordCount() - (isStatic? 0 : 1);
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void decode0() throws IOException {
240bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson        ByteInput bs = new ByteArrayByteInput(encoded);
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
242081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson        line = Leb128Utils.readUnsignedLeb128(bs);
243081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson        int szParams = Leb128Utils.readUnsignedLeb128(bs);
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StdTypeList params = desc.getParameterTypes();
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int curReg = getParamBase();
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (szParams != params.size()) {
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new RuntimeException(
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Mismatch between parameters_size and prototype");
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
251de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!isStatic) {
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Start off with implicit 'this' entry
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalEntry thisEntry =
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                new LocalEntry(0, true, curReg, thisStringIdx, 0, 0);
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            locals.add(thisEntry);
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lastEntryForReg[curReg] = thisEntry;
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            curReg++;
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < szParams; i++) {
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Type paramType = params.getType(i);
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalEntry le;
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int nameIdx = readStringIndex(bs);
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nameIdx == -1) {
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Unnamed parameter; often but not always filled in by an
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * extended start op after the prologue
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                le = new LocalEntry(0, true, curReg, -1, 0, 0);
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // TODO: Final 0 should be idx of paramType.getDescriptor().
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                le = new LocalEntry(0, true, curReg, nameIdx, 0, 0);
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            locals.add(le);
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lastEntryForReg[curReg] = le;
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            curReg += paramType.getCategory();
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (;;) {
284081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson            int opcode = bs.readByte() & 0xff;
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (opcode) {
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_START_LOCAL: {
288081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson                    int reg = Leb128Utils.readUnsignedLeb128(bs);
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int nameIdx = readStringIndex(bs);
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int typeIdx = readStringIndex(bs);
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry le = new LocalEntry(
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            address, true, reg, nameIdx, typeIdx, 0);
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    locals.add(le);
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lastEntryForReg[reg] = le;
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_START_LOCAL_EXTENDED: {
300081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson                    int reg = Leb128Utils.readUnsignedLeb128(bs);
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int nameIdx = readStringIndex(bs);
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int typeIdx = readStringIndex(bs);
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int sigIdx = readStringIndex(bs);
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry le = new LocalEntry(
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            address, true, reg, nameIdx, typeIdx, sigIdx);
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    locals.add(le);
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lastEntryForReg[reg] = le;
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_RESTART_LOCAL: {
313081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson                    int reg = Leb128Utils.readUnsignedLeb128(bs);
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry prevle;
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry le;
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    try {
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        prevle = lastEntryForReg[reg];
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (prevle.isStart) {
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            throw new RuntimeException("nonsensical "
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    + "RESTART_LOCAL on live register v"
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    + reg);
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        le = new LocalEntry(address, true, reg,
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                prevle.nameIndex, prevle.typeIndex, 0);
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } catch (NullPointerException ex) {
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        throw new RuntimeException(
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                "Encountered RESTART_LOCAL on new v" + reg);
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    locals.add(le);
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lastEntryForReg[reg] = le;
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_END_LOCAL: {
339081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson                    int reg = Leb128Utils.readUnsignedLeb128(bs);
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry prevle;
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry le;
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    try {
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        prevle = lastEntryForReg[reg];
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (!prevle.isStart) {
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            throw new RuntimeException("nonsensical "
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    + "END_LOCAL on dead register v" + reg);
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
350de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        le = new LocalEntry(address, false, reg,
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                prevle.nameIndex, prevle.typeIndex,
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                prevle.signatureIndex);
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } catch (NullPointerException ex) {
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        throw new RuntimeException(
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                "Encountered END_LOCAL on new v" + reg);
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    locals.add(le);
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lastEntryForReg[reg] = le;
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_END_SEQUENCE:
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // all done
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return;
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_ADVANCE_PC:
369081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson                    address += Leb128Utils.readUnsignedLeb128(bs);
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_ADVANCE_LINE:
373081c7142b29ccd6e1744b26e097b6a4d7c12f2bdJesse Wilson                    line += Leb128Utils.readSignedLeb128(bs);
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_SET_PROLOGUE_END:
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //TODO do something with this.
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_SET_EPILOGUE_BEGIN:
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //TODO do something with this.
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_SET_FILE:
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //TODO do something with this.
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                default:
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (opcode < DBG_FIRST_SPECIAL) {
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        throw new RuntimeException(
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                "Invalid extended opcode encountered "
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        + opcode);
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int adjopcode = opcode - DBG_FIRST_SPECIAL;
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    address += adjopcode / DBG_LINE_RANGE;
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    positions.add(new PositionEntry(address, line));
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Validates an encoded debug info stream against data used to encode it,
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * throwing an exception if they do not match. Used to validate the
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * encoder.
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param info encoded debug info
41399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param file {@code non-null;} file to refer to during decoding
41499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param ref {@code non-null;} method whose info is being decoded
41599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param code {@code non-null;} original code object that was encoded
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param isStatic whether the method is static
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static void validateEncode(byte[] info, DexFile file,
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            CstMethodRef ref, DalvCode code, boolean isStatic) {
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        PositionList pl = code.getPositions();
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LocalList ll = code.getLocals();
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DalvInsnList insns = code.getInsns();
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int codeSize = insns.codeSize();
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int countRegisters = insns.getRegistersSize();
425de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            validateEncode0(info, codeSize, countRegisters,
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    isStatic, ref, file, pl, ll);
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (RuntimeException ex) {
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.println("instructions:");
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insns.debugPrint(System.err, "  ", true);
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.println("local list:");
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ll.debugPrint(System.err, "  ");
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw ExceptionWithContext.withContext(ex,
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "while processing " + ref.toHuman());
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
438de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static void validateEncode0(byte[] info, int codeSize,
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int countRegisters, boolean isStatic, CstMethodRef ref,
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DexFile file, PositionList pl, LocalList ll) {
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DebugInfoDecoder decoder
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                = new DebugInfoDecoder(info, codeSize, countRegisters,
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    isStatic, ref, file);
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        decoder.decode();
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Go through the decoded position entries, matching up
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * with original entries.
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        List<PositionEntry> decodedEntries = decoder.getPositionList();
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (decodedEntries.size() != pl.size()) {
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new RuntimeException(
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Decoded positions table not same size was "
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    + decodedEntries.size() + " expected " + pl.size());
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (PositionEntry entry : decodedEntries) {
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean found = false;
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = pl.size() - 1; i >= 0; i--) {
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                PositionList.Entry ple = pl.get(i);
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (entry.line == ple.getPosition().getLine()
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        && entry.address == ple.getAddress()) {
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    found = true;
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!found) {
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new RuntimeException ("Could not match position entry: "
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + entry.address + ", " + entry.line);
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Go through the original local list, in order, matching up
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * with decoded entries.
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        List<LocalEntry> decodedLocals = decoder.getLocals();
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int thisStringIdx = decoder.thisStringIdx;
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int decodedSz = decodedLocals.size();
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int paramBase = decoder.getParamBase();
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Preflight to fill in any parameters that were skipped in
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the prologue (including an implied "this") but then
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * identified by full signature.
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < decodedSz; i++) {
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalEntry entry = decodedLocals.get(i);
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int idx = entry.nameIndex;
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((idx < 0) || (idx == thisStringIdx)) {
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (int j = i + 1; j < decodedSz; j++) {
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry e2 = decodedLocals.get(j);
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (e2.address != 0) {
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if ((entry.reg == e2.reg) && e2.isStart) {
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decodedLocals.set(i, e2);
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decodedLocals.remove(j);
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decodedSz--;
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
513de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int origSz = ll.size();
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int decodeAt = 0;
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean problem = false;
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < origSz; i++) {
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalList.Entry origEntry = ll.get(i);
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (origEntry.getDisposition()
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    == LocalList.Disposition.END_REPLACED) {
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * The encoded list doesn't represent replacements, so
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * ignore them for the sake of comparison.
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalEntry decodedEntry;
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            do {
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                decodedEntry = decodedLocals.get(decodeAt);
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (decodedEntry.nameIndex >= 0) {
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * A negative name index means this is an anonymous
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * parameter, and we shouldn't expect to see it in the
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * original list. So, skip it.
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                decodeAt++;
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } while (decodeAt < decodedSz);
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int decodedAddress = decodedEntry.address;
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (decodedEntry.reg != origEntry.getRegister()) {
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.err.println("local register mismatch at orig " + i +
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        " / decoded " + decodeAt);
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                problem = true;
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
553de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (decodedEntry.isStart != origEntry.isStart()) {
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.err.println("local start/end mismatch at orig " + i +
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        " / decoded " + decodeAt);
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                problem = true;
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * The secondary check here accounts for the fact that a
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * parameter might not be marked as starting at 0 in the
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * original list.
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
566de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro            if ((decodedAddress != origEntry.getAddress())
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    && !((decodedAddress == 0)
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            && (decodedEntry.reg >= paramBase))) {
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.err.println("local address mismatch at orig " + i +
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        " / decoded " + decodeAt);
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                problem = true;
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            decodeAt++;
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (problem) {
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.println("decoded locals:");
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (LocalEntry e : decodedLocals) {
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.err.println("  " + e);
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new RuntimeException("local table problem");
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
587