19ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein/* 29ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * Copyright (C) 2011 The Android Open Source Project 39ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * 49ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * Licensed under the Apache License, Version 2.0 (the "License"); 59ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * you may not use this file except in compliance with the License. 69ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * You may obtain a copy of the License at 79ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * 89ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * http://www.apache.org/licenses/LICENSE-2.0 99ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * 109ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * Unless required by applicable law or agreed to in writing, software 119ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * distributed under the License is distributed on an "AS IS" BASIS, 129ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * See the License for the specific language governing permissions and 149ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * limitations under the License. 159ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein */ 169ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 179ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein/* 189ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * Handling of method debug info in a .dex file. 199ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein */ 209ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 219ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein#include "DexDebugInfo.h" 229ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein#include "DexProto.h" 239ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein#include "Leb128.h" 249ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 259ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein#include <stdlib.h> 269ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein#include <string.h> 279ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 289ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein/* 299ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * Decode the arguments in a method signature, which looks something 309ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * like "(ID[Ljava/lang/String;)V". 319ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * 329ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * Returns the type signature letter for the next argument, or ')' if 339ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * there are no more args. Advances "pSig" to point to the character 349ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * after the one returned. 359ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein */ 369ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornsteinstatic char decodeSignature(const char** pSig) 379ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein{ 389ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const char* sig = *pSig; 399ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 409ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (*sig == '(') 419ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein sig++; 429ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 439ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (*sig == 'L') { 449ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein /* object ref */ 459ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein while (*++sig != ';') 469ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein ; 479ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein *pSig = sig+1; 489ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein return 'L'; 499ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 509ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (*sig == '[') { 519ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein /* array; advance past array type */ 529ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein while (*++sig == '[') 539ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein ; 549ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (*sig == 'L') { 559ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein while (*++sig != ';') 569ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein ; 579ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 589ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein *pSig = sig+1; 599ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein return '['; 609ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 619ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (*sig == '\0') 629ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein return *sig; /* don't advance further */ 639ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 649ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein *pSig = sig+1; 659ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein return *sig; 669ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein} 679ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 689ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein/* 699ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * returns the length of a type string, given the start of the 709ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * type string. Used for the case where the debug info format 719ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * references types that are inside a method type signature. 729ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein */ 739ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornsteinstatic int typeLength(const char *type) { 749ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein // Assumes any leading '(' has already been gobbled 759ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const char *end = type; 769ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein decodeSignature(&end); 779ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein return end - type; 789ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein} 799ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 809ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein/* 819ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * Reads a string index as encoded for the debug info format, 829ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * returning a string pointer or NULL as appropriate. 839ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein */ 849ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornsteinstatic const char* readStringIdx(const DexFile* pDexFile, 859ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const u1** pStream) { 869ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein u4 stringIdx = readUnsignedLeb128(pStream); 879ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 889ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein // Remember, encoded string indicies have 1 added to them. 899ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (stringIdx == 0) { 909ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein return NULL; 919ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } else { 929ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein return dexStringById(pDexFile, stringIdx - 1); 939ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 949ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein} 959ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 969ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein/* 979ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * Reads a type index as encoded for the debug info format, returning 989ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * a string pointer for its descriptor or NULL as appropriate. 999ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein */ 1009ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornsteinstatic const char* readTypeIdx(const DexFile* pDexFile, 1019ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const u1** pStream) { 1029ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein u4 typeIdx = readUnsignedLeb128(pStream); 1039ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 1049ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein // Remember, encoded type indicies have 1 added to them. 1059ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (typeIdx == 0) { 1069ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein return NULL; 1079ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } else { 1089ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein return dexStringByTypeIdx(pDexFile, typeIdx - 1); 1099ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 1109ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein} 1119ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 112bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapirostruct LocalInfo { 1139ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const char *name; 1149ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const char *descriptor; 1159ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const char *signature; 1169ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein u2 startAddress; 1179ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein bool live; 118bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro}; 1199ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 1209ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornsteinstatic void emitLocalCbIfLive(void *cnxt, int reg, u4 endAddress, 1219ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein LocalInfo *localInReg, DexDebugNewLocalCb localCb) 1229ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein{ 1239ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (localCb != NULL && localInReg[reg].live) { 1249ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localCb(cnxt, reg, localInReg[reg].startAddress, endAddress, 1259ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].name, 1269ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].descriptor, 1279ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].signature == NULL 1289ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein ? "" : localInReg[reg].signature ); 1299ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 1309ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein} 1319ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 132a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornsteinstatic void invalidStream(const char* classDescriptor, const DexProto* proto) { 133c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block IF_ALOGE() { 134a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein char* methodDescriptor = dexProtoCopyMethodDescriptor(proto); 135c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Invalid debug info stream. class %s; proto %s", 136a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein classDescriptor, methodDescriptor); 137a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein free(methodDescriptor); 138a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein } 139a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein} 140a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein 141a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornsteinstatic void dexDecodeDebugInfo0( 1429ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const DexFile* pDexFile, 1439ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const DexCode* pCode, 1449ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const char* classDescriptor, 1459ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein u4 protoIdx, 1469ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein u4 accessFlags, 1479ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb, 148a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein void* cnxt, 149a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein const u1* stream, 150a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein LocalInfo* localInReg) 1519ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein{ 1529ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein DexProto proto = { pDexFile, protoIdx }; 153a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein u4 insnsSize = pCode->insnsSize; 154a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein u4 line = readUnsignedLeb128(&stream); 155a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein u4 parametersSize = readUnsignedLeb128(&stream); 1569ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein u2 argReg = pCode->registersSize - pCode->insSize; 157a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein u4 address = 0; 1589ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 1599ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if ((accessFlags & ACC_STATIC) == 0) { 1609ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein /* 1619ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * The code is an instance method, which means that there is 1629ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * an initial this parameter. Also, the proto list should 1639ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * contain exactly one fewer argument word than the insSize 1649ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * indicates. 1659ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein */ 1669ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein assert(pCode->insSize == (dexProtoComputeArgsSize(&proto) + 1)); 1679ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[argReg].name = "this"; 1689ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[argReg].descriptor = classDescriptor; 1699ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[argReg].startAddress = 0; 1709ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[argReg].live = true; 1719ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein argReg++; 1729ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } else { 1739ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein assert(pCode->insSize == dexProtoComputeArgsSize(&proto)); 1749ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 1759ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 1769ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein DexParameterIterator iterator; 1779ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein dexParameterIteratorInit(&iterator, &proto); 1789ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 1799ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein while (parametersSize-- != 0) { 1809ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const char* descriptor = dexParameterIteratorNextDescriptor(&iterator); 1819ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein const char *name; 1829ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein int reg; 1839ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 1849ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if ((argReg >= pCode->registersSize) || (descriptor == NULL)) { 185a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein invalidStream(classDescriptor, &proto); 186a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein return; 1879ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 1889ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 1899ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein name = readStringIdx(pDexFile, &stream); 1909ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein reg = argReg; 1919ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 1929ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein switch (descriptor[0]) { 1939ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case 'D': 1949ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case 'J': 1959ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein argReg += 2; 1969ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein break; 1979ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein default: 1989ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein argReg += 1; 1999ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein break; 2009ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 2019ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2029ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (name != NULL) { 2039ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].name = name; 2049ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].descriptor = descriptor; 2059ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].signature = NULL; 2069ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].startAddress = address; 2079ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].live = true; 2089ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 2099ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 2109ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2119ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein for (;;) { 2129ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein u1 opcode = *stream++; 2139ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein u2 reg; 2149ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2159ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein switch (opcode) { 2169ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case DBG_END_SEQUENCE: 217a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein return; 2189ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2199ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case DBG_ADVANCE_PC: 2209ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein address += readUnsignedLeb128(&stream); 2219ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein break; 2229ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2239ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case DBG_ADVANCE_LINE: 2249ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein line += readSignedLeb128(&stream); 2259ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein break; 2269ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2279ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case DBG_START_LOCAL: 2289ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case DBG_START_LOCAL_EXTENDED: 2299ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein reg = readUnsignedLeb128(&stream); 230a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein if (reg > pCode->registersSize) { 231a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein invalidStream(classDescriptor, &proto); 232a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein return; 233a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein } 2349ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2359ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein // Emit what was previously there, if anything 236a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein emitLocalCbIfLive(cnxt, reg, address, 2379ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg, localCb); 2389ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2399ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].name = readStringIdx(pDexFile, &stream); 2409ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].descriptor = readTypeIdx(pDexFile, &stream); 2419ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (opcode == DBG_START_LOCAL_EXTENDED) { 2429ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].signature 2439ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein = readStringIdx(pDexFile, &stream); 2449ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } else { 2459ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].signature = NULL; 2469ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 2479ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].startAddress = address; 2489ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].live = true; 2499ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein break; 2509ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2519ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case DBG_END_LOCAL: 2529ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein reg = readUnsignedLeb128(&stream); 253a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein if (reg > pCode->registersSize) { 254a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein invalidStream(classDescriptor, &proto); 255a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein return; 256a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein } 2579ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2589ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein emitLocalCbIfLive (cnxt, reg, address, localInReg, localCb); 2599ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].live = false; 2609ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein break; 2619ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2629ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case DBG_RESTART_LOCAL: 2639ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein reg = readUnsignedLeb128(&stream); 264a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein if (reg > pCode->registersSize) { 265a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein invalidStream(classDescriptor, &proto); 266a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein return; 267a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein } 2689ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2699ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (localInReg[reg].name == NULL 2709ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein || localInReg[reg].descriptor == NULL) { 271a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein invalidStream(classDescriptor, &proto); 272a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein return; 2739ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 2749ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2759ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein /* 2769ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * If the register is live, the "restart" is superfluous, 2779ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein * and we don't want to mess with the existing start address. 2789ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein */ 2799ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (!localInReg[reg].live) { 2809ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].startAddress = address; 2819ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein localInReg[reg].live = true; 2829ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 2839ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein break; 2849ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2859ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case DBG_SET_PROLOGUE_END: 2869ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case DBG_SET_EPILOGUE_BEGIN: 2879ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein case DBG_SET_FILE: 2889ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein break; 2899ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2909ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein default: { 2919ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein int adjopcode = opcode - DBG_FIRST_SPECIAL; 2929ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2939ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein address += adjopcode / DBG_LINE_RANGE; 2949ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE); 2959ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 2969ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (posCb != NULL) { 2979ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein int done; 2989ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein done = posCb(cnxt, address, line); 2999ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 3009ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein if (done) { 3019ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein // early exit 302a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein return; 3039ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 3049ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 3059ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein break; 3069ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 3079ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 3089ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 309a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein} 3109ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 311a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein// TODO optimize localCb == NULL case 312a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornsteinvoid dexDecodeDebugInfo( 313a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein const DexFile* pDexFile, 314a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein const DexCode* pCode, 315a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein const char* classDescriptor, 316a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein u4 protoIdx, 317a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein u4 accessFlags, 318a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb, 319a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein void* cnxt) 320a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein{ 321a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein const u1* stream = dexGetDebugInfoStream(pDexFile, pCode); 322a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein LocalInfo localInReg[pCode->registersSize]; 323a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein 324a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein memset(localInReg, 0, sizeof(LocalInfo) * pCode->registersSize); 325a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein 326a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein if (stream != NULL) { 327a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein dexDecodeDebugInfo0(pDexFile, pCode, classDescriptor, protoIdx, accessFlags, 328a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein posCb, localCb, cnxt, stream, localInReg); 3299ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 3309ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein 331a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein for (int reg = 0; reg < pCode->registersSize; reg++) { 332a70a3d8faa8f7332549fa0c9ae2008d428e28606Dan Bornstein emitLocalCbIfLive(cnxt, reg, pCode->insnsSize, localInReg, localCb); 3339ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein } 3349ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein} 335