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