// 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); }
// 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'); } }