This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Symbol table resolution


Properly enforcing access rules in libgcj causes problems in that
compiler-generated code sometimes wants to access private methods.

This patch uses a single bit in the signature pointer to indicate that
this is a compiler-generated access, so we should not perform any
access checks.  Encoding the bit in this way isn't very nice, but it
is fast and backward compatible.

Bootstrapped x86_64.

Andrew.


2006-06-08  Andrew Haley  <aph@redhat.com>

        * expr.c (build_field_ref): Pass NULL_TREE as SPECIAL arg to
        get_symbol_table_index().
        (maybe_rewrite_invocation): Set SPECIAL if we need to access a
        private method.
        (build_known_method_ref): New arg: special.  Pass it to
        get_symbol_table_index.
        (get_symbol_table_index): Put SPECIAL in the TREE_PURPOSE field of
        the method list.
        (build_invokevirtual): New arg: special.  Pass it to
        get_symbol_table_index.
        (expand_invoke): New variable: special.
        Pass it to maybe_rewrite_invocation().
        Pass it to build_known_method_ref().
        * class.c (build_symbol_entry): Add new arg: special.  Use it to
        build the symbol table conbstructor.
        (emit_symbol_table): Extract SPECIAL from the method list and pass
        it to build_symbol_entry().
        * parse.y (patch_invoke): Call maybe_rewrite_invocation() and set
        special accordingly.

Index: java/parse.y
===================================================================
--- java/parse.y	(revision 114484)
+++ java/parse.y	(working copy)
@@ -11043,8 +11043,14 @@
       switch (invocation_mode (method, CALL_USING_SUPER (patch)))
 	{
 	case INVOKE_VIRTUAL:
-	  dtable = invoke_build_dtable (0, args);
-	  func = build_invokevirtual (dtable, method);
+	  {
+	    tree signature = build_java_signature (TREE_TYPE (method));
+	    tree special;
+	    maybe_rewrite_invocation (&method, &args, &signature, &special);
+
+	    dtable = invoke_build_dtable (0, args);
+	    func = build_invokevirtual (dtable, method, special);
+	  }
 	  break;
 
 	case INVOKE_NONVIRTUAL:
@@ -11066,10 +11072,11 @@
 	case INVOKE_STATIC:
 	  {
 	    tree signature = build_java_signature (TREE_TYPE (method));
-	    maybe_rewrite_invocation (&method, &args, &signature);
+	    tree special;
+	    maybe_rewrite_invocation (&method, &args, &signature, &special);
 	    func = build_known_method_ref (method, TREE_TYPE (method),
 					   DECL_CONTEXT (method),
-					   signature, args);
+					   signature, args, special);
 	  }
 	  break;
 
Index: java/class.c
===================================================================
--- java/class.c	(revision 114484)
+++ java/class.c	(working copy)
@@ -62,7 +62,7 @@
 static tree maybe_layout_super_class (tree, tree);
 static void add_miranda_methods (tree, tree);
 static int assume_compiled (const char *);
-static tree build_symbol_entry (tree);
+static tree build_symbol_entry (tree, tree);
 static tree emit_assertion_table (tree);
 static void register_class (void);
 
@@ -2651,7 +2651,7 @@
 /* Make a symbol_type (_Jv_MethodSymbol) node for DECL. */
 
 static tree
-build_symbol_entry (tree decl)
+build_symbol_entry (tree decl, tree special)
 {
   tree clname, name, signature, sym;
   clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
@@ -2667,6 +2667,12 @@
   signature = build_utf8_ref (unmangle_classname 
 			      (IDENTIFIER_POINTER (signature),
 			       IDENTIFIER_LENGTH (signature)));
+  /* SPECIAL is either NULL_TREE or integer_one_node.  We emit
+     signature addr+1 if SPECIAL, and this indicates to the runtime
+     system that this is a "special" symbol, i.e. one that should
+     bypass access controls.  */
+  if (special != NULL_TREE)
+    signature = build2 (PLUS_EXPR, TREE_TYPE (signature), signature, special);
       
   START_RECORD_CONSTRUCTOR (sym, symbol_type);
   PUSH_FIELD_VALUE (sym, "clname", clname);
@@ -2701,8 +2707,9 @@
   list = NULL_TREE;  
   while (method_list != NULL_TREE)
     {
+      tree special = TREE_PURPOSE (method_list);
       method = TREE_VALUE (method_list);
-      list = tree_cons (NULL_TREE, build_symbol_entry (method), list);
+      list = tree_cons (NULL_TREE, build_symbol_entry (method, special), list);
       method_list = TREE_CHAIN (method_list);
       index++;
     }
Index: java/expr.c
===================================================================
--- java/expr.c	(revision 114484)
+++ java/expr.c	(working copy)
@@ -1711,7 +1711,8 @@
 	{
 	  tree otable_index
 	    = build_int_cst (NULL_TREE, get_symbol_table_index 
-			     (field_decl, &TYPE_OTABLE_METHODS (output_class)));
+			     (field_decl, NULL_TREE, 
+			      &TYPE_OTABLE_METHODS (output_class)));
 	  tree field_offset
 	    = build4 (ARRAY_REF, integer_type_node,
 		      TYPE_OTABLE_DECL (output_class), otable_index,
@@ -2060,14 +2061,17 @@
    {NULL, NULL, NULL, NULL, 0, NULL}};
 
 /* Scan the rules list for replacements for *METHOD_P and replace the
-   args accordingly.  */
+   args accordingly.  If the rewrite results in an access to a private
+   method, update SPECIAL.*/
 
 void
 maybe_rewrite_invocation (tree *method_p, tree *arg_list_p, 
-			  tree *method_signature_p)
+			  tree *method_signature_p, tree *special)
 {
   tree context = DECL_NAME (TYPE_NAME (DECL_CONTEXT (*method_p)));
   rewrite_rule *p;
+  *special = NULL_TREE;
+
   for (p = rules; p->classname; p++)
     {
       if (get_identifier (p->classname) == context)
@@ -2091,6 +2095,7 @@
 	      gcc_assert (*method_p);
 	      *arg_list_p = p->rewrite_arglist (*arg_list_p);
 	      *method_signature_p = get_identifier (p->new_signature);
+	      *special = integer_one_node;
 
 	      break;
 	    }
@@ -2103,7 +2108,7 @@
 tree
 build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
 			tree self_type, tree method_signature ATTRIBUTE_UNUSED,
-			tree arg_list ATTRIBUTE_UNUSED)
+			tree arg_list ATTRIBUTE_UNUSED, tree special)
 {
   tree func;
   if (is_compiled_class (self_type))
@@ -2121,8 +2126,10 @@
       else
 	{
 	  tree table_index
-	    = build_int_cst (NULL_TREE, get_symbol_table_index 
-			     (method, &TYPE_ATABLE_METHODS (output_class)));
+	    = build_int_cst (NULL_TREE, 
+			     (get_symbol_table_index 
+			      (method, special,
+			       &TYPE_ATABLE_METHODS (output_class))));
 	  func 
 	    = build4 (ARRAY_REF,  
 		      TREE_TYPE (TREE_TYPE (TYPE_ATABLE_DECL (output_class))),
@@ -2207,14 +2214,14 @@
    reused.  */
 
 int
-get_symbol_table_index (tree t, tree *symbol_table)
+get_symbol_table_index (tree t, tree special, tree *symbol_table)
 {
   int i = 1;
   tree method_list;
 
   if (*symbol_table == NULL_TREE)
     {
-      *symbol_table = build_tree_list (t, t);
+      *symbol_table = build_tree_list (special, t);
       return 1;
     }
   
@@ -2223,7 +2230,8 @@
   while (1)
     {
       tree value = TREE_VALUE (method_list);
-      if (value == t)
+      tree purpose = TREE_PURPOSE (method_list);
+      if (value == t && purpose == special)
 	return i;
       i++;
       if (TREE_CHAIN (method_list) == NULL_TREE)
@@ -2232,12 +2240,12 @@
         method_list = TREE_CHAIN (method_list);
     }
 
-  TREE_CHAIN (method_list) = build_tree_list (t, t);
+  TREE_CHAIN (method_list) = build_tree_list (special, t);
   return i;
 }
 
 tree 
-build_invokevirtual (tree dtable, tree method)
+build_invokevirtual (tree dtable, tree method, tree special)
 {
   tree func;
   tree nativecode_ptr_ptr_type_node
@@ -2251,7 +2259,8 @@
 
       otable_index 
 	= build_int_cst (NULL_TREE, get_symbol_table_index 
-			 (method, &TYPE_OTABLE_METHODS (output_class)));
+			 (method, special,
+			  &TYPE_OTABLE_METHODS (output_class)));
       method_index = build4 (ARRAY_REF, integer_type_node, 
 			     TYPE_OTABLE_DECL (output_class), 
 			     otable_index, NULL_TREE, NULL_TREE);
@@ -2307,7 +2316,7 @@
     {
       int itable_index 
 	= 2 * (get_symbol_table_index 
-	       (method, &TYPE_ITABLE_METHODS (output_class)));
+	       (method, NULL_TREE, &TYPE_ITABLE_METHODS (output_class)));
       interface 
 	= build4 (ARRAY_REF, 
 		 TREE_TYPE (TREE_TYPE (TYPE_ITABLE_DECL (output_class))),
@@ -2360,6 +2369,8 @@
   tree call, func, method, arg_list, method_type;
   tree check = NULL_TREE;
 
+  tree special = NULL_TREE;
+
   if (! CLASS_LOADED_P (self_type))
     {
       load_class (self_type, 1);
@@ -2474,12 +2485,13 @@
   arg_list = pop_arguments (TYPE_ARG_TYPES (method_type));
   flush_quick_stack ();
 
-  maybe_rewrite_invocation (&method, &arg_list, &method_signature);
+  maybe_rewrite_invocation (&method, &arg_list, &method_signature,
+			    &special);
 
   func = NULL_TREE;
   if (opcode == OPCODE_invokestatic)
     func = build_known_method_ref (method, method_type, self_type,
-				   method_signature, arg_list);
+				   method_signature, arg_list, special);
   else if (opcode == OPCODE_invokespecial
 	   || (opcode == OPCODE_invokevirtual
 	       && (METHOD_PRIVATE (method)
@@ -2499,14 +2511,14 @@
       TREE_VALUE (arg_list) = save_arg;
       check = java_check_reference (save_arg, ! DECL_INIT_P (method));
       func = build_known_method_ref (method, method_type, self_type,
-				     method_signature, arg_list);
+				     method_signature, arg_list, special);
     }
   else
     {
       tree dtable = invoke_build_dtable (opcode == OPCODE_invokeinterface, 
 					 arg_list);
       if (opcode == OPCODE_invokevirtual)
-	func = build_invokevirtual (dtable, method);
+	func = build_invokevirtual (dtable, method, special);
       else
 	func = build_invokeinterface (dtable, method);
     }
Index: java/java-tree.h
===================================================================
--- java/java-tree.h	(revision 114484)
+++ java/java-tree.h	(working copy)
@@ -1241,11 +1241,11 @@
 extern void initialize_builtins (void);
 
 extern tree lookup_name (tree);
-extern void maybe_rewrite_invocation (tree *, tree *, tree *);
-extern tree build_known_method_ref (tree, tree, tree, tree, tree);
+extern void maybe_rewrite_invocation (tree *, tree *, tree *, tree *);
+extern tree build_known_method_ref (tree, tree, tree, tree, tree, tree);
 extern tree build_class_init (tree, tree);
 extern int attach_init_test_initialization_flags (void **, void *);
-extern tree build_invokevirtual (tree, tree);
+extern tree build_invokevirtual (tree, tree, tree);
 extern tree build_invokeinterface (tree, tree);
 extern tree build_jni_stub (tree);
 extern tree invoke_build_dtable (int, tree);
@@ -1393,7 +1393,7 @@
 extern void finish_method (tree);
 extern void java_expand_body (tree);
 
-extern int get_symbol_table_index (tree, tree *);
+extern int get_symbol_table_index (tree, tree, tree *);
 
 extern tree make_catch_class_record (tree, tree);
 extern tree emit_catch_table (tree);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]