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