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