DexDebugInfo.cpp revision 1a65052468068a4e9a859d185860510aa1d8cfd4
11a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 21a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Copyright (C) 2011 The Android Open Source Project 31a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 41a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Licensed under the Apache License, Version 2.0 (the "License"); 51a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * you may not use this file except in compliance with the License. 61a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * You may obtain a copy of the License at 71a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 81a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * http://www.apache.org/licenses/LICENSE-2.0 91a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Unless required by applicable law or agreed to in writing, software 111a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * distributed under the License is distributed on an "AS IS" BASIS, 121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * See the License for the specific language governing permissions and 141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * limitations under the License. 151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Handling of method debug info in a .dex file. 191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include "DexDebugInfo.h" 221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include "DexProto.h" 231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include "Leb128.h" 241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include <stdlib.h> 261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik#include <string.h> 271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Decode the arguments in a method signature, which looks something 301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * like "(ID[Ljava/lang/String;)V". 311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * 321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Returns the type signature letter for the next argument, or ')' if 331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * there are no more args. Advances "pSig" to point to the character 341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * after the one returned. 351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic char decodeSignature(const char** pSig) 371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* sig = *pSig; 391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (*sig == '(') 411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik sig++; 421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 431a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (*sig == 'L') { 441a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* object ref */ 451a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik while (*++sig != ';') 461a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ; 471a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik *pSig = sig+1; 481a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return 'L'; 491a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 501a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (*sig == '[') { 511a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* array; advance past array type */ 521a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik while (*++sig == '[') 531a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ; 541a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (*sig == 'L') { 551a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik while (*++sig != ';') 561a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ; 571a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 581a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik *pSig = sig+1; 591a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return '['; 601a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 611a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (*sig == '\0') 621a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return *sig; /* don't advance further */ 631a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 641a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik *pSig = sig+1; 651a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return *sig; 661a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 671a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 681a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 691a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * returns the length of a type string, given the start of the 701a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * type string. Used for the case where the debug info format 711a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * references types that are inside a method type signature. 721a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 731a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic int typeLength(const char *type) { 741a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik // Assumes any leading '(' has already been gobbled 751a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char *end = type; 761a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik decodeSignature(&end); 771a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return end - type; 781a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 791a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 801a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 811a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Reads a string index as encoded for the debug info format, 821a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * returning a string pointer or NULL as appropriate. 831a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 841a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic const char* readStringIdx(const DexFile* pDexFile, 851a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1** pStream) { 861a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 stringIdx = readUnsignedLeb128(pStream); 871a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 881a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik // Remember, encoded string indicies have 1 added to them. 891a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (stringIdx == 0) { 901a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return NULL; 911a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 921a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return dexStringById(pDexFile, stringIdx - 1); 931a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 941a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 951a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 961a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 971a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Reads a type index as encoded for the debug info format, returning 981a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * a string pointer for its descriptor or NULL as appropriate. 991a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 1001a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic const char* readTypeIdx(const DexFile* pDexFile, 1011a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1** pStream) { 1021a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 typeIdx = readUnsignedLeb128(pStream); 1031a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1041a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik // Remember, encoded type indicies have 1 added to them. 1051a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (typeIdx == 0) { 1061a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return NULL; 1071a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 1081a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return dexStringByTypeIdx(pDexFile, typeIdx - 1); 1091a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 1111a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstruct LocalInfo { 1131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char *name; 1141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char *descriptor; 1151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char *signature; 1161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u2 startAddress; 1171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik bool live; 1181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik}; 1191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic void emitLocalCbIfLive(void *cnxt, int reg, u4 endAddress, 1211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik LocalInfo *localInReg, DexDebugNewLocalCb localCb) 1221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 1231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (localCb != NULL && localInReg[reg].live) { 1241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localCb(cnxt, reg, localInReg[reg].startAddress, endAddress, 1251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].name, 1261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].descriptor, 1271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].signature == NULL 1281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ? "" : localInReg[reg].signature ); 1291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 1311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic void invalidStream(const char* classDescriptor, const DexProto* proto) { 1331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik IF_ALOGE() { 1341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik char* methodDescriptor = dexProtoCopyMethodDescriptor(proto); 1351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGE("Invalid debug info stream. class %s; proto %s", 1361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik classDescriptor, methodDescriptor); 1371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik free(methodDescriptor); 1381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 1401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic void dexDecodeDebugInfo0( 1421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexFile* pDexFile, 1431a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexCode* pCode, 1441a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* classDescriptor, 1451a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 protoIdx, 1461a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 accessFlags, 1471a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb, 1481a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik void* cnxt, 1491a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1* stream, 1501a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik LocalInfo* localInReg) 1511a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 1521a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexProto proto = { pDexFile, protoIdx }; 1531a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 insnsSize = pCode->insnsSize; 1541a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 line = readUnsignedLeb128(&stream); 1551a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 parametersSize = readUnsignedLeb128(&stream); 1561a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u2 argReg = pCode->registersSize - pCode->insSize; 1571a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 address = 0; 1581a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1591a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if ((accessFlags & ACC_STATIC) == 0) { 1601a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 1611a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * The code is an instance method, which means that there is 1621a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * an initial this parameter. Also, the proto list should 1631a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * contain exactly one fewer argument word than the insSize 1641a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * indicates. 1651a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 1661a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik assert(pCode->insSize == (dexProtoComputeArgsSize(&proto) + 1)); 1671a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[argReg].name = "this"; 1681a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[argReg].descriptor = classDescriptor; 1691a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[argReg].startAddress = 0; 1701a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[argReg].live = true; 1711a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik argReg++; 1721a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 1731a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik assert(pCode->insSize == dexProtoComputeArgsSize(&proto)); 1741a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1751a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1761a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexParameterIterator iterator; 1771a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik dexParameterIteratorInit(&iterator, &proto); 1781a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1791a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik while (parametersSize-- != 0) { 1801a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* descriptor = dexParameterIteratorNextDescriptor(&iterator); 1811a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char *name; 1821a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int reg; 1831a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1841a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if ((argReg >= pCode->registersSize) || (descriptor == NULL)) { 1851a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik invalidStream(classDescriptor, &proto); 1861a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 1871a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1881a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1891a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik name = readStringIdx(pDexFile, &stream); 1901a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik reg = argReg; 1911a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1921a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik switch (descriptor[0]) { 1931a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'D': 1941a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'J': 1951a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik argReg += 2; 1961a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 1971a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik default: 1981a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik argReg += 1; 1991a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 2001a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2011a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2021a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (name != NULL) { 2031a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].name = name; 2041a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].descriptor = descriptor; 2051a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].signature = NULL; 2061a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].startAddress = address; 2071a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].live = true; 2081a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2091a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2111a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik for (;;) { 2121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u1 opcode = *stream++; 2131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u2 reg; 2141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik switch (opcode) { 2161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_END_SEQUENCE: 2171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 2181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_ADVANCE_PC: 2201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik address += readUnsignedLeb128(&stream); 2211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 2221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_ADVANCE_LINE: 2241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik line += readSignedLeb128(&stream); 2251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 2261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_START_LOCAL: 2281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_START_LOCAL_EXTENDED: 2291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik reg = readUnsignedLeb128(&stream); 2301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (reg > pCode->registersSize) { 2311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik invalidStream(classDescriptor, &proto); 2321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 2331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik // Emit what was previously there, if anything 2361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik emitLocalCbIfLive(cnxt, reg, address, 2371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg, localCb); 2381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].name = readStringIdx(pDexFile, &stream); 2401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].descriptor = readTypeIdx(pDexFile, &stream); 2411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (opcode == DBG_START_LOCAL_EXTENDED) { 2421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].signature 2431a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik = readStringIdx(pDexFile, &stream); 2441a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 2451a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].signature = NULL; 2461a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2471a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].startAddress = address; 2481a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].live = true; 2491a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 2501a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2511a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_END_LOCAL: 2521a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik reg = readUnsignedLeb128(&stream); 2531a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (reg > pCode->registersSize) { 2541a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik invalidStream(classDescriptor, &proto); 2551a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 2561a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2571a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2581a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik emitLocalCbIfLive (cnxt, reg, address, localInReg, localCb); 2591a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].live = false; 2601a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 2611a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2621a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_RESTART_LOCAL: 2631a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik reg = readUnsignedLeb128(&stream); 2641a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (reg > pCode->registersSize) { 2651a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik invalidStream(classDescriptor, &proto); 2661a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 2671a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2681a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2691a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (localInReg[reg].name == NULL 2701a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik || localInReg[reg].descriptor == NULL) { 2711a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik invalidStream(classDescriptor, &proto); 2721a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 2731a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2741a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2751a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 2761a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * If the register is live, the "restart" is superfluous, 2771a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * and we don't want to mess with the existing start address. 2781a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 2791a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (!localInReg[reg].live) { 2801a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].startAddress = address; 2811a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].live = true; 2821a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2831a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 2841a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2851a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_SET_PROLOGUE_END: 2861a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_SET_EPILOGUE_BEGIN: 2871a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_SET_FILE: 2881a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 2891a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2901a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik default: { 2911a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int adjopcode = opcode - DBG_FIRST_SPECIAL; 2921a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2931a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik address += adjopcode / DBG_LINE_RANGE; 2941a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE); 2951a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2961a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (posCb != NULL) { 2971a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int done; 2981a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik done = posCb(cnxt, address, line); 2991a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3001a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (done) { 3011a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik // early exit 3021a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 3031a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3041a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3051a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 3061a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3071a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3081a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3091a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 3101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3111a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik// TODO optimize localCb == NULL case 3121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikvoid dexDecodeDebugInfo( 3131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexFile* pDexFile, 3141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexCode* pCode, 3151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* classDescriptor, 3161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 protoIdx, 3171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 accessFlags, 3181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb, 3191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik void* cnxt) 3201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 3211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1* stream = dexGetDebugInfoStream(pDexFile, pCode); 3221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik LocalInfo localInReg[pCode->registersSize]; 3231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik memset(localInReg, 0, sizeof(LocalInfo) * pCode->registersSize); 3251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (stream != NULL) { 3271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik dexDecodeDebugInfo0(pDexFile, pCode, classDescriptor, protoIdx, accessFlags, 3281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik posCb, localCb, cnxt, stream, localInReg); 3291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 3311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik for (int reg = 0; reg < pCode->registersSize; reg++) { 3321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik emitLocalCbIfLive(cnxt, reg, pCode->insnsSize, localInReg, localCb); 3331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 3341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 335