Example #1
0
// Verify the bytecode of one method m from class file cf
static void verifyMethod( ClassFile *cf, method_info *m ) {
    char *name = GetCPItemAsString(cf, m->name_index);
    char *retType;
    int numSlots = m->max_locals + m->max_stack;

    // initState is an array of strings, it has numSlots elements
    // retType describes the result type of this method
    char **initState = MapSigToInitState(cf, m, &retType);

    if (tracingExecution & TRACE_VERIFY)
    	printTypeCodesArray(initState, m, name);

    // Your code to verify the bytecode of the current method
    // begins here.

    // Feel free to define and use as many extra functions as
    // are appropriate for this problem.

    // Do include tracing output statements in your code
    // controlled by the tracingExecution variable to help
    // you debug the verification algorithm.

    FreeTypeDescriptorArray(initState, numSlots);
    SafeFree(name);
}
Example #2
0
// Given the immediate operand of a getfield or putfield instruction (which
// is an index into the constant pool), this function returns a string which
// represents the datatype of that field.
char *FieldTypeCode( ClassFile *cf, int ix ) {
    char *result = "";
    char *s = GetCPItemAsString(cf, ix);
    char *rp = strrchr(s, ':'); // find last occurrence of ':'
    assert(rp != NULL);
    ExtractOneType(&result, rp+1);
    SafeFree(s);
    return result;
}
void PrintByteCode( ClassFile *cf, uint8_t *code, int len ) {
    int ix = 0;
    while(ix < len) {
        int opcodeAddr = ix;
        uint8_t op = code[ix++];
        char *opname = OPCodeFormat[op].name;
        char *fmt = OPCodeFormat[op].opnds_format;
        printf("    %3d: %s", opcodeAddr, opname);
        if (fmt != NULL) {
            int opndCnt = 0;
            int dest, low, high, npairs;
            int cpref = 0;
            char *cptype = NULL;
            while(*fmt != '\0') {
                char f = *fmt++;
                if (f != '0') {
                    if (opndCnt++ > 0) putchar(',');
                    putchar(' ');
                }
                switch(f) {
                case 'v': /* one byte index to a local variable */
                    printf(" %d", code[ix++]);
                    break;
                case 'T': /* type (class/array/interface) ref,
                            as a two byte index into the constant pool */
                    cpref = uget2(code,ix);
                    cptype = "Type";
                    printf(" #%d", cpref);
                    ix += 2;
                    break;
                case 'C': /* class ref, as a two byte index into the constant pool */
                    cpref = uget2(code,ix);
                    cptype = "Class";
                    printf(" #%d", cpref);
                    ix += 2;
                    break;
                case 'u': /* one byte unsigned immediate integer */
                    printf(" %d", code[ix]);
                    ix++;
                    break;
                case 's': /* one byte signed immediate integer */
                    printf(" %d", (signed char)code[ix]);
                    ix++;
                    break;
                case 'F': /* field ref, as a two byte index into the constant pool */
                    cpref = uget2(code,ix);
                    cptype = "Field";
                    printf(" #%d", cpref);
                    ix += 2;
                    break;
                case 'I': /* interface ref, as a two byte index into the constant pool */
                    cpref = uget2(code,ix);
                    cptype = "Interface";
                    printf(" #%d", cpref);
                    ix += 2;
                    break;
                case 'b': /* two byte branch destination */
                    dest = opcodeAddr + iget2(code,ix);
                    printf(" %d", dest);
                    ix += 2;
                    break;
                case 'B': /* four byte branch destination */
                    printf(" %d", (int)(opcodeAddr + iget4(code,ix)));
                    ix += 4;
                    break;
                case 'M': /* method ref, as a two byte index into the constant pool */
                    cpref = uget2(code,ix);
                    cptype = "Method";
                    printf(" #%d", cpref);
                    ix += 2;
                    break;
                case 'k': /* simple constant in constant pool, one byte index */
                    cpref = code[ix];
                    cptype = " ";
                    printf(" #%d", cpref);
                    ix++;
                    break;
                case 'K': /* simple constant in constant pool, two byte index */
                    cpref = uget2(code,ix);
                    cptype = " ";
                    printf(" #%d", cpref);
                    ix += 2;
                    break;
                case 'a': /* one byte primitive type */
                    dest = code[ix] & 0xff;
                    if (dest >= 12) dest = 0;
                    printf(" %s", basicType[dest]);
                    ix++;
                    break;
                case 'S': /* two byte signed immediate integer */
                    printf(" %d", iget2(code,ix));
                    ix += 2;
                    break;
                case '*': /* lookupswitch */
                    ix = (ix + 3) & 0xFFFFFFFC;  /* skip over padding bytes */
                    printf("\n          default: %d\n",
                        (int)(opcodeAddr + iget4(code,ix)));
                    ix += 4;
                    npairs = iget4(code,ix);  ix += 4;
                    while(npairs-- > 0) {
                        printf("          case %d:", iget4(code,ix));  ix += 4;
                        printf(" %d\n", opcodeAddr + iget4(code,ix));  ix += 4;
                    }
                    break;
                case '&': /* tableswitch */
                    ix = (ix + 3) & 0xFFFFFFFC;  /* skip over padding bytes */
                    printf("\n          default: %d\n",
                        opcodeAddr + iget4(code,ix));
                    ix += 4;
                    low  = iget4(code,ix);  ix += 4;
                    high = iget4(code,ix);  ix += 4;
                    while(low <= high) {
                        printf("          case %d:", low++);
                        printf(" %d\n", opcodeAddr + iget4(code,ix));  ix += 4;
                    }
                    break;
                case 'w':  /* wide */
                    op = code[ix++];  /* the op being modified by wide */
                    printf("-%s %d", OPCodeFormat[op].name, uget2(code,ix));
                    ix += 2;
                    if (op == 0x84) { /* iinc -- Format 2 */
                        printf(", %d", iget2(code,ix));
                        ix += 2;
                    }
                    break;
                case '0': /* a zero byte */
                    ix++;
                    break;
                default:
                    fprintf(stderr, "bad operand format code; op=%s, code=%c\n",
                        opname, fmt[-1]);
                    printf(" ???\n");
                    return;
                }
            }
            if (cptype != NULL)
                printf(";  //%s %s", cptype, GetCPItemAsString(cf, cpref));
        }
        putchar('\n');
    }
}