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]

Re: StackTraceElement support


Thanks for the patch.

A niggle:

Your patch isn't as robust as the previous code in that it now fails
to produce any useful output if addr2line or c++filt are absent.
These executables aren't always present, and it's important to produce
some sort of stack trace if at all possible.  I hacked your patch
about a bit to re-introduce that robustness.

See what you think -- if you agree with what I've done, please check
it in.

Andrew.

FYI: I'm thinking of getting rid of the call to c++filt altogether --
it's not needed because addr2line will work on shared objects and can
now produce Java demangling.  That gets us line numbers in shared
objects too.  Bonus...


2002-07-06  Mark Wielaard  <mark@klomp.org>

  * java/lang/natThrowable.cc (printRawStackTrace): removed.
  (getStackTrace0): new method.
  * java/lang/Throwable.java (CPlusPlusDemangler): removed.
  (printStackTrace(PrintWriter)): replace with pure java implementation.
  (printRawStackTrace): removed.
  (getStackTrace0): new method.
  * gcj/javaprims.h: regenerate class list.
  * include/name-finder.h (lookup): returns StackTraceElement*.
  (method_name, file_name): fields removed.
  (pid2, f2_pipe, b2_pipe, b2_pipe_fd): new fields.
  (~_Jv_name_finder): close new descriptors.
  * name-finder.cc(_Jv_name_finder): setup c++filt helper process.
  (createStackTraceElement): new method.
  (lookup): returns StackTraceElement*, uses createStackTraceElement().

Index: libjava/name-finder.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/name-finder.cc,v
retrieving revision 1.11
diff -c -2 -p -r1.11 name-finder.cc
*** libjava/name-finder.cc	23 Mar 2002 16:14:27 -0000	1.11
--- libjava/name-finder.cc	11 Jul 2002 17:37:19 -0000
*************** _Jv_name_finder::_Jv_name_finder (char *
*** 60,64 ****
  {
  #if defined (HAVE_PIPE) && defined (HAVE_FORK) && defined (HAVE_EXECVP)
!   error = 0;
  
    // Initialize file descriptors so that shutdown works properly.
--- 60,64 ----
  {
  #if defined (HAVE_PIPE) && defined (HAVE_FORK) && defined (HAVE_EXECVP)
!   demangling_error = lookup_error = 0;
  
    // Initialize file descriptors so that shutdown works properly.
*************** _Jv_name_finder::_Jv_name_finder (char *
*** 69,73 ****
    b_pipe_fd = NULL;
  
!   char *argv[6];
    {
      int arg = 0;
--- 69,81 ----
    b_pipe_fd = NULL;
  
!   f2_pipe[0] = -1;
!   f2_pipe[1] = -1;
!   b2_pipe[0] = -1;
!   b2_pipe[1] = -1;
!   b2_pipe_fd = NULL;
! 
!   // addr2line helper process.
! 
!   char *argv[5];
    {
      int arg = 0;
*************** _Jv_name_finder::_Jv_name_finder (char *
*** 76,80 ****
  #else
      argv[arg++] = "addr2line";
-     argv[arg++] = "-C";
      argv[arg++] = "-f";
      argv[arg++] = "-e";
--- 84,87 ----
*************** _Jv_name_finder::_Jv_name_finder (char *
*** 84,91 ****
    }
  
!   error |= pipe (f_pipe) < 0;
!   error |= pipe (b_pipe) < 0;
  
!   if (error)
      return;
  
--- 91,98 ----
    }
  
!   lookup_error |= pipe (f_pipe) < 0;
!   lookup_error |= pipe (b_pipe) < 0;
  
!   if (lookup_error)
      return;
  
*************** _Jv_name_finder::_Jv_name_finder (char *
*** 110,125 ****
    if (pid < 0)
      {
!       error |= 1; 
        return;
      }
  
    b_pipe_fd = fdopen (b_pipe[0], "r");
!   error |= !b_pipe_fd;
  
!   if (! error)
      {
        // Don't try to close the fd twice.
        b_pipe[0] = -1;
      }
  #endif
  }
--- 117,179 ----
    if (pid < 0)
      {
!       lookup_error |= 1; 
        return;
      }
  
    b_pipe_fd = fdopen (b_pipe[0], "r");
!   lookup_error |= !b_pipe_fd;
  
!   if (! lookup_error)
      {
        // Don't try to close the fd twice.
        b_pipe[0] = -1;
      }
+ 
+   // c++filt helper process.
+   
+   char *argv2[4];
+   argv2[0] = "c++filt";
+   argv2[1] = "-s";
+   argv2[2] = "java";
+   argv2[3] = NULL;
+ 
+   demangling_error |= pipe (f2_pipe) < 0;
+   demangling_error |= pipe (b2_pipe) < 0;
+ 
+   if (demangling_error)
+     return;
+ 
+   pid2 = fork ();
+   if (pid2 == 0)
+     {
+       close (f2_pipe[1]);
+       close (b2_pipe[0]);
+       dup2 (f2_pipe[0], fileno (stdin));
+       dup2 (b2_pipe[1], fileno (stdout));
+       execvp (argv2[0], argv2);
+       _exit (127);
+     }
+ 
+   // Close child end of pipes.  Set local descriptors to -1 so we
+   // don't try to close the fd again.
+   close (f2_pipe [0]);
+   f2_pipe[0] = -1;
+   close (b2_pipe [1]);
+   b2_pipe[1] = -1;
+ 
+   if (pid2 < 0)
+     {
+       demangling_error |= 1; 
+       return;
+     }
+ 
+   b2_pipe_fd = fdopen (b2_pipe[0], "r");
+   demangling_error |= !b2_pipe_fd;
+ 
+   if (! demangling_error)
+     {
+       // Don't try to close the fd twice.
+       b2_pipe[0] = -1;
+     }
  #endif
  }
*************** _Jv_name_finder::toHex (void *p)
*** 145,148 ****
--- 199,290 ----
  }   
  
+ /* Creates a StackTraceElement given a string and a filename.
+    Splits the given string into the class and method part.
+    The string s will be a demangled to a fully qualified java method string.
+    The string f will be decomposed into a file name and a possible line number.
+    The given strings will be altered.  */
+ 
+ java::lang::StackTraceElement*
+ _Jv_name_finder::createStackTraceElement(char *s, char *f)
+ {
+   char *c;
+   char *class_name = NULL;
+   char *method_name = NULL;
+ 
+ #if defined (HAVE_PIPE) && defined (HAVE_FORK) && defined (HAVE_EXECVP)
+   if (demangling_error)
+     goto fail;
+ 
+   demangling_error |= write (f2_pipe[1], s, strlen (s)) < 0;
+   if (demangling_error)
+     goto fail;
+   demangling_error |= write (f2_pipe[1], "\n", 1) < 0;
+   if (demangling_error)
+     goto fail;
+ 
+   char name[1024];
+   demangling_error |= (fgets (name, sizeof name, b2_pipe_fd) == NULL);
+   if (demangling_error)
+     goto fail;
+ 
+   c = strchr (name, '\n');
+   if (c)
+     *c = 0;
+   s = name;
+ #endif
+ 
+   c = strchr (s, '(');
+   if (c)
+     {
+       while(c-->s)
+ 	if (*c == '.')
+ 	  break;
+ 
+       if (*c == '.')
+ 	{
+ 	  *c = 0;
+ 	  class_name = s;
+ 	  method_name = c+1;
+ 	}
+       else
+ 	{
+ 	  class_name = NULL;
+ 	  method_name = s;
+ 	}
+     }
+   else
+     {
+       class_name = NULL;
+       method_name = s;
+     }
+ 
+   // Get line number
+   int line_number;
+   c = strrchr (f, ':');
+   if (c)
+     {
+       if (c[1] != 0)
+ 	line_number = atoi(c+1);
+       else
+ 	line_number = -1;
+       *c = 0;
+     }
+   else
+     {
+       line_number = -1;
+       c = strchr (f, '\n');
+       if (c)
+ 	*c = 0;
+     }
+ 
+  fail:
+   return new java::lang::StackTraceElement(
+ 		  f ? JvNewStringLatin1 (f) : NULL,
+ 		  line_number,
+ 		  class_name ? JvNewStringLatin1 (class_name) : NULL,
+ 		  JvNewStringLatin1 (method_name ? method_name : s),
+ 		  false);
+ }
+ 
  /* Given a pointer to a function or method, try to convert it into a
     name and the appropriate line and source file.  The caller passes
*************** _Jv_name_finder::toHex (void *p)
*** 152,156 ****
     he will have been correctly filled in with the pointer.  */
  
! bool
  _Jv_name_finder::lookup (void *p)
  {
--- 294,298 ----
     he will have been correctly filled in with the pointer.  */
  
! java::lang::StackTraceElement*
  _Jv_name_finder::lookup (void *p)
  {
*************** _Jv_name_finder::lookup (void *p)
*** 158,161 ****
--- 300,308 ----
    toHex (p);
        
+   char name[1024];
+   char file_name[1024];
+ 
+   file_name[0] = 0;
+ 
  #if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
    {
*************** _Jv_name_finder::lookup (void *p)
*** 167,171 ****
  	  strncpy (file_name, dl_info.dli_fname, sizeof file_name);
  	if (dl_info.dli_sname)
! 	  strncpy (method_name, dl_info.dli_sname, sizeof method_name);
         
         /* Don't trust dladdr() if the address is from the main program. */
--- 314,318 ----
  	  strncpy (file_name, dl_info.dli_fname, sizeof file_name);
  	if (dl_info.dli_sname)
! 	  strncpy (name, dl_info.dli_sname, sizeof name);
         
         /* Don't trust dladdr() if the address is from the main program. */
*************** _Jv_name_finder::lookup (void *p)
*** 173,210 ****
             && dl_info.dli_sname != NULL
  	   && (_Jv_argv == NULL || strcmp (file_name, _Jv_argv[0]) != 0))
!          return true;
        }
    }
  #endif
  
! #if defined (HAVE_PIPE) && defined (HAVE_FORK) && defined (HAVE_EXECVP)
!   if (error)
!     return false;
  
!   error |= write (f_pipe[1], hex, strlen (hex)) < 0;
!   if (error)
!     return false;
!   error |= write (f_pipe[1], "\n", 1) < 0;
!   if (error)
!     return false;
! 
!   error |= (fgets (method_name, sizeof method_name, b_pipe_fd) == NULL);
!   if (error)
!     return false;
!   error |= (fgets (file_name, sizeof file_name, b_pipe_fd) == NULL);
!   if (error)
!     return false;
! 
!   char *newline = strchr (method_name, '\n');
!   if (newline)
!     *newline = 0;
!   newline = strchr (file_name, '\n');
!   if (newline)
!     *newline = 0;
  
!   return true;
  
! #else
!   return false;
  #endif /* defined (HAVE_PIPE) && defined (HAVE_FORK) && defined (HAVE_EXECVP) */
  }
--- 320,356 ----
             && dl_info.dli_sname != NULL
  	   && (_Jv_argv == NULL || strcmp (file_name, _Jv_argv[0]) != 0))
!          return createStackTraceElement (name, file_name);
        }
    }
  #endif
  
!   memcpy (name, hex, strlen (hex) + 1);
  
! #if defined (HAVE_PIPE) && defined (HAVE_FORK) && defined (HAVE_EXECVP)
!   if (lookup_error)
!     goto fail;
  
!   lookup_error |= write (f_pipe[1], hex, strlen (hex)) < 0;
!   if (lookup_error)
!     goto fail;
!   lookup_error |= write (f_pipe[1], "\n", 1) < 0;
!   if (lookup_error)
!     goto fail;
! 
!   lookup_error |= (fgets (name, sizeof name, b_pipe_fd) == NULL);
!   if (lookup_error)
!     goto fail;
!   lookup_error |= (fgets (file_name, sizeof file_name, b_pipe_fd) == NULL);
!   if (lookup_error)
!     goto fail;
  
!   {
!     char *newline = strchr (name, '\n');
!     if (newline)
!       *newline = 0;
!   }
  #endif /* defined (HAVE_PIPE) && defined (HAVE_FORK) && defined (HAVE_EXECVP) */
+ 
+  fail:
+   return (createStackTraceElement (name, file_name));
  }
Index: libjava/gcj/javaprims.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gcj/javaprims.h,v
retrieving revision 1.39
diff -c -2 -p -r1.39 javaprims.h
*** libjava/gcj/javaprims.h	18 Jun 2002 17:06:42 -0000	1.39
--- libjava/gcj/javaprims.h	11 Jul 2002 17:37:19 -0000
*************** extern "Java"
*** 135,139 ****
        class Boolean;
        class Byte;
-       class CPlusPlusDemangler;
        class CharSequence;
        class Character;
--- 135,138 ----
*************** extern "Java"
*** 365,368 ****
--- 364,371 ----
          class JarOutputStream;
          class Manifest;
+       };
+ 
+       namespace regex
+       {
        };
  
Index: libjava/include/name-finder.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/name-finder.h,v
retrieving revision 1.6
diff -c -2 -p -r1.6 name-finder.h
*** libjava/include/name-finder.h	23 Mar 2002 16:14:28 -0000	1.6
--- libjava/include/name-finder.h	11 Jul 2002 17:37:19 -0000
*************** details.  */
*** 30,33 ****
--- 30,35 ----
  #endif
  
+ #include <java/lang/StackTraceElement.h>
+ 
  /* _Jv_name_finder is a class wrapper around a mechanism that can
     convert addresses of methods to their names and the names of files
*************** public:  
*** 48,51 ****
--- 50,60 ----
  	fclose (b_pipe_fd);
  
+       myclose (f2_pipe[0]);
+       myclose (f2_pipe[1]);
+       myclose (b2_pipe[0]);
+       myclose (b2_pipe[1]);
+       if (b2_pipe_fd != NULL)
+ 	fclose (b2_pipe_fd);
+ 
        if (pid >= 0)
  	{
*************** public:  
*** 54,57 ****
--- 63,73 ----
  	  waitpid (pid, &wstat, 0);
  	}
+ 
+       if (pid2 >= 0)
+ 	{
+ 	  int wstat;
+ 	  // We don't care about errors here.
+ 	  waitpid (pid2, &wstat, 0);
+ 	}
  #endif
      }
*************** public:  
*** 61,83 ****
     the code pointer in p.
  
!    Returns false if the lookup fails.  Even if this happens, the field
!    hex will have been correctly filled in with the pointer. 
  
!    The other fields are method_name and file_name, which lookup will
!    attempt to fill appropriately.  If the lookup has failed, these
!    fields contain garbage.*/
!   bool lookup (void *p);
  
-   char method_name[1024];
-   char file_name[1024];
    char hex[sizeof (void *) * 2 + 5];
  
  private:
    void toHex (void *p);
  #if defined (HAVE_PIPE) && defined (HAVE_FORK)
!   pid_t pid;
!   int f_pipe[2], b_pipe[2];
!   FILE *b_pipe_fd;
!   int error;
  
    // Close a descriptor only if it has not been closed.
--- 77,95 ----
     the code pointer in p.
  
!    Returns NULL if the lookup fails.  Even if this happens, the field
!    hex will have been correctly filled in with the pointer. */
  
!   java::lang::StackTraceElement* lookup (void *p);
  
    char hex[sizeof (void *) * 2 + 5];
  
  private:
    void toHex (void *p);
+   java::lang::StackTraceElement* createStackTraceElement(char *s, char *f);
  #if defined (HAVE_PIPE) && defined (HAVE_FORK)
!   pid_t pid, pid2;
!   int f_pipe[2], b_pipe[2], f2_pipe[2], b2_pipe[2];
!   FILE *b_pipe_fd, *b2_pipe_fd;
!   int demangling_error, lookup_error;
  
    // Close a descriptor only if it has not been closed.
Index: libjava/java/lang/StackTraceElement.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/StackTraceElement.java,v
retrieving revision 1.1
diff -c -2 -p -r1.1 StackTraceElement.java
*** libjava/java/lang/StackTraceElement.java	24 May 2002 10:40:43 -0000	1.1
--- libjava/java/lang/StackTraceElement.java	11 Jul 2002 17:37:20 -0000
*************** public class StackTraceElement implement
*** 192,196 ****
      if (methodName != null)
        sb.append(methodName);
!     sb.append('(');
      if (fileName != null)
        sb.append(fileName);
--- 192,196 ----
      if (methodName != null)
        sb.append(methodName);
!     sb.append(" (");
      if (fileName != null)
        sb.append(fileName);
Index: libjava/java/lang/Throwable.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Throwable.java,v
retrieving revision 1.11
diff -c -2 -p -r1.11 Throwable.java
*** libjava/java/lang/Throwable.java	24 May 2002 10:40:42 -0000	1.11
--- libjava/java/lang/Throwable.java	11 Jul 2002 17:37:20 -0000
*************** import java.io.OutputStream;
*** 58,131 ****
   */
  
- /* A CPlusPlusDemangler sits on top of a PrintWriter.  All input is
-  * passed through the "c++filt" program (part of GNU binutils) which
-  * demangles internal symbols to their C++ source form.
-  *
-  * Closing a CPlusPlusDemangler doesn't close the underlying
-  * PrintWriter; it does, however close underlying process and flush
-  * all its buffers, so it's possible to guarantee that after a
-  * CPlusPlusDemangler has been closed no more will ever be written to
-  * the underlying PrintWriter.
-  *
-  * FIXME: This implictly converts data from the input stream, which is
-  * a stream of characters, to a stream of bytes.  We need a way of
-  * handling Unicode characters in demangled identifiers.  */
- 
- class CPlusPlusDemangler extends OutputStream
- {
-   java.io.OutputStream procOut;
-   java.io.InputStream procIn;
-   java.lang.Process proc;
-   PrintWriter p;
- 
-   /* The number of bytes written to the underlying PrintWriter.  This
-      provides a crude but fairly portable way to determine whether or
-      not the attempt to exec c++filt worked. */  
-   public int written = 0;
- 
-   CPlusPlusDemangler (PrintWriter writer) throws IOException
-   {
-     p = writer;
-     proc = Runtime.getRuntime ().exec ("c++filt -s java");
-     procOut = proc.getOutputStream ();
-     procIn = proc.getInputStream ();
-   }
- 
-   public void write (int b) throws IOException
-   {
-     procOut.write (b);
-     while (procIn.available () != 0)
-       {
- 	int c = procIn.read ();
- 	if (c == -1)
- 	  break;
- 	else
- 	  {
- 	    p.write (c);
- 	    written++;
- 	  }
-       }
-   }
-   
-   public void close () throws IOException
-   {
-     procOut.close ();
-     int c;
-     while ((c = procIn.read ()) != -1)
-       {
- 	p.write (c);
- 	written++;
-       }
-     p.flush ();
-     try
-       {
- 	proc.waitFor ();
-       }
-     catch (InterruptedException _)
-       {
-       }
-   }    
- }
- 
  /**
   * Throwable is the superclass of all exceptions that can be raised.
--- 58,61 ----
*************** public class Throwable implements Serial
*** 220,225 ****
     * @since 1.4
     */
!   // XXX Don't initialize this, once fillInStackTrace() does it.
!   private StackTraceElement[] stackTrace = {};
  
    /**
--- 150,154 ----
     * @since 1.4
     */
!   private StackTraceElement[] stackTrace;
  
    /**
*************** public class Throwable implements Serial
*** 450,473 ****
  
    /**
!    * Print a stack trace to the specified PrintWriter. See
!    * {@link #printStackTrace()} for the sample format.
     *
     * @param w the PrintWriter to write the trace to
     * @since 1.1
     */
!   public void printStackTrace (PrintWriter wr)
    {
!     try
        {
! 	CPlusPlusDemangler cPlusPlusFilter = new CPlusPlusDemangler (wr);
! 	PrintWriter writer = new PrintWriter (cPlusPlusFilter);
! 	printRawStackTrace (writer);
! 	writer.close ();
! 	if (cPlusPlusFilter.written == 0) // The demangler has failed...
! 	  printRawStackTrace (wr);
        }
!     catch (Exception e1)
        {
! 	printRawStackTrace (wr);
        }
    }
--- 379,478 ----
  
    /**
!    * <p>Prints the exception, the detailed message and the stack trace
!    * associated with this Throwable to the given <code>PrintWriter</code>.
!    * The actual output written is implemention specific. Use the result of
!    * <code>getStackTrace()</code> when more precise information is needed.
!    *
!    * <p>This implementation first prints a line with the result of this
!    * object's <code>toString()</code> method.
!    * <br>
!    * Then for all elements given by <code>getStackTrace</code> it prints
!    * a line containing three spaces, the string "at " and the result of calling
!    * the <code>toString()</code> method on the <code>StackTraceElement</code>
!    * object. If <code>getStackTrace()</code> returns an empty array it prints
!    * a line containing three spaces and the string
!    * "&lt;&lt;No stacktrace available&gt;&gt;".
!    * <br>
!    * Then if <code>getCause()</code> doesn't return null it adds a line
!    * starting with "Caused by: " and the result of calling
!    * <code>toString()</code> on the cause.
!    * <br>
!    * Then for every cause (of a cause, etc) the stacktrace is printed the
!    * same as for the top level <code>Throwable</code> except that as soon
!    * as all the remaining stack frames of the cause are the same as the
!    * the last stack frames of the throwable that the cause is wrapped in
!    * then a line starting with three spaces and the string "... X more" is
!    * printed, where X is the number of remaining stackframes.
     *
     * @param w the PrintWriter to write the trace to
     * @since 1.1
     */
!   public void printStackTrace (PrintWriter pw)
    {
!     // First line
!     pw.println(toString());
! 
!     // The stacktrace
!     StackTraceElement[] stack = getStackTrace();
!     if (stack == null || stack.length == 0)
        {
! 	pw.println("   <<No stacktrace available>>");
! 	return;
        }
!     else
        {
! 	for (int i = 0; i < stack.length; i++)
! 	  pw.println("   at " + stack[i]);
!       }
! 
!     // The cause(s)
!     Throwable cause = getCause();
!     while (cause != null)
!       {
!         // Cause first line
!         pw.println("Caused by: " + cause);
! 
!         // Cause stacktrace
!         StackTraceElement[] parentStack = stack;
!         stack = cause.getStackTrace();
! 	if (stack == null || stack.length == 0)
! 	  {
! 	    pw.println("   <<No stacktrace available>>");
! 	  }
! 	else if (parentStack == null || parentStack.length == 0)
! 	  {
! 	    for (int i = 0; i < stack.length; i++)
! 	      pw.println("   at " + stack[i]);
! 	  }
! 	else
! 	  {
! 	    boolean equal = false; // Is rest of stack equal to parent frame?
! 	    for (int i = 0; i < stack.length && ! equal; i++)
! 	      {
! 		// Check if we already printed the rest of the stack
! 		// since it was the tail of the parent stack
! 		int remaining = stack.length - i;
! 		int element = i;
! 		int parentElement = parentStack.length - remaining;
! 		equal = parentElement >= 0
! 		      && parentElement < parentStack.length; // be optimistic
! 		while (equal && element < stack.length)
! 		  {
! 		    if (stack[element].equals(parentStack[parentElement]))
! 		      {
! 			element++;
! 			parentElement++;
! 		      }
! 		    else
! 		      equal = false;
! 		  }
! 		// Print stacktrace element or indicate the rest is equal 
! 		if (! equal)
! 		  pw.println("   at " + stack[i]);
! 		else
! 		  pw.println("   ..." + remaining + " more");
! 	      }
! 	  }
!         cause = cause.getCause();
        }
    }
*************** public class Throwable implements Serial
*** 494,497 ****
--- 499,505 ----
    public StackTraceElement[] getStackTrace()
    {
+     if (stackTrace == null)
+       stackTrace = getStackTrace0();
+ 
      return stackTrace;
    }
*************** public class Throwable implements Serial
*** 514,519 ****
    }
  
!   private native final void printRawStackTrace (PrintWriter wr);
!   
    // Setting this flag to false prevents fillInStackTrace() from running.
    static boolean trace_enabled = true;
--- 522,527 ----
    }
  
!   private native final StackTraceElement[] getStackTrace0 ();
! 
    // Setting this flag to false prevents fillInStackTrace() from running.
    static boolean trace_enabled = true;
Index: libjava/java/lang/natThrowable.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natThrowable.cc,v
retrieving revision 1.12
diff -c -2 -p -r1.12 natThrowable.cc
*** libjava/java/lang/natThrowable.cc	24 May 2002 22:31:23 -0000	1.12
--- libjava/java/lang/natThrowable.cc	11 Jul 2002 17:37:20 -0000
*************** details.  */
*** 23,26 ****
--- 23,27 ----
  #include <java-threads.h>
  #include <java/lang/Throwable.h>
+ #include <java/lang/StackTraceElement.h>
  #include <java/io/PrintStream.h>
  #include <java/io/PrintWriter.h>
*************** java::lang::Throwable::fillInStackTrace 
*** 68,104 ****
  }
  
! void 
! java::lang::Throwable::printRawStackTrace (java::io::PrintWriter *wr)
  {
-   wr->println (toString ());
  #ifdef HAVE_BACKTRACE
    if (!stackTraceBytes)
!     return;
  
    int depth = stackTraceBytes->length / sizeof (void *);
    void *p[depth];
    memcpy (p, elements (stackTraceBytes), sizeof p);
  
    _Jv_name_finder finder (_Jv_ThisExecutable ());
  
    for (int i = 0; i < depth; i++)
!     {
!       bool found = finder.lookup (p[i]);
!       wr->print (JvNewStringLatin1 ("   at "));
!       wr->print (JvNewStringLatin1 (finder.hex));
!       if (found)
! 	{
! 	  wr->print (JvNewStringLatin1 (": "));
! 	  wr->print (JvNewStringLatin1 (finder.method_name));
! 	  if (finder.file_name[0])
! 	    {
! 	      wr->print (JvNewStringLatin1 (" ("));
! 	      wr->print (JvNewStringLatin1 (finder.file_name));
! 	      wr->print (JvNewStringLatin1 (")"));
! 	    }
! 	}
!       wr->println ();
!     }
  #endif /* HAVE_BACKTRACE */
-   wr->flush ();
  }
--- 69,99 ----
  }
  
! JArray<java::lang::StackTraceElement*> *
! java::lang::Throwable::getStackTrace0 ()
  {
  #ifdef HAVE_BACKTRACE
    if (!stackTraceBytes)
!     return NULL;
  
    int depth = stackTraceBytes->length / sizeof (void *);
    void *p[depth];
+   // This memcpy is esential; it ensures that the array of void* is
+   // correctly aligned.
    memcpy (p, elements (stackTraceBytes), sizeof p);
  
+   JArray<java::lang::StackTraceElement*> *result;
+   java::lang::StackTraceElement** el;
+   result = reinterpret_cast <JArray<java::lang::StackTraceElement *>*>
+     (JvNewObjectArray (depth, &java::lang::StackTraceElement::class$, NULL));
+   el = elements (result);
+ 
    _Jv_name_finder finder (_Jv_ThisExecutable ());
  
    for (int i = 0; i < depth; i++)
!     el[i] = finder.lookup (p[i]);
! 
!   return result;
! #else
!   return NULL;
  #endif /* HAVE_BACKTRACE */
  }


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