Beispiel #1
0
/*
 * Reads a string index as encoded for the debug info format,
 * returning a string pointer or NULL as appropriate.
 */
static const char* readStringIdx(const DexFile* pDexFile,
        const u1** pStream) {
    u4 stringIdx = readUnsignedLeb128(pStream);

    // Remember, encoded string indicies have 1 added to them.
    if (stringIdx == 0) {
        return NULL;
    } else {
        return dexStringById(pDexFile, stringIdx - 1);
    }
}
/*
 * Get information about a field.
 */
bool getFieldInfo(DexFile* pDexFile, u4 fieldIdx, FieldMethodInfo* pFieldInfo)
{
    const DexFieldId* pFieldId;

    if (fieldIdx >= pDexFile->pHeader->fieldIdsSize)
        return false;

    pFieldId = dexGetFieldId(pDexFile, fieldIdx);
    pFieldInfo->name = dexStringById(pDexFile, pFieldId->nameIdx);
    pFieldInfo->signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
    pFieldInfo->classDescriptor =
        dexStringByTypeIdx(pDexFile, pFieldId->classIdx);
    return true;
}
Beispiel #3
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;
}
Beispiel #5
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);
//		}
//	}

}
Beispiel #6
0
/*
 * Run through all direct and virtual methods in the class.
 */
void dumpClass(DexFile* pDexFile, int idx)
{
    const DexClassDef* pClassDef;
    DexClassData* pClassData;
    const u1* pEncodedData;
    const char* fileName;
    int i;

    pClassDef = dexGetClassDef(pDexFile, idx);
    pEncodedData = dexGetClassData(pDexFile, pClassDef);
    pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);

    if (pClassData == NULL) {
        fprintf(stderr, "Trouble reading class data\n");
        return;
    }

    if (pClassDef->sourceFileIdx == 0xffffffff) {
        fileName = NULL;
    } else {
        fileName = dexStringById(pDexFile, pClassDef->sourceFileIdx);
    }

    /*
     * TODO: Each class def points at a sourceFile, so maybe that
     * should be printed out. However, this needs to be coordinated
     * with the tools that parse this output.
     */

    for (i = 0; i < (int) pClassData->header.directMethodsSize; i++) {
        dumpMethod(pDexFile, fileName, &pClassData->directMethods[i], i);
    }

    for (i = 0; i < (int) pClassData->header.virtualMethodsSize; i++) {
        dumpMethod(pDexFile, fileName, &pClassData->virtualMethods[i], i);
    }

    free(pClassData);
}
/*
 * Dump an instance field.
 */
void dumpIField(const DexFile* pDexFile, const DexField* pIField, int i)
{
    const DexFieldId* pFieldId;
    const char* backDescriptor;
    const char* name;
    const char* typeDescriptor;
    char* accessStr;

    pFieldId = dexGetFieldId(pDexFile, pIField->fieldIdx);
    name = dexStringById(pDexFile, pFieldId->nameIdx);
    typeDescriptor = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
    backDescriptor = dexStringByTypeIdx(pDexFile, pFieldId->classIdx);

    accessStr = createAccessFlagStr(pIField->accessFlags, kAccessForField);

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

    free(accessStr);
}
/*
 * 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);
}
// 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);
}
Beispiel #10
0
/*
 * Get the descriptor string associated with a given type index.
 * The caller should not free() the returned string.
 */
DEX_INLINE const char* dexStringByTypeIdx(const DexFile* pDexFile, u4 idx) {
    const DexTypeId* typeId = dexGetTypeId(pDexFile, idx);
    return dexStringById(pDexFile, typeId->descriptorIdx);
}
Beispiel #11
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);
}
/*
 * Dump a single instruction.
 */
void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
    int insnWidth, const DecodedInstruction* pDecInsn)
{
    static const float gSpecialTab[16] = {
        -2.0f, -1.0f, -0.5f, -0.25f, -0.1f, 0.1f, 0.25f, 0.5f,
        1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 10.0f, 100.0f, 1000.0f
    };
    const u2* insns = pCode->insns;
    int i;

    printf("%06x:", ((u1*)insns - pDexFile->baseAddr) + insnIdx*2);
    for (i = 0; i < 8; i++) {
        if (i < insnWidth) {
            if (i == 7) {
                printf(" ... ");
            } else {
                /* print 16-bit value in little-endian order */
                const u1* bytePtr = (const u1*) &insns[insnIdx+i];
                printf(" %02x%02x", bytePtr[0], bytePtr[1]);
            }
        } else {
            fputs("     ", stdout);
        }
    }

    if (pDecInsn->opCode == OP_NOP) {
        u2 instr = get2LE((const u1*) &insns[insnIdx]);
        if (instr == kPackedSwitchSignature) {
            printf("|%04x: packed-switch-data (%d units)",
                insnIdx, insnWidth);
        } else if (instr == kSparseSwitchSignature) {
            printf("|%04x: sparse-switch-data (%d units)",
                insnIdx, insnWidth);
        } else if (instr == kArrayDataSignature) {
            printf("|%04x: array-data (%d units)",
                insnIdx, insnWidth);
        } else {
            printf("|%04x: nop // spacer", insnIdx);
        }
    } else {
        printf("|%04x: %s", insnIdx, getOpcodeName(pDecInsn->opCode));
    }

    switch (dexGetInstrFormat(gInstrFormat, pDecInsn->opCode)) {
    case kFmt10x:        // op
        break;
    case kFmt12x:        // op vA, vB
        printf(" v%d, v%d", pDecInsn->vA, pDecInsn->vB);
        break;
    case kFmt11n:        // op vA, #+B
        printf(" v%d, #int %d // #%x",
            pDecInsn->vA, (s4)pDecInsn->vB, (u1)pDecInsn->vB);
        break;
    case kFmt11x:        // op vAA
        printf(" v%d", pDecInsn->vA);
        break;
    case kFmt10t:        // op +AA
    case kFmt20t:        // op +AAAA
        {
            s4 targ = (s4) pDecInsn->vA;
            printf(" %04x // %c%04x",
                insnIdx + targ,
                (targ < 0) ? '-' : '+',
                (targ < 0) ? -targ : targ);
        }
        break;
    case kFmt22x:        // op vAA, vBBBB
        printf(" v%d, v%d", pDecInsn->vA, pDecInsn->vB);
        break;
    case kFmt21t:        // op vAA, +BBBB
        {
            s4 targ = (s4) pDecInsn->vB;
            printf(" v%d, %04x // %c%04x", pDecInsn->vA,
                insnIdx + targ,
                (targ < 0) ? '-' : '+',
                (targ < 0) ? -targ : targ);
        }
        break;
    case kFmt21s:        // op vAA, #+BBBB
        printf(" v%d, #int %d // #%x",
            pDecInsn->vA, (s4)pDecInsn->vB, (u2)pDecInsn->vB);
        break;
    case kFmt21h:        // op vAA, #+BBBB0000[00000000]
        // The printed format varies a bit based on the actual opcode.
        if (pDecInsn->opCode == OP_CONST_HIGH16) {
            s4 value = pDecInsn->vB << 16;
            printf(" v%d, #int %d // #%x",
                pDecInsn->vA, value, (u2)pDecInsn->vB);
        } else {
            s8 value = ((s8) pDecInsn->vB) << 48;
            printf(" v%d, #long %lld // #%x",
                pDecInsn->vA, value, (u2)pDecInsn->vB);
        }
        break;
    case kFmt21c:        // op vAA, thing@BBBB
        if (pDecInsn->opCode == OP_CONST_STRING) {
            printf(" v%d, \"%s\" // string@%04x", pDecInsn->vA,
                dexStringById(pDexFile, pDecInsn->vB), pDecInsn->vB);
        } else if (pDecInsn->opCode == OP_CHECK_CAST ||
                   pDecInsn->opCode == OP_NEW_INSTANCE ||
                   pDecInsn->opCode == OP_CONST_CLASS)
        {
            printf(" v%d, %s // class@%04x", pDecInsn->vA,
                getClassDescriptor(pDexFile, pDecInsn->vB), pDecInsn->vB);
        } else /* OP_SGET* */ {
            FieldMethodInfo fieldInfo;
            if (getFieldInfo(pDexFile, pDecInsn->vB, &fieldInfo)) {
                printf(" v%d, %s.%s:%s // field@%04x", pDecInsn->vA,
                    fieldInfo.classDescriptor, fieldInfo.name,
                    fieldInfo.signature, pDecInsn->vB);
            } else {
                printf(" v%d, ??? // field@%04x", pDecInsn->vA, pDecInsn->vB);
            }
        }
        break;
    case kFmt23x:        // op vAA, vBB, vCC
        printf(" v%d, v%d, v%d", pDecInsn->vA, pDecInsn->vB, pDecInsn->vC);
        break;
    case kFmt22b:        // op vAA, vBB, #+CC
        printf(" v%d, v%d, #int %d // #%02x",
            pDecInsn->vA, pDecInsn->vB, (s4)pDecInsn->vC, (u1)pDecInsn->vC);
        break;
    case kFmt22t:        // op vA, vB, +CCCC
        {
            s4 targ = (s4) pDecInsn->vC;
            printf(" v%d, v%d, %04x // %c%04x", pDecInsn->vA, pDecInsn->vB,
                insnIdx + targ,
                (targ < 0) ? '-' : '+',
                (targ < 0) ? -targ : targ);
        }
        break;
    case kFmt22s:        // op vA, vB, #+CCCC
        printf(" v%d, v%d, #int %d // #%04x",
            pDecInsn->vA, pDecInsn->vB, (s4)pDecInsn->vC, (u2)pDecInsn->vC);
        break;
    case kFmt22c:        // op vA, vB, thing@CCCC
        if (pDecInsn->opCode >= OP_IGET && pDecInsn->opCode <= OP_IPUT_SHORT) {
            FieldMethodInfo fieldInfo;
            if (getFieldInfo(pDexFile, pDecInsn->vC, &fieldInfo)) {
                printf(" v%d, v%d, %s.%s:%s // field@%04x", pDecInsn->vA,
                    pDecInsn->vB, fieldInfo.classDescriptor, fieldInfo.name,
                    fieldInfo.signature, pDecInsn->vC);
            } else {
                printf(" v%d, v%d, ??? // field@%04x", pDecInsn->vA,
                    pDecInsn->vB, pDecInsn->vC);
            }
        } else {
            printf(" v%d, v%d, %s // class@%04x",
                pDecInsn->vA, pDecInsn->vB,
                getClassDescriptor(pDexFile, pDecInsn->vC), pDecInsn->vC);
        }
        break;
    case kFmt22cs:       // [opt] op vA, vB, field offset CCCC
        printf(" v%d, v%d, [obj+%04x]",
            pDecInsn->vA, pDecInsn->vB, pDecInsn->vC);
        break;
    case kFmt30t:
        printf(" #%08x", pDecInsn->vA);
        break;
    case kFmt31i:        // op vAA, #+BBBBBBBB
        {
            /* this is often, but not always, a float */
            union {
                float f;
                u4 i;
            } conv;
            conv.i = pDecInsn->vB;
            printf(" v%d, #float %f // #%08x",
                pDecInsn->vA, conv.f, pDecInsn->vB);
        }
        break;
    case kFmt31c:        // op vAA, thing@BBBBBBBB
        printf(" v%d, \"%s\" // string@%08x", pDecInsn->vA,
            dexStringById(pDexFile, pDecInsn->vB), pDecInsn->vB);
        break;
    case kFmt31t:       // op vAA, offset +BBBBBBBB
        printf(" v%d, %08x // +%08x",
            pDecInsn->vA, insnIdx + pDecInsn->vB, pDecInsn->vB);
        break;
    case kFmt32x:        // op vAAAA, vBBBB
        printf(" v%d, v%d", pDecInsn->vA, pDecInsn->vB);
        break;
    case kFmt35c:        // op vB, {vD, vE, vF, vG, vA}, thing@CCCC
        {
            /* NOTE: decoding of 35c doesn't quite match spec */
            fputs(" {", stdout);
            for (i = 0; i < (int) pDecInsn->vA; i++) {
                if (i == 0)
                    printf("v%d", pDecInsn->arg[i]);
                else
                    printf(", v%d", pDecInsn->arg[i]);
            }
            if (pDecInsn->opCode == OP_FILLED_NEW_ARRAY) {
                printf("}, %s // class@%04x",
                    getClassDescriptor(pDexFile, pDecInsn->vB), pDecInsn->vB);
            } else {
                FieldMethodInfo methInfo;
                if (getMethodInfo(pDexFile, pDecInsn->vB, &methInfo)) {
                    printf("}, %s.%s:%s // method@%04x",
                        methInfo.classDescriptor, methInfo.name,
                        methInfo.signature, pDecInsn->vB);
                } else {
                    printf("}, ??? // method@%04x", pDecInsn->vB);
                }
            }
        }
        break;
    case kFmt35ms:       // [opt] invoke-virtual+super
    case kFmt35fs:       // [opt] invoke-interface
        {
            fputs(" {", stdout);
            for (i = 0; i < (int) pDecInsn->vA; i++) {
                if (i == 0)
                    printf("v%d", pDecInsn->arg[i]);
                else
                    printf(", v%d", pDecInsn->arg[i]);
            }
            printf("}, [%04x] // vtable #%04x", pDecInsn->vB, pDecInsn->vB);
        }
        break;
    case kFmt3rc:        // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
        {
            /*
             * This doesn't match the "dx" output when some of the args are
             * 64-bit values -- dx only shows the first register.
             */
            fputs(" {", stdout);
            for (i = 0; i < (int) pDecInsn->vA; i++) {
                if (i == 0)
                    printf("v%d", pDecInsn->vC + i);
                else
                    printf(", v%d", pDecInsn->vC + i);
            }
            if (pDecInsn->opCode == OP_FILLED_NEW_ARRAY_RANGE) {
                printf("}, %s // class@%04x",
                    getClassDescriptor(pDexFile, pDecInsn->vB), pDecInsn->vB);
            } else {
                FieldMethodInfo methInfo;
                if (getMethodInfo(pDexFile, pDecInsn->vB, &methInfo)) {
                    printf("}, %s.%s:%s // method@%04x",
                        methInfo.classDescriptor, methInfo.name,
                        methInfo.signature, pDecInsn->vB);
                } else {
                    printf("}, ??? // method@%04x", pDecInsn->vB);
                }
            }
        }
        break;
    case kFmt3rms:       // [opt] invoke-virtual+super/range
    case kFmt3rfs:       // [opt] invoke-interface/range
        {
            /*
             * This doesn't match the "dx" output when some of the args are
             * 64-bit values -- dx only shows the first register.
             */
            fputs(" {", stdout);
            for (i = 0; i < (int) pDecInsn->vA; i++) {
                if (i == 0)
                    printf("v%d", pDecInsn->vC + i);
                else
                    printf(", v%d", pDecInsn->vC + i);
            }
            printf("}, [%04x] // vtable #%04x", pDecInsn->vB, pDecInsn->vB);
        }
        break;
    case kFmt3inline:    // [opt] inline invoke
        {
#if 0
            const InlineOperation* inlineOpsTable = dvmGetInlineOpsTable();
            u4 tableLen = dvmGetInlineOpsTableLength();
#endif

            fputs(" {", stdout);
            for (i = 0; i < (int) pDecInsn->vA; i++) {
                if (i == 0)
                    printf("v%d", pDecInsn->arg[i]);
                else
                    printf(", v%d", pDecInsn->arg[i]);
            }
#if 0
            if (pDecInsn->vB < tableLen) {
                printf("}, %s.%s:%s // inline #%04x",
                    inlineOpsTable[pDecInsn->vB].classDescriptor,
                    inlineOpsTable[pDecInsn->vB].methodName,
                    inlineOpsTable[pDecInsn->vB].methodSignature,
                    pDecInsn->vB);
            } else {
#endif
                printf("}, [%04x] // inline #%04x", pDecInsn->vB, pDecInsn->vB);
#if 0
            }
#endif
        }
        break;
    case kFmt51l:        // op vAA, #+BBBBBBBBBBBBBBBB
        {
            /* this is often, but not always, a double */
            union {
                double d;
                u8 j;
            } conv;
            conv.j = pDecInsn->vB_wide;
            printf(" v%d, #double %f // #%016llx",
                pDecInsn->vA, conv.d, pDecInsn->vB_wide);
        }
        break;
    case kFmtUnknown:
        break;
    default:
        printf(" ???");
        break;
    }


    putchar('\n');

}
Beispiel #13
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);
}
Beispiel #14
0
//
//START AOC_DX_MGR
//
CHAR const* AOC_DX_MGR::get_string(UINT str_idx)
{
	return dexStringById(m_df, str_idx);
}
Beispiel #15
0
/*
 * Alternate version of dvmResolveInstField().
 *
 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
 */
InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx,
    VerifyError* pFailure)
{
    DvmDex* pDvmDex = referrer->pDvmDex;
    InstField* resField;

    resField = (InstField*) dvmDexGetResolvedField(pDvmDex, ifieldIdx);
    if (resField == NULL) {
        const DexFieldId* pFieldId;
        ClassObject* resClass;

        pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx);

        /*
         * Find the field's class.
         */
        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
        if (resClass == NULL) {
            //dvmClearOptException(dvmThreadSelf());
            assert(!dvmCheckException(dvmThreadSelf()));
            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
            return NULL;
        }

        resField = (InstField*)dvmFindFieldHier(resClass,
            dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
            dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
        if (resField == NULL) {
            ALOGD("DexOpt: couldn't find field %s.%s",
                resClass->descriptor,
                dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_NO_FIELD;
            return NULL;
        }
        if (dvmIsStaticField(resField)) {
            ALOGD("DexOpt: wanted instance, got static for field %s.%s",
                resClass->descriptor,
                dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_CLASS_CHANGE;
            return NULL;
        }

        /*
         * Add it to the resolved table so we're faster on the next lookup.
         */
        dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*) resField);
    }

    /* access allowed? */
    tweakLoader(referrer, resField->clazz);
    bool allowed = dvmCheckFieldAccess(referrer, (Field*)resField);
    untweakLoader(referrer, resField->clazz);
    if (!allowed) {
        ALOGI("DexOpt: access denied from %s to field %s.%s",
            referrer->descriptor, resField->clazz->descriptor,
            resField->name);
        if (pFailure != NULL)
            *pFailure = VERIFY_ERROR_ACCESS_FIELD;
        return NULL;
    }

    return resField;
}
/*
 * Dump the class.
 */
void dumpClass(DexFile* pDexFile, int idx)
{
    const DexTypeList* pInterfaces;
    const DexClassDef* pClassDef;
    DexClassData* pClassData;
    const u1* pEncodedData;
    const char* fileName;
    const char* classDescriptor;
    const char* superclassDescriptor;
    char* accessStr;
    int i;

    pClassDef = dexGetClassDef(pDexFile, idx);
    printf("Class #%d            -\n", idx);

    pEncodedData = dexGetClassData(pDexFile, pClassDef);
    pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);

    if (pClassData == NULL) {
        printf("Trouble reading class data\n");
        return;
    }
    
    classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
    printf("  Class descriptor  : '%s'\n", classDescriptor);

    accessStr = createAccessFlagStr(pClassDef->accessFlags, kAccessForClass);
    printf("  Access flags      : 0x%04x (%s)\n",
        pClassDef->accessFlags, accessStr);

    if (pClassDef->superclassIdx == kDexNoIndex)
        superclassDescriptor = "(none)";
    else {
        superclassDescriptor =
            dexStringByTypeIdx(pDexFile, pClassDef->superclassIdx);
        printf("  Superclass        : '%s'\n", superclassDescriptor);
    }

    printf("  Interfaces        -\n");
    pInterfaces = dexGetInterfacesList(pDexFile, pClassDef);
    if (pInterfaces != NULL) {
        for (i = 0; i < (int) pInterfaces->size; i++)
            dumpInterface(pDexFile, dexGetTypeItem(pInterfaces, i), i);
    }

    printf("  Static fields     -\n");
    for (i = 0; i < (int) pClassData->header.staticFieldsSize; i++) {
        dumpSField(pDexFile, &pClassData->staticFields[i], i);
    }

    printf("  Instance fields   -\n");
    for (i = 0; i < (int) pClassData->header.instanceFieldsSize; i++) {
        dumpIField(pDexFile, &pClassData->instanceFields[i], i);
    }

    printf("  Direct methods    -\n");
    for (i = 0; i < (int) pClassData->header.directMethodsSize; i++) {
        dumpMethod(pDexFile, &pClassData->directMethods[i], i);
    }

    printf("  Virtual methods   -\n");
    for (i = 0; i < (int) pClassData->header.virtualMethodsSize; i++) {
        dumpMethod(pDexFile, &pClassData->virtualMethods[i], i);
    }

    // TODO: Annotations.

    if (pClassDef->sourceFileIdx != kDexNoIndex)
        fileName = dexStringById(pDexFile, pClassDef->sourceFileIdx);
    else
        fileName = "unknown";
    printf("  source_file_idx   : %d (%s)\n",
        pClassDef->sourceFileIdx, fileName);

    printf("\n");

    free(pClassData);
    free(accessStr);
}
Beispiel #17
0
/* (documented in header file) */
const char* dexProtoGetShorty(const DexProto* pProto) {
    const DexProtoId* protoId = getProtoId(pProto);

    return dexStringById(pProto->dexFile, protoId->shortyIdx);
}
Beispiel #18
0
/*
 * 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;
}
Beispiel #19
0
/*
 * 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;
}
Beispiel #20
0
/*
 * Alternate version of dvmResolveStaticField().
 *
 * Does not force initialization of the resolved field's class.
 *
 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
 */
StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx,
    VerifyError* pFailure)
{
    DvmDex* pDvmDex = referrer->pDvmDex;
    StaticField* resField;

    resField = (StaticField*)dvmDexGetResolvedField(pDvmDex, sfieldIdx);
    if (resField == NULL) {
        const DexFieldId* pFieldId;
        ClassObject* resClass;

        pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx);

        /*
         * Find the field's class.
         */
        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
        if (resClass == NULL) {
            //dvmClearOptException(dvmThreadSelf());
            assert(!dvmCheckException(dvmThreadSelf()));
            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
            return NULL;
        }

        const char* fieldName =
            dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);

        resField = (StaticField*)dvmFindFieldHier(resClass, fieldName,
                    dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
        if (resField == NULL) {
            ALOGD("DexOpt: couldn't find static field %s.%s",
                resClass->descriptor, fieldName);
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_NO_FIELD;
            return NULL;
        }
        if (!dvmIsStaticField(resField)) {
            ALOGD("DexOpt: wanted static, got instance for field %s.%s",
                resClass->descriptor, fieldName);
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_CLASS_CHANGE;
            return NULL;
        }

        /*
         * Add it to the resolved table so we're faster on the next lookup.
         *
         * We can only do this if we're 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 (gDvm.optimizing)
            dvmDexSetResolvedField(pDvmDex, sfieldIdx, (Field*) resField);
    }

    /* access allowed? */
    tweakLoader(referrer, resField->clazz);
    bool allowed = dvmCheckFieldAccess(referrer, (Field*)resField);
    untweakLoader(referrer, resField->clazz);
    if (!allowed) {
        ALOGI("DexOpt: access denied from %s to field %s.%s",
            referrer->descriptor, resField->clazz->descriptor,
            resField->name);
        if (pFailure != NULL)
            *pFailure = VERIFY_ERROR_ACCESS_FIELD;
        return NULL;
    }

    return resField;
}
Beispiel #21
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);
        }