From 1bc5aee63eb72b341f506ad058502cd0361f0d10 Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Tue, 25 Mar 2014 22:37:19 -0700 Subject: Initial checkin of GCC 4.9.0 from trunk (r208799). Change-Id: I48a3c08bb98542aa215912a75f03c0890e497dba --- gcc-4.9/gcc/java/verify-glue.c | 503 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 503 insertions(+) create mode 100644 gcc-4.9/gcc/java/verify-glue.c (limited to 'gcc-4.9/gcc/java/verify-glue.c') diff --git a/gcc-4.9/gcc/java/verify-glue.c b/gcc-4.9/gcc/java/verify-glue.c new file mode 100644 index 000000000..f0e1e4f97 --- /dev/null +++ b/gcc-4.9/gcc/java/verify-glue.c @@ -0,0 +1,503 @@ +/* Glue to interface gcj with bytecode verifier. + Copyright (C) 2003-2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. + +Java and all Java-based marks are trademarks or registered trademarks +of Sun Microsystems, Inc. in the United States and other countries. +The Free Software Foundation is independent of Sun Microsystems, Inc. */ + +/* Written by Tom Tromey . */ + +#include "config.h" + +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "stringpool.h" +#include "parse.h" + +#include "verify.h" +#include "java-tree.h" +#include "java-except.h" +#include "diagnostic-core.h" + +void * +vfy_alloc (size_t bytes) +{ + return xmalloc (bytes); +} + +void +vfy_free (void *mem) +{ + free (mem); +} + +bool +vfy_strings_equal (vfy_string one, vfy_string two) +{ + return one == two; +} + +const char * +vfy_string_bytes (vfy_string str) +{ + return IDENTIFIER_POINTER (str); +} + +int +vfy_string_length (vfy_string str) +{ + return IDENTIFIER_LENGTH (str); +} + +vfy_string +vfy_init_name (void) +{ + return init_identifier_node; +} + +vfy_string +vfy_clinit_name (void) +{ + return clinit_identifier_node; +} + +static const char* +skip_one_type (const char* ptr) +{ + int ch = *ptr++; + + while (ch == '[') + { + ch = *ptr++; + } + + if (ch == 'L') + { + do { ch = *ptr++; } while (ch != ';'); + } + + return ptr; +} + +int +vfy_count_arguments (vfy_string signature) +{ + const char *ptr = IDENTIFIER_POINTER (signature); + int arg_count = 0; + + /* Skip '('. */ + ptr++; + + /* Count args. */ + while (*ptr != ')') + { + ptr = skip_one_type (ptr); + arg_count += 1; + } + + return arg_count; +} + +vfy_string +vfy_get_string (const char *s, int len) +{ + return get_identifier_with_length (s, len); +} + +vfy_string +vfy_get_signature (vfy_method *method) +{ + return method->signature; +} + +vfy_string +vfy_get_method_name (vfy_method *method) +{ + return method->name; +} + +bool +vfy_is_static (vfy_method *method) +{ + return METHOD_STATIC (method->method); +} + +const unsigned char * +vfy_get_bytecode (vfy_method *method) +{ + return method->bytes; +} + +vfy_exception * +vfy_get_exceptions (vfy_method *method) +{ + return method->exceptions; +} + +void +vfy_get_exception (vfy_exception *exceptions, int index, int *handler, + int *start, int *end, int *handler_type) +{ + *handler = exceptions[index].handler; + *start = exceptions[index].start; + *end = exceptions[index].end; + *handler_type = exceptions[index].type; +} + +int +vfy_tag (vfy_constants *pool, int index) +{ + int result = JPOOL_TAG (pool, index); + /* gcj will resolve constant pool entries other than string and + class references. The verifier doesn't care about the values, so + we just strip off the resolved flag. */ + if ((result & CONSTANT_ResolvedFlag) != 0 + && result != CONSTANT_ResolvedString + && result != CONSTANT_ResolvedClass) + result &= ~ CONSTANT_ResolvedFlag; + return result; +} + +void +vfy_load_indexes (vfy_constants *pool, int index, + vfy_uint_16 *index0, vfy_uint_16 *index1) +{ + *index0 = JPOOL_USHORT1 (pool, index); + *index1 = JPOOL_USHORT2 (pool, index); +} + +vfy_constants * +vfy_get_constants (vfy_jclass klass) +{ + return TYPE_JCF (klass); +} + +int +vfy_get_constants_size (vfy_jclass klass) +{ + return JPOOL_SIZE (TYPE_JCF (klass)); +} + +vfy_string +vfy_get_pool_string (vfy_constants *pool, int index) +{ + return get_name_constant (pool, index); +} + +vfy_jclass +vfy_get_pool_class (vfy_constants *pool, int index) +{ + vfy_jclass k; + k = get_class_constant (pool, index); + return k; +} + +vfy_string +vfy_get_class_name (vfy_jclass klass) +{ + return DECL_NAME (TYPE_NAME (klass)); +} + +bool +vfy_is_assignable_from (vfy_jclass target, vfy_jclass source) +{ + /* Any class is always assignable to itself, or java.lang.Object. */ + if (source == target || target == object_type_node) + return true; + + /* For the C++ ABI, perform this test statically. */ + if (! flag_indirect_dispatch) + return can_widen_reference_to (source, target); + + /* For the BC-ABI, we assume at compile time that reference types are always + compatible. However, a type assertion table entry is emitted so that the + runtime can detect binary-incompatible changes. */ + + add_type_assertion (current_class, JV_ASSERT_TYPES_COMPATIBLE, source, + target); + return true; +} + +char +vfy_get_primitive_char (vfy_jclass klass) +{ + tree sig; + gcc_assert (vfy_is_primitive (klass)); + sig = build_java_signature (klass); + return (IDENTIFIER_POINTER (sig))[0]; +} + +bool +vfy_is_array (vfy_jclass klass) +{ + return TYPE_ARRAY_P (klass); +} + +bool +vfy_is_interface (vfy_jclass klass) +{ + return CLASS_INTERFACE (TYPE_NAME (klass)); +} + +bool +vfy_is_primitive (vfy_jclass klass) +{ + return JPRIMITIVE_TYPE_P (klass); +} + +vfy_jclass +vfy_get_superclass (vfy_jclass klass) +{ + vfy_jclass k; + k = CLASSTYPE_SUPER (klass); + return k; +} + +vfy_jclass +vfy_get_array_class (vfy_jclass klass) +{ + vfy_jclass k; + k = build_java_array_type (klass, -1); + return k; +} + +vfy_jclass +vfy_get_component_type (vfy_jclass klass) +{ + vfy_jclass k; + gcc_assert (vfy_is_array (klass)); + k = TYPE_ARRAY_ELEMENT (klass); + if (TREE_CODE (k) == POINTER_TYPE) + k = TREE_TYPE (k); + return k; +} + +bool +vfy_is_abstract (vfy_jclass klass) +{ + return CLASS_ABSTRACT (TYPE_NAME (klass)); +} + +vfy_jclass +vfy_find_class (vfy_jclass ignore ATTRIBUTE_UNUSED, vfy_string name) +{ + vfy_jclass k; + + k = get_type_from_signature (name); + if (TREE_CODE (k) == POINTER_TYPE) + k = TREE_TYPE (k); + + return k; +} + +vfy_jclass +vfy_object_type (void) +{ + vfy_jclass k; + k = object_type_node; + return k; +} + +vfy_jclass +vfy_class_type (void) +{ + return class_type_node; +} + +vfy_jclass +vfy_string_type (void) +{ + vfy_jclass k; + k = string_type_node; + return k; +} + +vfy_jclass +vfy_throwable_type (void) +{ + vfy_jclass k; + k = throwable_type_node; + return k; +} + +vfy_jclass +vfy_unsuitable_type (void) +{ + return TYPE_SECOND; +} + +vfy_jclass +vfy_return_address_type (void) +{ + return TYPE_RETURN_ADDR; +} + +vfy_jclass +vfy_null_type (void) +{ + return TYPE_NULL; +} + +bool +vfy_class_has_field (vfy_jclass klass, vfy_string name, + vfy_string signature) +{ + tree field = TYPE_FIELDS (klass); + while (field != NULL_TREE) + { + if (DECL_NAME (field) == name + && build_java_signature (TREE_TYPE (field)) == signature) + return true; + field = DECL_CHAIN (field); + } + return false; +} + +int +vfy_fail (const char *message, int pc, vfy_jclass ignore1 ATTRIBUTE_UNUSED, + vfy_method *ignore2 ATTRIBUTE_UNUSED) +{ + if (pc == -1) + error ("verification failed: %s", message); + else + error ("verification failed at PC=%d: %s", pc, message); + /* We have to return a value for the verifier to throw. */ + return 1; +} + +vfy_jclass +vfy_get_primitive_type (int type) +{ + vfy_jclass k; + k = decode_newarray_type (type); + return k; +} + +void +vfy_note_stack_depth (vfy_method *method, int pc, int depth) +{ + tree val = make_tree_vec (method->max_locals + depth); + (*type_states)[pc] = val; + /* Called for side effects. */ + lookup_label (pc); +} + +void +vfy_note_stack_type (vfy_method *method, int pc, int slot, vfy_jclass type) +{ + tree vec; + + slot += method->max_locals; + + if (type == object_type_node) + type = object_ptr_type_node; + + vec = (*type_states)[pc]; + TREE_VEC_ELT (vec, slot) = type; + /* Called for side effects. */ + lookup_label (pc); +} + +void +vfy_note_local_type (vfy_method *method ATTRIBUTE_UNUSED, int pc, int slot, + vfy_jclass type) +{ + tree vec; + + if (type == object_type_node) + type = object_ptr_type_node; + + vec = (*type_states)[pc]; + TREE_VEC_ELT (vec, slot) = type; + /* Called for side effects. */ + lookup_label (pc); +} + +void +vfy_note_instruction_seen (int pc) +{ + instruction_bits[pc] |= BCODE_VERIFIED; +} + +/* Verify the bytecodes of the current method. + Return 1 on success, 0 on failure. */ +int +verify_jvm_instructions_new (JCF *jcf, const unsigned char *byte_ops, + long length) +{ + vfy_method method; + int i, result, eh_count; + vfy_exception *exceptions; + + method_init_exceptions (); + + JCF_SEEK (jcf, DECL_CODE_OFFSET (current_function_decl) + length); + eh_count = JCF_readu2 (jcf); + + exceptions = (vfy_exception *) xmalloc (eh_count * sizeof (vfy_exception)); + for (i = 0; i < eh_count; ++i) + { + int start_pc, end_pc, handler_pc, catch_type; + unsigned char *p = jcf->read_ptr + 8 * i; + start_pc = GET_u2 (p); + end_pc = GET_u2 (p+2); + handler_pc = GET_u2 (p+4); + catch_type = GET_u2 (p+6); + + if (start_pc < 0 || start_pc >= length + || end_pc < 0 || end_pc > length || start_pc >= end_pc + || handler_pc < 0 || handler_pc >= length) + { + error ("bad pc in exception_table"); + free (exceptions); + return 0; + } + + exceptions[i].handler = handler_pc; + exceptions[i].start = start_pc; + exceptions[i].end = end_pc; + exceptions[i].type = catch_type; + + add_handler (start_pc, end_pc, + lookup_label (handler_pc), + catch_type == 0 ? NULL_TREE + : get_class_constant (jcf, catch_type)); + instruction_bits[handler_pc] |= BCODE_EXCEPTION_TARGET; + } + + gcc_assert (sanity_check_exception_range (&whole_range)); + + method.method = current_function_decl; + method.signature = build_java_signature (TREE_TYPE (current_function_decl)); + method.name = DECL_NAME (current_function_decl); + method.bytes = byte_ops; + method.exceptions = exceptions; + method.defining_class = DECL_CONTEXT (current_function_decl); + method.max_stack = DECL_MAX_STACK (current_function_decl); + method.max_locals = DECL_MAX_LOCALS (current_function_decl); + method.code_length = length; + method.exc_count = eh_count; + + result = verify_method (&method); + + free (exceptions); + + return result; +} -- cgit v1.2.3