This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: MIPS support for libjava.


Greetings:

Here is a patch against 3.3.1 that adds SIGSEGV handling of
NullPointerExceptions for a MIPS host.  It also contains a custom
backtrace function as the version we have in our libc is broken.

After patching you have to run automake, autoconf and autoheader.

Some small notes on building...

This has only been tested with the configuration shown below.  The
target platform tested is linux 2.4.18 w/ glibc 2.2.4.

Use Binutils 2.14 or later.

I configured with this configure command:

../gcc-3.3.1/configure --host=i686-pc-linux-gnu --target=mipsisa32el-linux \
--enable-languages=c,c++,java \
--with-headers=/home/mipsel-linux/mipsel-linux/include \
--prefix=/home/mipsel-linux --with-custom-backtrace \
--with-libgcj-mips-xgot --with-broken-dladdr

My backtrace is broken hence the --with-custom-backtrace.

My dladdr also seems to be broken hence --with-broken-dladdr.

These two are only important if you are throwing and catching exceptions.

Binutils seems to have broken multi-got support.  So if you get GOT
overflow type messages from ld, configure with --with-libgcj-mips-xgot.

On an in-house build of libgcj I removed many unneeded files from
libgcj and am able to link without --with-libgcj-mips-xgot.


David Daney


2003-09-08  David Daney <ddaney@avtrex.com>

	MIPS support for libjava
	* libjava/acconfig.h: Added BROKEN_DLADDR and CUSTOM_BACKTRACE
	* libjava/Makefile.am: Support for extra .c and .S files.
	* libjava/configure.in: Added --with-custom-backtrace,
	--with-broken-dladdr, --with-libgcj-mips-xgot and mips*-*-linux* host.
	* libjava/configure.host: Added mips*el*-linux* host.
	* libjava/gnu/gcj/runtime/natNameFinder.cc (dladdrLookup): Don't use dladdr() if
	BROKEN_DLADDR is defined.
	* libjava/gnu/gcj/runtime/natStackTrace.cc (fillInStackTrace): Use
	CUSTOM_BACKTRACE if available.
	* libjava/include/mips-signal.h: New file.
	* libjava/sysdep/mips/mipsel-backtracer.c: New file.
	* libjava/sysdep/mips/mipsel-backtracer.h: New file.
	* libjava/sysdep/mips/mipsel-bthelper.S: New file.
	* libjava/sysdep/mips/mipsel-sighelper.S: New file.



diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/libjava/Makefile.am gcc-3.3.1.dave/libjava/Makefile.am
--- gcc-3.3.1/libjava/Makefile.am	Sat Mar  1 14:57:52 2003
+++ gcc-3.3.1.dave/libjava/Makefile.am	Fri Sep  5 15:37:07 2003
@@ -115,6 +115,8 @@
 x_nat_files = $(x_nat_source_files:.cc=.lo)
 ## Objects from C sources in subdirs.
 c_files = $(c_source_files:.c=.lo)
+
+s_files = $(s_source_files:.S=.lo)
 ## Objects from Java sources in subdirs.
 javao_files = $(java_source_files:.java=.lo) \
 	$(built_java_source_files:.java=.lo)
@@ -125,12 +127,13 @@
 	$(nat_source_files)
 EXTRA_libgcj_la_SOURCES = boehm.cc nogc.cc posix-threads.cc no-threads.cc \
 	win32-threads.cc posix.cc win32.cc \
-	$(c_source_files) $(java_source_files) $(built_java_source_files)
+	$(c_source_files) $(s_source_files) \
+        $(java_source_files) $(built_java_source_files)
 libgcj_la_DEPENDENCIES = libgcj-@gcc_version@.jar $(javao_files) \
-	$(c_files) $(GCOBJS) $(THREADOBJS) $(PLATFORMOBJS) $(LIBLTDL) \
-	$(LIBFFI) $(ZLIBS) $(GCLIBS)
+	$(c_files) $(s_files) $(GCOBJS) $(THREADOBJS) \
+        $(PLATFORMOBJS) $(LIBLTDL) $(LIBFFI) $(ZLIBS) $(GCLIBS)
 
-libgcj_la_LIBADD = $(javao_files) $(c_files) $(GCOBJS) \
+libgcj_la_LIBADD = $(javao_files) $(c_files) $(s_files) $(GCOBJS) \
 	$(THREADOBJS) $(PLATFORMOBJS)
 # Include THREADLIBS here to ensure that the correct version of
 # certain linuxthread functions get linked:
@@ -228,7 +231,8 @@
 	  sed -e '/\/\./d' -e '/\/xlib/d' | \
 	  $(ZIP) cfM0E@ $@
 
-MOSTLYCLEANFILES = $(javao_files) $(nat_files) $(nat_headers) $(c_files) $(x_javao_files) $(x_nat_files) $(x_nat_headers)
+MOSTLYCLEANFILES = $(javao_files) $(nat_files) $(nat_headers) $(c_files) \
+ $(s_files) $(x_javao_files) $(x_nat_files) $(x_nat_headers)
 CLEANFILES = libgcj-@gcc_version@.jar
 
 clean-local:
@@ -260,6 +264,9 @@
 $(c_files): %.lo: %.c
 	$(LTCOMPILE) -c -o $@ $<
 
+$(s_files): %.lo: %.S
+	$(LTCOMPILE) -c -o $@ $<
+
 $(c_files): java/lang/fdlibm.h java/lang/ieeefp.h java/lang/mprec.h
 
 ## FIXME: GNU make.
@@ -2311,7 +2318,10 @@
   java/lang/e_remainder.c java/lang/s_floor.c     java/lang/w_remainder.c \
   java/lang/e_scalb.c     java/lang/s_rint.c      java/lang/w_sqrt.c      \
   java/lang/e_sqrt.c      java/lang/s_scalbn.c    java/lang/sf_rint.c     \
-  java/lang/k_cos.c       java/lang/s_sin.c       java/lang/sf_fabs.c
+  java/lang/k_cos.c       java/lang/s_sin.c       java/lang/sf_fabs.c     \
+  $(EXTRA_C_FILES)
+
+s_source_files = $(EXTRA_S_FILES)
 
 #java/awt/natToolkit.cc
 
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/libjava/acconfig.h gcc-3.3.1.dave/libjava/acconfig.h
--- gcc-3.3.1/libjava/acconfig.h	Thu Aug 29 11:05:14 2002
+++ gcc-3.3.1.dave/libjava/acconfig.h	Mon Sep  8 16:23:39 2003
@@ -140,6 +140,9 @@
 /* Define if you have dladdr() */
 #undef HAVE_DLADDR
  
+/* Define if you have a broken dladdr() */
+#undef BROKEN_DLADDR
+ 
 /* Define if tzname is missing.  */
 #undef NO_TZNAME
 
@@ -160,6 +163,11 @@
 
 /* Define if your platform has a working backtrace() function.  */
 #undef HAVE_BACKTRACE
+
+/* Defined as the backtrace function name if your platform has a
+   custom backtrace() that should be used instead of the platform's
+   version.  */
+#undef CUSTOM_BACKTRACE
 
 /* Define if your platform has the global _timezone variable.  */
 #undef HAVE_UNDERSCORE_TIMEZONE
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/libjava/configure.host gcc-3.3.1.dave/libjava/configure.host
--- gcc-3.3.1/libjava/configure.host	Wed Feb 12 18:09:26 2003
+++ gcc-3.3.1.dave/libjava/configure.host	Fri Sep  5 15:37:07 2003
@@ -166,6 +166,12 @@
   x86_64*-linux*)
   	can_unwind_signal=yes
 	;;
+  mips*el*-linux*)
+  	can_unwind_signal=yes
+	if test "x${with_libgcj_mips_xgot}" = "xyes"; then
+		libgcj_flags="${libgcj_flags} -Wa,-xgot"
+	fi
+	;;
   *-*-darwin*)
 	enable_hash_synchronization_default=no
 	slow_pthread_self=
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/libjava/configure.in gcc-3.3.1.dave/libjava/configure.in
--- gcc-3.3.1/libjava/configure.in	Tue Jun 17 09:04:20 2003
+++ gcc-3.3.1.dave/libjava/configure.in	Mon Sep  8 16:28:23 2003
@@ -19,6 +19,15 @@
 AC_ARG_WITH(newlib,
 [  --with-newlib           Configuring with newlib])
 
+AC_ARG_WITH(custom-backtrace,
+[  --with-custom-backtrace           Configuring with custom backtrace() function])
+
+AC_ARG_WITH(broken-dladdr,
+[  --with-broken-dladdr              Configuring to not use dladdr because it is broken])
+
+AC_ARG_WITH(libgcj-mips-xgot,
+[  --with-libgcj-mips-xgot           For MIPS builds use -Wa,-xgot to build libgcj])
+
 LIBGCJ_CONFIGURE(.)
 
 AM_CONFIG_HEADER(include/config.h gcj/libgcj-config.h)
@@ -219,6 +228,11 @@
 TARGET_ECOS="$with_ecos"
 )
 
+EXTRA_S_FILES=
+AC_SUBST(EXTRA_S_FILES)
+EXTRA_C_FILES=
+AC_SUBST(EXTRA_C_FILES)
+
 PLATFORMOBJS=
 case "$TARGET_ECOS" in
    no) case "$host" in
@@ -440,6 +454,14 @@
 AC_SUBST(THREADSPEC)
 AC_SUBST(THREADLDFLAGS)
 
+if test "x${with_custom_backtrace}" = "xyes"; then
+   AC_DEFINE(CUSTOM_BACKTRACE, _Jv_CustomBacktrace, [Defined to be the custom backtracer])
+fi
+
+if test "x${with_broken_dladdr}" = "xyes"; then
+   AC_DEFINE(BROKEN_DLADDR, 1, [Do not use dladdr because it is broken])
+fi
+
 if test -d sysdep; then true; else mkdir sysdep; fi
 AC_LINK_FILES(sysdep/$sysdeps_dir/locks.h, sysdep/locks.h)
 
@@ -515,6 +537,16 @@
        ia64-*-linux*)
 	 # Has broken backtrace()
 	 ;;
+       mips*-*-linux*)
+         if test "x${with_custom_backtrace}" = "xyes"; then
+            # Has broken backtrace()
+            if test -d sysdep/mips; then true; else mkdir -p sysdep/mips; fi
+            EXTRA_C_FILES="${EXTRA_C_FILES} sysdep/mips/mipsel-backtracer.c"
+            EXTRA_S_FILES="${EXTRA_S_FILES} sysdep/mips/mipsel-bthelper.S"
+         else
+            AC_DEFINE(HAVE_BACKTRACE)
+         fi
+         ;;
        *)
          AC_DEFINE(HAVE_BACKTRACE)
 	 ;;
@@ -940,6 +972,10 @@
     ;;
  *mingw*)
     SIGNAL_HANDLER=include/win32-signal.h
+    ;;
+ mips*-*-linux*)
+    SIGNAL_HANDLER=include/mips-signal.h
+    EXTRA_S_FILES="${EXTRA_S_FILES} sysdep/mips/mipsel-sighelper.S"
     ;;
  *)
     SIGNAL_HANDLER=include/default-signal.h
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/libjava/gnu/gcj/runtime/natNameFinder.cc gcc-3.3.1.dave/libjava/gnu/gcj/runtime/natNameFinder.cc
--- gcc-3.3.1/libjava/gnu/gcj/runtime/natNameFinder.cc	Mon Mar 10 11:34:30 2003
+++ gcc-3.3.1.dave/libjava/gnu/gcj/runtime/natNameFinder.cc	Mon Sep  8 16:28:28 2003
@@ -92,7 +92,7 @@
 java::lang::StackTraceElement*
 gnu::gcj::runtime::NameFinder::dladdrLookup(RawData* addrs, jint n)
 {
-#if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
+#if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR) && !defined(BROKEN_DLADDR)
   extern char **_Jv_argv;
   char name[1024];
   char file_name[1024];
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/libjava/gnu/gcj/runtime/natStackTrace.cc gcc-3.3.1.dave/libjava/gnu/gcj/runtime/natStackTrace.cc
--- gcc-3.3.1/libjava/gnu/gcj/runtime/natStackTrace.cc	Wed Feb 19 08:27:22 2003
+++ gcc-3.3.1.dave/libjava/gnu/gcj/runtime/natStackTrace.cc	Fri Sep  5 15:37:07 2003
@@ -45,14 +45,22 @@
 #include <unwind.h>
 
 
+#ifdef CUSTOM_BACKTRACE
+extern "C" int CUSTOM_BACKTRACE (void **, int);
+#endif
+
 // Fill in this stack trace with MAXLEN elements starting at offset.
 void
 gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset)
 {
-#ifdef HAVE_BACKTRACE
+#if defined(HAVE_BACKTRACE) || defined(CUSTOM_BACKTRACE)
   offset += 1;
   void *_p[maxlen + offset];
+#ifdef CUSTOM_BACKTRACE
+  len = CUSTOM_BACKTRACE (_p, maxlen + offset) - offset;
+#else // must be HAVE_BACKTRACE
   len = backtrace (_p, maxlen + offset) - offset;
+#endif // CUSTOM_BACKTRACE
   void **p = _p + offset;
   _Jv_frame_info *frame;
   if (len > 0)
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/libjava/include/mips-signal.h gcc-3.3.1.dave/libjava/include/mips-signal.h
--- gcc-3.3.1/libjava/include/mips-signal.h	Wed Dec 31 16:00:00 1969
+++ gcc-3.3.1.dave/libjava/include/mips-signal.h	Fri Sep  5 15:37:07 2003
@@ -0,0 +1,108 @@
+// mips-signal.h - Catch runtime signals and turn them into exceptions
+// on an mipsel based Linux system that use the "o32" ABI. 
+
+/* Copyright (C) 1998, 1999, 2001, 2002, 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.  */
+
+/* Adapted (loosely) from sparc-signal.h by David Daney <ddaney@avtrex.com> */
+
+#ifndef JAVA_SIGNAL_H
+#define JAVA_SIGNAL_H 1
+
+#include <signal.h>
+/* #include <asm/ucontext.h> structures we use are here but clash with
+   sys/ucontext.h included by java-signal.h from prims.cc */
+
+#define HANDLE_SEGV 1
+#undef HANDLE_FPE
+
+
+/* The third parameter to the signal handler points to something with
+ * this structure defined in asm/ucontext.h, but the name clashes with
+ * struct ucontext from sys/ucontext.h so this private copy is used. */
+typedef struct _sig_ucontext {
+    unsigned long	  uc_flags;
+    struct _sig_ucontext  *uc_link;
+    stack_t		  uc_stack;
+    struct sigcontext uc_mcontext;
+    sigset_t	  uc_sigmask;
+} sig_ucontext_t;
+
+
+#define SIGNAL_HANDLER(_name)	             \
+extern "C" void _Jv_MipselThrowNPE();        \
+void _Jv_MipselThrowNPE()                    \
+{                                            \
+  _Jv_ThrowSignal (nullp);                   \
+}                                            \
+static void _name (int _dummy, siginfo_t *_info, void *arg)
+
+/*
+ *  Build a stack frame with the layout used by __sig2exdummy just
+ *  above the frame of the faulting function.  And then jump to
+ *  _Jv_MipselThrowNPE() simulating a jal from
+ *  $sig2exdummy_fakeout_point.
+ *	
+ * The result is that the signal handler's stack frame and trampoline
+ * code are obliterated and the stack is in a state that looks like
+ * __sig2exdummy was called from the faulting point, and it then
+ * called _Jv_MipselThrowNPE().  Unwinding can then proceed
+ * "normally".
+ *
+ * Note that in prims.cc that the call to _Jv_ThrowSignal(nullp) is
+ * never reached.
+ */
+
+#define MAKE_THROW_FRAME(_exception)				\
+do								\
+{                                                               \
+  sig_ucontext_t *_context = (sig_ucontext_t *) arg;            \
+  (void)_dummy;							\
+  (void)_info;                                                  \
+  void *reg_save_area = (void *)_context->uc_mcontext.sc_regs;  \
+  char *xxx = (char *)(long)_context->uc_mcontext.sc_regs[29];  \
+  xxx -= 32;                                                    \
+  void **dummy_frame = (void **)xxx;                            \
+  dummy_frame[7] = (void *)(((long)_context->uc_mcontext.sc_pc) + 4); \
+  asm volatile ("lw\t$16,128(%1)\n\t"                           \
+                "lw\t$17,136(%1)\n\t"                           \
+                "lw\t$18,144(%1)\n\t"                           \
+                "lw\t$19,152(%1)\n\t"                           \
+                "lw\t$20,160(%1)\n\t"                           \
+                "lw\t$21,168(%1)\n\t"                           \
+                "lw\t$22,176(%1)\n\t"                           \
+                "lw\t$23,184(%1)\n\t"                           \
+                "lw\t$30,240(%1)\n\t"                           \
+                "lw\t$31,__sig2exdummy_fakeout_point\n\t"       \
+                "la\t$25,_Jv_MipselThrowNPE\n\t"                \
+                ".set\tnoreorder\n\t"                           \
+                ".set\tnomacro\n\t"                             \
+                "move\t$29,%0\n\t"                              \
+                "jr\t$25\n\t"                                   \
+                "nop\n\t"                                       \
+                ".set\tmacro\n\t"                               \
+                ".set\treorder"                                 \
+                :  : "r" (dummy_frame), "r" (reg_save_area));   \
+}								\
+while (0)
+
+#define INIT_SEGV						\
+do								\
+  {								\
+    nullp = new java::lang::NullPointerException ();		\
+    struct sigaction act;					\
+    act.sa_sigaction = catch_segv;				\
+    act.sa_flags = SA_SIGINFO | SA_NODEFER;			\
+    sigemptyset (&act.sa_mask);					\
+    sigaction (SIGSEGV, &act, NULL);				\
+  }								\
+while (0)
+								
+
+#endif /* JAVA_SIGNAL_H */
+  
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/libjava/sysdep/mips/mipsel-backtracer.c gcc-3.3.1.dave/libjava/sysdep/mips/mipsel-backtracer.c
--- gcc-3.3.1/libjava/sysdep/mips/mipsel-backtracer.c	Wed Dec 31 16:00:00 1969
+++ gcc-3.3.1.dave/libjava/sysdep/mips/mipsel-backtracer.c	Fri Sep  5 15:37:07 2003
@@ -0,0 +1,493 @@
+/* mipsel-backtracer.c - Helper functions for generating a backtrace
+ * on mipsel platforms that use the "o32" ABI. 
+ */
+
+/* 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.  */
+
+/* Written by David Daney <ddaney@avtrex.com> */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <unistd.h>
+#include <signal.h>
+#include <ucontext.h>
+#include <execinfo.h>
+
+#include "config.h"
+#include "mipsel-backtracer.h"
+
+#ifdef HAVE_PROC_SELF_EXE
+#define USE_PROC_MAPS 1
+#endif
+
+#ifdef USE_PROC_MAPS
+
+#define FILENAME_SIZE 128
+#define PROC_MAPSLINE_LEN (80 + FILENAME_SIZE)
+
+#define MEMORY_EXECUTABLE 1
+#define MEMORY_READABLE 4
+#define MEMORY_WRITABLE 2
+
+typedef struct _memory_map_block
+{
+    struct _memory_map_block *next, *prev;
+    void *start;
+    void *end;
+    unsigned offset;
+    int flags;
+    char filename[FILENAME_SIZE];
+} memory_map_block;
+
+static void dump_maps(memory_map_block *f);
+static void free_maps(memory_map_block *f);
+static memory_map_block *parse_maps();
+static memory_map_block *find_in_maps(memory_map_block *start_point, void *addr, int mode);
+
+#endif /* USE_PROC_MAPS */
+
+static int
+is_branch(int opcode)
+{
+    if(0x10000000 == (opcode & 0xb0000000) || /* branch instructions */
+       0x08000000 == (opcode & 0xf8000000) || /* j and jl */
+       0x04000000 == (opcode & 0xfc0c0000) || /* more branches */
+       0x00000009 == (opcode & 0xfc1f003f) || /* jalr */
+       0x00000008 == (opcode & 0xfc1ff83f) || /* jr */
+       0xa1000000 == (opcode & 0xf3e00000) ){ /* coprocessor branch */
+        return 1;
+    }
+    return 0;
+}
+
+/*
+ * Look for a move which could be (ADDU, OR, SUBU, XOR) with a source of $sp
+ * op $fp, $sp, $0
+ * op $fp, $0, $sp
+ *
+ * return the dest reg or -1
+ */
+static int
+is_fp_reg(int opcode)
+{
+    int i;
+    
+    if((0x03a00020 == (opcode & 0xffff07f8)) || /* op ??, $sp, $0 */
+       (0x001d0020 == (opcode & 0xffff07f8))) {    /* op ??, $0, $sp */
+        i = opcode & 7;
+        if(1 == i || /* addu */
+           3 == i || /* subu */
+           5 == i || /* or */
+           6 == i) { /* xor */
+            i = (opcode >> 11) & 0x1f;
+            return i;
+        }
+    }
+    return -1;
+}
+
+/*
+ * Is the opcode a sw $fp,##(sp)
+ *
+ */
+static int
+get_fp_save_location(int opcode)
+{
+    int rv = -1;
+    
+    if(0xafbe0000 == (0xffff0000 & opcode)){
+        rv = 0xffff & opcode;
+        if(0x8000 & rv) {
+            rv |= 0xffff0000;
+        }
+    }
+    return rv;
+}
+
+/*
+ * Is the opcode a sw $31,##(sp)
+ *
+ */
+static int
+get_ra_save_location(int opcode)
+{
+    int rv = -1;
+    
+    if(0xafbf0000 == (0xffff0000 & opcode)){
+        rv = 0xffff & opcode;
+        if(0x8000 & rv) {
+            rv |= 0xffff0000;
+        }
+    }
+    return rv;
+}
+
+/*
+ * Do the backtrace.  Normally called only from
+ * mips_backtracer_with_skip or mips_backtracer which are located in
+ * mipsel-bthelper.S
+ **/
+int
+do_mips_backtrace(void **locations,
+                  int len,
+                  char *callers_sp,
+                  char *callers_fp,
+                  char *callers_return,
+                  int frame_skip_count)
+{
+    int *ip;  /* instruction pointer */
+    int stack_adjustment;
+    int ra_save_location;
+    
+    int fp_register, fp_save_location;
+    int num_saved; /* number of stack trace elements saved so far. */
+
+#ifdef USE_PROC_MAPS
+    memory_map_block *maps;    /* memory map info */
+    memory_map_block *s_map;   /* positioned on stack area */
+    memory_map_block *c_map;   /* positioned on code area */
+    memory_map_block *t_map;   /* temp */
+    
+
+    maps = parse_maps();
+    
+    s_map = maps;
+    c_map = maps;
+#endif /* USE_PROC_MAPS */
+    
+    num_saved = 0;
+    
+    if(0 == len) {
+        /*
+         * zero frames requested.  we are already done.
+         */
+        goto error_exit;
+    }
+    else {
+        /* The first one is just our ra argument.
+         * adjust by 8 bytes to get address before the call.
+         */
+        if(frame_skip_count) {
+            frame_skip_count--;
+        }
+        else {
+            locations[num_saved++] = (callers_return - 8);
+        }
+    }
+    
+    while(num_saved < len) {
+        ip = (int *)callers_return;
+    
+        /*
+         * Find function prolog.  It will have the form:
+         *
+         *	3c1c???? 	lui	gp,????
+         *	279c???? 	addiu	gp,gp,????
+         *	0399e021 	addu	gp,gp,t9
+         *	27bd#### 	addiu	sp,sp,####
+         *
+         * Where ???? are the offset of the GOT from the function
+         * entrypoint, and #### is the amount added to the stack poiner.
+         */
+        for(;;) {
+#ifdef USE_PROC_MAPS
+            t_map = find_in_maps(c_map, ip, MEMORY_EXECUTABLE);
+            if(!t_map) {
+                goto error_exit;
+            }
+            c_map = t_map;
+#endif          
+            if(*ip == 0x0399e021) {
+                break;
+            }
+            ip--;
+        }
+#ifdef USE_PROC_MAPS
+        t_map = find_in_maps(c_map, ip - 2, MEMORY_EXECUTABLE);
+        if(!t_map) {
+            goto error_exit;
+        }
+        c_map = t_map;
+#endif        
+
+        if(0x279c0000 == ((ip[-1]) & 0xffff0000) &&
+           0x3c1c0000 == ((ip[-2]) & 0xffff0000) &&
+           0x27bd8000 == ((ip[ 1]) & 0xffff8000)) {
+            /* We found a function prolog!! */
+            stack_adjustment = ip[1] | 0xffff0000;
+            ip += 2; /* to end of prolog */
+        
+            /*
+             * Now find where things are in the stack frame by
+             * analyzing the function prolog.
+             *
+             */
+            ra_save_location = -1;
+            fp_register = -1;
+            fp_save_location = -1;
+        
+            while(((char *)ip) < callers_return) {
+                if(is_branch(*ip)) {
+                    break;
+                }
+                if(-1 == ra_save_location) {
+                    ra_save_location = get_ra_save_location(*ip);
+                    if(fp_register > 0 &&
+                       -1 != fp_save_location &&
+                       -1 != ra_save_location) {
+                        break;
+                    }
+                }
+                if(-1 == fp_save_location) {
+                    fp_save_location = get_fp_save_location(*ip);
+                }
+                if (fp_register  < 0) {
+                    fp_register = is_fp_reg(*ip);
+                    if(fp_register > 0 &&
+                       -1 != fp_save_location &&
+                       ra_save_location != -1) {
+                        break;
+                    }
+                }
+                ip++;
+            }
+            if(-1 == ra_save_location) {
+                break;
+            }
+            if(30 == fp_register) {
+                /* this frame used the fp */
+#ifdef USE_PROC_MAPS
+                /* if stack not writable, then we probably are out of sync */
+                t_map = find_in_maps(s_map, callers_fp + ra_save_location, MEMORY_WRITABLE);
+                if(!t_map) {
+                    goto error_exit;
+                }
+                s_map = t_map;
+                t_map = find_in_maps(s_map, callers_fp + fp_save_location, MEMORY_WRITABLE);
+                if(!t_map) {
+                    goto error_exit;
+                }
+                s_map = t_map;
+#endif          
+                callers_return = *(char **)(callers_fp + ra_save_location);
+                callers_sp = callers_fp - stack_adjustment;
+                callers_fp = *(char **)(callers_fp + fp_save_location);
+            }
+            else if(-1 == fp_register) {
+                /* this frame uses sp as frame pointer */
+#ifdef USE_PROC_MAPS
+                /* if stack not writable, then we probably are out of sync */
+                t_map = find_in_maps(s_map, callers_sp + ra_save_location, MEMORY_WRITABLE);
+                if(!t_map) {
+                    goto error_exit;
+                }
+                s_map = t_map;
+#endif          
+                callers_return = *(char **)(callers_sp + ra_save_location);
+                if(-1 != fp_save_location) {
+                    /* fp was saved, but unused in this frame.
+                     * we may need it in subsequent frames
+                     */
+#ifdef USE_PROC_MAPS
+                    t_map = find_in_maps(s_map, callers_sp + fp_save_location, MEMORY_WRITABLE);
+                    if(!t_map) {
+                        goto error_exit;
+                    }
+                    s_map = t_map;
+#endif
+                    callers_fp = *(char **)(callers_sp + fp_save_location);
+                }
+                callers_sp = callers_sp - stack_adjustment;
+            }
+            else {
+                printf("Cannot handle fp in register %d, aborting trace\n", fp_register);
+                break;
+            }
+#ifdef USE_PROC_MAPS
+            t_map = find_in_maps(c_map, callers_return, MEMORY_EXECUTABLE);
+            if(!t_map) {
+                goto error_exit;
+            }
+            c_map = t_map;
+#else
+            if(NULL == callers_return) {
+                break;
+            }
+#endif          
+            if(frame_skip_count) {
+                frame_skip_count--;
+            }
+            else {
+                /* 
+                 * Adjust by 8 bytes to get address before the call.
+                 */
+                locations[num_saved++] = (callers_return - 8);
+            }
+        }
+        else {
+            /* Prolog search failed. */
+            goto error_exit;
+        }
+    }
+    error_exit:
+#ifdef USE_PROC_MAPS
+    free_maps(maps);
+#endif
+    return num_saved;
+}
+
+#ifdef USE_PROC_MAPS
+static memory_map_block *
+find_in_maps(memory_map_block *start_point, void *addr, int mode)
+{
+    int dir = 0; /* 0 = unknown, -1 down, 1 up */
+    
+    while(start_point) {
+        if(addr >= start_point->start) {
+            if(addr < start_point->end){
+                /* it is in this block */
+                if(mode & start_point->flags) {
+                    return start_point;
+                }
+                else {
+                    /* wrong mode */
+                    break;
+                }
+            }
+            else {
+                if(0 <= dir) {
+                    start_point = start_point->next;
+                    dir = 1;
+                    continue;
+                }
+                else {
+                    /* must be between blocks */
+                    break;
+                }
+            }
+        }
+        else {
+            if(0 >= dir) {
+                start_point = start_point->prev;
+                dir = -1;
+                continue;
+            }
+            else {
+                /* must be between blocks */
+                break;
+            }
+        }
+    }
+    return NULL;
+}
+
+
+static void
+dump_maps(memory_map_block *f)
+{
+    while(f) {
+        printf("%p-%p %1.1x <%s>:%x\n", f->start, f->end, f->flags, f->filename, f->offset);
+        f = f->next;
+    }
+}
+
+static void
+free_maps(memory_map_block *f)
+{
+    memory_map_block *n;
+    
+    while(f) {
+        n = f->next;
+        free(f);
+        f = n;
+    }
+}
+
+
+static memory_map_block *
+parse_maps()
+{
+    int n;
+    
+    char fn[FILENAME_SIZE];
+    char line[PROC_MAPSLINE_LEN + 1];
+    char mode[4];
+    
+    FILE *f;
+    unsigned s, e, o;
+
+    memory_map_block *first, *current;
+    first = NULL;
+    current = NULL;
+    
+    f = fopen("/proc/self/maps", "r");
+    if(NULL == f) {
+        perror("could not open proc file");
+        return NULL;
+    }
+
+    while(fgets(line, PROC_MAPSLINE_LEN, f)) {
+        n = sscanf(line, "%8x-%8x %4s %8x %*s %*s %s\n", &s, &e, mode, &o, fn);
+        if(n >= 4) {
+            if('r' != mode[0]) {
+                /* not readable, do not worry about it */
+                continue;
+            }
+            /* good parse. */
+            memory_map_block *mbp = (memory_map_block *)calloc(1, sizeof(memory_map_block));
+            if(NULL == mbp) {
+                break;
+            }
+            if(NULL == first) {
+                first = mbp;
+                current = mbp;
+            }
+            else {
+                current->next = mbp;
+                mbp->prev = current;
+                current = mbp;
+            }
+            current->start = (void *)s;
+            current->end = (void *)e;
+            current->offset = o;
+            current->flags = MEMORY_READABLE;
+            if('x' == mode[2]) {
+                current->flags |= MEMORY_EXECUTABLE;
+            }
+            if('w' == mode[1]) {
+                current->flags |= MEMORY_WRITABLE;
+            }
+            if(5 == n) {
+                strncpy(current->filename, fn, FILENAME_SIZE);
+                current->filename[FILENAME_SIZE - 1] = 0;
+            }
+        }
+    }
+
+    fclose(f);
+
+    return first;
+}
+
+#endif /* USE_PROC_MAPS */
+
+#ifdef CUSTOM_BACKTRACE
+int
+CUSTOM_BACKTRACE (void **locations, int len)
+{
+    return mips_backtracer_with_skip(locations, len, 1);
+}
+
+
+#endif
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/libjava/sysdep/mips/mipsel-backtracer.h gcc-3.3.1.dave/libjava/sysdep/mips/mipsel-backtracer.h
--- gcc-3.3.1/libjava/sysdep/mips/mipsel-backtracer.h	Wed Dec 31 16:00:00 1969
+++ gcc-3.3.1.dave/libjava/sysdep/mips/mipsel-backtracer.h	Fri Sep  5 15:37:07 2003
@@ -0,0 +1,28 @@
+/* mipsel-backtracer.h - Include file for mipsel-backtracer.c */
+
+/* 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.  */
+
+/* Written by David Daney <ddaney@avtrex.com> */
+
+#ifndef _MIPSEL_BACKTRACER_H
+#define _MIPSEL_BACKTRACER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int do_mips_backtrace(void **locations, int len, char *sp, char *fp, char *ra, int frame_skip_count);
+int mips_backtracer(void **locations, int len);
+int mips_backtracer_with_skip(void **locations, int len, int frame_skip_count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MIPSEL_BACKTRACER_H */
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/libjava/sysdep/mips/mipsel-bthelper.S gcc-3.3.1.dave/libjava/sysdep/mips/mipsel-bthelper.S
--- gcc-3.3.1/libjava/sysdep/mips/mipsel-bthelper.S	Wed Dec 31 16:00:00 1969
+++ gcc-3.3.1.dave/libjava/sysdep/mips/mipsel-bthelper.S	Fri Sep  5 15:37:07 2003
@@ -0,0 +1,93 @@
+	# mipsel-bthelper.S - Generate a stacktrace on mipsel o32 ABI platform.
+	#
+	#
+	# 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.
+	#
+	# Written by David Daney <ddaney@avtrex.com>
+	#
+	
+#include <sys/asm.h>
+#include <sys/regdef.h>
+	
+	#
+	# Create a backtrace by passing some values to do_mips_backtrace
+	# 
+	# Our stack frame is layed out as follows:
+	# 32 -> top of stack
+	# 28 -> ra.
+	# 24 -> gp (aka cprestore value)
+	# 20 -> 6th argument to do_mips_backtrace() i.e. frame_skip_count
+	# 16 -> 5th argument to do_mips_backtrace() i.e. return address
+	# 12 -> callee saves 4th arg
+	# 8  -> callee saves 3rd arg
+	# 4  -> callee saves 2nd arg
+	# 0  -> callee saves 1st arg
+	
+	.equ	stack_size,32
+	.equ	ra_loc,28
+	.equ	gp_loc,24
+	.equ	sa_loc,20
+	.equ	fa_loc,16
+	
+	.abicalls
+	.text
+mips_backtracer:
+	NESTED(mips_backtracer, stack_size, ra)
+	.mask	0x90000000,ra_loc-stack_size 
+	.fmask	0x00000000,0
+	.set	noreorder
+	CPLOAD(t9)			# standard function entry
+	.set	reorder
+	subu	sp,sp,stack_size	# allocate local stack frame
+	sw	ra,ra_loc(sp)		# $ra
+	CPRESTORE(gp_loc)		# $gp
+					# first and second parameters are passed through
+	move	a2,sp			# $sp is third parameter
+	addu	a2,a2,stack_size	# but it has to be re-adjusted!
+	move	a3,s8			# $s8/$fp is fourth parameter
+	sw	ra,fa_loc(sp)		# $ra is the fifth parameter
+	sw	zero,sa_loc(sp)		# frame_skip_count of zero.
+	la	t9,do_mips_backtrace
+	jal	ra,t9			# call do_mips_backtrace()
+	lw	ra,ra_loc(sp)		# restore $ra
+	.set	noreorder
+	.set	nomacro
+	j	ra			# return with do_back_trace's return values
+	addu	sp,sp,stack_size	# delay slot restores stack
+	.set	macro
+	.set	reorder
+	END(mips_backtracer)
+
+mips_backtracer_with_skip:
+	NESTED(mips_backtracer_with_skip, stack_size, ra)
+	.mask	0x90000000,ra_loc-stack_size 
+	.fmask	0x00000000,0
+	.set	noreorder
+	CPLOAD(t9)			# standard function entry
+	.set	reorder
+	subu	sp,sp,stack_size	# allocate local stack frame
+	sw	ra,ra_loc(sp)		# $ra
+	CPRESTORE(gp_loc)		# $gp
+					# first and second arguments are passed through
+	sw	a2,sa_loc(sp)		# our third parameter goes to 6th (frame_skip_count).
+	move	a2,sp			# $sp is third parameter
+	addu	a2,a2,stack_size	# but it has to be re-adjusted!
+	move	a3,s8			# $s8/$fp is fourth parameter
+	sw	ra,fa_loc(sp)		# $ra is the fifth parameter
+	la	t9,do_mips_backtrace
+	jal	ra,t9			# call do_mips_backtrace()
+	lw	ra,ra_loc(sp)		# restore $ra
+	.set	noreorder
+	.set	nomacro
+	j	ra			# return with do_back_trace's return values
+	addu	sp,sp,stack_size	# delay slot restores stack
+	.set	macro
+	.set	reorder
+	END(mips_backtracer_with_skip)
+
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/libjava/sysdep/mips/mipsel-sighelper.S gcc-3.3.1.dave/libjava/sysdep/mips/mipsel-sighelper.S
--- gcc-3.3.1/libjava/sysdep/mips/mipsel-sighelper.S	Wed Dec 31 16:00:00 1969
+++ gcc-3.3.1.dave/libjava/sysdep/mips/mipsel-sighelper.S	Fri Sep  5 15:37:07 2003
@@ -0,0 +1,122 @@
+	# mipsel-sighelper.S - Help convert signals to java Exceptions
+	#
+	#
+	# 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.
+	#
+	# Written by David Daney <ddaney@avtrex.com>
+	#
+	# The following was generated by gcc-3.3 by compiling this code (ttx.c):
+	#
+	#typedef void (*vpf)();
+	#void __sig2exdummy()
+	#{
+	#    vpf x = (vpf)0x40000;
+	#    (*x)();
+	#}
+	#
+	# like this:
+	# mipsel-linux-gcc -S -O2 -fexceptions ttx.c
+	#
+	# We make gcc do the hard part of generating the eh_frame data.
+	#
+	# Then the $sig2exdummy_fakeout_point: label is added after the jal
+	# instruction and __sig2exdummy_fakeout_point: which contains the
+	# address of $sig2exdummy_fakeout_point:
+	#
+	# The code in mips-signal.h then builds a stack frame with the
+	# layout used by this function just above the frame of the faulting
+	# function.  And then jumps to _Jv_MipselThrowNPE() simulating a
+	# jal from $sig2exdummy_fakeout_point:
+	#
+	# The result is that the signal handler's stack frame and trampoline code
+	# are obliterated and the stack is in a state that looks like __sig2exdummy
+	# was called from the faulting point, and it then called _Jv_MipselThrowNPE().
+	# Unwinding can then proceed "normally".
+	#
+	
+	.section .mdebug.abi32
+	.previous
+	.abicalls
+	.text
+	.align	2
+	.globl	__sig2exdummy
+	.ent	__sig2exdummy
+	.type	__sig2exdummy, @function
+__sig2exdummy:
+$LFB3:
+	.frame	$sp,32,$31		# vars= 0, regs= 2/0, args= 16, extra= 8
+	.mask	0x90000000,-4
+	.fmask	0x00000000,0
+	.set	noreorder
+	.cpload	$25
+	.set	reorder
+	subu	$sp,$sp,32
+	.cprestore 16
+$LCFI0:
+	sw	$31,28($sp)
+$LCFI1:
+	sw	$28,24($sp)
+$LCFI2:
+	li	$25,262144
+	jal	$31,$25
+$sig2exdummy_fakeout_point:
+	lw	$31,28($sp)
+	#nop
+	.set	noreorder
+	.set	nomacro
+	j	$31
+	addu	$sp,$sp,32
+	.set	macro
+	.set	reorder
+
+$LFE3:
+	.end	__sig2exdummy
+	.data
+	.globl	__sig2exdummy_fakeout_point
+__sig2exdummy_fakeout_point:
+	.word	$sig2exdummy_fakeout_point
+	.section	.eh_frame,"a",@progbits
+$Lframe1:
+	.4byte	$LECIE1-$LSCIE1
+$LSCIE1:
+	.4byte	0x0
+	.byte	0x1
+	.ascii	"zR\000"
+	.uleb128 0x1
+	.sleb128 4
+	.byte	0x40
+	.uleb128 0x1
+	.byte	0x1b
+	.byte	0xc
+	.uleb128 0x1d
+	.uleb128 0x0
+	.align	2
+$LECIE1:
+$LSFDE1:
+	.4byte	$LEFDE1-$LASFDE1
+$LASFDE1:
+	.4byte	$LASFDE1-$Lframe1
+	.4byte	$LFB3-.
+	.4byte	$LFE3-$LFB3
+	.uleb128 0x0
+	.byte	0x4
+	.4byte	$LCFI0-$LFB3
+	.byte	0xe
+	.uleb128 0x20
+	.byte	0x4
+	.4byte	$LCFI2-$LCFI0
+	.byte	0x11
+	.uleb128 0x1c
+	.sleb128 -2
+	.byte	0x11
+	.uleb128 0x40
+	.sleb128 -1
+	.align	2
+$LEFDE1:
+	.align	0

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]