aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/lang/natThrowable.cc
blob: 9c1e31d9b6194464f1fefb043a672e3d1576ad15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// natThrowable.cc - Superclass for all exceptions.

/* Copyright (C) 2000  Red Hat Inc

   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.  */

/**
 * @author Andrew Haley <aph@cygnus.com>
 * @date Jan 6  2000
 */

#include <config.h>

#include <string.h>

#pragma implementation "Throwable.h"

#include <gcj/cni.h>
#include <jvm.h>
#include <java/lang/Object.h>
#include <java-threads.h>
#include <java/lang/Throwable.h>
#include <java/io/PrintStream.h>
#include <java/io/PrintWriter.h>

#include <sys/types.h>

#include <stdlib.h>
#include <stdio.h>

#include <unistd.h>

#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif

#include <name-finder.h>

/* 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.  */

java::lang::Throwable *
java::lang::Throwable::fillInStackTrace (void)
{
#ifdef HAVE_BACKTRACE
  void *p[128];
  
  // We subtract 1 from the number of elements because we don't want
  // to include the call to fillInStackTrace in the trace.
  int n = backtrace (p, 128) - 1;  

  // ???  Might this cause a problem if the byte array isn't aligned?
  stackTrace = JvNewByteArray (n * sizeof p[0]);
  memcpy (elements (stackTrace), p+1, (n * sizeof p[0]));
#endif

  return this;
}

void 
java::lang::Throwable::printStackTrace (java::io::PrintWriter *wr)
{
  wr->println (toString ());
#ifdef HAVE_BACKTRACE
  if (!stackTrace)
    return;

  void **p = (void **)elements (stackTrace);
  int depth = stackTrace->length / sizeof p[0];

  _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));
	  wr->print (JvNewStringLatin1 (" ("));
	  wr->print (JvNewStringLatin1 (finder.file_name));
	  wr->print (JvNewStringLatin1 (")"));
	}
      wr->println ();
    }
#endif /* HAVE_BACKTRACE */
}