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