Commit 18744d9b by Bryce McKinlay Committed by Bryce McKinlay

New Stack Trace infrastructure.

2005-03-10  Bryce McKinlay  <mckinlay@redhat.com>

	New Stack Trace infrastructure.
	* Makefile.am (libgcj0_convenience_la_SOURCES): Add stacktrace.cc.
	(gnu/gcj/runtime/StackTrace.lo): Removed.
	(ordinary_java_source_files): Remove obsolete files.
	(nat_source_files): Remove obsolete files. Add natVMThrowable.cc.
	* configure.host (fallback_backtrace_h): Set backtrace header
	for mingw and cygwin targets.
	* configure.ac: Make symlink for fallback backtrace headers.
	* Makefile.in, configure: Rebuilt.
	* defineclass.cc (_Jv_ClassReader::read_one_code_attribute):
	Read 'LineNumberTable' attribute.
	(_Jv_ClassReader::read_one_class_attribute): Read 'SourceFile'
	attribute.
	(_Jv_ClassReader::handleCodeAttribute): Initialize method line
	table fields.
	* exception.cc: Remove unused include.
	* interpret.cc (DIRECT_THREADED, insn_slot): Moved to java-interp.h.
	(SAVE_PC): New macro. Save current PC in the interpreter frame.
	(NULLCHECK, NULLARRAYCHECK): Use SAVE_PC.
	(_Jv_InterpMethod::compile): Translate bytecode PC values in the line
	table to direct threaded instruction values.
	(_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): Removed.
	(_Jv_InterpMethod::run): No longer member function. All
	callers updated. Remove _Unwind calls. Call SAVE_PC whenever a call
	is made or where an instruction could throw.
	(_Jv_InterpMethod::get_source_line): New. Look up source line numbers
	in line_table.
	* prims.cc (catch_segv): Construct exception after MAKE_THROW_FRAME.
	(catch_fpe): Likewise.
	* stacktrace.cc: New file. Stack trace code now here.
	* gnu/gcj/runtime/MethodRef.java:
	* gnu/gcj/runtime/NameFinder.java: Mostly reimplemented. Now simply
	calls addr2line to look up PC addresses in a given binary or shared
	library.
	* gnu/gcj/runtime/StackTrace.java, gnu/gcj/runtime/natNameFinder.cc,
	gnu/gcj/runtime/natStackTrace.cc: Removed.
	* gnu/java/lang/MainThread.java (call_main): Add comment warning that
	this function name is specially recognised by the stack trace code
	and shouldn't be changed.
	* include/java-interp.h (DIRECT_THREADED, insn_slot): Moved here.
	(struct  _Jv_LineTableEntry, line_table, line_table_len): New.
	(_Jv_InterpMethod::run): Update declaration.
	(_Jv_StackTrace_): New friend. NameFinder and StackTrace no longer
	friends.
	(_Jv_InterpFrame): Renamed from _Jv_MethodChain. Add PC field.
	* include/java-stack.h: New file. Declarations for stack tracing.
	* include/jvm.h (_Jv_Frame_info): Removed.
	* java/lang/Class.h: Update friend declarations.
	* java/lang/VMClassLoader.java (getSystemClassLoader): Simplify
	exception message.
	* java/lang/VMThrowable.java (fillInStackTrace): Now native.
	(getStackTrace): Now native.
	(data): New RawDataManaged field.
	* java/lang/natClass.cc: Update includes.
	(forName): Use _Jv_StackTrace::GetCallingClass for
	calling-classloader check.
	(getClassLoader): Likewise.
	* java/lang/natRuntime.cc: Update includes.
	(_load): Use _Jv_StackTrace::GetFirstNonSystemClassLoader.
	* java/lang/natVMSecurityManager.cc: Update includes.
	(getClassContext): Use _Jv_StackTrace::GetClassContext.
	* java/lang/natVMThrowable.cc: New file. Native methods for
	VMThrowable.
	* java/lang/reflect/natArray.cc: Update includes.
	(newInstance): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/lang/reflect/natConstructor.cc: Update includes.
	(newInstance): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/lang/reflect/natField.cc: Update includes.
	(getAddr): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/lang/reflect/natMethod.cc: Update includes.
	(invoke): Use _Jv_StackTrace::GetCallingClass to implement
	accessibility check.
	* java/util/natResourceBundle.cc: Update includes.
	(getCallingClassLoader): Use _Jv_StackTrace::GetCallingClass.
	* java/util/logging/natLogger.cc: Update includes. Use
	_Jv_StackTrace::GetCallerInfo to get call-site info.
	* sysdep/generic/backtrace.h: Fallback backtrace code. Stub
	implementation.
	* sysdep/i386/backtrace.h: New. Fallback backtrace code. i386
	implementation.

From-SVN: r96253
parent ca1593fd
2005-03-10 Bryce McKinlay <mckinlay@redhat.com>
New Stack Trace infrastructure.
* Makefile.am (libgcj0_convenience_la_SOURCES): Add stacktrace.cc.
(gnu/gcj/runtime/StackTrace.lo): Removed.
(ordinary_java_source_files): Remove obsolete files.
(nat_source_files): Remove obsolete files. Add natVMThrowable.cc.
* configure.host (fallback_backtrace_h): Set backtrace header
for mingw and cygwin targets.
* configure.ac: Make symlink for fallback backtrace headers.
* Makefile.in, configure: Rebuilt.
* defineclass.cc (_Jv_ClassReader::read_one_code_attribute):
Read 'LineNumberTable' attribute.
(_Jv_ClassReader::read_one_class_attribute): Read 'SourceFile'
attribute.
(_Jv_ClassReader::handleCodeAttribute): Initialize method line
table fields.
* exception.cc: Remove unused include.
* interpret.cc (DIRECT_THREADED, insn_slot): Moved to java-interp.h.
(SAVE_PC): New macro. Save current PC in the interpreter frame.
(NULLCHECK, NULLARRAYCHECK): Use SAVE_PC.
(_Jv_InterpMethod::compile): Translate bytecode PC values in the line
table to direct threaded instruction values.
(_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): Removed.
(_Jv_InterpMethod::run): No longer member function. All
callers updated. Remove _Unwind calls. Call SAVE_PC whenever a call
is made or where an instruction could throw.
(_Jv_InterpMethod::get_source_line): New. Look up source line numbers
in line_table.
* prims.cc (catch_segv): Construct exception after MAKE_THROW_FRAME.
(catch_fpe): Likewise.
* stacktrace.cc: New file. Stack trace code now here.
* gnu/gcj/runtime/MethodRef.java:
* gnu/gcj/runtime/NameFinder.java: Mostly reimplemented. Now simply
calls addr2line to look up PC addresses in a given binary or shared
library.
* gnu/gcj/runtime/StackTrace.java, gnu/gcj/runtime/natNameFinder.cc,
gnu/gcj/runtime/natStackTrace.cc: Removed.
* gnu/java/lang/MainThread.java (call_main): Add comment warning that
this function name is specially recognised by the stack trace code
and shouldn't be changed.
* include/java-interp.h (DIRECT_THREADED, insn_slot): Moved here.
(struct _Jv_LineTableEntry, line_table, line_table_len): New.
(_Jv_InterpMethod::run): Update declaration.
(_Jv_StackTrace_): New friend. NameFinder and StackTrace no longer
friends.
(_Jv_InterpFrame): Renamed from _Jv_MethodChain. Add PC field.
* include/java-stack.h: New file. Declarations for stack tracing.
* include/jvm.h (_Jv_Frame_info): Removed.
* java/lang/Class.h: Update friend declarations.
* java/lang/VMClassLoader.java (getSystemClassLoader): Simplify
exception message.
* java/lang/VMThrowable.java (fillInStackTrace): Now native.
(getStackTrace): Now native.
(data): New RawDataManaged field.
* java/lang/natClass.cc: Update includes.
(forName): Use _Jv_StackTrace::GetCallingClass for
calling-classloader check.
(getClassLoader): Likewise.
* java/lang/natRuntime.cc: Update includes.
(_load): Use _Jv_StackTrace::GetFirstNonSystemClassLoader.
* java/lang/natVMSecurityManager.cc: Update includes.
(getClassContext): Use _Jv_StackTrace::GetClassContext.
* java/lang/natVMThrowable.cc: New file. Native methods for
VMThrowable.
* java/lang/reflect/natArray.cc: Update includes.
(newInstance): Use _Jv_StackTrace::GetCallingClass to implement
accessibility check.
* java/lang/reflect/natConstructor.cc: Update includes.
(newInstance): Use _Jv_StackTrace::GetCallingClass to implement
accessibility check.
* java/lang/reflect/natField.cc: Update includes.
(getAddr): Use _Jv_StackTrace::GetCallingClass to implement
accessibility check.
* java/lang/reflect/natMethod.cc: Update includes.
(invoke): Use _Jv_StackTrace::GetCallingClass to implement
accessibility check.
* java/util/natResourceBundle.cc: Update includes.
(getCallingClassLoader): Use _Jv_StackTrace::GetCallingClass.
* java/util/logging/natLogger.cc: Update includes. Use
_Jv_StackTrace::GetCallerInfo to get call-site info.
* sysdep/generic/backtrace.h: Fallback backtrace code. Stub
implementation.
* sysdep/i386/backtrace.h: New. Fallback backtrace code. i386
implementation.
2005-03-10 Ranjit Mathew <rmathew@hotmail.com>
* testsuite/libjava.compile/PR20312.java: New file.
......
......@@ -217,7 +217,7 @@ libgij_la_LDFLAGS = -rpath $(toolexeclibdir) \
# convenience library suddenly invokes the --whole-archive path instead.
# This allows the build to succeed for targets that allocate multiple got
# subsections in the linker, such as Alpha and MIPS.
libgcj0_convenience_la_SOURCES = prims.cc jni.cc exception.cc \
libgcj0_convenience_la_SOURCES = prims.cc jni.cc exception.cc stacktrace.cc \
link.cc defineclass.cc interpret.cc verify.cc \
$(nat_source_files) $(math_c_source_files) $(java_source_files) \
$(gnu_xml_source_files) $(built_java_source_files) \
......@@ -588,20 +588,12 @@ clean-nat:
SUFFIXES = .class .java .h .properties
## Note: we omit StackTrace here, since it has an explicit rule a bit
## later, and GNU make will warn in this case.
$(filter-out gnu/gcj/runtime/StackTrace.lo, $(javao_files)) $(xlib_javao_files): %.lo: %.java
$(javao_files) $(xlib_javao_files): %.lo: %.java
$(LTGCJCOMPILE) -o $@ -c $<
$(gtk_awt_peer_sources:.java=.lo) $(gnu_xml_source_files:.java=.lo): %.lo: %.java
$(LTGCJCOMPILE) -fjni -o $@ -c $<
## A special case. The sibcall optimization can change the number of
## frames on the stack, and StackTrace makes assumptions about this
## number.
gnu/gcj/runtime/StackTrace.lo: gnu/gcj/runtime/StackTrace.java
$(LTGCJCOMPILE) -fno-optimize-sibling-calls -o $@ -c $<
## Pass the list of object files to libtool in a temporary file to
## avoid tripping platform command line length limits.
libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES)
......@@ -2911,12 +2903,10 @@ gnu/gcj/io/SimpleSHSStream.java \
gnu/gcj/runtime/FileDeleter.java \
gnu/gcj/runtime/FinalizerThread.java \
gnu/gcj/runtime/JNIWeakRef.java \
gnu/gcj/runtime/MethodRef.java \
gnu/gcj/runtime/NameFinder.java \
gnu/gcj/runtime/PersistentByteMap.java \
gnu/gcj/runtime/SharedLibHelper.java \
gnu/gcj/runtime/SharedLibLoader.java \
gnu/gcj/runtime/StackTrace.java \
gnu/gcj/runtime/StringBuffer.java \
gnu/gcj/runtime/SystemClassLoader.java \
gnu/gcj/runtime/VMClassLoader.java \
......@@ -3676,9 +3666,7 @@ gnu/gcj/convert/natOutput_SJIS.cc \
gnu/gcj/io/natSimpleSHSStream.cc \
gnu/gcj/io/shs.cc \
gnu/gcj/runtime/natFinalizerThread.cc \
gnu/gcj/runtime/natNameFinder.cc \
gnu/gcj/runtime/natSharedLibLoader.cc \
gnu/gcj/runtime/natStackTrace.cc \
gnu/gcj/runtime/natStringBuffer.cc \
gnu/gcj/runtime/natVMClassLoader.cc \
gnu/gcj/util/natDebug.cc \
......@@ -3708,6 +3696,7 @@ java/lang/natSystem.cc \
java/lang/natThread.cc \
java/lang/natVMClassLoader.cc \
java/lang/natVMSecurityManager.cc \
java/lang/natVMThrowable.cc \
java/lang/ref/natReference.cc \
java/lang/reflect/natArray.cc \
java/lang/reflect/natConstructor.cc \
......
......@@ -8454,6 +8454,8 @@ fi
if test -d sysdep; then true; else mkdir sysdep; fi
ac_config_links="$ac_config_links sysdep/locks.h:sysdep/$sysdeps_dir/locks.h"
ac_config_links="$ac_config_links sysdep/backtrace.h:$fallback_backtrace_h"
HASH_SYNC_SPEC=
# Hash synchronization is only useful with posix threads right now.
......@@ -16482,6 +16484,7 @@ do
"include/java-gc.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-gc.h:include/$GCHDR" ;;
"include/java-threads.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-threads.h:include/$THREADH" ;;
"sysdep/locks.h" ) CONFIG_LINKS="$CONFIG_LINKS sysdep/locks.h:sysdep/$sysdeps_dir/locks.h" ;;
"sysdep/backtrace.h" ) CONFIG_LINKS="$CONFIG_LINKS sysdep/backtrace.h:$fallback_backtrace_h" ;;
"include/java-signal.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-signal.h:$SIGNAL_HANDLER" ;;
"include/java-signal-aux.h" ) CONFIG_LINKS="$CONFIG_LINKS include/java-signal-aux.h:$SIGNAL_HANDLER_AUX" ;;
"depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
......
......@@ -710,6 +710,7 @@ AM_CONDITIONAL(USING_NO_THREADS, test "$THREADS" = none)
if test -d sysdep; then true; else mkdir sysdep; fi
AC_CONFIG_LINKS(sysdep/locks.h:sysdep/$sysdeps_dir/locks.h)
AC_CONFIG_LINKS(sysdep/backtrace.h:$fallback_backtrace_h)
HASH_SYNC_SPEC=
# Hash synchronization is only useful with posix threads right now.
......
......@@ -30,6 +30,8 @@
# from a signal handler.
# disable_dladdr Set to "yes" if dladdr should not be used
# (i.e it is broken).
# fallback_backtrace_h Header to use for fallback backtrace implementation
# (only for targets that don't support DWARF2 unwind)
libgcj_flags=
libgcj_cflags=
......@@ -42,6 +44,7 @@ sysdeps_dir=generic
slow_pthread_self=
can_unwind_signal=no
disable_dladdr=
fallback_backtrace_h=sysdep/generic/backtrace.h
case "${target_optspace}:${host}" in
yes:*)
......@@ -258,6 +261,13 @@ EOF
;;
esac
case "${host}" in
*-cygwin* | *-mingw*)
fallback_backtrace_h=sysdep/i386/backtrace.h
;;
esac
libgcj_cflags="${libgcj_cflags} ${libgcj_flags}"
libgcj_cxxflags="${libgcj_cxxflags} ${libgcj_flags}"
libgcj_javaflags="${libgcj_javaflags} ${libgcj_flags}"
......@@ -229,6 +229,7 @@ struct _Jv_ClassReader {
len = length;
pos = 0;
def = klass;
def->size_in_bytes = -1;
def->vtable_method_count = -1;
def->engine = &_Jv_soleInterpreterEngine;
......@@ -613,26 +614,54 @@ void _Jv_ClassReader::read_one_method_attribute (int method_index)
}
}
void _Jv_ClassReader::read_one_code_attribute (int /*method*/)
void _Jv_ClassReader::read_one_code_attribute (int method_index)
{
/* ignore for now, ... later we may want to pick up
line number information, for debugging purposes;
in fact, the whole debugger issue is open! */
/* int name = */ read2u ();
int name = read2u ();
int length = read4 ();
skip (length);
if (is_attribute_name (name, "LineNumberTable"))
{
_Jv_InterpMethod *method = reinterpret_cast<_Jv_InterpMethod *>
(def_interp->interpreted_methods[method_index]);
if (method->line_table != NULL)
throw_class_format_error ("Method already has LineNumberTable");
int table_len = read2u ();
_Jv_LineTableEntry* table
= (_Jv_LineTableEntry *) JvAllocBytes (table_len
* sizeof (_Jv_LineTableEntry));
for (int i = 0; i < table_len; i++)
{
table[i].bytecode_pc = read2u ();
table[i].line = read2u ();
}
method->line_table_len = table_len;
method->line_table = table;
}
else
{
/* ignore unknown code attributes */
skip (length);
}
}
void _Jv_ClassReader::read_one_class_attribute ()
{
/* we also ignore the class attributes, ...
some day we'll add inner-classes support. */
/* int name = */ read2u ();
int name = read2u ();
int length = read4 ();
skip (length);
if (is_attribute_name (name, "SourceFile"))
{
int source_index = read2u ();
check_tag (source_index, JV_CONSTANT_Utf8);
prepare_pool_entry (source_index, JV_CONSTANT_Utf8);
def_interp->source_file_name = _Jv_NewStringUtf8Const
(def->constants.data[source_index].utf8);
}
else
{
/* Currently, we ignore most class attributes.
FIXME: Add inner-classes attributes support. */
skip (length);
}
}
......@@ -1279,6 +1308,9 @@ void _Jv_ClassReader::handleCodeAttribute
method->defining_class = def;
method->self = &def->methods[method_index];
method->prepared = NULL;
method->line_table_len = 0;
method->line_table = NULL;
// grab the byte code!
memcpy ((void*) method->bytecode (),
......
......@@ -15,7 +15,6 @@ details. */
#include <java/lang/Class.h>
#include <java/lang/NullPointerException.h>
#include <gnu/gcj/runtime/StackTrace.h>
#include <gnu/gcj/runtime/MethodRef.h>
#include <gnu/gcj/RawData.h>
#include <gcj/cni.h>
......
......@@ -52,7 +52,7 @@ public interface Configuration
// For libgcj we never load the JNI libraries.
boolean INIT_LOAD_LIBRARY = false;
// For libgcj we have native methods for proxy support....
// For libgcj we have native methods for dynamic proxy support....
boolean HAVE_NATIVE_GET_PROXY_DATA = false;
boolean HAVE_NATIVE_GET_PROXY_CLASS = false;
boolean HAVE_NATIVE_GENERATE_PROXY_CLASS = false;
......
......@@ -127,5 +127,7 @@ final class MainThread extends Thread
return mainName;
}
// Note: this function name is known to the stack tracing code.
// You shouldn't change this without also updating stacktrace.cc.
private native void call_main();
}
......@@ -23,6 +23,11 @@ details. */
#include <java/lang/ClassLoader.h>
#include <java/lang/reflect/Modifier.h>
// Define this to get the direct-threaded interpreter. If undefined,
// we revert to a basic bytecode interpreter. The former is faster
// but uses more memory.
#define DIRECT_THREADED
extern "C" {
#include <ffi.h>
}
......@@ -95,6 +100,41 @@ public:
}
};
// The type of the PC depends on whether we're doing direct threading
// or a more ordinary bytecode interpreter.
#ifdef DIRECT_THREADED
// Slot in the "compiled" form of the bytecode.
union insn_slot
{
// Address of code.
void *insn;
// An integer value used by an instruction.
jint int_val;
// A pointer value used by an instruction.
void *datum;
};
typedef insn_slot *pc_t;
#else
typedef unsigned char *pc_t;
#endif
// This structure holds the bytecode pc and corresponding source code
// line number. An array (plus length field) of this structure is put
// in each _Jv_InterpMethod and used to resolve the (internal) program
// counter of the interpreted method to an actual java source file
// line.
struct _Jv_LineTableEntry
{
union
{
pc_t pc;
int bytecode_pc;
};
int line;
};
class _Jv_InterpMethod : public _Jv_MethodBase
{
_Jv_ushort max_stack;
......@@ -103,6 +143,10 @@ class _Jv_InterpMethod : public _Jv_MethodBase
_Jv_ushort exc_count;
// Length of the line_table - when this is zero then line_table is NULL.
int line_table_len;
_Jv_LineTableEntry *line_table;
void *prepared;
unsigned char* bytecode ()
......@@ -135,17 +179,19 @@ class _Jv_InterpMethod : public _Jv_MethodBase
static void run_class (ffi_cif*, void*, ffi_raw*, void*);
static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*);
void run (void*, ffi_raw *);
static void run (void*, ffi_raw *, _Jv_InterpMethod *);
// Returns source file line number for given PC value, or -1 if line
// number info is unavailable.
int get_source_line(pc_t mpc);
public:
static void dump_object(jobject o);
friend class _Jv_ClassReader;
friend class _Jv_BytecodeVerifier;
friend class gnu::gcj::runtime::NameFinder;
friend class gnu::gcj::runtime::StackTrace;
friend class _Jv_StackTrace;
friend class _Jv_InterpreterEngine;
#ifdef JV_MARKOBJ_DECL
friend JV_MARKOBJ_DECL;
......@@ -155,11 +201,14 @@ class _Jv_InterpMethod : public _Jv_MethodBase
class _Jv_InterpClass
{
_Jv_MethodBase **interpreted_methods;
_Jv_ushort *field_initializers;
_Jv_ushort *field_initializers;
jstring source_file_name;
friend class _Jv_ClassReader;
friend class _Jv_InterpMethod;
friend class _Jv_StackTrace;
friend class _Jv_InterpreterEngine;
friend void _Jv_InitField (jobject, jclass, int);
#ifdef JV_MARKOBJ_DECL
friend JV_MARKOBJ_DECL;
......@@ -219,23 +268,24 @@ public:
}
};
// A structure of this type is used to link together interpreter
// invocations on the stack.
struct _Jv_MethodChain
// The interpreted call stack, represented by a linked list of frames.
struct _Jv_InterpFrame
{
const _Jv_InterpMethod *self;
_Jv_MethodChain **ptr;
_Jv_MethodChain *next;
_Jv_InterpMethod *self;
_Jv_InterpFrame **ptr;
_Jv_InterpFrame *next;
pc_t pc;
_Jv_MethodChain (const _Jv_InterpMethod *s, _Jv_MethodChain **n)
_Jv_InterpFrame (_Jv_InterpMethod *s, _Jv_InterpFrame **n)
{
self = s;
ptr = n;
next = *n;
*n = this;
pc = NULL;
}
~_Jv_MethodChain ()
~_Jv_InterpFrame ()
{
*ptr = next;
}
......
// java-stack.h - Definitions for unwinding & inspecting the call stack.
/* Copyright (C) 2003 Free Software Foundation
/* Copyright (C) 2005 Free Software Foundation
This file is part of libgcj.
......@@ -21,10 +21,12 @@ details. */
#include <java/lang/Class.h>
#include <java/lang/StackTraceElement.h>
#include <java/lang/Throwable.h>
#include <java/lang/Thread.h>
#include <gnu/gcj/runtime/NameFinder.h>
using namespace gnu::gcj::runtime;
using namespace java::lang;
enum _Jv_FrameType
{
......@@ -51,13 +53,44 @@ struct _Jv_StackFrame
#ifdef INTERPRETER
_Jv_InterpFrameInfo interp;
#endif
void *ip;
struct {
void *ip;
void *start_ip;
};
};
// _Jv_FrameInfo info; /* Frame-type specific data. */
jclass klass;
_Jv_Method *meth;
};
typedef struct _Jv_UnwindState;
typedef _Unwind_Reason_Code (*_Jv_TraceFn) (_Jv_UnwindState *);
struct _Jv_UnwindState
{
jint length; // length of FRAMES
jint pos; // current position in FRAMES
_Jv_StackFrame *frames; // array of stack frame data to be filled.
_Jv_InterpFrame *interp_frame; // current frame in the interpreter stack.
_Jv_TraceFn trace_function; // function to call back after each frame
// is enumerated. May be NULL.
void *trace_data; // additional state data for trace_function.
_Jv_UnwindState (jint ln)
{
length = ln;
pos = 0;
frames = NULL;
Thread *thread = Thread::currentThread();
// Check for NULL currentThread(), in case an exception is created
// very early during the runtime startup.
if (thread)
interp_frame = (_Jv_InterpFrame *) thread->interp_frame;
trace_function = NULL;
trace_data = NULL;
}
};
class _Jv_StackTrace
{
private:
......@@ -65,20 +98,28 @@ private:
_Jv_StackFrame frames[];
static void UpdateNCodeMap ();
static jclass ClassForIP (void *ip, void **ncode);
static jclass ClassForFrame (_Jv_StackFrame *frame);
static void FillInFrameInfo (_Jv_StackFrame *frame);
static void getLineNumberForFrame(_Jv_StackFrame *frame, NameFinder *finder,
jstring *sourceFileName, jint *lineNum);
static _Unwind_Reason_Code UnwindTraceFn (struct _Unwind_Context *context,
void *state_ptr);
static _Unwind_Reason_Code calling_class_trace_fn (_Jv_UnwindState *state);
static _Unwind_Reason_Code non_system_trace_fn (_Jv_UnwindState *state);
public:
static _Jv_StackTrace *GetStackTrace (void);
static JArray< ::java::lang::StackTraceElement *>*
GetStackTraceElements (_Jv_StackTrace *trace,
java::lang::Throwable *throwable);
static jclass GetCallingClass (void);
static jclass GetCallingClass (jclass);
static void GetCallerInfo (jclass checkClass, jclass *, _Jv_Method **);
static JArray<jclass> *GetClassContext (jclass checkClass);
static ClassLoader *GetFirstNonSystemClassLoader (void);
};
#endif /* __JV_STACKTRACE_H__ */
......@@ -120,20 +120,6 @@ union _Jv_value
jobject object_value;
};
// An instance of this type is used to represent a single frame in a
// backtrace. If the interpreter has been built, we also include
// information about the interpreted method.
struct _Jv_frame_info
{
// PC value.
void *addr;
#ifdef INTERPRETER
// Actually a _Jv_InterpMethod, but we don't want to include
// java-interp.h everywhere.
void *interp;
#endif // INTERPRETER
};
/* Extract a character from a Java-style Utf8 string.
* PTR points to the current character.
* LIMIT points to the end of the Utf8 string.
......
......@@ -21,7 +21,6 @@ details. */
#include <java/lang/reflect/Modifier.h>
#include <java/security/ProtectionDomain.h>
#include <java/lang/Package.h>
#include <gnu/gcj/runtime/StackTrace.h>
// We declare these here to avoid including gcj/cni.h.
extern "C" void _Jv_InitClass (jclass klass);
......@@ -238,13 +237,13 @@ jclass _Jv_GetArrayClass (jclass klass, java::lang::ClassLoader *loader);
jboolean _Jv_IsInterpretedClass (jclass);
void _Jv_InitField (jobject, jclass, int);
class _Jv_ClassReader;
class _Jv_ClassReader;
class _Jv_InterpClass;
class _Jv_InterpMethod;
#endif
class _Jv_StackTrace;
class _Jv_BytecodeVerifier;
class gnu::gcj::runtime::StackTrace;
class java::io::VMObjectStreamClass;
void _Jv_sharedlib_register_hook (jclass klass);
......@@ -473,6 +472,7 @@ private:
friend class ::_Jv_ClassReader;
friend class ::_Jv_InterpClass;
friend class ::_Jv_InterpMethod;
friend class ::_Jv_StackTrace;
#endif
#ifdef JV_MARKOBJ_DECL
......@@ -480,7 +480,6 @@ private:
#endif
friend class ::_Jv_BytecodeVerifier;
friend class gnu::gcj::runtime::StackTrace;
friend class java::io::VMObjectStreamClass;
friend class ::_Jv_Linker;
......
......@@ -304,12 +304,10 @@ final class VMClassLoader
default_sys
= (ClassLoader) c.newInstance(new Object[] { default_sys });
}
catch (Exception e)
catch (Exception ex)
{
System.err.println("Requested system classloader "
+ loader + " failed, using "
+ "gnu.gcj.runtime.VMClassLoader");
e.printStackTrace();
throw new Error("Failed to load requested system classloader "
+ loader, ex);
}
}
return default_sys;
......
/* java.lang.VMThrowable -- VM support methods for Throwable.
Copyright (C) 1998, 1999, 2002, 2004 Free Software Foundation, Inc.
Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
......@@ -37,8 +37,7 @@ exception statement from your version. */
package java.lang;
import gnu.gcj.runtime.NameFinder;
import gnu.gcj.runtime.StackTrace;
import gnu.gcj.RawDataManaged;
/**
* VM dependent state and support methods Throwable.
......@@ -51,10 +50,8 @@ import gnu.gcj.runtime.StackTrace;
*/
final class VMThrowable
{
private gnu.gcj.runtime.StackTrace trace;
/**
* Private contructor, create VMThrowables with fillInStackTrace();
* Private contructor, create VMThrowables with StackTrace();
*/
private VMThrowable() { }
......@@ -67,20 +64,7 @@ final class VMThrowable
* @return a new VMThrowable containing the current execution stack trace.
* @see Throwable#fillInStackTrace()
*/
static VMThrowable fillInStackTrace(Throwable t)
{
VMThrowable state = null;
/* FIXME: size of the stack trace is limited to 128 elements.
It's undoubtedly sensible to limit the stack trace, but 128 is
rather arbitrary. It may be better to configure this. */
if (trace_enabled)
{
state = new VMThrowable ();
state.trace = new gnu.gcj.runtime.StackTrace(128);
}
return state;
}
static native VMThrowable fillInStackTrace(Throwable t);
/**
* Returns an <code>StackTraceElement</code> array based on the execution
......@@ -90,21 +74,11 @@ final class VMThrowable
* @return a non-null but possible zero length array of StackTraceElement.
* @see Throwable#getStackTrace()
*/
StackTraceElement[] getStackTrace(Throwable t)
{
StackTraceElement[] result;
if (trace != null)
{
NameFinder nameFinder = new NameFinder();
result = nameFinder.lookup(t, trace);
nameFinder.close();
}
else
result = new StackTraceElement[0];
return result;
}
native StackTraceElement[] getStackTrace(Throwable t);
// Setting this flag to false prevents fillInStackTrace() from running.
static boolean trace_enabled = true;
// Native stack data.
private RawDataManaged data;
}
......@@ -53,7 +53,6 @@ details. */
#include <java/lang/SecurityManager.h>
#include <java/lang/StringBuffer.h>
#include <java/lang/VMClassLoader.h>
#include <gnu/gcj/runtime/StackTrace.h>
#include <gcj/method.h>
#include <gnu/gcj/runtime/MethodRef.h>
#include <gnu/gcj/RawData.h>
......@@ -62,6 +61,7 @@ details. */
#include <java-cpool.h>
#include <java-interp.h>
#include <java-assert.h>
#include <java-stack.h>
#include <execution.h>
......@@ -101,20 +101,10 @@ jclass
java::lang::Class::forName (jstring className)
{
java::lang::ClassLoader *loader = NULL;
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4);
java::lang::Class *klass = NULL;
try
{
for (int i = 1; !klass; i++)
{
klass = t->classAt (i);
}
loader = klass->getClassLoaderInternal();
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
if (caller)
loader = caller->getClassLoaderInternal();
return forName (className, true, loader);
}
......@@ -125,21 +115,10 @@ java::lang::Class::getClassLoader (void)
java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
if (s != NULL)
{
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
ClassLoader *caller_loader = NULL;
try
{
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
caller_loader = caller->getClassLoaderInternal();
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
if (caller)
caller_loader = caller->getClassLoaderInternal();
// If the caller has a non-null class loader, and that loader
// is not this class' loader or an ancestor thereof, then do a
......
......@@ -16,6 +16,7 @@ details. */
#include <gcj/cni.h>
#include <jvm.h>
#include <java-props.h>
#include <java-stack.h>
#include <java/lang/Long.h>
#include <java/lang/Runtime.h>
#include <java/lang/UnknownError.h>
......@@ -29,8 +30,6 @@ details. */
#include <java/lang/Process.h>
#include <java/lang/ConcreteProcess.h>
#include <java/lang/ClassLoader.h>
#include <gnu/gcj/runtime/StackTrace.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <jni.h>
......@@ -164,27 +163,7 @@ java::lang::Runtime::_load (jstring path, jboolean do_search)
if (do_search)
{
ClassLoader *sys = ClassLoader::systemClassLoader;
ClassLoader *look = NULL;
gnu::gcj::runtime::StackTrace *t = new gnu::gcj::runtime::StackTrace(10);
try
{
for (int i = 0; i < 10; ++i)
{
jclass klass = t->classAt(i);
if (klass != NULL)
{
ClassLoader *loader = klass->getClassLoaderInternal();
if (loader != NULL && loader != sys)
{
look = loader;
break;
}
}
}
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
ClassLoader *look = _Jv_StackTrace::GetFirstNonSystemClassLoader ();
if (look != NULL)
{
......
......@@ -12,43 +12,18 @@ details. */
#include <gcj/cni.h>
#include <jvm.h>
#include <java-stack.h>
#include <java/lang/VMSecurityManager.h>
#include <java/lang/SecurityManager.h>
#include <java/lang/ClassLoader.h>
#include <java/lang/Class.h>
#include <gnu/gcj/runtime/StackTrace.h>
JArray<jclass> *
java::lang::VMSecurityManager::getClassContext ()
{
JArray<jclass> *result = NULL;
gnu::gcj::runtime::StackTrace *t = new gnu::gcj::runtime::StackTrace();
if (t)
{
int maxlen = t->length();
int len = 0;
for (int i=0; i<maxlen; i++)
{
jclass klass = t->classAt(i);
if (klass != NULL && klass != &java::lang::VMSecurityManager::class$
&& klass != &java::lang::SecurityManager::class$)
++len;
}
result =
(JArray<jclass> *) _Jv_NewObjectArray (len, &java::lang::Class::class$,
NULL);
len = 0;
for (int i=0; i<maxlen; i++)
{
jclass klass = t->classAt(i);
if (klass != NULL && klass != &java::lang::VMSecurityManager::class$
&& klass != &java::lang::SecurityManager::class$)
elements(result)[len++] = klass;
}
}
JArray<jclass> *result =
_Jv_StackTrace::GetClassContext (&SecurityManager::class$);
return result;
}
// natVMThrowable.cc - Native part of VMThrowable class.
/* Copyright (C) 2003 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#include <stdlib.h>
#include <gcj/cni.h>
#include <jvm.h>
#include <java-stack.h>
#include <java/lang/Throwable.h>
#include <java/lang/VMThrowable.h>
using namespace gnu::gcj;
java::lang::VMThrowable *
java::lang::VMThrowable::fillInStackTrace (java::lang::Throwable *)
{
using namespace java::lang;
// Don't trace stack during initialization of the runtime.
if (! trace_enabled)
return NULL;
_Jv_StackTrace *trace = _Jv_StackTrace::GetStackTrace ();
VMThrowable *vmthrowable = new VMThrowable ();
vmthrowable->data = (RawDataManaged *) trace;
return vmthrowable;
}
JArray< ::java::lang::StackTraceElement *> *
java::lang::VMThrowable::getStackTrace (java::lang::Throwable *throwable)
{
_Jv_StackTrace *trace = reinterpret_cast <_Jv_StackTrace *> (data);
return _Jv_StackTrace::GetStackTraceElements (trace, throwable);
}
......@@ -14,6 +14,7 @@ details. */
#include <jvm.h>
#include <gcj/cni.h>
#include <java-stack.h>
#include <java/lang/reflect/Array.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/IllegalArgumentException.h>
......@@ -54,21 +55,10 @@ java::lang::reflect::Array::newInstance (jclass componentType,
if (ndims == 1)
return newInstance (componentType, dims[0]);
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
Class *caller = _Jv_StackTrace::GetCallingClass (&Array::class$);
ClassLoader *caller_loader = NULL;
try
{
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
caller_loader = caller->getClassLoaderInternal();
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
if (caller)
caller_loader = caller->getClassLoaderInternal();
jclass arrayType = componentType;
for (int i = 0; i < ndims; i++)
......
......@@ -12,6 +12,7 @@ details. */
#include <gcj/cni.h>
#include <jvm.h>
#include <java-stack.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/IllegalAccessException.h>
......@@ -55,20 +56,7 @@ java::lang::reflect::Constructor::newInstance (jobjectArray args)
// Check accessibility, if required.
if (! (Modifier::isPublic (meth->accflags) || this->isAccessible()))
{
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
try
{
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
Class *caller = _Jv_StackTrace::GetCallingClass (&Constructor::class$);
if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags))
throw new IllegalAccessException;
}
......
......@@ -13,6 +13,7 @@ details. */
#include <stdlib.h>
#include <jvm.h>
#include <java-stack.h>
#include <java/lang/reflect/Field.h>
#include <java/lang/reflect/Modifier.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
......@@ -78,18 +79,7 @@ getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj,
// Check accessibility, if required.
if (! (Modifier::isPublic (flags) || field->isAccessible()))
{
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(7);
try
{
// We want to skip all the frames on the stack from this class.
for (int i = 1; !caller || caller == &Field::class$; i++)
caller = t->classAt (i);
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
caller = _Jv_StackTrace::GetCallingClass (&Field::class$);
if (! _Jv_CheckAccess (caller, field->getDeclaringClass(), flags))
throw new java::lang::IllegalAccessException;
}
......
......@@ -13,6 +13,7 @@ details. */
#include <gcj/cni.h>
#include <jvm.h>
#include <jni.h>
#include <java-stack.h>
#include <java/lang/reflect/Method.h>
#include <java/lang/reflect/Constructor.h>
......@@ -168,20 +169,7 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
// Check accessibility, if required.
if (! (Modifier::isPublic (meth->accflags) || this->isAccessible()))
{
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4);
Class *caller = NULL;
try
{
for (int i = 1; !caller; i++)
{
caller = t->classAt (i);
}
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
Class *caller = _Jv_StackTrace::GetCallingClass (&Method::class$);
if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags))
throw new IllegalAccessException;
}
......
......@@ -17,7 +17,7 @@ details. */
#include <gcj/cni.h>
#include <jvm.h>
#include <java-stack.h>
#include <java/lang/Object.h>
#include <java/lang/Class.h>
......@@ -25,31 +25,19 @@ details. */
#include <java/lang/StackTraceElement.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
using namespace java::util::logging;
java::lang::StackTraceElement*
java::util::logging::Logger::getCallerStackFrame ()
{
gnu::gcj::runtime::StackTrace *t
= new gnu::gcj::runtime::StackTrace(4);
java::lang::Class *klass = NULL;
int i = 2;
try
{
// skip until this class
while ((klass = t->classAt (i)) != getClass())
i++;
// skip the stackentries of this class
while ((klass = t->classAt (i)) == getClass() || klass == NULL)
i++;
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
// FIXME: RuntimeError
}
jclass klass = NULL;
_Jv_Method *meth = NULL;
_Jv_StackTrace::GetCallerInfo (&Logger::class$, &klass, &meth);
java::lang::StackTraceElement *e
= new java::lang::StackTraceElement
(JvNewStringUTF (""), 0,
klass->getName(), t->methodAt(i), false);
klass->getName(), _Jv_NewStringUtf8Const (meth->name), false);
return e;
}
/* Copyright (C) 2002, 2003 Free Software Foundation
/* Copyright (C) 2002, 2003, 2005 Free Software Foundation
This file is part of libgcj.
......@@ -12,31 +12,18 @@ details. */
#include <gcj/cni.h>
#include <jvm.h>
#include <java-stack.h>
#include <java/util/ResourceBundle.h>
#include <java/lang/SecurityManager.h>
#include <java/lang/ClassLoader.h>
#include <java/lang/Class.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <gnu/gcj/runtime/StackTrace.h>
using namespace java::lang;
java::lang::ClassLoader *
java::util::ResourceBundle::getCallingClassLoader ()
{
gnu::gcj::runtime::StackTrace *t = new gnu::gcj::runtime::StackTrace(6);
try
{
/* Frame 0 is this method, frame 1 is getBundle, so starting at
frame 2 we might see the user's class. FIXME: should account
for reflection, JNI, etc, here. */
for (int i = 2; ; ++i)
{
jclass klass = t->classAt(i);
if (klass != NULL)
return klass->getClassLoaderInternal();
}
}
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
{
}
jclass caller = _Jv_StackTrace::GetCallingClass (&ResourceBundle::class$);
if (caller)
return caller->getClassLoaderInternal();
return NULL;
}
......@@ -147,10 +147,10 @@ unblock_signal (int signum __attribute__ ((__unused__)))
#ifdef HANDLE_SEGV
SIGNAL_HANDLER (catch_segv)
{
java::lang::NullPointerException *nullp
= new java::lang::NullPointerException;
unblock_signal (SIGSEGV);
MAKE_THROW_FRAME (nullp);
java::lang::NullPointerException *nullp
= new java::lang::NullPointerException;
throw nullp;
}
#endif
......@@ -158,14 +158,14 @@ SIGNAL_HANDLER (catch_segv)
#ifdef HANDLE_FPE
SIGNAL_HANDLER (catch_fpe)
{
java::lang::ArithmeticException *arithexception
= new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
unblock_signal (SIGFPE);
#ifdef HANDLE_DIVIDE_OVERFLOW
HANDLE_DIVIDE_OVERFLOW;
#else
MAKE_THROW_FRAME (arithexception);
#endif
java::lang::ArithmeticException *arithexception
= new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
throw arithexception;
}
#endif
......
// backtrace.h - Fallback backtrace implementation. default implementation.
/* Copyright (C) 2005 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __SYSDEP_BACKTRACE_H__
#define __SYSDEP_BACKTRACE_H__
#include <java-stack.h>
/* Store return addresses of the current program stack in
STATE and return the exact number of values stored. */
void
fallback_backtrace (_Jv_UnwindState *)
{
}
#endif
// backtrace.h - Fallback backtrace implementation. i386 implementation.
/* Copyright (C) 2005 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#ifndef __SYSDEP_BACKTRACE_H__
#define __SYSDEP_BACKTRACE_H__
#include <java-stack.h>
#define HAVE_FALLBACK_BACKTRACE
/* Store return addresses of the current program stack in
STATE and return the exact number of values stored. */
void
fallback_backtrace (_Jv_UnwindState *state)
{
register void *_ebp __asm__ ("ebp");
register void *_esp __asm__ ("esp");
unsigned int *rfp;
int i = state->pos;
for (rfp = *(unsigned int**)_ebp;
rfp && i < state->length;
rfp = *(unsigned int **)rfp)
{
int diff = *rfp - (unsigned int)rfp;
if ((void*)rfp < _esp || diff > 4 * 1024 || diff < 0)
break;
state->frames[i].type = frame_native;
state->frames[i].ip = (void*)(rfp[1]-4);
i++;
}
state->pos = i;
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment