📄 pvmjac.c
字号:
const void *attr = pre_method_code(method); const char *annotation = jac_get_method_annotation(commitments, constant_pool, method_index); ju2 max_locals = pre_attribute_code_max_locals(attr); ju2 i = 0; if (annotation != 0) { /* Type for this */ if (! pre_method_is_static(method)) { state->locals[i] = *annotation; ++i; } ++annotation; /* Skip left bracket */ ++annotation; /* Initialize arguments */ while (*annotation != J_ASCII_rbracket) { state->locals[i] = *annotation; ++annotation; ++i; } } else { const char *descriptor = pre_classfile_method_descriptor(classfile, method_index); /* Type for this */ if (! pre_method_is_static(method)) { state->locals[i] = JAC_TYP_Writable; ++i; } /* Skip left bracket */ ++descriptor; /* Initialize arguments */ while (*descriptor != J_ASCII_rbracket) { switch (*descriptor) { case J_ASCII_boolean: case J_ASCII_byte: case J_ASCII_char: case J_ASCII_short: case J_ASCII_int: case J_ASCII_float: state->locals[i] = JAC_TYP_Writable; ++i; ++descriptor; break; case J_ASCII_long: case J_ASCII_double: state->locals[i] = JAC_TYP_Writable; ++i; state->locals[i] = JAC_TYP_Writable; ++i; ++descriptor; break; case J_ASCII_reference: state->locals[i] = JAC_TYP_Writable; ++i; do { ++descriptor; } while (*descriptor != J_ASCII_terminator); ++descriptor; break; case J_ASCII_array: state->locals[i] = JAC_TYP_Writable; ++i; do { ++descriptor; } while (*descriptor == J_ASCII_array); switch (*descriptor) { case J_ASCII_boolean: case J_ASCII_byte: case J_ASCII_char: case J_ASCII_short: case J_ASCII_int: case J_ASCII_float: case J_ASCII_long: case J_ASCII_double: ++descriptor; break; case J_ASCII_reference: do { ++descriptor; } while (*descriptor != J_ASCII_terminator); ++descriptor; break; default: j_assert_not_reached(); } break; default: j_assert_not_reached(); } } } /* The rest are uninitialized values */ while (i < max_locals) { state->locals[i] = JAC_TYP_Writable; ++i; } /* Stack is initially empty */ state->top = state->stack;}booljac_compute_state_meet(JArena *arena, JACState **des, const JACState *src, bool *updated) { j_assert(arena != 0 && src != 0 && des != 0 && updated != 0); if (*des == 0) { /* Destination state is not initialized at all */ /* Create new state */ *des = jac_allocate_state(arena, src->max_locals, src->max_stack); if (*des == 0) return false; /* Copy source state content to destination state */ jac_copy_state(*des, src); /* Indicate that destination state is updated */ *updated = true; } else { /* Destination state has been initialized */ j_assert((*des)->max_locals == src->max_locals); j_assert((*des)->max_stack == src->max_stack); j_assert((*des)->top - (*des)->stack == src->top - src->stack); /* Compute meet values for local variables */ char *p = (*des)->locals; const char *q = src->locals; const char *r = q + src->max_locals; while (q != r) { if (! jac_meet(p, q, updated)) return false; ++p; ++q; } /* Compute meet values for stack */ p = (*des)->stack; q = src->stack; r = src->top; while (q != r) { if (! jac_meet(p, q, updated)) return false; ++p; ++q; } } /* Return successfully */ return true;}booljac_compute_routine_meet(JArena *arena, JACState **des, const JACState *jsr, const JACState *ret, const PRERoutine *routine, bool *updated) { ju2 i; if (*des == 0) { /* Destination state has not been initialized yet */ /* Create destination state */ *des = jac_allocate_state(arena, jsr->max_locals, jsr->max_stack); if (*des == 0) return false; /* Initialize destination state with content of the state at the ret instruction */ jac_copy_state(*des, ret); /* Overwrite the non-parameter local variables with content of the state at the jsr instruction */ for (i = 0; i < ret->max_locals; i++) if (! pre_routine_locals_is_marked(routine, i)) (*des)->locals[i] = jsr->locals[i]; /* Indicate that the destination state has been changed */ *updated = true; } else { /* Compute content of local variables */ for (i = 0; i < ret->max_locals; i++) { char *p = (*des)->locals + i; const char *q; /* Select where the local variable values come from */ if (pre_routine_locals_is_marked(routine, i)) /* Ret state if local variable is a subroutine parameter */ q = ret->locals + i; else /* Jsr state if local variable is not a subroutine parameter */ q = jsr->locals + i; /* Compute meet value */ if (! jac_meet(p, q, updated)) return false; } /* Compute stack content by taking the meet of original values with those from the jsr state */ char *p = (*des)->stack; const char *q = jsr->stack; const char *r = jsr->top; while (q != r) { if (! jac_meet(p, q, updated)) return false; ++p; ++q; } } return true;}// pre_merge_all_handler_states(context, analysis, &flag, next, S);booljac_compute_handler_meet(JArena *arena, const void *attr, JACState **states, ju2 addr, bool *updated) { const JACState *src = states[addr]; ju2 handlers_count = pre_attribute_code_exception_table_length(attr); ju2 i; for (i = 0; i < handlers_count; i++) { const PREHandler *H = pre_attribute_code_exception_table_entry(attr, i); ju2 start_pc = pre_handler_start_pc(H); ju2 end_pc = pre_handler_end_pc(H); ju2 handler_pc = pre_handler_handler_pc(H); if (addr >= start_pc && addr < end_pc) { JACState *des = states[handler_pc]; if (des == 0) { /* Destination state has not been initialized yet */ /* Create destination state */ des = states[handler_pc] = jac_allocate_state(arena, src->max_locals, src->max_stack); if (des == 0) return false; /* Initialize destination locals */ j_memcpy(des->locals, src->locals, src->max_locals); /* Destination stack contains a writable */ des->stack[0] = JAC_TYP_Writable; des->top = des->stack + 1; } else { /* Destination already there */ /* Check destination locals */ ju2 j; for (j = 0; j < src->max_locals; j++) { if (! jac_meet(des->locals + j, src->locals + j, updated)) return false; } /* Check destination stack */ if (des->stack[0] != JAC_TYP_Writable) return false; } } } return true;}static inlinevoidjac_microcode_stack_push_type(JACState *S, char type) { *(S->top) = type; S->top++;}static inlinecharjac_microcode_stack_pop_type(JACState *S) { S->top--; return *(S->top);}static inlinevoidjac_microcode_stack_pop(JACState *S, unsigned delta) { S->top -= delta;}static inlinevoidjac_microcode_stack_empty(JACState *S) { S->top = S->stack;}static inlinevoidjac_microcode_stack_write(JACState *S, int offset, char type) { S->top[offset] = type;}static inlinecharjac_microcode_stack_read(JACState *S, int offset) { return S->top[offset];}static inlinevoidjac_microcode_load(JACState *S, ju2 index) { *(S->top) = S->locals[index]; S->top++;}static inlinevoidjac_microcode_store(JACState *S, ju2 index) { S->top--; S->locals[index] = *(S->top);}voidjac_print_state(FILE *file, const JACState *state) { ju2 i, depth; fprintf(file, "locals = \""); for (i = 0; i < state->max_locals; i++) fprintf(file, "%c", state->locals[i]); fprintf(file, "\"\nstack = \""); depth = state->top - state->stack; for (i = 0; i < depth; i++) fprintf(file, "%c", state->stack[i]); fprintf(file, "\"\n");}booljac_run_flow_analysis(JArena *arena, const PREAnalysis *analysis, const struct jac_commitments *commitments, JACState **states) { const PREClassFile *classfile = pre_analysis_classfile(analysis); const PREConstantPool *constant_pool = pre_classfile_constant_pool(classfile); ju2 method_index = pre_analysis_method_index(analysis); const PREMethod *method = pre_classfile_method(classfile, method_index); const void *attr = pre_method_code(method); ju4 code_length = pre_attribute_code_length(attr); /* Cache return type annotation */ const char *annotation = jac_get_method_annotation(commitments, constant_pool, method_index); char return_type; if (annotation != 0) { do /* look for right bracket */ ++annotation; while (*annotation != J_ASCII_rbracket); return_type = annotation[1]; /* skip right bracket */ } else { return_type = JAC_TYP_Writable; } /* Construct local state struct */ ju2 max_locals = pre_attribute_code_max_locals(attr); ju2 max_stack = pre_attribute_code_max_stack(attr); char locals[max_locals]; char stack[max_stack]; JACState state = { max_locals, max_stack, locals, stack, stack }; register JACState *S = &state; /* Loop until no change */ bool flag = true; while (flag) { ju4 j; const void *instr; flag = false; for (j = 0; j < code_length; j += pre_instr_len(instr)) { instr = pre_attribute_code_code(attr, j); if (states[j] == 0) continue; jac_copy_state(S, states[j]); ju2 index; ju1 opcode = pre_instr_opcode(instr);#ifdef JAC_PVM_DEBUG fprintf(stderr, "========\n"); fprintf(stderr, "%08x: %s\n", j, j_opcode_mnemonic(opcode)); fprintf(stderr, "Before:\n"); jac_print_state(stderr, states[j]);#endif /* * Compute state change */ switch (opcode) { /* no-op */ case J_OPC_nop: case J_OPC_goto: case J_OPC_goto_w: case J_OPC_ineg: case J_OPC_lneg: case J_OPC_fneg: case J_OPC_dneg: case J_OPC_i2b: case J_OPC_i2c: case J_OPC_i2s: case J_OPC_i2f: case J_OPC_f2i: case J_OPC_d2l: case J_OPC_l2d: case J_OPC_iinc: case J_OPC_checkcast: case J_OPC_anewarray: case J_OPC_ret: break; /* push one writable */ case J_OPC_aconst_null: case J_OPC_iconst_m1: case J_OPC_iconst_0: case J_OPC_iconst_1: case J_OPC_iconst_2: case J_OPC_iconst_3: case J_OPC_iconst_4: case J_OPC_iconst_5: case J_OPC_bipush: case J_OPC_sipush: case J_OPC_fconst_0: case J_OPC_fconst_1: case J_OPC_fconst_2: case J_OPC_ldc: case J_OPC_ldc_w: case J_OPC_new: case J_OPC_newarray: case J_OPC_i2l: case J_OPC_i2d: case J_OPC_f2l: case J_OPC_f2d: case J_OPC_iload: case J_OPC_iload_0: case J_OPC_iload_1: case J_OPC_iload_2: case J_OPC_iload_3: case J_OPC_fload: case J_OPC_fload_0: case J_OPC_fload_1: case J_OPC_fload_2: case J_OPC_fload_3: case J_OPC_jsr: case J_OPC_jsr_w: jac_microcode_stack_push_type(S, JAC_TYP_Writable); break; /* push two writables */ case J_OPC_lconst_0: case J_OPC_lconst_1: case J_OPC_dconst_0: case J_OPC_dconst_1: case J_OPC_ldc2_w: case J_OPC_lload: case J_OPC_lload_0: case J_OPC_lload_1: case J_OPC_lload_2: case J_OPC_lload_3: case J_OPC_dload: case J_OPC_dload_0: case J_OPC_dload_1: case J_OPC_dload_2: case J_OPC_dload_3: jac_microcode_stack_push_type(S, JAC_TYP_Writable); jac_microcode_stack_push_type(S, JAC_TYP_Writable); break; /* pop one and dispose */ case J_OPC_pop: case J_OPC_iadd: case J_OPC_isub: case J_OPC_imul: case J_OPC_idiv: case J_OPC_irem: case J_OPC_ishl: case J_OPC_ishr: case J_OPC_iushr: case J_OPC_iand: case J_OPC_ior: case J_OPC_ixor: case J_OPC_fadd: case J_OPC_fsub: case J_OPC_fmul: case J_OPC_fdiv: case J_OPC_frem: case J_OPC_l2i: case J_OPC_l2f: case J_OPC_d2i: case J_OPC_d2f: case J_OPC_lshl: case J_OPC_lshr: case J_OPC_lushr: case J_OPC_monitorenter: case J_OPC_monitorexit: case J_OPC_ifeq: case J_OPC_ifne: case J_OPC_iflt: case J_OPC_ifge: case J_OPC_ifgt: case J_OPC_ifle: case J_OPC_tableswitch: case J_OPC_lookupswitch: case J_OPC_fcmpl: case J_OPC_fcmpg: case J_OPC_ifnull: case J_OPC_ifnonnull: case J_OPC_aaload: jac_microcode_stack_pop(S, 1); break; /* pop two and dispose */ case J_OPC_pop2: case J_OPC_ladd: case J_OPC_lsub: case J_OPC_lmul: case J_OPC_ldiv: case J_OPC_lrem: case J_OPC_land: case J_OPC_lor: case J_OPC_lxor: case J_OPC_dadd: case J_OPC_dsub: case J_OPC_dmul: case J_OPC_ddiv: case J_OPC_drem: case J_OPC_if_icmpeq: case J_OPC_if_icmpne: case J_OPC_if_icmplt: case J_OPC_if_icmpge: case J_OPC_if_icmpgt: case J_OPC_if_icmple:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -