// Based on dvmResolveInstField/dvmResolveStaticField. static void preloadDexCachesResolveField(DvmDex* pDvmDex, uint32_t fieldIdx, bool instance) { Field* field = dvmDexGetResolvedField(pDvmDex, fieldIdx); if (field != NULL) { return; } const DexFile* pDexFile = pDvmDex->pDexFile; const DexFieldId* pFieldId = dexGetFieldId(pDexFile, fieldIdx); ClassObject* clazz = dvmDexGetResolvedClass(pDvmDex, pFieldId->classIdx); if (clazz == NULL) { return; } // Skip static fields for uninitialized classes because a filled // cache entry implies the class is initialized. if (!instance && !dvmIsClassInitialized(clazz)) { return; } const char* fieldName = dexStringById(pDexFile, pFieldId->nameIdx); const char* signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx); if (instance) { field = dvmFindInstanceFieldHier(clazz, fieldName, signature); } else { field = dvmFindStaticFieldHier(clazz, fieldName, signature); } if (field == NULL) { return; } // ALOGI("VMRuntime.preloadDexCaches found field %s %s.%s", // signature, clazz->descriptor, fieldName); dvmDexSetResolvedField(pDvmDex, fieldIdx, field); }
//field_id: field number in dexfile. CHAR const* AOC_DX_MGR::get_field_name(UINT field_idx) { DexFieldId const* fid = dexGetFieldId(m_df, field_idx); IS_TRUE0(fid); //Get field's name via nameIdx in symbol table. return dexStringById(m_df, fid->nameIdx); }
//field_id: field number in dexfile. CHAR const* get_field_name(DexFile * df, UINT field_id) { DexFieldId const* fid = dexGetFieldId(df, field_id); IS_TRUE0(fid); //Get field's name via nameIdx in symbol table. return dexStringById(df, fid->nameIdx); }
//field_id: field number in dexfile. CHAR const* get_field_type_name(DexFile * df, UINT field_id) { DexFieldId const* fid = dexGetFieldId(df, field_id); IS_TRUE0(fid); //Get field's type name. return dexStringByTypeIdx(df, fid->typeIdx); }
/* * Resolve a static field reference. The DexFile format doesn't distinguish * between static and instance field references, so the "resolved" pointer * in the Dex struct will have the wrong type. We trivially cast it here. * * Causes the field's class to be initialized. */ StaticField* dvmResolveStaticField(const ClassObject* referrer, u4 sfieldIdx) { DvmDex* pDvmDex = referrer->pDvmDex; ClassObject* resClass; const DexFieldId* pFieldId; StaticField* resField; pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx); /* * Find the field's class. */ resClass = dvmResolveClass(referrer, pFieldId->classIdx, false); if (resClass == NULL) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } resField = dvmFindStaticFieldHier(resClass, dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx), dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx)); if (resField == NULL) { dvmThrowNoSuchFieldError( dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx)); return NULL; } /* * If we're the first to resolve the field in which this class resides, * we need to do it now. Note that, if the field was inherited from * a superclass, it is not necessarily the same as "resClass". */ if (!dvmIsClassInitialized(resField->clazz) && !dvmInitClass(resField->clazz)) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } /* * If the class has been initialized, add a pointer to our data structure * so we don't have to jump through the hoops again. If it's still * initializing (i.e. this thread is executing <clinit>), don't do * the store, otherwise other threads could use the field without waiting * for class init to finish. */ if (dvmIsClassInitialized(resField->clazz)) { dvmDexSetResolvedField(pDvmDex, sfieldIdx, (Field*) resField); } else { LOGVV("--- not caching resolved field %s.%s (class init=%d/%d)", resField->clazz->descriptor, resField->name, dvmIsClassInitializing(resField->clazz), dvmIsClassInitialized(resField->clazz)); } return resField; }
/* * Resolve an instance field reference. * * Returns NULL and throws an exception on error (no such field, illegal * access). */ InstField* dvmResolveInstField(const ClassObject* referrer, u4 ifieldIdx) { DvmDex* pDvmDex = referrer->pDvmDex; ClassObject* resClass; const DexFieldId* pFieldId; InstField* resField; LOGVV("--- resolving field %u (referrer=%s cl=%p)", ifieldIdx, referrer->descriptor, referrer->classLoader); pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx); /* * Find the field's class. */ resClass = dvmResolveClass(referrer, pFieldId->classIdx, false); if (resClass == NULL) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } resField = dvmFindInstanceFieldHier(resClass, dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx), dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx)); if (resField == NULL) { dvmThrowNoSuchFieldError( dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx)); return NULL; } /* * Class must be initialized by now (unless verifier is buggy). We * could still be in the process of initializing it if the field * access is from a static initializer. */ assert(dvmIsClassInitialized(resField->clazz) || dvmIsClassInitializing(resField->clazz)); /* * The class is initialized (or initializing), the field has been * found. Add a pointer to our data structure so we don't have to * jump through the hoops again. * * Anything that uses the resolved table entry must have an instance * of the class, so any class init activity has already happened (or * been deliberately bypassed when <clinit> created an instance). * So it's always okay to update the table. */ dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*)resField); LOGVV(" field %u is %s.%s", ifieldIdx, resField->clazz->descriptor, resField->name); return resField; }
/* * 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; }
/* * Resolve an instance field reference. * * Returns NULL and throws an exception on error (no such field, illegal * access). */ InstField* dvmResolveInstField(const ClassObject* referrer, u4 ifieldIdx) { DvmDex* pDvmDex = referrer->pDvmDex; ClassObject* resClass; const DexFieldId* pFieldId; InstField* resField; LOGVV("--- resolving field %u (referrer=%s cl=%p)\n", ifieldIdx, referrer->descriptor, referrer->classLoader); pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx); /* * Find the field's class. */ resClass = dvmResolveClass(referrer, pFieldId->classIdx, false); if (resClass == NULL) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } resField = dvmFindInstanceFieldHier(resClass, dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx), dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx)); if (resField == NULL) { dvmThrowException("Ljava/lang/NoSuchFieldError;", dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx)); return NULL; } /* * Class must be initialized by now (unless verifier is buggy). We * could still be in the process of initializing it if the field * access is from a static initializer. */ assert(dvmIsClassInitialized(resField->field.clazz) || dvmIsClassInitializing(resField->field.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. */ dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*)resField); LOGVV(" field %u is %s.%s\n", ifieldIdx, resField->field.clazz->descriptor, resField->field.name); return resField; }
/* * Resolve a static field reference. The DexFile format doesn't distinguish * between static and instance field references, so the "resolved" pointer * in the Dex struct will have the wrong type. We trivially cast it here. * * Causes the field's class to be initialized. */ StaticField* dvmResolveStaticField(const ClassObject* referrer, u4 sfieldIdx) { DvmDex* pDvmDex = referrer->pDvmDex; ClassObject* resClass; const DexFieldId* pFieldId; StaticField* resField; pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx); /* * Find the field's class. */ resClass = dvmResolveClass(referrer, pFieldId->classIdx, false); if (resClass == NULL) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } resField = dvmFindStaticFieldHier(resClass, dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx), dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx)); if (resField == NULL) { dvmThrowException("Ljava/lang/NoSuchFieldError;", dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx)); return NULL; } /* * If we're the first to resolve the field in which this class resides, * we need to do it now. Note that, if the field was inherited from * a superclass, it is not necessarily the same as "resClass". */ if (!dvmIsClassInitialized(resField->field.clazz) && !dvmInitClass(resField->field.clazz)) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } /* * 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. */ dvmDexSetResolvedField(pDvmDex, sfieldIdx, (Field*) resField); return resField; }
/* * 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); }
//Return the class name which 'field_id' was place in. CHAR const* get_field_class_name(DexFile * df, UINT field_id) { DexFieldId const* fid = dexGetFieldId(df, field_id); IS_TRUE0(fid); return dexStringByTypeIdx(df, fid->classIdx); }
CHAR const* AOC_DX_MGR::get_class_name_by_field_id(UINT field_idx) { DexFieldId const* fid = dexGetFieldId(m_df, field_idx); IS_TRUE0(fid); return dexStringByTypeIdx(m_df, fid->classIdx); }
/* * 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; }
/* * 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; }