Fix VMStackWalker.getClassContext()

Andrew Haley aph@redhat.com
Wed Jan 24 12:48:00 GMT 2007


VMStackWalker.getClassContext() is very fragile.  This is to some
extent due to the way that _Jv_StackTrace::GetStackWalkerStack() is
written, which breaks when sibcalled.

Two fixes here.  Firstly, make sure that VMStackWalker is linked: if
it isn't, none of its methods are registered in the Map used by the
unwinder.  Secondly, make sure that VMStackWalker doesn't sibcall
GetStackWalkerStack().  The volatile asm I use here to prevent the
sibcall is inelegant but it's certainly effective.

Andrew.


2007-01-24  Andrew Haley  <aph@redhat.com>

	* gnu/classpath/natVMStackWalker.cc: Call InitClass everywhere.
	(getClassContext) Add a barrier to prevent GetStackWalkerStack()
	from being sibcalled.

Index: gnu/classpath/natVMStackWalker.cc
===================================================================
--- gnu/classpath/natVMStackWalker.cc	(revision 121108)
+++ gnu/classpath/natVMStackWalker.cc	(working copy)
@@ -17,22 +17,29 @@
 #include <gnu/classpath/VMStackWalker.h>
 #include <gnu/gcj/RawData.h>
 #include <java/lang/ClassLoader.h>
+#include <java/lang/Class.h>
 
 JArray<jclass> *
 gnu::classpath::VMStackWalker::getClassContext(void)
 {
-  return _Jv_StackTrace::GetStackWalkerStack ();
+  _Jv_InitClass (&::gnu::classpath::VMStackWalker::class$);
+  JArray<jclass> *result = _Jv_StackTrace::GetStackWalkerStack ();
+  // Prevent GetStackWalkerStack() from being sibcalled.
+  __asm__ __volatile__ ("" : : "g" (result));
+  return result;
 }
 
 jclass
 gnu::classpath::VMStackWalker::getCallingClass(void)
 {
+  _Jv_InitClass (&::gnu::classpath::VMStackWalker::class$);
   return _Jv_StackTrace::GetStackWalkerCallingClass ();
 }
 
 jclass
 gnu::classpath::VMStackWalker::getCallingClass(::gnu::gcj::RawData *pc)
 {
+  _Jv_InitClass (&::gnu::classpath::VMStackWalker::class$);
   void *f = _Unwind_FindEnclosingFunction (pc);
 
   // FIXME: it might well be a good idea to cache pc values here in
@@ -57,12 +64,14 @@
 ::java::lang::ClassLoader *
 gnu::classpath::VMStackWalker::getClassLoader(::java::lang::Class *c)
 {
+  _Jv_InitClass (&::gnu::classpath::VMStackWalker::class$);
   return c->getClassLoaderInternal ();
 }
 
 ::java::lang::ClassLoader *
 gnu::classpath::VMStackWalker::getCallingClassLoader(void)
 {
+  _Jv_InitClass (&::gnu::classpath::VMStackWalker::class$);
   return
     _Jv_StackTrace::GetStackWalkerCallingClass ()->getClassLoaderInternal ();
 }
@@ -70,11 +79,13 @@
 ::java::lang::ClassLoader *
 gnu::classpath::VMStackWalker::getCallingClassLoader(::gnu::gcj::RawData *pc)
 {
+  _Jv_InitClass (&::gnu::classpath::VMStackWalker::class$);
   return getCallingClass (pc)->getClassLoaderInternal ();
 }
 
 ::java::lang::ClassLoader *
 gnu::classpath::VMStackWalker::firstNonNullClassLoader(void)
 {
+  _Jv_InitClass (&::gnu::classpath::VMStackWalker::class$);
   return _Jv_StackTrace::GetStackWalkerFirstNonNullLoader ();
 }



More information about the Java-patches mailing list