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