📄 verify.c
字号:
/* FIXME: If we exit a subroutine via a throw, we might have returned to an earlier caller. Obviously a "ret" can only return one level, but a throw may return many levels.*/ current_subr = caller; if (RETURN_MAP_ADJUSTED (ret_map)) { /* Since we are done with this subroutine , set up the (so far known) return address as pending - with the merged type state. */ for ( ; tmp != NULL_TREE; tmp = TREE_CHAIN (tmp)) { tree return_label = TREE_VALUE (tmp); tree return_state = LABEL_TYPE_STATE (return_label); if (return_state == NULL_TREE) { /* This means means we had not verified the subroutine earlier, so this is the first jsr to call it. In this case, the type_map of the return address is just the current type_map - and that is handled by the following PUSH_PENDING. */ } else { /* In this case we have to do a merge. But first restore the type_map for unused slots to those that were in effect at the jsr. */ for (index = size; --index >= 0; ) { type_map[index] = TREE_VEC_ELT (ret_map, index); if (type_map[index] == TYPE_UNUSED) type_map[index] = TREE_VEC_ELT (return_state, index); } } PUSH_PENDING (return_label); } } } } if (PC == INVALID_PC) { label = pending_blocks; if (label == NULL_TREE) break; /* We're done! */ pending_blocks = LABEL_PENDING_CHAIN (label); LABEL_CHANGED (label) = 0; if (LABEL_IN_SUBR (label)) current_subr = LABEL_SUBR_START (label); else current_subr = NULL_TREE; /* Restore type_map and stack_pointer from LABEL_TYPE_STATE (label), and continue compiling from there. */ load_type_state (label); PC = LABEL_PC (label); } else if (PC >= length) VERIFICATION_ERROR ("falling through end of method"); /* fprintf (stderr, "** %d\n", PC); */ oldpc = PC; if (!(instruction_bits [PC] & BCODE_INSTRUCTION_START) && ! wide) VERIFICATION_ERROR ("PC not at instruction start"); instruction_bits[PC] |= BCODE_VERIFIED; eh_ranges = find_handler (oldpc); op_code = byte_ops[PC++]; switch (op_code) { int is_static, is_putting; case OPCODE_nop: break; case OPCODE_iconst_m1: case OPCODE_iconst_0: case OPCODE_iconst_1: case OPCODE_iconst_2: case OPCODE_iconst_3: case OPCODE_iconst_4: case OPCODE_iconst_5: i = op_code - OPCODE_iconst_0; goto push_int; push_int: if (byte_ops[PC] == OPCODE_newarray || byte_ops[PC] == OPCODE_newarray) int_value = i; push_type (int_type_node); break; case OPCODE_lconst_0: case OPCODE_lconst_1: push_type (long_type_node); break; case OPCODE_fconst_0: case OPCODE_fconst_1: case OPCODE_fconst_2: push_type (float_type_node); break; case OPCODE_dconst_0: case OPCODE_dconst_1: push_type (double_type_node); break; case OPCODE_bipush: i = IMMEDIATE_s1; goto push_int; case OPCODE_sipush: i = IMMEDIATE_s2; goto push_int; case OPCODE_iload: type = int_type_node; goto general_load; case OPCODE_lload: type = long_type_node; goto general_load; case OPCODE_fload: type = float_type_node; goto general_load; case OPCODE_dload: type = double_type_node; goto general_load; case OPCODE_aload: type = ptr_type_node; goto general_load; general_load: index = wide ? IMMEDIATE_u2 : IMMEDIATE_u1; wide = 0; goto load; case OPCODE_iload_0: type = int_type_node; index = 0; goto load; case OPCODE_iload_1: type = int_type_node; index = 1; goto load; case OPCODE_iload_2: type = int_type_node; index = 2; goto load; case OPCODE_iload_3: type = int_type_node; index = 3; goto load; case OPCODE_lload_0: type = long_type_node; index = 0; goto load; case OPCODE_lload_1: type = long_type_node; index = 1; goto load; case OPCODE_lload_2: type = long_type_node; index = 2; goto load; case OPCODE_lload_3: type = long_type_node; index = 3; goto load; case OPCODE_fload_0: type = float_type_node; index = 0; goto load; case OPCODE_fload_1: type = float_type_node; index = 1; goto load; case OPCODE_fload_2: type = float_type_node; index = 2; goto load; case OPCODE_fload_3: type = float_type_node; index = 3; goto load; case OPCODE_dload_0: type = double_type_node; index = 0; goto load; case OPCODE_dload_1: type = double_type_node; index = 1; goto load; case OPCODE_dload_2: type = double_type_node; index = 2; goto load; case OPCODE_dload_3: type = double_type_node; index = 3; goto load; case OPCODE_aload_0: type = ptr_type_node; index = 0; goto load; case OPCODE_aload_1: type = ptr_type_node; index = 1; goto load; case OPCODE_aload_2: type = ptr_type_node; index = 2; goto load; case OPCODE_aload_3: type = ptr_type_node; index = 3; goto load; load: if (index < 0 || (index + TYPE_IS_WIDE (type) >= DECL_MAX_LOCALS (current_function_decl))) VERIFICATION_ERROR ("invalid local variable index in load"); tmp = type_map[index]; if (tmp == TYPE_UNKNOWN || tmp == TYPE_SECOND || (TYPE_IS_WIDE (type) && type_map[index+1] != void_type_node) || (type == ptr_type_node ? TREE_CODE (tmp) != POINTER_TYPE : type == int_type_node ? (! INTEGRAL_TYPE_P (tmp) || TYPE_PRECISION (tmp) > 32) : type != tmp)) VERIFICATION_ERROR("invalid local variable type in load"); push_type (tmp); goto note_used; case OPCODE_istore: type = int_type_node; goto general_store; case OPCODE_lstore: type = long_type_node; goto general_store; case OPCODE_fstore: type = float_type_node; goto general_store; case OPCODE_dstore: type = double_type_node; goto general_store; case OPCODE_astore: type = ptr_type_node; goto general_store; general_store: index = wide ? IMMEDIATE_u2 : IMMEDIATE_u1; wide = 0; goto store; case OPCODE_istore_0: type = int_type_node; index = 0; goto store; case OPCODE_istore_1: type = int_type_node; index = 1; goto store; case OPCODE_istore_2: type = int_type_node; index = 2; goto store; case OPCODE_istore_3: type = int_type_node; index = 3; goto store; case OPCODE_lstore_0: type = long_type_node; index=0; goto store; case OPCODE_lstore_1: type = long_type_node; index=1; goto store; case OPCODE_lstore_2: type = long_type_node; index=2; goto store; case OPCODE_lstore_3: type = long_type_node; index=3; goto store; case OPCODE_fstore_0: type=float_type_node; index=0; goto store; case OPCODE_fstore_1: type=float_type_node; index=1; goto store; case OPCODE_fstore_2: type=float_type_node; index=2; goto store; case OPCODE_fstore_3: type=float_type_node; index=3; goto store; case OPCODE_dstore_0: type=double_type_node; index=0; goto store; case OPCODE_dstore_1: type=double_type_node; index=1; goto store; case OPCODE_dstore_2: type=double_type_node; index=2; goto store; case OPCODE_dstore_3: type=double_type_node; index=3; goto store; case OPCODE_astore_0: type = ptr_type_node; index = 0; goto store; case OPCODE_astore_1: type = ptr_type_node; index = 1; goto store; case OPCODE_astore_2: type = ptr_type_node; index = 2; goto store; case OPCODE_astore_3: type = ptr_type_node; index = 3; goto store; store: if (index < 0 || (index + TYPE_IS_WIDE (type) >= DECL_MAX_LOCALS (current_function_decl))) { VERIFICATION_ERROR ("invalid local variable index in store"); return 0; } type = pop_type (type); type_map[index] = type; /* If local variable changed, we need to reconsider eh handlers. */ prev_eh_ranges = NULL_EH_RANGE; /* Allocate decl and rtx for this variable now, so if we're not optmizing, we get a temporary that survives the whole method. */ find_local_variable (index, type, oldpc); if (TYPE_IS_WIDE (type)) type_map[index+1] = TYPE_SECOND; /* ... fall through to note_used ... */ note_used: /* For store or load, note that local variable INDEX is used. This is needed to verify try-finally sub-routines. */ if (current_subr) { tree vec = LABEL_RETURN_TYPE_STATE (current_subr); tree subr_vec = LABEL_TYPE_STATE (current_subr); int len = 1 + TYPE_IS_WIDE (type); while (--len >= 0) { if (TREE_VEC_ELT (vec, index) == TYPE_UNUSED) TREE_VEC_ELT (vec, index) = TREE_VEC_ELT (subr_vec, index); } } break; case OPCODE_iadd: case OPCODE_iand: case OPCODE_idiv: case OPCODE_imul: case OPCODE_ior: case OPCODE_irem: case OPCODE_ishl: case OPCODE_ishr: case OPCODE_isub: case OPCODE_iushr: case OPCODE_ixor: type = int_type_node; goto binop; case OPCODE_ineg: case OPCODE_i2c: case OPCODE_i2b: case OPCODE_i2s: type = int_type_node; goto unop; case OPCODE_ladd: case OPCODE_land: case OPCODE_ldiv: case OPCODE_lsub: case OPCODE_lmul: case OPCODE_lrem: case OPCODE_lor: case OPCODE_lxor: type = long_type_node; goto binop; case OPCODE_lneg: type = long_type_node; goto unop; case OPCODE_fadd: case OPCODE_fsub: case OPCODE_fmul: case OPCODE_fdiv: case OPCODE_frem: type = float_type_node; goto binop; case OPCODE_fneg: type = float_type_node; goto unop; case OPCODE_dadd: case OPCODE_dsub: case OPCODE_dmul: case OPCODE_ddiv: case OPCODE_drem: type = double_type_node; goto binop; case OPCODE_dneg: type = double_type_node; goto unop; unop: pop_type (type); push_type (type); break; binop: pop_type (type); pop_type (type); push_type (type); break; case OPCODE_lshl: case OPCODE_lshr: case OPCODE_lushr: pop_type (int_type_node); pop_type (long_type_node); push_type (long_type_node); break; case OPCODE_iinc: index = wide ? IMMEDIATE_u2 : IMMEDIATE_u1; PC += wide + 1; wide = 0; if (index < 0 || index >= DECL_MAX_LOCALS (current_function_decl)) VERIFICATION_ERROR ("invalid local variable index in iinc"); tmp = type_map[index]; if (! INTEGRAL_TYPE_P (tmp) || TYPE_PRECISION (tmp) > 32) VERIFICATION_ERROR ("invalid local variable type in iinc"); break; case OPCODE_i2l: pop_type (int_type_node); push_type (long_type_node); break; case OPCODE_i2f: pop_type (int_type_node); push_type (float_type_node); break; case OPCODE_i2d: pop_type (int_type_node); push_type (double_type_node); break; case OPCODE_l2i: pop_type (long_type_node); push_type (int_type_node); break; case OPCODE_l2f: pop_type (long_type_node); push_type (float_type_node); break; case OPCODE_l2d: pop_type (long_type_node); push_type (double_type_node); break; case OPCODE_f2i: pop_type (float_type_node); push_type (int_type_node); break; case OPCODE_f2l: pop_type (float_type_node); push_type (long_type_node); break; case OPCODE_f2d: pop_type (float_type_node); push_type (double_type_node); break; case OPCODE_d2i: pop_type (double_type_node); push_type (int_type_node); break; case OPCODE_d2l: pop_type (double_type_node); push_type (long_type_node); break; case OPCODE_d2f: pop_type (double_type_node); push_type (float_type_node); break; case OPCODE_lcmp: type = long_type_node; goto compare; case OPCODE_fcmpl: case OPCODE_fcmpg: type = float_type_node; goto compare; case OPCODE_dcmpl: case OPCODE_dcmpg: type = double_type_node; goto compare; compare: pop_type (type); pop_type (type); push_type (int_type_node); break; case OPCODE_ifeq: case OPCODE_ifne: case OPCODE_iflt: case OPCODE_ifge: case OPCODE_ifgt: case OPCODE_ifle: pop_type (int_type_node); goto cond; case OPCODE_ifnull: case OPCODE_ifnonnull: pop_type (ptr_type_node ); goto cond; case OPCODE_if_icmpeq: case OPCODE_if_icmpne: case OPCODE_if_icmplt: case OPCODE_if_icmpge: case OPCODE_if_icmpgt: case OPCODE_if_icmple: pop_type (int_type_node); pop_type (int_type_node); goto cond; case OPCODE_if_acmpeq: case OPCODE_if_acmpne: pop_type (object_ptr_type_node); pop_type (object_ptr_type_node); goto cond; cond: PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s2)); break; case OPCODE_goto: PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s2)); INVALIDATE_PC; break; case OPCODE_wide: switch (byte_ops[PC]) { case OPCODE_iload: case OPCODE_lload: case OPCODE_fload: case OPCODE_dload: case OPCODE_aload: case OPCODE_istore: case OPCODE_lstore: case OPCODE_fstore: case OPCODE_dstore: case OPCODE_astore: case OPCODE_iinc: case OPCODE_ret: wide = 1; break; default: VERIFICATION_ERROR ("invalid use of wide instruction"); } break; case OPCODE_return: type = void_type_node; goto ret; case OPCODE_ireturn: if ((TREE_CODE (return_type) == BOOLEAN_TYPE || TREE_CODE (return_type) == CHAR_TYPE || TREE_CODE (return_type) == INTEGER_TYPE) && TYPE_PRECISION (return_type) <= 32) type = return_type; else type = NULL_TREE; goto ret; case OPCODE_lreturn: type = long_type_node; goto ret; case OPCODE_freturn: type = float_type_node; goto ret; case OPCODE_dreturn: type = double_type_node; goto ret; case OPCODE_areturn: if (TREE_CODE (return_type) == POINTER_TYPE) type = return_type; else type = NULL_TREE; goto ret; ret: if (type != return_type) VERIFICATION_ERROR ("incorrect ?return opcode"); if (type != void_type_node) { if (pop_type_0 (type) == NULL_TREE) VERIFICATION_ERROR ("return value has wrong type"); } INVALIDATE_PC; break; case OPCODE_getstatic: is_putting = 0; is_static = 1; goto field; case OPCODE_putstatic: is_putting = 1; is_static = 1; goto field; case OPCODE_getfield: is_putting = 0; is_static = 0; goto field; case OPCODE_putfield: is_putting = 1; is_static = 0; goto field; field: { int index = IMMEDIATE_u2; tree field_signature = COMPONENT_REF_SIGNATURE (¤t_jcf->cpool, index); tree field_type = get_type_from_signature (field_signature); if (is_putting) pop_type (field_type); if (! is_static) { int clindex = COMPONENT_REF_CLASS_INDEX (¤t_jcf->cpool, index); tree self_type = get_class_constant (current_jcf, clindex); /* Defer actual checking until next pass. */ if (pop_type_0 (self_type) == NULL_TREE) VERIFICATION_ERROR ("incorrect type for field reference"); } if (! is_putting) push_type (field_type); break; } case OPCODE_new: push_type (get_class_constant (jcf, IMMEDIATE_u2)); break; case OPCODE_dup: type_stack_dup (1, 0); break; case OPCODE_dup_x1: type_stack_dup (1, 1); break; case OPCODE_dup_x2: type_stack_dup (1, 2); break; case OPCODE_dup2: type_stack_dup (2, 0); break; case OPCODE_dup2_x1: type_stack_dup (2, 1); break; case OPCODE_dup2_x2: type_stack_dup (2, 2); break; case OPCODE_pop: index = 1; goto pop; case OPCODE_pop2: index = 2; goto pop; pop: if (stack_pointer < index) VERIFICATION_ERROR ("stack underflow"); stack_pointer -= index; break; case OPCODE_swap: if (stack_pointer < 2) VERIFICATION_ERROR ("stack underflow (in swap)"); else { tree type1 = stack_type_map[stack_pointer - 1]; tree type2 = stack_type_map[stack_pointer - 2]; if (type1 == void_type_node || type2 == void_type_node) VERIFICATION_ERROR ("verifier (swap): double or long value"); stack_type_map[stack_pointer - 2] = type1; stack_type_map[stack_pointer - 1] = type2; } break; case OPCODE_ldc: index = IMMEDIATE_u1; goto ldc; case OPCODE_ldc2_w: case OPCODE_ldc_w: index = IMMEDIATE_u2; goto ldc; ldc: if (index <= 0 || index >= JPOOL_SIZE(current_jcf)) VERIFICATION_ERROR ("bad constant pool index in ldc"); int_value = -1; switch (JPOOL_TAG (current_jcf, index) & ~CONSTANT_ResolvedFlag) { case CONSTANT_Integer: type = int_type_node; goto check_ldc; case CONSTANT_Float: type = float_type_node; goto check_ldc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -