/* * static void dumpHprofData(String fileName, FileDescriptor fd) * * Cause "hprof" data to be dumped. We can throw an IOException if an * error occurs during file handling. */ static void Dalvik_dalvik_system_VMDebug_dumpHprofData(const u4* args, JValue* pResult) { StringObject* fileNameStr = (StringObject*) args[0]; Object* fileDescriptor = (Object*) args[1]; char* fileName; int result; /* * Only one of these may be NULL. */ if (fileNameStr == NULL && fileDescriptor == NULL) { dvmThrowNullPointerException("fileName == null && fd == null"); RETURN_VOID(); } if (fileNameStr != NULL) { fileName = dvmCreateCstrFromString(fileNameStr); if (fileName == NULL) { /* unexpected -- malloc failure? */ dvmThrowRuntimeException("malloc failure?"); RETURN_VOID(); } } else { fileName = strdup("[fd]"); } int fd = -1; if (fileDescriptor != NULL) { fd = getFileDescriptor(fileDescriptor); if (fd < 0) { free(fileName); RETURN_VOID(); } } result = hprofDumpHeap(fileName, fd, false); free(fileName); if (result != 0) { /* ideally we'd throw something more specific based on actual failure */ dvmThrowRuntimeException( "Failure during heap dump; check log output for details"); RETURN_VOID(); } RETURN_VOID(); }
void fastiva_Dalvik_dalvik_system_VMRuntime_registerNativeFree(dalvik_system_VMRuntime_p self, jint bytes) { #endif if (bytes < 0) { dvmThrowRuntimeException("allocation size negative"); } else { dvmHeapSourceRegisterNativeFree(bytes); } RETURN_VOID(); }
/* * private static int openDexFile(byte[] fileContents) throws IOException * * Open a DEX file represented in a byte[], returning a pointer to our * internal data structure. * 打开一个字节数组表示的DEX文件,返回指针指向的内部数据结构 * * The system will only perform "essential" optimizations on the given file. * * TODO: should be using "long" for a pointer. */ static void Dalvik_dalvik_system_DexFile_openDexFile_bytearray(const u4* args, JValue* pResult) { ArrayObject* fileContentsObj = (ArrayObject*) args[0]; u4 length; u1* pBytes; RawDexFile* pRawDexFile; DexOrJar* pDexOrJar = NULL; if (fileContentsObj == NULL) { dvmThrowNullPointerException("fileContents == null"); RETURN_VOID(); } /* TODO: Avoid making a copy of the array. (note array *is* modified) */ length = fileContentsObj->length; pBytes = (u1*) malloc(length); if (pBytes == NULL) { dvmThrowRuntimeException("unable to allocate DEX memory"); RETURN_VOID(); } memcpy(pBytes, fileContentsObj->contents, length); if (dvmRawDexFileOpenArray(pBytes, length, &pRawDexFile) != 0) { ALOGV("Unable to open in-memory DEX file"); free(pBytes); dvmThrowRuntimeException("unable to open in-memory DEX file"); RETURN_VOID(); } ALOGV("Opening in-memory DEX"); pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar)); pDexOrJar->isDex = true; pDexOrJar->pRawDexFile = pRawDexFile; pDexOrJar->pDexMemory = pBytes; pDexOrJar->fileName = strdup("<memory>"); // Needs to be free()able. addToDexFileTable(pDexOrJar); RETURN_PTR(pDexOrJar); }
static void Dalvik_dalvik_system_VMRuntime_registerNativeFree(const u4* args, JValue* pResult) { int bytes = args[1]; if (bytes < 0) { dvmThrowRuntimeException("allocation size negative"); } else { dvmHeapSourceRegisterNativeFree(bytes); } RETURN_VOID(); }
/* * Extracts the fd from a FileDescriptor object. * * If an error is encountered, or the extracted descriptor is numerically * invalid, this returns -1 with an exception raised. */ static int getFileDescriptor(Object* obj) { assert(obj != NULL); assert(strcmp(obj->clazz->descriptor, "Ljava/io/FileDescriptor;") == 0); int fd = dvmGetFieldInt(obj, gDvm.offJavaIoFileDescriptor_descriptor); if (fd < 0) { dvmThrowRuntimeException("Invalid file descriptor"); return -1; } return fd; }
/* * static void dumpHprofDataDdms() * * Cause "hprof" data to be computed and sent directly to DDMS. */ static void Dalvik_dalvik_system_VMDebug_dumpHprofDataDdms(const u4* args, JValue* pResult) { int result; result = hprofDumpHeap("[DDMS]", -1, true); if (result != 0) { /* ideally we'd throw something more specific based on actual failure */ dvmThrowRuntimeException( "Failure during heap dump; check log output for details"); RETURN_VOID(); } RETURN_VOID(); }
/* * Verify that the "cookie" is a DEX file we opened. * * Expects that the hash table will be *unlocked* here. * * If the cookie is invalid, we throw an exception and return "false". */ static bool validateCookie(int cookie) { DexOrJar* pDexOrJar = (DexOrJar*) cookie; LOGVV("+++ dex verifying cookie %p", pDexOrJar); if (pDexOrJar == NULL) return false; u4 hash = cookie; dvmHashTableLock(gDvm.userDexFiles); void* result = dvmHashTableLookup(gDvm.userDexFiles, hash, pDexOrJar, hashcmpDexOrJar, false); dvmHashTableUnlock(gDvm.userDexFiles); if (result == NULL) { dvmThrowRuntimeException("invalid DexFile cookie"); return false; } return true; }
/* * static boolean cacheRegisterMap(String classAndMethodDescr) * * If the specified class is loaded, and the named method exists, ensure * that the method's register map is ready for use. If the class/method * cannot be found, nothing happens. * * This can improve the zygote's sharing of compressed register maps. Do * this after class preloading. * * Returns true if the register map is cached and ready, either as a result * of this call or earlier activity. Returns false if the class isn't loaded, * if the method couldn't be found, or if the method has no register map. * * (Uncomment logs in dvmGetExpandedRegisterMap0() to gather stats.) */ static void Dalvik_dalvik_system_VMDebug_cacheRegisterMap(const u4* args, JValue* pResult) { StringObject* classAndMethodDescStr = (StringObject*) args[0]; ClassObject* clazz; bool result = false; if (classAndMethodDescStr == NULL) { dvmThrowNullPointerException("classAndMethodDesc == null"); RETURN_VOID(); } char* classAndMethodDesc = NULL; /* * Pick the string apart. We have a local copy, so just modify it * in place. */ classAndMethodDesc = dvmCreateCstrFromString(classAndMethodDescStr); char* methodName = strchr(classAndMethodDesc, '.'); if (methodName == NULL) { dvmThrowRuntimeException("method name not found in string"); RETURN_VOID(); } *methodName++ = '\0'; char* methodDescr = strchr(methodName, ':'); if (methodDescr == NULL) { dvmThrowRuntimeException("method descriptor not found in string"); RETURN_VOID(); } *methodDescr++ = '\0'; //ALOGD("GOT: %s %s %s", classAndMethodDesc, methodName, methodDescr); /* * Find the class, but only if it's already loaded. */ clazz = dvmLookupClass(classAndMethodDesc, NULL, false); if (clazz == NULL) { ALOGD("Class %s not found in bootstrap loader", classAndMethodDesc); goto bail; } Method* method; /* * Find the method, which could be virtual or direct, defined directly * or inherited. */ if (methodName[0] == '<') { /* * Constructor or class initializer. Only need to examine the * "direct" list, and don't need to search up the class hierarchy. */ method = dvmFindDirectMethodByDescriptor(clazz, methodName, methodDescr); } else { /* * Try both lists, and scan up the tree. */ method = dvmFindVirtualMethodHierByDescriptor(clazz, methodName, methodDescr); if (method == NULL) { method = dvmFindDirectMethodHierByDescriptor(clazz, methodName, methodDescr); } } if (method != NULL) { /* * Got it. See if there's a register map here. */ const RegisterMap* pMap; pMap = dvmGetExpandedRegisterMap(method); if (pMap == NULL) { ALOGV("No map for %s.%s %s", classAndMethodDesc, methodName, methodDescr); } else { ALOGV("Found map %s.%s %s", classAndMethodDesc, methodName, methodDescr); result = true; } } else { ALOGV("Unable to find %s.%s %s", classAndMethodDesc, methodName, methodDescr); } bail: free(classAndMethodDesc); RETURN_BOOLEAN(result); }
GOTO_TARGET(filledNewArray, bool methodCallRange, bool) { ClassObject* arrayClass; ArrayObject* newArray; u4* contents; char typeCh; int i; u4 arg5; EXPORT_PC(); ref = FETCH(1); /* class ref */ vdst = FETCH(2); /* first 4 regs -or- range base */ if (methodCallRange) { vsrc1 = INST_AA(inst); /* #of elements */ arg5 = -1; /* silence compiler warning */ ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}", vsrc1, ref, vdst, vdst+vsrc1-1); } else { arg5 = INST_A(inst); vsrc1 = INST_B(inst); /* #of elements */ ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}", vsrc1, ref, vdst, arg5); } /* * Resolve the array class. */ arrayClass = dvmDexGetResolvedClass(methodClassDex, ref); if (arrayClass == NULL) { arrayClass = dvmResolveClass(curMethod->clazz, ref, false); if (arrayClass == NULL) GOTO_exceptionThrown(); } /* if (!dvmIsArrayClass(arrayClass)) { dvmThrowRuntimeException( "filled-new-array needs array class"); GOTO_exceptionThrown(); } */ /* verifier guarantees this is an array class */ assert(dvmIsArrayClass(arrayClass)); assert(dvmIsClassInitialized(arrayClass)); /* * Create an array of the specified type. */ LOGVV("+++ filled-new-array type is '%s'", arrayClass->descriptor); typeCh = arrayClass->descriptor[1]; if (typeCh == 'D' || typeCh == 'J') { /* category 2 primitives not allowed */ dvmThrowRuntimeException("bad filled array req"); GOTO_exceptionThrown(); } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') { /* TODO: requires multiple "fill in" loops with different widths */ ALOGE("non-int primitives not implemented"); dvmThrowInternalError( "filled-new-array not implemented for anything but 'int'"); GOTO_exceptionThrown(); } newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK); if (newArray == NULL) GOTO_exceptionThrown(); /* * Fill in the elements. It's legal for vsrc1 to be zero. */ contents = (u4*)(void*)newArray->contents; if (methodCallRange) { for (i = 0; i < vsrc1; i++) contents[i] = GET_REGISTER(vdst+i); } else { assert(vsrc1 <= 5); if (vsrc1 == 5) { contents[4] = GET_REGISTER(arg5); vsrc1--; } for (i = 0; i < vsrc1; i++) { contents[i] = GET_REGISTER(vdst & 0x0f); vdst >>= 4; } } if (typeCh == 'L' || typeCh == '[') { dvmWriteBarrierArray(newArray, 0, newArray->length); } retval.l = (Object*)newArray; }