⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 verify.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
	    case CONSTANT_String:   type = string_type_node; goto check_ldc;	    case CONSTANT_Long:    type = long_type_node;    goto check_ldc;	    case CONSTANT_Double:  type = double_type_node;  goto check_ldc;	    check_ldc:	      if (TYPE_IS_WIDE (type) == (op_code == OPCODE_ldc2_w))		break;	      /* ... else fall through ... */	    default:	      VERIFICATION_ERROR ("bad constant pool tag in ldc");	    }	  if (type == int_type_node)	    {	      i = TREE_INT_CST_LOW (get_constant (current_jcf, index));	      goto push_int;	    }	  push_type (type);	  break;	case OPCODE_invokevirtual:	case OPCODE_invokespecial:	case OPCODE_invokestatic:	case OPCODE_invokeinterface:	  {	    int index = IMMEDIATE_u2;	    tree sig = COMPONENT_REF_SIGNATURE (&current_jcf->cpool, index);	    tree self_type = get_class_constant	      (current_jcf, COMPONENT_REF_CLASS_INDEX (&current_jcf->cpool,						       index));	    tree method_name = COMPONENT_REF_NAME (&current_jcf->cpool, index);	    tree method_type;	    method_type = parse_signature_string (IDENTIFIER_POINTER (sig),						  IDENTIFIER_LENGTH (sig));	    if (TREE_CODE (method_type) != FUNCTION_TYPE)	      VERIFICATION_ERROR ("bad method signature");	    pop_argument_types (TYPE_ARG_TYPES (method_type));	    /* Can't invoke <clinit> */	    if (method_name == clinit_identifier_node)	      VERIFICATION_ERROR ("invoke opcode can't invoke <clinit>");	    /* Apart invokespecial, can't invoke <init> */	    if (op_code != OPCODE_invokespecial		&& method_name == init_identifier_node)	      VERIFICATION_ERROR ("invoke opcode can't invoke <init>");	    if (op_code != OPCODE_invokestatic)	      pop_type (self_type);	    switch (op_code)	      {	      case OPCODE_invokeinterface:	        {		  int nargs    = IMMEDIATE_u1;		  int notZero  = IMMEDIATE_u1;				  if (!nargs || notZero)		      VERIFICATION_ERROR 		        ("invalid argument number in invokeinterface");		  break;		  		}	      }	    if (TREE_TYPE (method_type) != void_type_node)	      push_type (TREE_TYPE (method_type));	    break;	  }	case OPCODE_arraylength:	    /* Type checking actually made during code generation */	    pop_type( ptr_type_node );	    push_type( int_type_node );	    break;	            /* Q&D verification *or* more checking done during code generation	   for byte/boolean/char/short, the value popped is a int coerced	   into the right type before being stored.  */	case OPCODE_iastore: type = int_type_node;     goto astore;	case OPCODE_lastore: type = long_type_node;    goto astore;	case OPCODE_fastore: type = float_type_node;   goto astore;	case OPCODE_dastore: type = double_type_node;  goto astore;	case OPCODE_aastore: type = ptr_type_node;     goto astore;	case OPCODE_bastore: type = int_type_node; goto astore;	case OPCODE_castore: type = int_type_node; goto astore;	case OPCODE_sastore: type = int_type_node; goto astore;	astore:	  /* FIXME - need better verification here */	  pop_type (type);	     /* new value */	  pop_type (int_type_node);  /* index */	  pop_type (ptr_type_node);  /* array */	  break;        /* Q&D verification *or* more checking done during code generation	   for byte/boolean/char/short, the value pushed is a int.  */	case OPCODE_iaload: type = int_type_node;     goto aload;	case OPCODE_laload: type = long_type_node;    goto aload;	case OPCODE_faload: type = float_type_node;   goto aload;	case OPCODE_daload: type = double_type_node;  goto aload;	case OPCODE_aaload: type = ptr_type_node;     goto aload;	case OPCODE_baload: type = promote_type (byte_type_node);  goto aload;	case OPCODE_caload: type = promote_type (char_type_node);  goto aload;	case OPCODE_saload: type = promote_type (short_type_node); goto aload;        aload:	  pop_type (int_type_node);	  tmp = pop_type (ptr_type_node);	  if (is_array_type_p (tmp))	    type = TYPE_ARRAY_ELEMENT (TREE_TYPE (tmp));	  else if (tmp != TYPE_NULL)	    VERIFICATION_ERROR ("array load from non-array type");	  push_type (type);	  break;	case OPCODE_anewarray:	  type = get_class_constant (current_jcf, IMMEDIATE_u2);	  type = promote_type (type);	  goto newarray;	case OPCODE_newarray:	  index = IMMEDIATE_u1;	  type = decode_newarray_type (index);	  if (type == NULL_TREE)	    VERIFICATION_ERROR ("invalid type code in newarray opcode");	  goto newarray;	newarray:	  if (int_value >= 0 && prevpc >= 0)	    {	      /* If previous instruction pushed int constant,		 we want to use it. */	      switch (byte_ops[prevpc])		{		case OPCODE_iconst_0: case OPCODE_iconst_1:		case OPCODE_iconst_2: case OPCODE_iconst_3:		case OPCODE_iconst_4: case OPCODE_iconst_5:		case OPCODE_bipush:  case OPCODE_sipush:		case OPCODE_ldc: case OPCODE_ldc_w:		  break;		default:		  int_value = -1;		}	    }	  else	    int_value = -1;	  type = build_java_array_type (type, int_value);	  pop_type (int_type_node);	  push_type (type);	  break;	case OPCODE_multianewarray:	  {	    int ndim, i;	    index = IMMEDIATE_u2;	    ndim  = IMMEDIATE_u1;            if( ndim < 1 )              VERIFICATION_ERROR ("number of dimension lower that 1 in multianewarray" );	    for( i = 0; i < ndim; i++ )	      pop_type (int_type_node);	    push_type (get_class_constant (current_jcf, index));	    break;	  }	case OPCODE_aconst_null:	  push_type (ptr_type_node);	  break;	case OPCODE_athrow:	  // FIXME: athrow also empties the stack.	  pop_type (throwable_type_node);	  INVALIDATE_PC;	  break;	case OPCODE_checkcast:	  pop_type (ptr_type_node);	  type = get_class_constant (current_jcf, IMMEDIATE_u2);	  push_type (type);	  break;	case OPCODE_instanceof:	  pop_type (ptr_type_node);	  get_class_constant (current_jcf, IMMEDIATE_u2);	  push_type (int_type_node);	  break;	case OPCODE_tableswitch:	  {	    jint low, high;	    pop_type (int_type_node);	    while (PC%4)	      {	        if (byte_ops[PC++])		  VERIFICATION_ERROR ("bad alignment in tableswitch pad");	      }	    PUSH_PENDING (lookup_label (oldpc+IMMEDIATE_s4));	    low  = IMMEDIATE_s4;	    high = IMMEDIATE_s4;	    if (low > high)	      VERIFICATION_ERROR ("unsorted low/high value in tableswitch");	    while (low++ <= high)	      PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s4));	    INVALIDATE_PC;	    break;	  }	case OPCODE_lookupswitch:	  {	    jint npairs, last, not_registered = 1;	    pop_type (int_type_node);	    while (PC%4)	      {	        if (byte_ops[PC++])		  VERIFICATION_ERROR ("bad alignment in lookupswitch pad");	      }	    PUSH_PENDING (lookup_label (oldpc+IMMEDIATE_s4));	    npairs = IMMEDIATE_s4;	    	    if (npairs < 0)	      VERIFICATION_ERROR ("invalid number of targets in lookupswitch");	    while (npairs--)	      {	        int match = IMMEDIATE_s4;		if (not_registered)		  not_registered = 0;		else if (last >= match)		  VERIFICATION_ERROR ("unsorted match value in lookupswitch");		last = match;		PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s4));	      }	    INVALIDATE_PC;	    break;	  }	case OPCODE_monitorenter: 	  /* fall thru */	case OPCODE_monitorexit:	  pop_type (ptr_type_node);	  break;	case OPCODE_goto_w:	  PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s4));	  INVALIDATE_PC;	  break;	case OPCODE_jsr:	  {	    tree target = lookup_label (oldpc + IMMEDIATE_s2);	    tree return_label = lookup_label (PC);	    push_type (return_address_type_node);	    if (! LABEL_VERIFIED (target))	      {		/* first time seen */		tree return_type_map;		int nlocals = DECL_MAX_LOCALS (current_function_decl);		index = nlocals + DECL_MAX_STACK (current_function_decl);		return_type_map = make_tree_vec (index);		while (index > nlocals)		  TREE_VEC_ELT (return_type_map, --index) = TYPE_UNKNOWN;		while (index > 0)		  TREE_VEC_ELT (return_type_map, --index) = TYPE_UNUSED;		LABEL_RETURN_LABEL (target)		  = build_decl (LABEL_DECL, NULL_TREE, TREE_TYPE (target));		LABEL_PC (LABEL_RETURN_LABEL (target)) = -1;		LABEL_RETURN_TYPE_STATE (target) = return_type_map;		LABEL_IS_SUBR_START (target) = 1;		LABEL_IN_SUBR (target) = 1;		LABEL_SUBR_START (target) = target;		LABEL_SUBR_CONTEXT (target) = current_subr;	      }	    else if (! LABEL_IS_SUBR_START (target)		     || LABEL_SUBR_CONTEXT (target) != current_subr)	      VERIFICATION_ERROR ("label part of different subroutines");	    i = merge_type_state (target);	    if (i != 0)	      {		if (i < 0)		  VERIFICATION_ERROR ("types could not be merged at jsr");		push_pending_label (target);	      }	    current_subr = target;	    /* Chain return_pc onto LABEL_RETURN_LABELS (target) if needed. */	    if (! value_member (return_label, LABEL_RETURN_LABELS (target)))	      {		LABEL_RETURN_LABELS (target)		  = tree_cons (NULL_TREE, return_label,			       LABEL_RETURN_LABELS (target));	      }	    if (LABEL_VERIFIED (target))	      {		tree return_map = LABEL_RETURN_TYPE_STATE (target);		int len = TREE_VEC_LENGTH (return_map);		stack_pointer = len - DECL_MAX_LOCALS (current_function_decl);		while (--len >= 0)		  {		    if (TREE_VEC_ELT (return_map, len) != TYPE_UNUSED)		      type_map[len] = TREE_VEC_ELT (return_map, len);		  }		current_subr = LABEL_SUBR_CONTEXT (target);		PUSH_PENDING (return_label);	      }	    INVALIDATE_PC;	  }	  break;	case OPCODE_ret:	  if (current_subr == NULL)	    VERIFICATION_ERROR ("ret instruction not in a jsr subroutine");	  else	    {	      tree ret_map = LABEL_RETURN_TYPE_STATE (current_subr);	      tree caller = LABEL_SUBR_CONTEXT (current_subr);	      int size = DECL_MAX_LOCALS(current_function_decl)+stack_pointer;	      index = wide ? IMMEDIATE_u2 : IMMEDIATE_u1;	      wide = 0;	      INVALIDATE_PC;	      if (index < 0 || index >= DECL_MAX_LOCALS (current_function_decl)		  || type_map[index] != TYPE_RETURN_ADDR)		VERIFICATION_ERROR ("invalid ret index");	      /* The next chunk of code is similar to an inlined version of	       *     merge_type_state (LABEL_RETURN_LABEL (current_subr)).	       * The main differences are that LABEL_RETURN_LABEL is	       * pre-allocated by the jsr (but we don't know the size then);	       * and that we have to handle TYPE_UNUSED. */	      if (! RETURN_MAP_ADJUSTED (ret_map))		{ /* First return from this subroutine - fix stack pointer. */		  TREE_VEC_LENGTH (ret_map) = size;		  for (index = size;  --index >= 0; )		    {		      if (TREE_VEC_ELT (ret_map, index) != TYPE_UNUSED)			TREE_VEC_ELT (ret_map, index) = type_map[index];		    }		  RETURN_MAP_ADJUSTED (ret_map) = 1;		}	      else		{		  if (TREE_VEC_LENGTH (ret_map) != size)		    VERIFICATION_ERROR ("inconsistent stack size on ret");		  for (index = 0;  index < size;  index++)		    {		      tree type = TREE_VEC_ELT (ret_map, index);		      if (type != TYPE_UNUSED)			{			  type = merge_types (type, type_map [index]);			  TREE_VEC_ELT (ret_map, index) = type;			  if (type == TYPE_UNKNOWN)			    {			      if (index >= size - stack_pointer)				VERIFICATION_ERROR				  ("inconsistent types on ret from jsr");			    }			  else if (TYPE_IS_WIDE (type))			    index++;			}		    }		}            }          break;        case OPCODE_jsr_w:                case OPCODE_ret_w:        default:          error ("unknown opcode %d@pc=%d during verification", op_code, PC-1);          return 0;        }      prevpc = oldpc;      /* The following test is true if we have entered or exited an exception	 handler range *or* we have done a store to a local variable.	 In either case we need to consider any exception handlers that	 might "follow" this instruction. */      if (eh_ranges != prev_eh_ranges)	{	  int save_stack_pointer = stack_pointer;	  int index = DECL_MAX_LOCALS (current_function_decl);	  tree save_type = type_map[index];	  tree save_current_subr = current_subr;	  struct eh_range *ranges = find_handler (oldpc);	  stack_pointer = 1;	  for (; ranges != NULL_EH_RANGE;  ranges = ranges->outer)	    {	      tree chain = ranges->handlers;	      /* We need to determine if the handler is part of current_subr.		 The are two cases:  (1) The exception catch range		 is entirely within current_subr.  In that case the handler		 is also part of current_subr.		 (2) Some of the catch range is not in current_subr.		 In that case, the handler is *not* part of current_subr.		 Figuring out which is the case is not necessarily obvious,		 in the presence of clever code generators (and obfuscators).		 We make a simplifying assumption that in case (2) we		 have that the current_subr is entirely within the catch range.		 In that case we can assume if that if a caller (the jsr) of		 a subroutine is within the catch range, then the handler is		 *not* part of the subroutine, and vice versa. */	      current_subr = save_current_subr;	      for ( ; current_subr != NULL_TREE;		    current_subr = LABEL_SUBR_CONTEXT (current_subr))		{		  tree return_labels = LABEL_RETURN_LABELS (current_subr);		  /* There could be multiple return_labels, but		     we only need to check one. */		  int return_pc = LABEL_PC (TREE_VALUE (return_labels));		  if (return_pc <= ranges->start_pc		      || return_pc > ranges->end_pc)		    break;		}	      for ( ;  chain != NULL_TREE;  chain = TREE_CHAIN (chain))		{		  tree handler = TREE_VALUE (chain);		  tree type = TREE_PURPOSE (chain);		  if (type == NULL_TREE)  /* a finally handler */		    type = throwable_type_node;		  type_map[index] = promote_type (type);		  PUSH_PENDING (handler);		}	    }	  stack_pointer = save_stack_pointer;	  current_subr = save_current_subr;	  type_map[index] = save_type;	  prev_eh_ranges = eh_ranges;	}    }  return 1; bad_pc:  message = "program counter out of range";  goto verify_error; verify_error:  error ("verification error at PC=%d", oldpc);  error (message);  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -