/*
 * 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);
}
Exemple #9
0
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;
    }