DebugInfoDecoder.java revision de75089fb7216d19e9c22cce4dc62a49513477d3
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;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ExceptionWithContext;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ByteArrayInputStream;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.InputStream;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.List;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport static com.android.dx.dex.file.DebugInfoConstants.*;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * A decoder for the dex debug info state machine format.
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This code exists mostly as a reference implementation and test for
4199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * for the {@code DebugInfoEncoder}
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class DebugInfoDecoder {
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** encoded debug info */
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final byte[] encoded;
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** positions decoded */
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final ArrayList<PositionEntry> positions;
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** locals decoded */
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final ArrayList<LocalEntry> locals;
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** size of code block in code units */
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int codesize;
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** indexed by register, the last local variable live in a reg */
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final LocalEntry[] lastEntryForReg;
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** method descriptor of method this debug info is for */
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final Prototype desc;
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** true if method is static */
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final boolean isStatic;
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** dex file this debug info will be stored in */
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final DexFile file;
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * register size, in register units, of the register space
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * used by this method
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int regSize;
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** current decoding state: line number */
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int line = 1;
76de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** current decoding state: bytecode address */
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int address = 0;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** string index of the string "this" */
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int thisStringIdx;
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param encoded encoded debug info
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param codesize size of code block in code units
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param regSize register size, in register units, of the register space
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * used by this method
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param isStatic true if method is static
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ref method descriptor of method this debug info is for
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file dex file this debug info will be stored in
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DebugInfoDecoder(byte[] encoded, int codesize, int regSize,
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean isStatic, CstMethodRef ref, DexFile file) {
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (encoded == null) {
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("encoded == null");
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.encoded = encoded;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.isStatic = isStatic;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.desc = ref.getPrototype();
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.file = file;
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.regSize = regSize;
105de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        positions = new ArrayList<PositionEntry>();
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        locals = new ArrayList<LocalEntry>();
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.codesize = codesize;
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lastEntryForReg = new LocalEntry[regSize];
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int idx = -1;
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            idx = file.getStringIds().indexOf(new CstUtf8("this"));
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IllegalArgumentException ex) {
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Silently tolerate not finding "this". It just means that
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * no method has local variable info that looks like
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * a standard instance method.
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        thisStringIdx = idx;
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * An entry in the resulting postions table
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static private class PositionEntry {
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** bytecode address */
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int address;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** line number */
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int line;
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public PositionEntry(int address, int line) {
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.address = address;
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.line = line;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * An entry in the resulting locals table
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static private class LocalEntry {
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** address of event */
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int address;
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** {@code true} iff it's a local start */
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public boolean isStart;
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** register number */
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int reg;
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** index of name in strings table */
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int nameIndex;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** index of type in types table */
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int typeIndex;
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** index of type signature in strings table */
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int signatureIndex;
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public LocalEntry(int address, boolean isStart, int reg, int nameIndex,
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int typeIndex, int signatureIndex) {
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.address        = address;
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.isStart        = isStart;
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.reg            = reg;
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.nameIndex      = nameIndex;
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.typeIndex      = typeIndex;
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.signatureIndex = signatureIndex;
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public String toString() {
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return String.format("[%x %s v%d %04x %04x %04x]",
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    address, isStart ? "start" : "end", reg,
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    nameIndex, typeIndex, signatureIndex);
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the decoded positions list.
18399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Valid after calling {@code decode}.
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return positions list in ascending address order.
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public List<PositionEntry> getPositionList() {
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return positions;
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the decoded locals list, in ascending start-address order.
19399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Valid after calling {@code decode}.
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return locals list in ascending address order.
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public List<LocalEntry> getLocals() {
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return locals;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Decodes the debug info sequence.
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void decode() {
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            decode0();
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (Exception ex) {
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw ExceptionWithContext.withContext(ex,
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "...while decoding debug info");
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Reads a string index. String indicies are offset by 1, and a 0 value
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the stream (-1 as returned by this method) means "null"
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param bs
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     */
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int readStringIndex(InputStream bs) throws IOException {
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int offsetIndex = 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 {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ByteArrayInputStream bs = new ByteArrayInputStream(encoded);
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        line = readUnsignedLeb128(bs);
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int szParams = 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 (;;) {
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int opcode = bs.read();
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (opcode < 0) {
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new RuntimeException
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        ("Reached end of debug stream without "
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                + "encountering end marker");
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (opcode) {
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_START_LOCAL: {
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int reg = readUnsignedLeb128(bs);
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int nameIdx = readStringIndex(bs);
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int typeIdx = readStringIndex(bs);
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry le = new LocalEntry(
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            address, true, reg, nameIdx, typeIdx, 0);
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    locals.add(le);
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lastEntryForReg[reg] = le;
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_START_LOCAL_EXTENDED: {
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int reg = readUnsignedLeb128(bs);
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int nameIdx = readStringIndex(bs);
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int typeIdx = readStringIndex(bs);
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int sigIdx = readStringIndex(bs);
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry le = new LocalEntry(
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            address, true, reg, nameIdx, typeIdx, sigIdx);
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    locals.add(le);
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lastEntryForReg[reg] = le;
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_RESTART_LOCAL: {
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int reg = readUnsignedLeb128(bs);
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry prevle;
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry le;
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    try {
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        prevle = lastEntryForReg[reg];
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (prevle.isStart) {
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            throw new RuntimeException("nonsensical "
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    + "RESTART_LOCAL on live register v"
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    + reg);
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        le = new LocalEntry(address, true, reg,
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                prevle.nameIndex, prevle.typeIndex, 0);
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } catch (NullPointerException ex) {
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        throw new RuntimeException(
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                "Encountered RESTART_LOCAL on new v" + reg);
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    locals.add(le);
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lastEntryForReg[reg] = le;
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_END_LOCAL: {
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int reg = readUnsignedLeb128(bs);
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry prevle;
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry le;
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    try {
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        prevle = lastEntryForReg[reg];
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (!prevle.isStart) {
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            throw new RuntimeException("nonsensical "
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    + "END_LOCAL on dead register v" + reg);
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
356de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        le = new LocalEntry(address, false, reg,
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                prevle.nameIndex, prevle.typeIndex,
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                prevle.signatureIndex);
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } catch (NullPointerException ex) {
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        throw new RuntimeException(
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                "Encountered END_LOCAL on new v" + reg);
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    locals.add(le);
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lastEntryForReg[reg] = le;
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_END_SEQUENCE:
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // all done
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return;
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_ADVANCE_PC:
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    address += readUnsignedLeb128(bs);
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_ADVANCE_LINE:
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    line += readSignedLeb128(bs);
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_SET_PROLOGUE_END:
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //TODO do something with this.
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_SET_EPILOGUE_BEGIN:
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //TODO do something with this.
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case DBG_SET_FILE:
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //TODO do something with this.
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                default:
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (opcode < DBG_FIRST_SPECIAL) {
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        throw new RuntimeException(
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                "Invalid extended opcode encountered "
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        + opcode);
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int adjopcode = opcode - DBG_FIRST_SPECIAL;
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    address += adjopcode / DBG_LINE_RANGE;
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    positions.add(new PositionEntry(address, line));
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Validates an encoded debug info stream against data used to encode it,
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * throwing an exception if they do not match. Used to validate the
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * encoder.
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param info encoded debug info
41999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param file {@code non-null;} file to refer to during decoding
42099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param ref {@code non-null;} method whose info is being decoded
42199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param code {@code non-null;} original code object that was encoded
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param isStatic whether the method is static
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static void validateEncode(byte[] info, DexFile file,
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            CstMethodRef ref, DalvCode code, boolean isStatic) {
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        PositionList pl = code.getPositions();
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LocalList ll = code.getLocals();
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DalvInsnList insns = code.getInsns();
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int codeSize = insns.codeSize();
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int countRegisters = insns.getRegistersSize();
431de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            validateEncode0(info, codeSize, countRegisters,
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    isStatic, ref, file, pl, ll);
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (RuntimeException ex) {
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.println("instructions:");
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insns.debugPrint(System.err, "  ", true);
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.println("local list:");
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ll.debugPrint(System.err, "  ");
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw ExceptionWithContext.withContext(ex,
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "while processing " + ref.toHuman());
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
444de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static void validateEncode0(byte[] info, int codeSize,
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int countRegisters, boolean isStatic, CstMethodRef ref,
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DexFile file, PositionList pl, LocalList ll) {
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DebugInfoDecoder decoder
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                = new DebugInfoDecoder(info, codeSize, countRegisters,
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    isStatic, ref, file);
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        decoder.decode();
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Go through the decoded position entries, matching up
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * with original entries.
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        List<PositionEntry> decodedEntries = decoder.getPositionList();
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (decodedEntries.size() != pl.size()) {
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new RuntimeException(
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Decoded positions table not same size was "
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    + decodedEntries.size() + " expected " + pl.size());
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (PositionEntry entry : decodedEntries) {
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean found = false;
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = pl.size() - 1; i >= 0; i--) {
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                PositionList.Entry ple = pl.get(i);
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (entry.line == ple.getPosition().getLine()
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        && entry.address == ple.getAddress()) {
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    found = true;
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!found) {
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new RuntimeException ("Could not match position entry: "
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + entry.address + ", " + entry.line);
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Go through the original local list, in order, matching up
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * with decoded entries.
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        List<LocalEntry> decodedLocals = decoder.getLocals();
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int thisStringIdx = decoder.thisStringIdx;
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int decodedSz = decodedLocals.size();
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int paramBase = decoder.getParamBase();
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Preflight to fill in any parameters that were skipped in
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the prologue (including an implied "this") but then
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * identified by full signature.
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < decodedSz; i++) {
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalEntry entry = decodedLocals.get(i);
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int idx = entry.nameIndex;
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((idx < 0) || (idx == thisStringIdx)) {
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (int j = i + 1; j < decodedSz; j++) {
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LocalEntry e2 = decodedLocals.get(j);
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (e2.address != 0) {
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if ((entry.reg == e2.reg) && e2.isStart) {
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decodedLocals.set(i, e2);
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decodedLocals.remove(j);
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decodedSz--;
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
519de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int origSz = ll.size();
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int decodeAt = 0;
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean problem = false;
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < origSz; i++) {
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalList.Entry origEntry = ll.get(i);
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (origEntry.getDisposition()
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    == LocalList.Disposition.END_REPLACED) {
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * The encoded list doesn't represent replacements, so
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * ignore them for the sake of comparison.
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalEntry decodedEntry;
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            do {
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                decodedEntry = decodedLocals.get(decodeAt);
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (decodedEntry.nameIndex >= 0) {
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * A negative name index means this is an anonymous
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * parameter, and we shouldn't expect to see it in the
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * original list. So, skip it.
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                decodeAt++;
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } while (decodeAt < decodedSz);
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int decodedAddress = decodedEntry.address;
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (decodedEntry.reg != origEntry.getRegister()) {
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.err.println("local register mismatch at orig " + i +
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        " / decoded " + decodeAt);
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                problem = true;
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
559de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (decodedEntry.isStart != origEntry.isStart()) {
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.err.println("local start/end mismatch at orig " + i +
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        " / decoded " + decodeAt);
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                problem = true;
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * The secondary check here accounts for the fact that a
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * parameter might not be marked as starting at 0 in the
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * original list.
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
572de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro            if ((decodedAddress != origEntry.getAddress())
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    && !((decodedAddress == 0)
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            && (decodedEntry.reg >= paramBase))) {
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.err.println("local address mismatch at orig " + i +
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        " / decoded " + decodeAt);
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                problem = true;
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            decodeAt++;
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (problem) {
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.err.println("decoded locals:");
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (LocalEntry e : decodedLocals) {
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.err.println("  " + e);
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new RuntimeException("local table problem");
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Reads a DWARFv3-style signed LEB128 integer to the specified stream.
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * See DWARF v3 section 7.6. An invalid sequence produces an IOException.
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param bs stream to input from
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return read value
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException on invalid sequence in addition to
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * those caused by the InputStream
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static int readSignedLeb128(InputStream bs) throws IOException {
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int result = 0;
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int cur;
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = 0;
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int signBits = -1;
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        do {
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cur = bs.read();
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result |= (cur & 0x7f) << (count * 7);
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signBits <<= 7;
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            count++;
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } while (((cur & 0x80) == 0x80) && count < 5);
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((cur & 0x80) == 0x80) {
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IOException ("invalid LEB128 sequence");
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Sign extend if appropriate
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (((signBits >> 1) & result) != 0 ) {
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result |= signBits;
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Reads a DWARFv3-style unsigned LEB128 integer to the specified stream.
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * See DWARF v3 section 7.6. An invalid sequence produces an IOException.
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param bs stream to input from
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return read value, which should be treated as an unsigned value.
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException on invalid sequence in addition to
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * those caused by the InputStream
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static int readUnsignedLeb128(InputStream bs) throws IOException {
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int result = 0;
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int cur;
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = 0;
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        do {
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cur = bs.read();
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result |= (cur & 0x7f) << (count * 7);
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            count++;
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } while (((cur & 0x80) == 0x80) && count < 5);
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((cur & 0x80) == 0x80) {
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IOException ("invalid LEB128 sequence");
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
654