Exemple #1
0
CHAR const* AOC_DX_MGR::get_class_name_by_method_id(UINT method_idx)
{
	DexMethodId const* method_id = dexGetMethodId(m_df, method_idx);
	IS_TRUE0(method_id);
	CHAR const* class_name = dexStringByTypeIdx(m_df, method_id->classIdx);
	return class_name;
}
Exemple #2
0
CHAR const* AOC_DX_MGR::get_method_name(UINT method_idx)
{
	DexMethodId const* method_id = dexGetMethodId(m_df, method_idx);
	IS_TRUE0(method_id);
	CHAR const* method_name = dexStringById(m_df, method_id->nameIdx);
	IS_TRUE0(method_name);
	return method_name;
}
Exemple #3
0
/*
 * Dump a method.
 */
void dumpMethod(DexFile* pDexFile, const char* fileName,
    const DexMethod* pDexMethod, int i)
{
    const DexMethodId* pMethodId;
    const DexCode* pCode;
    const char* classDescriptor;
    const char* methodName;
    int firstLine;

    /* abstract and native methods don't get listed */
    if (pDexMethod->codeOff == 0)
        return;

    pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
    methodName = dexStringById(pDexFile, pMethodId->nameIdx);

    classDescriptor = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);

    pCode = dexGetCode(pDexFile, pDexMethod);
    assert(pCode != NULL);

    /*
     * If the filename is empty, then set it to something printable
     * so that it is easier to parse.
     *
     * TODO: A method may override its class's default source file by
     * specifying a different one in its debug info. This possibility
     * should be handled here.
     */
    if (fileName == NULL || fileName[0] == 0) {
        fileName = "(none)";
    }

    firstLine = -1;
    dexDecodeDebugInfo(pDexFile, pCode, classDescriptor, pMethodId->protoIdx,
        pDexMethod->accessFlags, positionsCallback, NULL, &firstLine);

    char* className = descriptorToDot(classDescriptor);
    char* desc = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);
    u4 insnsOff = pDexMethod->codeOff + offsetof(DexCode, insns);

    if (gParms.methodToFind != NULL &&
        (strcmp(gParms.classToFind, className) != 0 ||
         strcmp(gParms.methodToFind, methodName) != 0))
    {
        goto skip;
    }

    printf("0x%08x %d %s %s %s %s %d\n",
        insnsOff, pCode->insnsSize * 2,
        className, methodName, desc,
        fileName, firstLine);

skip:
    free(desc);
    free(className);
}
/*
 * Dump the positions list.
 */
void dumpPositions(DexFile* pDexFile, const DexCode* pCode, 
        const DexMethod *pDexMethod)
{
    printf("      positions     : \n");
    const DexMethodId *pMethodId 
            = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
    const char *classDescriptor
            = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);

    dexDecodeDebugInfo(pDexFile, pCode, classDescriptor, pMethodId->protoIdx,
            pDexMethod->accessFlags, dumpPositionsCb, NULL, NULL);
}
Exemple #5
0
/* Fill in the configuration Map from config file priority only*/
void dvmDexConfigMap(DvmDex* pDvmDex, DvmConfigMap* pconfigMap){

	//ToDo: Handle this exception later
	if(pDvmDex==NULL) return;
	if(!pDvmDex->isConfigFile) return;

	const char* curMethodName =NULL;
	const char* sensitiveMethodName =NULL;
	unsigned int priority = 0;
    const DexClassDef* pDexClassDef = NULL;
    const DexMethodId* pDexMethodId = NULL;
	unsigned int methodIdsSize = pDvmDex->pDexFile->pHeader->methodIdsSize;
	DvmConfigFile* pConfigFile = pDvmDex->pConfigFile;

	//DvmConfigMap configMap; // it is already set in the previous function so we will access the pointer directly

	for(int i =0; i<pConfigFile->numSensitiveClasses; i++){
		 pDexClassDef = dexFindClass(pDvmDex->pDexFile,pConfigFile->sensitiveClasses.at(i).className.c_str() );
		 if(pDexClassDef==NULL){
			 ALOGE("dvmDexConfigMap: pDexClassDef == NULL");
			 return;
		 }
		unsigned int classIdx = dexGetIndexForClassDef(pDvmDex->pDexFile,pDexClassDef);
		// ALOGD("dvmDexConfigMap: classIdx:%d",classIdx); //this is correct // 256
		 //sensitiveClassIdx.push_back(classIdx);

		//((DexClassDef)(pDvmDex->pDexFile->pClassDefs[classIdx])).isSensitiveClass = 1;
		// pDvmDex->pDexFile->pClassDefs[classIdx].isSensitiveClass = 1;

		 for(int j=0; j< pConfigFile->sensitiveClasses.at(i).numSensitiveMethods; j++){
			 sensitiveMethodName = pConfigFile->sensitiveClasses.at(i).sensitiveMethods.at(j).methodName.c_str();
			// ALOGD("sensitiveMethodName = %s",sensitiveMethodName);
			 priority =  pConfigFile->sensitiveClasses.at(i).sensitiveMethods.at(j).methodparam.priority;
			// ALOGD("priority =%d",priority );
			 for(unsigned int methodIdx=0; methodIdx<methodIdsSize; methodIdx++){
				 pDexMethodId = dexGetMethodId(pDvmDex->pDexFile,methodIdx);
				 curMethodName = dexStringById(pDvmDex->pDexFile, pDexMethodId->nameIdx);
				//if(curMethodName) ALOGD("curMethodName = %s",curMethodName);
				 if(curMethodName == NULL) return;
				 if(strcmp(curMethodName,sensitiveMethodName) == 0){

					 pconfigMap->insert(std::make_pair(key(classIdx,methodIdx),priority));
					// ALOGD("After mapping");
				 }
			 }
		 }
	}

}
/*
 * Get information about a method.
 */
bool getMethodInfo(DexFile* pDexFile, u4 methodIdx, FieldMethodInfo* pMethInfo)
{
    const DexMethodId* pMethodId;

    if (methodIdx >= pDexFile->pHeader->methodIdsSize)
        return false;

    pMethodId = dexGetMethodId(pDexFile, methodIdx);
    pMethInfo->name = dexStringById(pDexFile, pMethodId->nameIdx);
    pMethInfo->signature = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);

    pMethInfo->classDescriptor = 
            dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
    return true;
}
Exemple #7
0
/* Is called from vm/JarFile.cpp*/
void dvmDexConfigMethodMap(DvmDex* pDvmDex, DvmConfigMethodMap* pconfigMethodMap){

	//ToDo: Handle this exception later
	if(pDvmDex==NULL) return;
	if(!pDvmDex->isConfigFile) return;

	const char* curMethodName =NULL;
	const char* sensitiveMethodName =NULL;
    const DexClassDef* pDexClassDef = NULL;
    const DexMethodId* pDexMethodId = NULL;
	unsigned int methodIdsSize = pDvmDex->pDexFile->pHeader->methodIdsSize;
	DvmConfigFile* pConfigFile = pDvmDex->pConfigFile;

	for(int i =0; i<pConfigFile->numSensitiveClasses; i++){
		 pDexClassDef = dexFindClass(pDvmDex->pDexFile,pConfigFile->sensitiveClasses.at(i).className.c_str() );
		 if(pDexClassDef==NULL){
			 ALOGE("dvmDexConfigMap: pDexClassDef == NULL");
			 return;
		 }
		 unsigned int classIdx = dexGetIndexForClassDef(pDvmDex->pDexFile,pDexClassDef);
		 for(int j=0; j< pConfigFile->sensitiveClasses.at(i).numSensitiveMethods; j++){
			 sensitiveMethodName = pConfigFile->sensitiveClasses.at(i).sensitiveMethods.at(j).methodName.c_str();
			 for(unsigned int methodIdx=0; methodIdx<methodIdsSize; methodIdx++){
				 pDexMethodId = dexGetMethodId(pDvmDex->pDexFile,methodIdx);
				 curMethodName = dexStringById(pDvmDex->pDexFile, pDexMethodId->nameIdx);
				 if(curMethodName == NULL) return;
				 if(strcmp(curMethodName,sensitiveMethodName) == 0){
					 pconfigMethodMap->insert(std::make_pair(key(classIdx,methodIdx), pConfigFile->sensitiveClasses.at(i).sensitiveMethods.at(j).methodparam));
				 }
			 }
		 }
	}

	//DEBUG
//	if(pDvmDex->pconfigMethodMap!=NULL){
//		ALOGD("dvmDexConfigMapMethodDebug");
//		if(pDvmDex->pconfigMethodMap==NULL) return;
//		if(pDvmDex->pconfigMethodMap->size() ==0 ) return;
//
//		ALOGD("dvmDexConfigMapDebug: pDvmConfigMap exists and size = %d",pDvmDex->pconfigMethodMap->size() );
//
//		for(DvmConfigMethodMapIter it=pDvmDex->pconfigMethodMap->begin(); it!=pDvmDex->pconfigMethodMap->end(); ++it){
//			ALOGD("ClassID:%d MethodID:%d ==> tag:%d, priority:%d, powerindex:%d, tempindex:%d, voltindex:%d ",it->first.first, it->first.second, it->second.tag, it->second.priority, it->second.ids.first, it->second.ids.second, it->second.ids.third);
//		}
//	}

}
// Based on dvmResolveMethod.
static void preloadDexCachesResolveMethod(DvmDex* pDvmDex,
                                          uint32_t methodIdx,
                                          MethodType methodType) {
    Method* method = dvmDexGetResolvedMethod(pDvmDex, methodIdx);
    if (method != NULL) {
        return;
    }
    const DexFile* pDexFile = pDvmDex->pDexFile;
    const DexMethodId* pMethodId = dexGetMethodId(pDexFile, methodIdx);
    ClassObject* clazz = dvmDexGetResolvedClass(pDvmDex, pMethodId->classIdx);
    if (clazz == NULL) {
        return;
    }
    // Skip static methods for uninitialized classes because a filled
    // cache entry implies the class is initialized.
    if ((methodType == METHOD_STATIC) && !dvmIsClassInitialized(clazz)) {
        return;
    }
    const char* methodName = dexStringById(pDexFile, pMethodId->nameIdx);
    DexProto proto;
    dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);

    if (methodType == METHOD_DIRECT) {
        method = dvmFindDirectMethod(clazz, methodName, &proto);
    } else if (methodType == METHOD_STATIC) {
        method = dvmFindDirectMethodHier(clazz, methodName, &proto);
    } else {
        method = dvmFindVirtualMethodHier(clazz, methodName, &proto);
    }
    if (method == NULL) {
        return;
    }
    // ALOGI("VMRuntime.preloadDexCaches found method %s.%s",
    //        clazz->descriptor, methodName);
    dvmDexSetResolvedMethod(pDvmDex, methodIdx, method);
}
/*
 * Dump a method.
 */
void dumpMethod(DexFile* pDexFile, const DexMethod* pDexMethod, int i)
{
    const DexMethodId* pMethodId;
    const char* backDescriptor;
    const char* name;
    char* typeDescriptor;
    char* accessStr;

    pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
    name = dexStringById(pDexFile, pMethodId->nameIdx);
    typeDescriptor = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);

    backDescriptor = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);

    accessStr = createAccessFlagStr(pDexMethod->accessFlags,
                    kAccessForMethod);

    printf("    #%d              : (in %s)\n", i, backDescriptor);
    printf("      name          : '%s'\n", name);
    printf("      type          : '%s'\n", typeDescriptor);
    printf("      access        : 0x%04x (%s)\n",
        pDexMethod->accessFlags, accessStr);

    if (pDexMethod->codeOff == 0) {
        printf("      code          : (none)\n");
    } else {
        printf("      code          -\n");
        dumpCode(pDexFile, pDexMethod);
    }

    if (gOptions.disassemble)
        putchar('\n');

    free(typeDescriptor);
    free(accessStr);
}
Exemple #10
0
//Dump LIR stmts stored in fu->lirList array.
void dump_lir2(LIR * lir, DexFile * df, INT pos)
{
	if (g_tfile == NULL || lir == NULL) return;
	if (pos < 0) {
		fprintf(g_tfile, "%s", LIR_name(lir));
	} else {
		fprintf(g_tfile, "(%dth)%s", pos, LIR_name(lir));
	}
	switch (LIR_opcode(lir)) {
	case LOP_NOP:
		break;
	case LOP_CONST:
		switch (LIR_dt(lir)) {
		case LIR_JDT_unknown:
			fprintf(g_tfile, ", INT");
			if (is_s4(LIR_int_imm(lir)) && LIR_res(lir) < 16) {
				//AB
				fprintf(g_tfile, ", v%d <- %d",
						LIR_res(lir), (INT)LIR_int_imm(lir));
			} else if (is_s16(LIR_int_imm(lir))) {
				//AABBBB
				fprintf(g_tfile, ", v%d <- %d",
						LIR_res(lir), (INT)LIR_int_imm(lir));
			} else {
				//AABBBBBBBB
				fprintf(g_tfile, ", v%d <- %d",
						LIR_res(lir), (INT)LIR_int_imm(lir));
			}
			break;
		case LIR_JDT_wide:
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			if (is_swide16(LIR_int_imm(lir))) {
				//AABBBB
				fprintf(g_tfile, ", (v%d,v%d) <- %d",
						LIR_res(lir), LIR_res(lir) + 1, (INT)LIR_int_imm(lir));
			} else if (is_swide32(LIR_int_imm(lir))) {
				//AABBBBBBBB
				fprintf(g_tfile, ", (v%d,v%d) <- %d",
						LIR_res(lir), LIR_res(lir) + 1, (INT)LIR_int_imm(lir));
			} else {
				//AABBBBBBBBBBBBBBBB
				fprintf(g_tfile, ", (v%d,v%d) <- %lld",
						LIR_res(lir), LIR_res(lir) + 1, LIR_int_imm(lir));
			}
			break;
		default:
			/* It seems dex does not distinguish
			float and integer const. And regard float as
			32bit integer, double will be 64bit integer. */
			IS_TRUE0(0);
		}
		break;
	case LOP_RETURN:
		{
			switch (LIR_dt(lir)) {
			case LIR_JDT_unknown: //return preg.
				fprintf(g_tfile, ", INT");
				fprintf(g_tfile, ", v%d", LIR_res(lir));
				break;
			case LIR_JDT_void: //No return value.
				break;
			case LIR_JDT_object: //return object.
				fprintf(g_tfile, ", obj_ptr:v%d", LIR_res(lir));
				break;
			case LIR_JDT_wide:
				fprintf(g_tfile, ", %s", get_dt_name(lir));
				fprintf(g_tfile, ", (v%d,v%d)", LIR_res(lir), LIR_res(lir) + 1);
				break;
			default: IS_TRUE0(0);
			}
		}
		break;
	case LOP_THROW: //AA
		//Throws an exception object.
		//The reference of the exception object is in vx.
		fprintf(g_tfile, ", v%d", LIR_res(lir));
		break;
	case LOP_MONITOR_ENTER  :
		fprintf(g_tfile, ", v%d", LIR_res(lir));
		break;
	case LOP_MONITOR_EXIT   :
		break;
	case LOP_MOVE_RESULT    :
		{
			//Move function return value to regisiter.
			//AA
			LIRAOp * p = (LIRAOp*)lir;
			switch (LIR_dt(lir)) {
			case LIR_JDT_unknown: //lexOpcode = lc_mov_result32; break;
				fprintf(g_tfile, ", INT");
				fprintf(g_tfile, ", retval -> v%d", LIR_res(lir));
				break;
			case LIR_JDT_wide: //lexOpcode = lc_mov_result64; break;
				fprintf(g_tfile, ", %s", get_dt_name(lir));
				fprintf(g_tfile, ", retval -> (v%d,v%d)",
						LIR_res(lir), LIR_res(lir) + 1);
				break;
			case LIR_JDT_object: //lexOpcode = lc_mov_result_object; break;
				fprintf(g_tfile, ", obj-ptr");
				fprintf(g_tfile, ", retval -> v%d", LIR_res(lir));
				break;
			}
		}
		break;
	case LOP_MOVE_EXCEPTION : //AA
		fprintf(g_tfile, ", v%d", LIR_res(lir));
		break;
	case LOP_GOTO		    : //AABBBBBBBB
		{
			LIRGOTOOp * p = (LIRGOTOOp*)lir;
			fprintf(g_tfile, ", (lirIdx)%dth", p->target);
		}
		break;
	case LOP_MOVE		:
		switch (LIR_dt(lir)) {
		case LIR_JDT_unknown:
			fprintf(g_tfile, ", INT");
			if ((LIR_op0(lir) | LIR_res(lir)) < 16) {
				//AB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			} else if (LIR_res(lir) < 256) {
				//AABBBB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			} else {
				//AAAABBBB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			}
			break;
		case LIR_JDT_wide:
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			if ((LIR_op0(lir) | LIR_res(lir)) < 16) {
				//AB
				fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
						LIR_res(lir), LIR_res(lir) + 1,
						LIR_op0(lir), LIR_op0(lir) + 1);
			} else if (LIR_res(lir) < 256) {
				//AABBBB
				fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
						LIR_res(lir), LIR_res(lir) + 1,
						LIR_op0(lir), LIR_op0(lir) + 1);
			} else {
				//AAAABBBB
				fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
						LIR_res(lir), LIR_res(lir) + 1,
						LIR_op0(lir), LIR_op0(lir) + 1);
			}
			break;
		case LIR_JDT_object:
			fprintf(g_tfile, ", obj-ptr");
			if ((LIR_op0(lir) | LIR_res(lir)) < 16) {
				//AB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			} else if (LIR_res(lir) < 256) {
				//AABBBB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			} else {
				//AAAABBBB
				fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			}
			break;
		}
		break;
	case LOP_NEG        : //AB
	case LOP_NOT		: //AB
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir), LIR_op0(lir)+1);
		} else {
			fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
		}
		break;
	case LOP_CONVERT	: //AB
		switch (LIR_dt(lir)) {
		case LIR_convert_i2l:
			fprintf(g_tfile, ", INT->LONG");
			fprintf(g_tfile, ", (v%d,v%d) <- v%d",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir));
			break;
		case LIR_convert_i2f: fprintf(g_tfile, ", INT->FLOAT");  break;
		case LIR_convert_i2d:
			fprintf(g_tfile, ", INT->DOUBLE");
			fprintf(g_tfile, ", (v%d,v%d) <- v%d",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir));
			break;
		case LIR_convert_l2i:
			fprintf(g_tfile, ", LONG->INT");
			fprintf(g_tfile, ", v%d <- (v%d,v%d)",
					LIR_res(lir), LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_l2f:
			fprintf(g_tfile, ", LONG->FLOAT");
			fprintf(g_tfile, ", v%d <- (v%d,v%d)",
					LIR_res(lir), LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_l2d:
			fprintf(g_tfile, ", LONG->DOUBLE");
			fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_f2i: fprintf(g_tfile, ", FLOAT->INT");  break;
		case LIR_convert_f2l:
			fprintf(g_tfile, ", FLOAT->LONG");
			fprintf(g_tfile, ", (v%d,v%d) <- v%d",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir));
			break;
		case LIR_convert_f2d:
			fprintf(g_tfile, ", FLOAT->DOUBLE");
			fprintf(g_tfile, ", (v%d,v%d) <- v%d",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir));
			break;
		case LIR_convert_d2i:
			fprintf(g_tfile, ", DOUBLE->INT");
			fprintf(g_tfile, ", v%d <- (v%d,v%d)",
					LIR_res(lir), LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_d2l:
			fprintf(g_tfile, ", DOUBLE->LONG");
			fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d)",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_d2f:
			fprintf(g_tfile, ", DOUBLE->FLOAT");
			fprintf(g_tfile, ", v%d <- (v%d,v%d)",
					LIR_res(lir), LIR_op0(lir), LIR_op0(lir)+1);
			break;
		case LIR_convert_i2b:
			fprintf(g_tfile, ", INT->BOOL");
			fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			break;
		case LIR_convert_i2c:
			fprintf(g_tfile, ", INT->CHAR");
			fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			break;
		case LIR_convert_i2s:
			fprintf(g_tfile, ", INT->SHORT");
			fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
			break;
		default:
			IS_TRUE0(0);
		}
		break;
	case LOP_ADD_ASSIGN :
	case LOP_SUB_ASSIGN :
	case LOP_MUL_ASSIGN :
	case LOP_DIV_ASSIGN :
	case LOP_REM_ASSIGN :
	case LOP_AND_ASSIGN :
	case LOP_OR_ASSIGN  :
	case LOP_XOR_ASSIGN :
	case LOP_SHL_ASSIGN :
	case LOP_SHR_ASSIGN :
	case LOP_USHR_ASSIGN:
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d), (v%d,v%d)",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir), LIR_op0(lir)+1);
		} else {
			fprintf(g_tfile, ", v%d <- v%d, v%d",
					LIR_res(lir), LIR_res(lir), LIR_op0(lir));
		}
		break;
	case LOP_ARRAY_LENGTH: //AABBBB
		//Calculates the number of elements of the array referenced by vy
		//and puts the length value into vx.
		fprintf(g_tfile, ", v%d <- v%d", LIR_res(lir), LIR_op0(lir));
		break;
	case LOP_IFZ         :
		//AABBBB
		switch (LIR_dt(lir)) {
		case LIR_cond_EQ: fprintf(g_tfile, ", =="); break;
		case LIR_cond_NE: fprintf(g_tfile, ", !="); break;
		case LIR_cond_LT: fprintf(g_tfile, ", <"); break;
		case LIR_cond_GE: fprintf(g_tfile, ", >="); break;
		case LIR_cond_GT: fprintf(g_tfile, ", >"); break;
		case LIR_cond_LE: fprintf(g_tfile, ", <="); break;
		}
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d), 0, (lirIdx)%dth",
					LIR_res(lir), LIR_res(lir)+1, LIR_op0(lir));
		} else {
			fprintf(g_tfile, ", v%d, 0, (lirIdx)%dth",
					LIR_res(lir), LIR_op0(lir));
		}
		break;
	case LOP_NEW_INSTANCE:
		//AABBBB
		//LIR_op0(lir) is class-type-id, not class-declaration-id.
		IS_TRUE0(df);
		fprintf(g_tfile, ", (obj_ptr)v%d <- (clsname<%d>)%s",
				LIR_res(lir),
				LIR_op0(lir),
				get_class_name(df, LIR_op0(lir)));
		break;
	case LOP_CONST_STRING:
		//AABBBB or AABBBBBBBB
		IS_TRUE0(df);
		fprintf(g_tfile, ", v%d <- (strofst<%d>)\"%s\"",
				LIR_res(lir),
				LIR_op0(lir),
				dexStringById(df, LIR_op0(lir)));
		break;
	case LOP_CONST_CLASS :
		//AABBBB
		//const-class vx,type_id
		//Moves the class object of a class identified by
		//type_id (e.g. Object.class) into vx.
		fprintf(g_tfile, ", v%d <- (clsname<%d>)%s",
				LIR_res(lir),
				LIR_op0(lir),
				dexStringByTypeIdx(df, LIR_op0(lir)));
		break;
	case LOP_SGET        :
		//AABBBB
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		IS_TRUE0(df);
		fprintf(g_tfile, ", v%d <- (ofst<%d>)%s::%s",
				LIR_res(lir),
				LIR_op0(lir),
				get_field_class_name(df, LIR_op0(lir)),
				get_field_name(df, LIR_op0(lir)));
		break;
	case LOP_CHECK_CAST  :
		//AABBBB
		IS_TRUE0(df);
		fprintf(g_tfile, ", v%d '%s'",
				LIR_res(lir),
				dexStringByTypeIdx(df, LIR_op0(lir)));
		break;
	case LOP_SPUT        :
		{
			//AABBBB
			LIRABOp * p = (LIRABOp*)lir;
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			IS_TRUE0(df);
			if (is_wide(lir)) {
				fprintf(g_tfile, ", (v%d,v%d) -> %s::%s",
						LIR_res(lir), LIR_res(lir)+1,
						get_field_class_name(df, LIR_op0(lir)),
						get_field_name(df, LIR_op0(lir)));
			} else {
				fprintf(g_tfile, ", v%d -> %s::%s",
						LIR_res(lir),
						get_field_class_name(df, LIR_op0(lir)),
						get_field_name(df, LIR_op0(lir)));
			}
		}
		break;
	case LOP_APUT        :
		//AABBCC
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		IS_TRUE0(df);
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) -> (array_base_ptr)v%d, (array_elem)v%d",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir), (UINT)LIR_op1(lir));
		} else {
			fprintf(g_tfile, ", v%d -> (array_base_ptr)v%d, (array_elem)v%d",
					LIR_res(lir), LIR_op0(lir), (UINT)LIR_op1(lir));
		}
		break;
	case LOP_AGET      :
		//AABBCC
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		IS_TRUE0(df);
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) <- (array_base_ptr)v%d, (array_elem)v%d",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir), (UINT)LIR_op1(lir));
		} else {
			fprintf(g_tfile, ", v%d <- (array_base_ptr)v%d, (array_elem)v%d",
					LIR_res(lir), LIR_op0(lir), (UINT)LIR_op1(lir));
		}
		break;
	case LOP_CMPL      :
	case LOP_CMP_LONG  :
		//AABBCC
		IS_TRUE0(df);
		switch (LIR_dt(lir)) {
		case LIR_CMP_float:
			fprintf(g_tfile, ", FLOAT");
			fprintf(g_tfile, ", v%d, v%d, %d",
					LIR_res(lir), LIR_op0(lir), (UINT)LIR_op1(lir));
			break;
		case LIR_CMP_double:
			fprintf(g_tfile, ", DOUBLE");
			fprintf(g_tfile, ", (v%d,v%d), (v%d,v%d), %d",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir), LIR_op0(lir)+1,
					(UINT)LIR_op1(lir));
			break;
		default: IS_TRUE0(0);
		}
		break;
	case LOP_ADD       :
	case LOP_SUB       :
	case LOP_MUL       :
	case LOP_DIV       :
	case LOP_REM       :
	case LOP_AND       :
	case LOP_OR        :
	case LOP_XOR       :
	case LOP_SHL       :
	case LOP_SHR       :
	case LOP_USHR      :
		{
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			LIRABCOp * p = (LIRABCOp*)lir;
			if (is_wide(lir)) {
				fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d), (v%d,v%d)",
						LIR_res(lir), LIR_res(lir)+1,
						LIR_op0(lir), LIR_op0(lir)+1,
						(UINT)LIR_op1(lir), (UINT)LIR_op1(lir)+1);
			} else {
				fprintf(g_tfile, ", v%d <- v%d, v%d",
						LIR_res(lir), LIR_op0(lir), (UINT)LIR_op1(lir));
			}
		}
		break;
	case LOP_IF        :
		//ABCCCC
		switch (LIR_dt(lir)) {
		case LIR_cond_EQ: fprintf(g_tfile, ", =="); break;
		case LIR_cond_NE: fprintf(g_tfile, ", !="); break;
		case LIR_cond_LT: fprintf(g_tfile, ", <"); break;
		case LIR_cond_GE: fprintf(g_tfile, ", >="); break;
		case LIR_cond_GT: fprintf(g_tfile, ", >"); break;
		case LIR_cond_LE: fprintf(g_tfile, ", <="); break;
		}
		fprintf(g_tfile, ", v%d, v%d, (lirIdx)%dth",
				LIR_res(lir), LIR_op0(lir), (UINT)LIR_op1(lir));
		break;
	case LOP_ADD_LIT   : //AABBCC, AABBCCCC
	case LOP_SUB_LIT   : //AABBCC, AABBCCCC
	case LOP_MUL_LIT   : //AABBCC, AABBCCCC
	case LOP_DIV_LIT   : //AABBCC, AABBCCCC
	case LOP_REM_LIT   : //AABBCC, AABBCCCC
	case LOP_AND_LIT   : //AABBCC, AABBCCCC
	case LOP_OR_LIT    : //AABBCC, AABBCCCC
	case LOP_XOR_LIT   : //AABBCC, AABBCCCC
	case LOP_SHL_LIT   : //AABBCC
	case LOP_SHR_LIT   : //AABBCC
	case LOP_USHR_LIT   : //AABBCC
		{
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			LIRABCOp * p = (LIRABCOp*)lir;
			if (is_wide(lir)) {
				fprintf(g_tfile, ", (v%d,v%d) <- (v%d,v%d),",
						LIR_res(lir), LIR_res(lir)+1,
						LIR_op0(lir), LIR_op0(lir)+1);
			} else {
				fprintf(g_tfile, ", v%d <- v%d,",
						LIR_res(lir), LIR_op0(lir));
			}

			if (is_s8((INT)LIR_op1(lir))) {
				//8bit imm
				fprintf(g_tfile, "(lit8)%d", (INT)LIR_op1(lir));
			} else if (is_s16((INT)LIR_op1(lir))) {
				//16bit imm
				fprintf(g_tfile, "(lit16)%d", (INT)LIR_op1(lir));
			} else {
				IS_TRUE0(0);
			}
		}
		break;
	case LOP_IPUT       :
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		//ABCCCC
		IS_TRUE0(df);
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) -> (obj_ptr)v%d, (ofst<%d>)%s::%s",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir), (UINT)LIR_op1(lir),
					get_field_class_name(df, (UINT)LIR_op1(lir)),
					get_field_name(df, (UINT)LIR_op1(lir)));
		} else {
			fprintf(g_tfile, ", v%d -> (obj_ptr)v%d, (ofst<%d>)%s::%s",
					LIR_res(lir),
					LIR_op0(lir),
					(UINT)LIR_op1(lir),
					get_field_class_name(df, (UINT)LIR_op1(lir)),
					get_field_name(df, (UINT)LIR_op1(lir)));
		}
		break;
	case LOP_IGET       :
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		//ABCCCC
		IS_TRUE0(df);
		if (is_wide(lir)) {
			fprintf(g_tfile, ", (v%d,v%d) <- (obj_ptr)v%d, (ofst<%d>)%s::%s",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir),
					(UINT)LIR_op1(lir),
					get_field_class_name(df, (UINT)LIR_op1(lir)),
					get_field_name(df, (UINT)LIR_op1(lir)));
		} else {
			fprintf(g_tfile, ", v%d <- (obj_ptr)v%d, (ofst<%d>)%s::%s",
					LIR_res(lir),
					LIR_op0(lir),
					(UINT)LIR_op1(lir),
					get_field_class_name(df, (UINT)LIR_op1(lir)),
					get_field_name(df, (UINT)LIR_op1(lir)));
		}
		break;
	case LOP_INSTANCE_OF:
		fprintf(g_tfile, ", (pred)v%d <- v%d, (clsname<%d>)'%s'",
				LIR_res(lir),
				LIR_op0(lir),
				(UINT)LIR_op1(lir),
				dexStringByTypeIdx(df, (UINT)LIR_op1(lir)));
		break;
	case LOP_NEW_ARRAY  :
		//ABCCCC
		//new-array v%d(res) <- v%d(op0), LCAnimal(op1)
		fprintf(g_tfile, ", %s", get_dt_name(lir));
		//ABCCCC
		IS_TRUE0(df);
		fprintf(g_tfile, ", v%d <- (num_of_elem)v%d, (elem_type<%d>)'%s'",
				LIR_res(lir),
				LIR_op0(lir),
				(UINT)LIR_op1(lir),
				dexStringByTypeIdx(df, (UINT)LIR_op1(lir)));
		break;
	case LOP_TABLE_SWITCH:
		{
			LIRSwitchOp * p = (LIRSwitchOp*)lir;
			IS_TRUE0(LIR_dt(p) == 0x1);
			fprintf(g_tfile, ", v%d", p->value);
			USHORT * pdata = p->data;

			//data[0]: flag to indicate switch-table type:
			//	0x1 TABLE_SWITCH, 0x2 LOOKUP_SWITCH
			USHORT f = pdata[0];
			IS_TRUE0(f == 0x100);
			//data[1]: the number of CASE entry.
			USHORT num_of_case = pdata[1];

			//data[2..3]: the base value of case-table
			UINT base_val = *((UINT*)(&pdata[2]));
			fprintf(g_tfile, ", basev:%d", base_val);

			//((BYTE*)data)[4..num_of_case*4]:
			//	the position of the index table is at current instruction.
			if (num_of_case > 0) {
				UINT * pcase_entry = (UINT*)&pdata[4];
				fprintf(g_tfile, " tgtidx:");
				for (USHORT i = 0; i < num_of_case; i++) {
					UINT idx_of_insn = pcase_entry[i];
					fprintf(g_tfile, "%d", idx_of_insn);
					if (i != num_of_case - 1) {
						fprintf(g_tfile, ",");
					}
				}
			}
		}
		break;
	case LOP_LOOKUP_SWITCH:
		{
			LIRSwitchOp * p = (LIRSwitchOp*)lir;
			IS_TRUE0(LIR_dt(p) == 0x2);
			fprintf(g_tfile, ", v%d", p->value);
			USHORT * pdata = p->data;

			//pdata[0]: flag to indicate switch-table type:
			//	0x1 TABLE_SWITCH, 0x2 LOOKUP_SWITCH
			UINT f = pdata[0];
			IS_TRUE0(f == 0x200);

			//pdata[1]: the number of CASE entry.
			UINT num_of_case = pdata[1];
			if (num_of_case > 0) {
				BYTE * tp = (BYTE*)pdata;
				//((BYTE*)pdata)[4..4+num_of_case*4-1]: the case-value buffer.
				UINT * pcase_value = (UINT*)&tp[4];

				//((BYTE*)pdata)[4+num_of_case*4, 4+num_of_case*8-1]:
				//	the position of the index table is at current instruction.
				UINT * pcase_entry = (UINT*)&tp[4 + num_of_case * 4];
				fprintf(g_tfile, " val2idx(");
				for (UINT i = 0; i < num_of_case; i++) {
					UINT idx_of_insn = pcase_entry[i];
					fprintf(g_tfile, "%d:%d", pcase_value[i], idx_of_insn);
					if (i != num_of_case - 1) {
						fprintf(g_tfile, ",");
					}
				}
				fprintf(g_tfile, ")");
			}
		}
		break;
	case LOP_FILL_ARRAY_DATA:
		{
			fprintf(g_tfile, ", %s", get_dt_name(lir));
			//AABBBBBBBB
			//pdata[0]: the magic number of code
			//0x100 PACKED_SWITCH, 0x200 SPARSE_SWITCH, 0x300 FILL_ARRAY_DATA
			LIRSwitchOp * r = (LIRSwitchOp*)lir;
			UInt16 const* pdata = (UInt16 const*)r->data;
			IS_TRUE0(pdata[0] == 0x300);
			//pdata[1]: size of each element.
			//pdata[2]: the number of element.
			UINT size_of_elem = pdata[1];
			UINT num_of_elem = pdata[2];
			UINT data_size = num_of_elem * size_of_elem;
			//fprintf(g_tfile, ", (elem_sz<%d>), (elem_num<%d>), (data_ptr)0x%x",
			fprintf(g_tfile, ", (elem_sz<%d>), (elem_num<%d>)",
					size_of_elem, num_of_elem);
		}
		break;
	case LOP_INVOKE:
		{
			/*
			ABCCCCDDDD the layout clarifies:
				A(p4), B(argc), CCCC(method_id), DDDD(p0, p1, p2, p3)
				where p0,p1,p2,p3,p4 are five parameters.

			AABBBBCCCC the layout clarifies:
				AA(argc), BBBB(method_id), CCCC(p0,p1,...p(argc-1))
			*/
			LIRInvokeOp * r = (LIRInvokeOp*)lir;
			UINT flags = LIR_dt(lir);
			UINT flag1 = flags & 0x0F;
			UINT flag2 = flags & 0xF0;
			IS_TRUE(flag1 != 0, ("means LIR is LOP_FILLED_NEW_ARRAY"));
			DexMethodId const* method_id = dexGetMethodId(df, r->ref);
			IS_TRUE0(method_id);
			CHAR const* method_name = dexStringById(df, method_id->nameIdx);
			CHAR const* class_name =
				dexStringByTypeIdx(df, method_id->classIdx);
			IS_TRUE0(method_name);
			DexProtoId const* proto_id =
				dexGetProtoId(df, method_id->protoIdx);
			CHAR const* shorty_name = dexStringById(df, proto_id->shortyIdx);
			fprintf(g_tfile, ", %s::%s", class_name, method_name);

			UINT k = LIR_dt(lir);
			bool is_range = HAVE_FLAG((k & 0xf0), LIR_Range);
			if (is_range) {
				switch (k & 0x0f) {
				case LIR_invoke_unknown: IS_TRUE0(0); break;
				case LIR_invoke_virtual:
					fprintf(g_tfile, ", virtual-range"); break;
				case LIR_invoke_direct:
					fprintf(g_tfile, ", direct-range"); break;
				case LIR_invoke_super:
					fprintf(g_tfile, ", super-range"); break;
				case LIR_invoke_interface:
					fprintf(g_tfile, ", interface-range"); break;
				case LIR_invoke_static:
					fprintf(g_tfile, ", static-range"); break;
				default: IS_TRUE0(0);
				}
			} else {
				switch (k & 0x0f) {
				case LIR_invoke_unknown: IS_TRUE0(0); break;
				case LIR_invoke_virtual:
					fprintf(g_tfile, ", virtual"); break;
				case LIR_invoke_direct:
					fprintf(g_tfile, ", direct"); break;
				case LIR_invoke_super:
					fprintf(g_tfile, ", super"); break;
				case LIR_invoke_interface:
					fprintf(g_tfile, ", interface"); break;
				case LIR_invoke_static:
					fprintf(g_tfile, ", static"); break;
				default: IS_TRUE0(0);
				}
			}

			if (r->argc != 0) {
				fprintf(g_tfile, ", arg(");
				for (USHORT i = 0; i < r->argc; i++) {
					fprintf(g_tfile, "v%d", r->args[i]);
					if (i != r->argc-1) {
						fprintf(g_tfile, ",");
					}
				}
				fprintf(g_tfile, ")");
			}
		}
		break;
	case LOP_FILLED_NEW_ARRAY:
		{
			/*
			AABBBBCCCC or ABCCCCDEFG
			e.g:
				A(argc), B,D,E,F,G(parampters), CCCC(class_tyid)
			*/
			LIRInvokeOp * r = (LIRInvokeOp*)lir;
			UINT flags = LIR_dt(lir);
			CHAR const* class_name = dexStringByTypeIdx(df, r->ref);
			IS_TRUE0(class_name);
			fprintf(g_tfile, ", %s", class_name);
			if (r->argc != 0) {
				fprintf(g_tfile, ", arg(");
				for (USHORT i = 0; i < r->argc; i++) {
					fprintf(g_tfile, "v%d", r->args[i]);
					if (i != r->argc-1) {
						fprintf(g_tfile, ",");
					}
				}
				fprintf(g_tfile, ")");
			}
		}
		break;
	case LOP_CMPG:
		//AABBCC
		IS_TRUE0(df);
		switch (LIR_dt(lir)) {
		case LIR_CMP_float:
			fprintf(g_tfile, ", FLOAT");
			fprintf(g_tfile, ", v%d, v%d, %d",
					LIR_res(lir),
					LIR_op0(lir),
					(INT)LIR_op1(lir));
			break;
		case LIR_CMP_double:
			fprintf(g_tfile, ", DOUBLE");
			fprintf(g_tfile, ", (v%d,v%d), v%d, %d",
					LIR_res(lir), LIR_res(lir)+1,
					LIR_op0(lir),
					(INT)LIR_op1(lir));
			break;
		default: IS_TRUE0(0);
		}
		break;
	case LOP_PHI:
		IS_TRUE0(0);
		break;
	default: IS_TRUE0(0);
	} //end switch
	fflush(g_tfile);
}
Exemple #11
0
CHAR const* get_func_name(DexFile * df, DexMethod const* dm)
{
	IS_TRUE0(df && dm);
	DexMethodId const* pMethodId = dexGetMethodId(df, dm->methodIdx);
	return dexStringById(df, pMethodId->nameIdx);
}
Exemple #12
0
CHAR const* get_class_name(DexFile * df, DexMethod const* dm)
{
	IS_TRUE0(df && dm);
	DexMethodId const* pMethodId = dexGetMethodId(df, dm->methodIdx);
	return dexStringByTypeIdx(df, pMethodId->classIdx);
}
/*
 * Resolve an interface method reference.
 *
 * Returns NULL with an exception raised on failure.
 */
Method* dvmResolveInterfaceMethod(const ClassObject* referrer, u4 methodIdx)
{
    DvmDex* pDvmDex = referrer->pDvmDex;
    ClassObject* resClass;
    const DexMethodId* pMethodId;
    Method* resMethod;
    int i;

    LOGVV("--- resolving interface method %d (referrer=%s)\n",
          methodIdx, referrer->descriptor);
    pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);

    resClass = dvmResolveClass(referrer, pMethodId->classIdx, false);
    if (resClass == NULL) {
        /* can't find the class that the method is a part of */
        assert(dvmCheckException(dvmThreadSelf()));
        return NULL;
    }
    if (!dvmIsInterfaceClass(resClass)) {
        /* whoops */
        dvmThrowExceptionWithClassMessage(
            "Ljava/lang/IncompatibleClassChangeError;",
            resClass->descriptor);
        return NULL;
    }

    /*
     * This is the first time the method has been resolved.  Set it in our
     * resolved-method structure.  It always resolves to the same thing,
     * so looking it up and storing it doesn't create a race condition.
     *
     * If we scan into the interface's superclass -- which is always
     * java/lang/Object -- we will catch things like:
     *   interface I ...
     *   I myobj = (something that implements I)
     *   myobj.hashCode()
     * However, the Method->methodIndex will be an offset into clazz->vtable,
     * rather than an offset into clazz->iftable.  The invoke-interface
     * code can test to see if the method returned is abstract or concrete,
     * and use methodIndex accordingly.  I'm not doing this yet because
     * (a) we waste time in an unusual case, and (b) we're probably going
     * to fix it in the DEX optimizer.
     *
     * We do need to scan the superinterfaces, in case we're invoking a
     * superinterface method on an interface reference.  The class in the
     * DexTypeId is for the static type of the object, not the class in
     * which the method is first defined.  We have the full, flattened
     * list in "iftable".
     */
    const char* methodName =
        dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);

    DexProto proto;
    dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);

    LOGVV("+++ looking for '%s' '%s' in resClass='%s'\n",
          methodName, methodSig, resClass->descriptor);
    resMethod = dvmFindVirtualMethod(resClass, methodName, &proto);
    if (resMethod == NULL) {
        LOGVV("+++ did not resolve immediately\n");
        for (i = 0; i < resClass->iftableCount; i++) {
            resMethod = dvmFindVirtualMethod(resClass->iftable[i].clazz,
                                             methodName, &proto);
            if (resMethod != NULL)
                break;
        }

        if (resMethod == NULL) {
            dvmThrowException("Ljava/lang/NoSuchMethodError;", methodName);
            return NULL;
        }
    } else {
        LOGVV("+++ resolved immediately: %s (%s %d)\n", resMethod->name,
              resMethod->clazz->descriptor, (u4) resMethod->methodIndex);
    }

    LOGVV("--- found interface method %d (%s.%s)\n",
          methodIdx, resClass->descriptor, resMethod->name);

    /* we're expecting this to be abstract */
    assert(dvmIsAbstractMethod(resMethod));

    /* interface methods are always public; no need to check access */

    /*
     * The interface class *may* be initialized.  According to VM spec
     * v2 2.17.4, the interfaces a class refers to "need not" be initialized
     * when the class is initialized.
     *
     * It isn't necessary for an interface class to be initialized before
     * we resolve methods on that interface.
     *
     * We choose not to do the initialization now.
     */
    //assert(dvmIsClassInitialized(resMethod->clazz));

    /*
     * The class is initialized, the method has been found.  Add a pointer
     * to our data structure so we don't have to jump through the hoops again.
     */
    dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);

    return resMethod;
}
/*
 * Find the method corresponding to "methodRef".
 *
 * We use "referrer" to find the DexFile with the constant pool that
 * "methodRef" is an index into.  We also use its class loader.  The method
 * being resolved may very well be in a different DEX file.
 *
 * If this is a static method, we ensure that the method's class is
 * initialized.
 */
Method* dvmResolveMethod(const ClassObject* referrer, u4 methodIdx,
                         MethodType methodType)
{
    DvmDex* pDvmDex = referrer->pDvmDex;
    ClassObject* resClass;
    const DexMethodId* pMethodId;
    Method* resMethod;

    assert(methodType != METHOD_INTERFACE);

    LOGVV("--- resolving method %u (referrer=%s)\n", methodIdx,
          referrer->descriptor);
    pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);

    resClass = dvmResolveClass(referrer, pMethodId->classIdx, false);
    if (resClass == NULL) {
        /* can't find the class that the method is a part of */
        assert(dvmCheckException(dvmThreadSelf()));
        return NULL;
    }
    if (dvmIsInterfaceClass(resClass)) {
        /* method is part of an interface */
        dvmThrowExceptionWithClassMessage(
            "Ljava/lang/IncompatibleClassChangeError;",
            resClass->descriptor);
        return NULL;
    }

    const char* name = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
    DexProto proto;
    dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);

    /*
     * We need to chase up the class hierarchy to find methods defined
     * in super-classes.  (We only want to check the current class
     * if we're looking for a constructor; since DIRECT calls are only
     * for constructors and private methods, we don't want to walk up.)
     */
    if (methodType == METHOD_DIRECT) {
        resMethod = dvmFindDirectMethod(resClass, name, &proto);
    } else if (methodType == METHOD_STATIC) {
        resMethod = dvmFindDirectMethodHier(resClass, name, &proto);
    } else {
        resMethod = dvmFindVirtualMethodHier(resClass, name, &proto);
    }

    if (resMethod == NULL) {
        dvmThrowException("Ljava/lang/NoSuchMethodError;", name);
        return NULL;
    }

    LOGVV("--- found method %d (%s.%s)\n",
          methodIdx, resClass->descriptor, resMethod->name);

    /* see if this is a pure-abstract method */
    if (dvmIsAbstractMethod(resMethod) && !dvmIsAbstractClass(resClass)) {
        dvmThrowException("Ljava/lang/AbstractMethodError;", name);
        return NULL;
    }

    /*
     * If we're the first to resolve this class, we need to initialize
     * it now.  Only necessary for METHOD_STATIC.
     */
    if (methodType == METHOD_STATIC) {
        if (!dvmIsClassInitialized(resMethod->clazz) &&
                !dvmInitClass(resMethod->clazz))
        {
            assert(dvmCheckException(dvmThreadSelf()));
            return NULL;
        } else {
            assert(!dvmCheckException(dvmThreadSelf()));
        }
    } else {
        /*
         * Edge case: if the <clinit> for a class creates an instance
         * of itself, we will call <init> on a class that is still being
         * initialized by us.
         */
        assert(dvmIsClassInitialized(resMethod->clazz) ||
               dvmIsClassInitializing(resMethod->clazz));
    }

    /*
     * The class is initialized, the method has been found.  Add a pointer
     * to our data structure so we don't have to jump through the hoops again.
     */
    dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);

    return resMethod;
}
Exemple #15
0
/*
 * Alternate version of dvmResolveMethod().
 *
 * Doesn't throw exceptions, and checks access on every lookup.
 *
 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
 */
Method* dvmOptResolveMethod(ClassObject* referrer, u4 methodIdx,
    MethodType methodType, VerifyError* pFailure)
{
    DvmDex* pDvmDex = referrer->pDvmDex;
    Method* resMethod;

    assert(methodType == METHOD_DIRECT ||
           methodType == METHOD_VIRTUAL ||
           methodType == METHOD_STATIC);

    LOGVV("--- resolving method %u (referrer=%s)", methodIdx,
        referrer->descriptor);

    resMethod = dvmDexGetResolvedMethod(pDvmDex, methodIdx);
    if (resMethod == NULL) {
        const DexMethodId* pMethodId;
        ClassObject* resClass;

        pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);

        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, pFailure);
        if (resClass == NULL) {
            /*
             * Can't find the class that the method is a part of, or don't
             * have permission to access the class.
             */
            ALOGV("DexOpt: can't find called method's class (?.%s)",
                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
            return NULL;
        }
        if (dvmIsInterfaceClass(resClass)) {
            /* method is part of an interface; this is wrong method for that */
            ALOGW("DexOpt: method is in an interface");
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_GENERIC;
            return NULL;
        }

        /*
         * We need to chase up the class hierarchy to find methods defined
         * in super-classes.  (We only want to check the current class
         * if we're looking for a constructor.)
         */
        DexProto proto;
        dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);

        if (methodType == METHOD_DIRECT) {
            resMethod = dvmFindDirectMethod(resClass,
                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto);
        } else {
            /* METHOD_STATIC or METHOD_VIRTUAL */
            resMethod = dvmFindMethodHier(resClass,
                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto);
        }

        if (resMethod == NULL) {
            ALOGV("DexOpt: couldn't find method '%s'",
                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_NO_METHOD;
            return NULL;
        }
        if (methodType == METHOD_STATIC) {
            if (!dvmIsStaticMethod(resMethod)) {
                ALOGD("DexOpt: wanted static, got instance for method %s.%s",
                    resClass->descriptor, resMethod->name);
                if (pFailure != NULL)
                    *pFailure = VERIFY_ERROR_CLASS_CHANGE;
                return NULL;
            }
        } else if (methodType == METHOD_VIRTUAL) {
            if (dvmIsStaticMethod(resMethod)) {
                ALOGD("DexOpt: wanted instance, got static for method %s.%s",
                    resClass->descriptor, resMethod->name);
                if (pFailure != NULL)
                    *pFailure = VERIFY_ERROR_CLASS_CHANGE;
                return NULL;
            }
        }

        /* see if this is a pure-abstract method */
        if (dvmIsAbstractMethod(resMethod) && !dvmIsAbstractClass(resClass)) {
            ALOGW("DexOpt: pure-abstract method '%s' in %s",
                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx),
                resClass->descriptor);
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_GENERIC;
            return NULL;
        }

        /*
         * Add it to the resolved table so we're faster on the next lookup.
         *
         * We can only do this for static methods if we're not in "dexopt",
         * because the presence of a valid value in the resolution table
         * implies that the class containing the static field has been
         * initialized.
         */
        if (methodType != METHOD_STATIC || gDvm.optimizing)
            dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
    }

    LOGVV("--- found method %d (%s.%s)",
        methodIdx, resMethod->clazz->descriptor, resMethod->name);

    /* access allowed? */
    tweakLoader(referrer, resMethod->clazz);
    bool allowed = dvmCheckMethodAccess(referrer, resMethod);
    untweakLoader(referrer, resMethod->clazz);
    if (!allowed) {
        IF_ALOGI() {
            char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
            ALOGI("DexOpt: illegal method access (call %s.%s %s from %s)",
                resMethod->clazz->descriptor, resMethod->name, desc,
                referrer->descriptor);
            free(desc);
        }