Exemple #1
0
/* (documented in header file) */
const char* dexProtoGetParameterDescriptors(const DexProto* pProto,
        DexStringCache* pCache) {
    DexParameterIterator iterator;
    size_t length = 1; /* +1 for the terminating '\0' */

    dexParameterIteratorInit(&iterator, pProto);

    for (;;) {
        const char* descriptor = dexParameterIteratorNextDescriptor(&iterator);
        if (descriptor == NULL) {
            break;
        }

        length += strlen(descriptor);
    }

    dexParameterIteratorInit(&iterator, pProto);

    dexStringCacheAlloc(pCache, length);
    char *at = (char*) pCache->value;

    for (;;) {
        const char* descriptor = dexParameterIteratorNextDescriptor(&iterator);
        if (descriptor == NULL) {
            break;
        }

        strcpy(at, descriptor);
        at += strlen(descriptor);
    }

    return pCache->value;
}
Exemple #2
0
/* (documented in header file) */
size_t dexProtoGetParameterCount(const DexProto* pProto) {
#ifdef FASTIVA
	DexParameterIterator it;
	dexParameterIteratorInit(&it, pProto);
	return it.parameterCount;
#else
    const DexProtoId* protoId = getProtoId(pProto);
    const DexTypeList* typeList =
        dexGetProtoParameters(pProto->dexFile, protoId);
    return (typeList == NULL) ? 0 : typeList->size;
#endif
}
Exemple #3
0
/*
 * 比较名称。以较特定的方法,参数、内容和返回值,如果他们相等或者不等于0,则返回0
 *
 */
static inline int compareMethodHelper(Method* method, const char* methodName,
    const char* returnType, size_t argCount, const char** argTypes)
{
    DexParameterIterator iterator;
    const DexProto* proto;

    if (strcmp(methodName, method->name) != 0) {
        return 1;
    }

    proto = &method->prototype;

    if (strcmp(returnType, dexProtoGetReturnType(proto)) != 0) {
        return 1;
    }

    if (dexProtoGetParameterCount(proto) != argCount) {
        return 1;
    }

    dexParameterIteratorInit(&iterator, proto);

    for (/*argCount*/; argCount != 0; argCount--, argTypes++) {
        const char* argType = *argTypes;
        const char* paramType = dexParameterIteratorNextDescriptor(&iterator);

        if (paramType == NULL) {
            /* Param list ended early; no match */
            break;
        } else if (strcmp(argType, paramType) != 0) {
            /* Types aren't the same; no match. */
            break;
        }
    }

    if (argCount == 0) {
        /* We ran through all the given arguments... */
        if (dexParameterIteratorNextDescriptor(&iterator) == NULL) {
            /* ...and through all the method's arguments; success! */
            return 0;
        }
    }

    return 1;
}
/* Returns the index in args[] corresponding to the parameter
 * string entry.
 * - It doesn't matter if the entry has multiple parts, e.g.,
 *   "param1.foo.bar", as long as the variable name after the first
 *   "." is not a number. Since the signature comes next, we can 
 *   safely assume this is the case.
 * - returns -1 on parsing error
 * - If descriptor is not NULL, it will point to a newly allocated 
 *   descriptor that needs to be free()'d (unless there was an error)
 */
int paramToArgIndex(const char* entry, const Method* method, char** descriptor) {
    int pIdx, aIdx, i;
    char* endptr;
    const char* num = entry + 5; /* "param" is the first 5 characters */
    const DexProto* proto = &method->prototype;
    DexParameterIterator pIterator;

    /* Step 1: determine the parameter index (pIdx) */
    pIdx = strtol(num, &endptr, 10);
    if (num == endptr) {
	/* error parsing */
	return -1;
    } 

    /* Step 2: translate parameter index into args array index */
    dexParameterIteratorInit(&pIterator, proto);
    aIdx = (dvmIsStaticMethod(method)?0:1); /* index where params start */
    for (i=0; i<=pIdx ; i++) {
	const char* desc = dexParameterIteratorNextDescriptor(&pIterator);

	if (desc == NULL) {
	    /* This index doesn't exist, error */
	    return -1;
	} 

	if (i == pIdx) {
	    /* This is the index */
	    if (descriptor != NULL) {
		*descriptor = strdup(desc);
	    }
	    break;
	}

	/* increment the args array index */
	aIdx++;

	if (desc[0] == 'J' || desc[0] == 'D') {
	    /* wide argument, increment index one more */
	    aIdx++;
	}
    }

    return aIdx;
}
/* Used to propagate taint for JNI methods
 * Two types of propagation:
 *  1) simple conservative propagation based on parameters
 *  2) propagation based on function profile policies
 */
void dvmTaintPropJniMethod(const u4* args, JValue* pResult, const Method* method, const int nativeTaint)
{
    const DexProto* proto = &method->prototype;
    DexParameterIterator pIterator;
    int nParams = dexProtoGetParameterCount(proto);
    int pStart = (dvmIsStaticMethod(method)?0:1); /* index where params start */

    /* Consider 3 arguments. [x] indicates return taint index
     * 0 1 2 [3] 4 5 6
     */
    int nArgs = method->insSize;
    u4* rtaint = (u4*) &args[nArgs]; /* The return taint value */
    int tStart = nArgs+1; /* index of args[] where taint values start */
    int tEnd   = nArgs*2; /* index of args[] where taint values end */
    u4	tag = TAINT_CLEAR;
    int i;

#if 0
    {
        char *desc = dexProtoCopyMethodDescriptor(proto);
        ALOGW("Jni: %s.%s%s, descriptor: %s", 
            method->clazz->descriptor, method->name, 
            dvmIsStaticMethod(method)?"[static]":"", desc);
        free(desc);
    }
#endif

#ifdef TAINT_JNI_LOG
    /* JNI logging for debugging purposes */
    if (gJniLog) {
	u4 hash;
	int len;
	char *inStr, *outStr;

	len = strlen(method->clazz->descriptor) + 1 + strlen(method->name);
	inStr = (char*) malloc(len+1);
	strcpy(inStr, method->clazz->descriptor);
	strcat(inStr, ".");
	strcat(inStr, method->name);
	hash = dvmComputeUtf8Hash(inStr);

	dvmHashTableLock(gJniLogSeen);

	outStr = (char*) dvmHashTableLookup(gJniLogSeen, hash, inStr, 
		(HashCompareFunc) strcmp, false);

	if (outStr == NULL) {
	    /* New method! */
	    /* add it */
	    dvmHashTableLookup(gJniLogSeen, hash, inStr, 
		(HashCompareFunc) strcmp, true);
	} else {
	    free(inStr); /* don't need this anymore */
	}

	dvmHashTableUnlock(gJniLogSeen);
    }
#endif

    /* Union the taint tags, this includes object ref tags 
     * - we don't need to worry about static vs. not static, because getting
     *	 the taint tag on the "this" object reference is a good
     * - we don't need to worry about wide registers, because the stack
     *	 interleaving of taint tags makes it transparent
     */
    /*for (i = tStart; i <= tEnd; i++) {
    	tag |= args[i];
    	if (args[i]!=0 && args[i]!=TAINT_ACCELEROMETER) //found a taint, and its not the accelerometer spam either
    		ALOGD("dvmTaintPropJNIMethod found taint %08x in method=%s:%s(%s) for arg[%d]=%08x",
    				args[i], method->clazz->descriptor, method->name, method->shorty, i-nArgs, args[i-nArgs]);
    }*/

    /* If not static, pull any taint from the "this" object */
    /*if (!dvmIsStaticMethod(method)) {
	tag |= getObjectTaint((Object*)args[0], method->clazz->descriptor);
    }*/

    /* Union taint from Objects we care about */
    dexParameterIteratorInit(&pIterator, proto);
    for (i=pStart; ; i++) {
	const char* desc = dexParameterIteratorNextDescriptor(&pIterator);

	if (desc == NULL) {
	    break;
	} 
	
	if (desc[0] == '[' || desc[0] == 'L') {
	    tag |= getObjectTaint((Object*) args[i], desc);
	}

	if (desc[0] == 'J' || desc[0] == 'D') {
	    /* wide argument, increment index one more */
	    i++;
	}
    }

    /* Look at the taint policy profiles (may have return taint) */
    //tag |= propMethodProfile(args, method);

    /* Update return taint according to the return type */
    //Native Tainting: get taint Value from native code
    //if (tag) {
    if (nativeTaint) {
	const char* desc = dexProtoGetReturnType(proto);
	//setReturnTaint(tag, rtaint, pResult, desc);
	ALOGD("dvmTaintPropJniMethod: setting result taint to %x", nativeTaint);
	setReturnTaint(nativeTaint, rtaint, pResult, desc);
    }
}
Exemple #6
0
// TODO optimize localCb == NULL case
void dexDecodeDebugInfo(
            const DexFile* pDexFile,
            const DexCode* pCode,
            const char* classDescriptor,
            u4 protoIdx,
            u4 accessFlags,
            DexDebugNewPositionCb posCb, DexDebugNewLocalCb localCb,
            void* cnxt)
{
    const u1 *stream = dexGetDebugInfoStream(pDexFile, pCode);
    u4 line;
    u4 parametersSize;
    u4 address = 0;
    LocalInfo localInReg[pCode->registersSize];
    u4 insnsSize = pCode->insnsSize;
    DexProto proto = { pDexFile, protoIdx };

    memset(localInReg, 0, sizeof(LocalInfo) * pCode->registersSize);

    if (stream == NULL) {
        goto end;
    }

    line = readUnsignedLeb128(&stream);
    parametersSize = readUnsignedLeb128(&stream);

    u2 argReg = pCode->registersSize - pCode->insSize;

    if ((accessFlags & ACC_STATIC) == 0) {
        /*
         * The code is an instance method, which means that there is
         * an initial this parameter. Also, the proto list should
         * contain exactly one fewer argument word than the insSize
         * indicates.
         */
        assert(pCode->insSize == (dexProtoComputeArgsSize(&proto) + 1));
        localInReg[argReg].name = "this";
        localInReg[argReg].descriptor = classDescriptor;
        localInReg[argReg].startAddress = 0;
        localInReg[argReg].live = true;
        argReg++;
    } else {
        assert(pCode->insSize == dexProtoComputeArgsSize(&proto));
    }

    DexParameterIterator iterator;
    dexParameterIteratorInit(&iterator, &proto);

    while (parametersSize-- != 0) {
        const char* descriptor = dexParameterIteratorNextDescriptor(&iterator);
        const char *name;
        int reg;

        if ((argReg >= pCode->registersSize) || (descriptor == NULL)) {
            goto invalid_stream;
        }

        name = readStringIdx(pDexFile, &stream);
        reg = argReg;

        switch (descriptor[0]) {
            case 'D':
            case 'J':
                argReg += 2;
                break;
            default:
                argReg += 1;
                break;
        }

        if (name != NULL) {
            localInReg[reg].name = name;
            localInReg[reg].descriptor = descriptor;
            localInReg[reg].signature = NULL;
            localInReg[reg].startAddress = address;
            localInReg[reg].live = true;
        }
    }

    for (;;)  {
        u1 opcode = *stream++;
        u2 reg;

        switch (opcode) {
            case DBG_END_SEQUENCE:
                goto end;

            case DBG_ADVANCE_PC:
                address += readUnsignedLeb128(&stream);
                break;

            case DBG_ADVANCE_LINE:
                line += readSignedLeb128(&stream);
                break;

            case DBG_START_LOCAL:
            case DBG_START_LOCAL_EXTENDED:
                reg = readUnsignedLeb128(&stream);
                if (reg > pCode->registersSize) goto invalid_stream;

                // Emit what was previously there, if anything
                emitLocalCbIfLive (cnxt, reg, address,
                    localInReg, localCb);

                localInReg[reg].name = readStringIdx(pDexFile, &stream);
                localInReg[reg].descriptor = readTypeIdx(pDexFile, &stream);
                if (opcode == DBG_START_LOCAL_EXTENDED) {
                    localInReg[reg].signature
                        = readStringIdx(pDexFile, &stream);
                } else {
                    localInReg[reg].signature = NULL;
                }
                localInReg[reg].startAddress = address;
                localInReg[reg].live = true;
                break;

            case DBG_END_LOCAL:
                reg = readUnsignedLeb128(&stream);
                if (reg > pCode->registersSize) goto invalid_stream;

                emitLocalCbIfLive (cnxt, reg, address, localInReg, localCb);
                localInReg[reg].live = false;
                break;

            case DBG_RESTART_LOCAL:
                reg = readUnsignedLeb128(&stream);
                if (reg > pCode->registersSize) goto invalid_stream;

                if (localInReg[reg].name == NULL
                        || localInReg[reg].descriptor == NULL) {
                    goto invalid_stream;
                }

                /*
                 * If the register is live, the "restart" is superfluous,
                 * and we don't want to mess with the existing start address.
                 */
                if (!localInReg[reg].live) {
                    localInReg[reg].startAddress = address;
                    localInReg[reg].live = true;
                }
                break;

            case DBG_SET_PROLOGUE_END:
            case DBG_SET_EPILOGUE_BEGIN:
            case DBG_SET_FILE:
                break;

            default: {
                int adjopcode = opcode - DBG_FIRST_SPECIAL;

                address += adjopcode / DBG_LINE_RANGE;
                line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);

                if (posCb != NULL) {
                    int done;
                    done = posCb(cnxt, address, line);

                    if (done) {
                        // early exit
                        goto end;
                    }
                }
                break;
            }
        }
    }

end:
    {
        int reg;
        for (reg = 0; reg < pCode->registersSize; reg++) {
            emitLocalCbIfLive (cnxt, reg, insnsSize, localInReg, localCb);
        }
    }
    return;

invalid_stream:
    IF_LOGE() {
        char* methodDescriptor = dexProtoCopyMethodDescriptor(&proto);
        LOGE("Invalid debug info stream. class %s; proto %s",
                classDescriptor, methodDescriptor);
        free(methodDescriptor);
    }
}
Exemple #7
0
/*
 * Common implementation for dexProtoCompareToDescriptor() and
 * dexProtoCompareToParameterDescriptors(). The descriptor argument
 * can be either a full method descriptor (with parens and a return
 * type) or an unadorned concatenation of types (e.g. a list of
 * argument types).
 */
static int protoCompareToParameterDescriptors(const DexProto* proto,
        const char* descriptor, bool expectParens) {
    char expectedEndChar = expectParens ? ')' : '\0';
    DexParameterIterator iterator;
    dexParameterIteratorInit(&iterator, proto);

    if (expectParens) {
        // Skip the '('.
        assert (*descriptor == '(');
        descriptor++;
    }

    for (;;) {
        const char* protoDesc = dexParameterIteratorNextDescriptor(&iterator);

        if (*descriptor == expectedEndChar) {
            // It's the end of the descriptor string.
            if (protoDesc == NULL) {
                // It's also the end of the prototype's arguments.
                return 0;
            } else {
                // The prototype still has more arguments.
                return 1;
            }
        }

        if (protoDesc == NULL) {
            /*
             * The prototype doesn't have arguments left, but the
             * descriptor string does.
             */
            return -1;
        }

        // Both prototype and descriptor have arguments. Compare them.

        const char* nextDesc = methodDescriptorNextType(descriptor);
        assert(nextDesc != NULL);

        for (;;) {
            char c1 = *(protoDesc++);
            char c2 = (descriptor < nextDesc) ? *(descriptor++) : '\0';

            if (c1 < c2) {
                // This includes the case where the proto is shorter.
                return -1;
            } else if (c1 > c2) {
                // This includes the case where the desc is shorter.
                return 1;
            } else if (c1 == '\0') {
                // The two types are equal in length. (c2 necessarily == '\0'.)
                break;
            }
        }

        /*
         * If we made it here, the two arguments matched, and
         * descriptor == nextDesc.
         */
    }
}
Exemple #8
0
/*
 * Common implementation for dexProtoCompare() and dexProtoCompareParameters().
 */
static int protoCompare(const DexProto* pProto1, const DexProto* pProto2,
        bool compareReturnType) {

    if (pProto1 == pProto2) {
        // Easy out.
        return 0;
    } else {
#ifdef FASTIVA
		DexParameterIterator list1;
		dexParameterIteratorInit(&list1, pProto1);

        //const DexFile* dexFile1 = pProto1->dexFile;
        //const DexProtoId* protoId1 = getProtoId(pProto1);
        //const DexTypeList* typeList1 =
        //    dexGetProtoParameters(dexFile1, protoId1);
        int paramCount1 = list1.parameterCount;

		DexParameterIterator list2;
		dexParameterIteratorInit(&list2, pProto2);

		//const DexFile* dexFile2 = pProto2->dexFile;
        //const DexProtoId* protoId2 = getProtoId(pProto2);
        //const DexTypeList* typeList2 =
        //    dexGetProtoParameters(dexFile2, protoId2);
        int paramCount2 = list2.parameterCount;

        // Compare return types.

        if (compareReturnType) {
            int result =
                strcmp(fastiva_dexGetReturnTypeDescriptor(pProto1),
					   fastiva_dexGetReturnTypeDescriptor(pProto2));

            if (result != 0) {
                return result;
            }
        }


		if (list1.parameters == list2.parameters) {
            // @Zee must after return type comparing.
            return 0;
        }

        // Compare parameters.

        int minParam = (paramCount1 > paramCount2) ? paramCount2 : paramCount1;
        int i;

        for (i = 0; i < minParam; i++) {
            int result =
                strcmp(dexParameterIteratorNextDescriptor(&list1),
                       dexParameterIteratorNextDescriptor(&list2));

            if (result != 0) {
                return result;
            }
        }
#else
        const DexFile* dexFile1 = pProto1->dexFile;
        const DexProtoId* protoId1 = getProtoId(pProto1);
        const DexTypeList* typeList1 =
            dexGetProtoParameters(dexFile1, protoId1);
        int paramCount1 = (typeList1 == NULL) ? 0 : typeList1->size;

        const DexFile* dexFile2 = pProto2->dexFile;
        const DexProtoId* protoId2 = getProtoId(pProto2);
        const DexTypeList* typeList2 =
            dexGetProtoParameters(dexFile2, protoId2);
        int paramCount2 = (typeList2 == NULL) ? 0 : typeList2->size;

        if (protoId1 == protoId2) {
            // Another easy out.
            return 0;
        }

        // Compare return types.

        if (compareReturnType) {
            int result =
                strcmp(dexStringByTypeIdx(dexFile1, protoId1->returnTypeIdx),
                        dexStringByTypeIdx(dexFile2, protoId2->returnTypeIdx));

            if (result != 0) {
                return result;
            }
        }

        // Compare parameters.

        int minParam = (paramCount1 > paramCount2) ? paramCount2 : paramCount1;
        int i;

        for (i = 0; i < minParam; i++) {
            u4 idx1 = dexTypeListGetIdx(typeList1, i);
            u4 idx2 = dexTypeListGetIdx(typeList2, i);
            int result =
                strcmp(dexStringByTypeIdx(dexFile1, idx1),
                        dexStringByTypeIdx(dexFile2, idx2));

            if (result != 0) {
                return result;
            }
        }
#endif
        if (paramCount1 < paramCount2) {
            return -1;
        } else if (paramCount1 > paramCount2) {
            return 1;
        } else {
            return 0;
        }
    }
}