OSDN Git Service

2006-06-07 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / link.cc
index f95b128..5fc82e5 100644 (file)
@@ -55,8 +55,6 @@ details.  */
 
 using namespace gcj;
 
-typedef unsigned int uaddr __attribute__ ((mode (pointer)));
-
 template<typename T>
 struct aligner
 {
@@ -461,19 +459,11 @@ _Jv_Linker::resolve_pool_entry (jclass klass, int index, bool lazy)
              goto end_of_method_search;
          }
 
-       // Finally, search superclasses. 
-       for (jclass cls = owner->getSuperclass (); cls != 0; 
-            cls = cls->getSuperclass ())
-         {
-           the_method = search_method_in_class (cls, klass, method_name,
-                                                method_signature);
-           if (the_method != 0)
-             {
-               found_class = cls;
-               break;
-             }
-         }
-
+       // Finally, search superclasses.
+       the_method = (search_method_in_superclasses 
+                     (owner->getSuperclass (), klass, method_name, 
+                      method_signature, &found_class));
+       
       end_of_method_search:
     
        // FIXME: if (cls->loader != klass->loader), then we
@@ -534,11 +524,12 @@ _Jv_Linker::resolve_class_ref (jclass klass, jclass *classref)
 }
 
 // Find a method declared in the cls that is referenced from klass and
-// perform access checks.
+// perform access checks if CHECK_PERMS is true.
 _Jv_Method *
 _Jv_Linker::search_method_in_class (jclass cls, jclass klass, 
                                    _Jv_Utf8Const *method_name, 
-                                   _Jv_Utf8Const *method_signature)
+                                   _Jv_Utf8Const *method_signature,
+                                   bool check_perms)
 {
   using namespace java::lang::reflect;
 
@@ -551,7 +542,7 @@ _Jv_Linker::search_method_in_class (jclass cls, jclass klass,
                                    method_signature)))
        continue;
 
-      if (_Jv_CheckAccess (klass, cls, method->accflags))
+      if (!check_perms || _Jv_CheckAccess (klass, cls, method->accflags))
        return method;
       else
        {
@@ -568,6 +559,30 @@ _Jv_Linker::search_method_in_class (jclass cls, jclass klass,
   return 0;
 }
 
+// Like search_method_in_class, but work our way up the superclass
+// chain.
+_Jv_Method *
+_Jv_Linker::search_method_in_superclasses (jclass cls, jclass klass, 
+                                          _Jv_Utf8Const *method_name, 
+                                          _Jv_Utf8Const *method_signature,
+                                          jclass *found_class, bool check_perms)
+{
+  _Jv_Method *the_method = NULL;
+
+  for ( ; cls != 0; cls = cls->getSuperclass ())
+    {
+      the_method = search_method_in_class (cls, klass, method_name,
+                                          method_signature, check_perms);
+      if (the_method != 0)
+       {
+         if (found_class)
+           *found_class = cls;
+         break;
+       }
+    }
+  
+  return the_method;
+}
 
 #define INITIAL_IOFFSETS_LEN 4
 #define INITIAL_IFACES_LEN 4
@@ -1076,6 +1091,8 @@ _Jv_Linker::link_symbol_table (jclass klass)
       _Jv_Method *meth = NULL;            
 
       _Jv_Utf8Const *signature = sym.signature;
+      uaddr special;
+      maybe_adjust_signature (signature, special);
 
       if (target_class == NULL)
        throw new java::lang::NoClassDefFoundError 
@@ -1101,8 +1118,15 @@ _Jv_Linker::link_symbol_table (jclass klass)
          // it out now.
          wait_for_state(target_class, JV_STATE_PREPARED);
 
-         meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
-                                         sym.signature);
+         try
+           {
+             meth = (search_method_in_superclasses 
+                     (target_class, klass, sym.name, signature, 
+                      NULL, special == 0));
+           }
+         catch (::java::lang::IllegalAccessError *e)
+           {
+           }
 
          // Every class has a throwNoSuchMethodErrorIndex method that
          // it inherits from java.lang.Object.  Find its vtable
@@ -1158,7 +1182,7 @@ _Jv_Linker::link_symbol_table (jclass klass)
        try
          {
            the_field = find_field (klass, target_class, &found_class,
-                                   sym.name, sym.signature);
+                                   sym.name, signature);
            if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
              throw new java::lang::IncompatibleClassChangeError;
            else
@@ -1185,7 +1209,10 @@ _Jv_Linker::link_symbol_table (jclass klass)
         _Jv_FindClassNoException (sym.class_name, klass->loader);
 
       _Jv_Method *meth = NULL;            
+
       _Jv_Utf8Const *signature = sym.signature;
+      uaddr special;
+      maybe_adjust_signature (signature, special);
 
       // ??? Setting this pointer to null will at least get us a
       // NullPointerException
@@ -1193,7 +1220,7 @@ _Jv_Linker::link_symbol_table (jclass klass)
 
       // If the target class is missing we prepare a function call
       // that throws a NoClassDefFoundError and store the address of
-      // that newly prepare method in the atable. The user can run
+      // that newly prepared method in the atable. The user can run
       // code in classes where the missing class is part of the
       // execution environment as long as it is never referenced.
       if (target_class == NULL)
@@ -1219,8 +1246,15 @@ _Jv_Linker::link_symbol_table (jclass klass)
              throw new VerifyError(sb->toString());
            }
 
-         meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
-                                         sym.signature);
+         try
+           {
+             meth = (search_method_in_superclasses 
+                     (target_class, klass, sym.name, signature, 
+                      NULL, special == 0));
+           }
+         catch (::java::lang::IllegalAccessError *e)
+           {
+           }
 
          if (meth != NULL)
            {
@@ -1250,7 +1284,7 @@ _Jv_Linker::link_symbol_table (jclass klass)
        wait_for_state(target_class, JV_STATE_PREPARED);
        jclass found_class;
        _Jv_Field *the_field = find_field (klass, target_class, &found_class,
-                                          sym.name, sym.signature);
+                                          sym.name, signature);
        if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
          klass->atable->addresses[index] = the_field->u.addr;
        else
@@ -1270,14 +1304,17 @@ _Jv_Linker::link_symbol_table (jclass klass)
        ++index)
     {
       jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
+
       _Jv_Utf8Const *signature = sym.signature;
+      uaddr special;
+      maybe_adjust_signature (signature, special);
 
       jclass cls;
       int i;
 
       wait_for_state(target_class, JV_STATE_LOADED);
       bool found = _Jv_getInterfaceMethod (target_class, cls, i,
-                                          sym.name, sym.signature);
+                                          sym.name, signature);
 
       if (found)
        {