Esempio n. 1
0
void main(int argc, char **argv) {
	int i;

	void *libdvm = dlopen("libdvm.so", RTLD_LAZY);

	if (libdvm == NULL) {
		printf("Failed to load libdvm: %s\n", dlerror());
		return;
	}

	dvmGetInlineOpsTablePtr dvmGetInlineOpsTable = dlsym(libdvm, "dvmGetInlineOpsTable");

	if (dvmGetInlineOpsTable == NULL) {
		// clear the error, and retry with the c++ mangled name
		dlerror();
		dvmGetInlineOpsTable = dlsym(libdvm, "_Z20dvmGetInlineOpsTablev");
	}

	if (dvmGetInlineOpsTable == NULL) {
		printf("Failed to load dvmGetInlineOpsTable: %s\n", dlerror());
		dlclose(libdvm);
		return;
	}

	dvmGetInlineOpsTableLengthPtr dvmGetInlineOpsTableLength = dlsym(libdvm, "dvmGetInlineOpsTableLength");

	if (dvmGetInlineOpsTableLength == NULL) {
		// clear the error, and retry with the c++ mangled name
		dlerror();
		dvmGetInlineOpsTableLength = dlsym(libdvm, "_Z26dvmGetInlineOpsTableLengthv");
	}

	if (dvmGetInlineOpsTableLength == NULL) {
		printf("Failed to load dvmGetInlineOpsTableLength: %s\n", dlerror());
		dlclose(libdvm);
		return;
	}

	const InlineOperation *inlineTable = dvmGetInlineOpsTable();
	int length = dvmGetInlineOpsTableLength();

	for (i=0; i<length; i++) {
		InlineOperation *item = &inlineTable[i];

		printf("%s->%s%s\n", item->classDescriptor, item->methodName, item->methodSignature);
	}

	dlclose(libdvm);
	return;
}
Esempio n. 2
0
/*
 * Create a table of inline substitutions.  Sets gDvm.inlineSubs.
 *
 * TODO: this is currently just a linear array.  We will want to put this
 * into a hash table as the list size increases.
 */
bool dvmCreateInlineSubsTable()
{
    const InlineOperation* ops = dvmGetInlineOpsTable();
    const int count = dvmGetInlineOpsTableLength();
    InlineSub* table;
    int i, tableIndex;

    assert(gDvm.inlineSubs == NULL);

    /*
     * One slot per entry, plus an end-of-list marker.
     */
    table = (InlineSub*) calloc(count + 1, sizeof(InlineSub));
    if (!table)
    {
      ALOGE("table allocation failed");
      return false;
    }

    tableIndex = 0;
    for (i = 0; i < count; i++) {
        Method* method = dvmFindInlinableMethod(ops[i].classDescriptor,
            ops[i].methodName, ops[i].methodSignature);
        if (method == NULL) {
            /*
             * Not expected.  We only use this for key methods in core
             * classes, so we should always be able to find them.
             */
            ALOGE("Unable to find method for inlining: %s.%s:%s",
                ops[i].classDescriptor, ops[i].methodName,
                ops[i].methodSignature);
            free(table);
            return false;
        }

        table[tableIndex].method = method;
        table[tableIndex].inlineIdx = i;
        tableIndex++;
    }

    /* mark end of table */
    table[tableIndex].method = NULL;

    gDvm.inlineSubs = table;
    return true;
}
Esempio n. 3
0
static jobject getInlineOperation(JNIEnv* env, jclass obj) {
	int i;
	void *libdvm = dlopen("libdvm.so", RTLD_LAZY);
	if (libdvm == NULL) {
		LOGV("Failed to load libdvm\n");
		return;
	}
	dvmGetInlineOpsTablePtr dvmGetInlineOpsTable = dlsym(libdvm, "dvmGetInlineOpsTable");
	if (dvmGetInlineOpsTable == NULL) {
		dvmGetInlineOpsTable = dlsym(libdvm, "_Z20dvmGetInlineOpsTablev");
	}
	if (dvmGetInlineOpsTable == NULL) {
		LOGV("Failed to load dvmGetInlineOpsTable\n");
		dlclose(libdvm);
		return;
	}
	dvmGetInlineOpsTableLengthPtr dvmGetInlineOpsTableLength = dlsym(libdvm, "dvmGetInlineOpsTableLength");
	if (dvmGetInlineOpsTableLength == NULL) {
		dvmGetInlineOpsTableLength = dlsym(libdvm, "_Z26dvmGetInlineOpsTableLengthv");
	}
	if (dvmGetInlineOpsTableLength == NULL) {
		printf("Failed to load dvmGetInlineOpsTableLength\n");
		dlclose(libdvm);
		return;
	}
    jclass  stringBuilder_class = (*env)->FindClass(env,"java/lang/StringBuilder"); 
    jmethodID initMethod = (*env)->GetMethodID(env,stringBuilder_class,"<init>","()V");  
	jobject stringBuilder_obj = (*env)->NewObject(env,stringBuilder_class,initMethod); 
	jmethodID stringbuilder_append =  (*env)->GetMethodID(env,stringBuilder_class,"append","(Ljava/lang/String;)Ljava/lang/StringBuilder;");
	jmethodID tostring_method =  (*env)->GetMethodID(env,stringBuilder_class,"toString","()Ljava/lang/String;");
	const InlineOperation *inlineTable = dvmGetInlineOpsTable();
	int length = dvmGetInlineOpsTableLength();
    char* buffer = malloc(400);
	for (i=0; i<length; i++) {
		InlineOperation *item = &inlineTable[i];
		sprintf(buffer,"%s->%s%s\n", item->classDescriptor, item->methodName, item->methodSignature);
		jstring descror = (*env)->NewStringUTF(env,buffer);
		(*env)->CallObjectMethod(env,stringBuilder_obj,stringbuilder_append,descror);
	}
	dlclose(libdvm);
	return (*env)->CallObjectMethod(env,stringBuilder_obj,tostring_method);
}
/*
 * 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');

}