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 * Reads a string index as encoded for the debug info format, 301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * returning a string pointer or NULL as appropriate. 311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic const char* readStringIdx(const DexFile* pDexFile, 331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1** pStream) { 341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 stringIdx = readUnsignedLeb128(pStream); 351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik // Remember, encoded string indicies have 1 added to them. 371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (stringIdx == 0) { 381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return NULL; 391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return dexStringById(pDexFile, stringIdx - 1); 411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 431a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 441a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik/* 451a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * Reads a type index as encoded for the debug info format, returning 461a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * a string pointer for its descriptor or NULL as appropriate. 471a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 481a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic const char* readTypeIdx(const DexFile* pDexFile, 491a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1** pStream) { 501a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 typeIdx = readUnsignedLeb128(pStream); 511a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 521a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik // Remember, encoded type indicies have 1 added to them. 531a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (typeIdx == 0) { 541a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return NULL; 551a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 561a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return dexStringByTypeIdx(pDexFile, typeIdx - 1); 571a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 581a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 591a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 601a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstruct LocalInfo { 611a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char *name; 621a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char *descriptor; 631a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char *signature; 641a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u2 startAddress; 651a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik bool live; 661a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik}; 671a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 681a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic void emitLocalCbIfLive(void *cnxt, int reg, u4 endAddress, 691a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik LocalInfo *localInReg, DexDebugNewLocalCb localCb) 701a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 711a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (localCb != NULL && localInReg[reg].live) { 721a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localCb(cnxt, reg, localInReg[reg].startAddress, endAddress, 731a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].name, 741a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].descriptor, 751a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].signature == NULL 761a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ? "" : localInReg[reg].signature ); 771a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 781a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 791a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 801a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic void invalidStream(const char* classDescriptor, const DexProto* proto) { 811a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik IF_ALOGE() { 821a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik char* methodDescriptor = dexProtoCopyMethodDescriptor(proto); 831a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik ALOGE("Invalid debug info stream. class %s; proto %s", 841a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik classDescriptor, methodDescriptor); 851a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik free(methodDescriptor); 861a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 871a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 881a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 891a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikstatic void dexDecodeDebugInfo0( 901a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexFile* pDexFile, 911a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexCode* pCode, 921a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* classDescriptor, 931a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 protoIdx, 941a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 accessFlags, 951a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb, 961a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik void* cnxt, 971a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1* stream, 981a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik LocalInfo* localInReg) 991a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 1001a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexProto proto = { pDexFile, protoIdx }; 1011a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 line = readUnsignedLeb128(&stream); 1021a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 parametersSize = readUnsignedLeb128(&stream); 1031a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u2 argReg = pCode->registersSize - pCode->insSize; 1041a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 address = 0; 1051a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1061a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if ((accessFlags & ACC_STATIC) == 0) { 1071a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 1081a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * The code is an instance method, which means that there is 1091a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * an initial this parameter. Also, the proto list should 1101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * contain exactly one fewer argument word than the insSize 1111a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * indicates. 1121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 1131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik assert(pCode->insSize == (dexProtoComputeArgsSize(&proto) + 1)); 1141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[argReg].name = "this"; 1151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[argReg].descriptor = classDescriptor; 1161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[argReg].startAddress = 0; 1171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[argReg].live = true; 1181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik argReg++; 1191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 1201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik assert(pCode->insSize == dexProtoComputeArgsSize(&proto)); 1211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexParameterIterator iterator; 1241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik dexParameterIteratorInit(&iterator, &proto); 1251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik while (parametersSize-- != 0) { 1271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* descriptor = dexParameterIteratorNextDescriptor(&iterator); 1281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char *name; 1291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int reg; 1301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if ((argReg >= pCode->registersSize) || (descriptor == NULL)) { 1321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik invalidStream(classDescriptor, &proto); 1331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 1341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik name = readStringIdx(pDexFile, &stream); 1371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik reg = argReg; 1381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik switch (descriptor[0]) { 1401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'D': 1411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case 'J': 1421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik argReg += 2; 1431a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 1441a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik default: 1451a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik argReg += 1; 1461a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 1471a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1481a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1491a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (name != NULL) { 1501a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].name = name; 1511a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].descriptor = descriptor; 1521a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].signature = NULL; 1531a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].startAddress = address; 1541a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].live = true; 1551a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1561a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1571a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1581a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik for (;;) { 1591a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u1 opcode = *stream++; 1601a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u2 reg; 1611a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1621a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik switch (opcode) { 1631a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_END_SEQUENCE: 1641a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 1651a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1661a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_ADVANCE_PC: 1671a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik address += readUnsignedLeb128(&stream); 1681a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 1691a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1701a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_ADVANCE_LINE: 1711a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik line += readSignedLeb128(&stream); 1721a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 1731a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1741a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_START_LOCAL: 1751a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_START_LOCAL_EXTENDED: 1761a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik reg = readUnsignedLeb128(&stream); 1771a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (reg > pCode->registersSize) { 1781a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik invalidStream(classDescriptor, &proto); 1791a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 1801a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1811a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1821a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik // Emit what was previously there, if anything 1831a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik emitLocalCbIfLive(cnxt, reg, address, 1841a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg, localCb); 1851a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1861a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].name = readStringIdx(pDexFile, &stream); 1871a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].descriptor = readTypeIdx(pDexFile, &stream); 1881a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (opcode == DBG_START_LOCAL_EXTENDED) { 1891a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].signature 1901a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik = readStringIdx(pDexFile, &stream); 1911a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } else { 1921a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].signature = NULL; 1931a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 1941a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].startAddress = address; 1951a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].live = true; 1961a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 1971a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 1981a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_END_LOCAL: 1991a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik reg = readUnsignedLeb128(&stream); 2001a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (reg > pCode->registersSize) { 2011a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik invalidStream(classDescriptor, &proto); 2021a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 2031a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2041a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2051a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik emitLocalCbIfLive (cnxt, reg, address, localInReg, localCb); 2061a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].live = false; 2071a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 2081a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2091a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_RESTART_LOCAL: 2101a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik reg = readUnsignedLeb128(&stream); 2111a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (reg > pCode->registersSize) { 2121a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik invalidStream(classDescriptor, &proto); 2131a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 2141a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2151a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2161a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (localInReg[reg].name == NULL 2171a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik || localInReg[reg].descriptor == NULL) { 2181a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik invalidStream(classDescriptor, &proto); 2191a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 2201a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2211a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2221a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik /* 2231a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * If the register is live, the "restart" is superfluous, 2241a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik * and we don't want to mess with the existing start address. 2251a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik */ 2261a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (!localInReg[reg].live) { 2271a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].startAddress = address; 2281a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik localInReg[reg].live = true; 2291a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2301a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 2311a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2321a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_SET_PROLOGUE_END: 2331a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_SET_EPILOGUE_BEGIN: 2341a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik case DBG_SET_FILE: 2351a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 2361a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2371a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik default: { 2381a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int adjopcode = opcode - DBG_FIRST_SPECIAL; 2391a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2401a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik address += adjopcode / DBG_LINE_RANGE; 2411a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE); 2421a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2431a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (posCb != NULL) { 2441a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik int done; 2451a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik done = posCb(cnxt, address, line); 2461a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2471a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (done) { 2481a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik // early exit 2491a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik return; 2501a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2511a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2521a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik break; 2531a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2541a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2551a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2561a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 2571a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2581a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik// TODO optimize localCb == NULL case 2591a65052468068a4e9a859d185860510aa1d8cfd4Aart Bikvoid dexDecodeDebugInfo( 2601a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexFile* pDexFile, 2611a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const DexCode* pCode, 2621a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const char* classDescriptor, 2631a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 protoIdx, 2641a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik u4 accessFlags, 2651a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb, 2661a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik void* cnxt) 2671a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik{ 2681a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik const u1* stream = dexGetDebugInfoStream(pDexFile, pCode); 2691a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik LocalInfo localInReg[pCode->registersSize]; 2701a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2711a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik memset(localInReg, 0, sizeof(LocalInfo) * pCode->registersSize); 2721a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2731a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik if (stream != NULL) { 2741a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik dexDecodeDebugInfo0(pDexFile, pCode, classDescriptor, protoIdx, accessFlags, 2751a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik posCb, localCb, cnxt, stream, localInReg); 2761a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2771a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik 2781a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik for (int reg = 0; reg < pCode->registersSize; reg++) { 2791a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik emitLocalCbIfLive(cnxt, reg, pCode->insnsSize, localInReg, localCb); 2801a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik } 2811a65052468068a4e9a859d185860510aa1d8cfd4Aart Bik} 282