PR149: Used wrong class loader.
[cacao.git] / src / vm / jit / stacktrace.cpp
index e3389e4ac49a33cc210d7b3963a255058bb1fb4e..c59d05ac1bf7299add8422432dbd1cc7041da8ba 100644 (file)
@@ -1,7 +1,8 @@
 /* src/vm/jit/stacktrace.cpp - machine independent stacktrace system
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2011
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
@@ -32,6 +33,7 @@
 
 #include "vm/types.h"
 
+#include "arch.h"
 #include "md.h"
 
 #include "mm/gc.hpp"
@@ -137,7 +139,7 @@ void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, vo
                /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
                   the RA from stack. */
 
-               framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
+               framesize = md_stacktrace_get_framesize(code);
 
                ra = md_stacktrace_get_returnaddress(sp, framesize);
 # else
@@ -148,7 +150,7 @@ void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, vo
                   the asm_vm_call_method special case. */
 
                if ((code == NULL) || !code_is_leafmethod(code)) {
-                       framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
+                       framesize = md_stacktrace_get_framesize(code);
 
                        ra = md_stacktrace_get_returnaddress(sp, framesize);
                }
@@ -305,7 +307,7 @@ static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
  
        /* Get the current stack frame size. */
 
-       framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
+       framesize = md_stacktrace_get_framesize(code);
 
        /* Get the RA of the current stack frame (RA to the parent Java
           method) if the current method is a non-leaf method.  Otherwise
@@ -356,7 +358,7 @@ static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
        else
 #endif
                {
-#if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
+#if STACKFRMAE_RA_BETWEEN_FRAMES
                        sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
 #elif defined(__SPARC_64__)
                        /* already has the new sp */
@@ -872,17 +874,12 @@ classinfo *stacktrace_get_caller_class(int depth)
 #endif
 
 
-/* stacktrace_first_nonnull_classloader ****************************************
-
-   Returns the first non-null (user-defined) classloader on the stack.
-   If none is found NULL is returned.
-
-   RETURN:
-       classloader
-
-*******************************************************************************/
-
-classloader_t *stacktrace_first_nonnull_classloader(void)
+/**
+ * Returns the first non-null (user-defined) classloader on the stack.
+ *
+ * @return The first non-null classloader or NULL if none is found.
+ */
+classloader_t* stacktrace_first_nonnull_classloader(void)
 {
        stackframeinfo_t *sfi;
        stackframeinfo_t  tmpsfi;
@@ -907,6 +904,14 @@ classloader_t *stacktrace_first_nonnull_classloader(void)
                m  = tmpsfi.code->m;
                cl = class_get_classloader(m->clazz);
 
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+               /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
+                  (vframeStreamCommon::skip_reflection_related_frames). */
+               if (class_issubclass(m->clazz, class_sun_reflect_MethodAccessorImpl) ||
+                       class_issubclass(m->clazz, class_sun_reflect_ConstructorAccessorImpl))
+                       continue;
+#endif
+
                if (cl != NULL)
                        return cl;
        }
@@ -915,6 +920,82 @@ classloader_t *stacktrace_first_nonnull_classloader(void)
 }
 
 
+/**
+ * Checks if a given classloader is equal to the the second classloader
+ * or one of its ancestors (parents).
+ *
+ * XXX: This helper method should be moved to java_lang_Classloader.
+ */
+#if defined(ENABLE_JAVASE)
+static bool is_ancestor_of(classloader_t* loader, classloader_t* parent)
+{
+       // Iterate over chain of possible parents.
+       while (parent != NULL) {
+
+               // Check if given loader is parent.
+               if (loader == parent)
+                       return true;
+
+               // Jump to next parent.
+               java_lang_ClassLoader jlcl(parent);
+               parent = jlcl.get_parent();
+       }
+
+       return false;
+}
+#endif /* defined(ENABLE_JAVASE) */
+
+
+/**
+ * Returns the first non-system (user-defined) classloader on the stack.
+ * A non-system classloader is a non-null classloader being not equal to
+ * the system classloader (or one of its ancestors).
+ *
+ * @return The first non-system classloader or NULL if none is found.
+ */
+#if defined(ENABLE_JAVASE)
+classloader_t* stacktrace_first_nonsystem_classloader(void)
+{
+       stackframeinfo_t *sfi;
+       stackframeinfo_t  tmpsfi;
+       methodinfo       *m;
+       classloader_t    *cl;
+       classloader_t    *syscl;
+
+#if !defined(NDEBUG)
+       if (opt_DebugStackTrace)
+               log_println("[stacktrace_first_nonsystem_classloader]");
+#endif
+
+       // Get the stackframeinfo of the current thread.
+       sfi = threads_get_current_stackframeinfo();
+
+       // Get the system class class loader.
+       syscl = java_lang_ClassLoader::invoke_getSystemClassLoader();
+
+       // Iterate over the whole stack.
+       for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+                stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+                stacktrace_stackframeinfo_next(&tmpsfi)) {
+
+               m  = tmpsfi.code->m;
+               cl = class_get_classloader(m->clazz);
+
+               if (cl == NULL)
+                       continue;
+
+               // XXX if a method in a class in a trusted loader is in a
+               // doPrivileged, return NULL (or break) here.
+
+               if (!is_ancestor_of(cl, syscl))
+                       return cl;
+       }
+
+       return NULL;
+}
+#endif /* defined(ENABLE_JAVASE) */
+
+
 /* stacktrace_getClassContext **************************************************
 
    Creates a Class context array.
@@ -1329,7 +1410,8 @@ stacktrace_t* stacktrace_get_of_thread(threadobject* t)
 
 /* stacktrace_print_of_thread **************************************************
 
-   Print the current stacktrace of the given thread.
+   Print the current stacktrace of the given thread. It will only work
+   for suspended threads.
 
    ARGUMENTS:
        t ... thread
@@ -1349,7 +1431,7 @@ void stacktrace_print_of_thread(threadobject *t)
 
        sfi = t->_stackframeinfo;
        
-       if (sfi == NULL) {
+       if (!t->suspended || sfi == NULL) {
                puts("\t<<No stacktrace available>>");
                fflush(stdout);
                return;