This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: Symbol table resolution
- From: Andrew Haley <aph at redhat dot com>
- To: gcc at gcc dot gnu dot org, java at gcc dot gnu dot org
- Date: Thu, 8 Jun 2006 14:13:22 +0100
- Subject: Re: Symbol table resolution
- References: <17543.3948.293570.795837@dell.pink>
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);