/* 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.
#include "vm/types.h"
+#include "arch.h"
#include "md.h"
#include "mm/gc.hpp"
/* 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
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);
}
/* 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
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 */
#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;
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;
}
}
+/**
+ * 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.
/* 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
sfi = t->_stackframeinfo;
- if (sfi == NULL) {
+ if (!t->suspended || sfi == NULL) {
puts("\t<<No stacktrace available>>");
fflush(stdout);
return;