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