source: trunk/gcc/libjava/gnu/gcj/runtime/natStackTrace.cc

Last change on this file was 1598, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1597,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 4.5 KB
Line 
1// natStackTrace.cc - native helper methods for Throwable
2
3/* Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11/**
12 * @author Andrew Haley <aph@cygnus.com>
13 * @author Mark Wielaard <mark@klomp.org>
14 *
15 * Native helper methods for VM specific Throwable support.
16 */
17
18#include <config.h>
19#include <platform.h>
20
21#include <string.h>
22
23#include <jvm.h>
24#include <gcj/cni.h>
25#include <gnu/gcj/RawData.h>
26#include <java/lang/Object.h>
27#include <java-threads.h>
28#include <gnu/gcj/runtime/MethodRef.h>
29#include <gnu/gcj/runtime/StackTrace.h>
30#include <java/lang/Thread.h>
31#include <java-interp.h>
32#include <java/util/IdentityHashMap.h>
33#include <java/lang/ArrayIndexOutOfBoundsException.h>
34
35#include <sys/types.h>
36
37#include <stdlib.h>
38
39#include <unistd.h>
40
41#ifdef HAVE_EXECINFO_H
42#include <execinfo.h>
43#endif
44
45#include <unwind.h>
46
47
48// Fill in this stack trace with MAXLEN elements starting at offset.
49void
50gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset)
51{
52#ifdef HAVE_BACKTRACE
53 offset += 1;
54 void *_p[maxlen + offset];
55 len = backtrace (_p, maxlen + offset) - offset;
56 void **p = _p + offset;
57 _Jv_frame_info *frame;
58 if (len > 0)
59 {
60#ifdef INTERPRETER
61 extern void _Jv_StartOfInterpreter (void);
62 extern void _Jv_EndOfInterpreter (void);
63
64 java::lang::Thread *thread = java::lang::Thread::currentThread();
65 _Jv_MethodChain *interp_frame
66 = (thread ? reinterpret_cast<_Jv_MethodChain *> (thread->interp_frame)
67 : NULL);
68#endif // INTERPRETER
69
70 frame = (_Jv_frame_info *) _Jv_Malloc (len * sizeof (_Jv_frame_info));
71 for (int n = 0; n < len; n++)
72 {
73 frame[n].addr = p[n];
74#ifdef INTERPRETER
75 if (p[n] >= &_Jv_StartOfInterpreter && p[n] <= &_Jv_EndOfInterpreter)
76 {
77 frame[n].interp = (void *) interp_frame->self;
78 interp_frame = interp_frame->next;
79 }
80 else
81 frame[n].interp = 0;
82#endif // INTERPRETER
83 }
84 }
85 else
86 frame = NULL;
87
88 addrs = reinterpret_cast<gnu::gcj::RawData *> (frame);
89#else // HAVE_BACKTRACE
90 (void)maxlen;
91 (void)offset;
92#endif // HAVE_BACKTRACE
93}
94
95/* Obtain the next power-of-2 of some integer. */
96static inline jint
97nextpowerof2 (jint n)
98{
99 n |= (n >> 1);
100 n |= (n >> 2);
101 n |= (n >> 4);
102 n |= (n >> 8);
103 n |= (n >> 16);
104 return n+1;
105}
106
107#define GET_FRAME(N) \
108({ \
109 if ((N) >= len) \
110 fillInStackTrace (nextpowerof2 (N), 1); \
111 if ((N) < 0 || (N) >= len) \
112 throw new ::java::lang::ArrayIndexOutOfBoundsException (); \
113 \
114 _Jv_frame_info *frame = (_Jv_frame_info *)addrs; \
115 &frame[N]; \
116})
117
118gnu::gcj::runtime::MethodRef *
119gnu::gcj::runtime::StackTrace::getCompiledMethodRef (gnu::gcj::RawData *addr)
120{
121 void *p = _Unwind_FindEnclosingFunction (addr);
122 return gnu::gcj::runtime::StackTrace
123 ::methodAtAddress ((gnu::gcj::RawData *)p);
124}
125
126java::lang::Class *
127gnu::gcj::runtime::StackTrace::classAt (jint n)
128{
129 _Jv_frame_info *frame = GET_FRAME (n);
130
131#ifdef INTERPRETER
132 if (frame->interp)
133 {
134 _Jv_InterpMethod *meth
135 = reinterpret_cast<_Jv_InterpMethod *> (frame->interp);
136 return meth->defining_class;
137 }
138#endif // INTERPRETER
139
140 gnu::gcj::runtime::MethodRef *ref
141 = getCompiledMethodRef ((gnu::gcj::RawData *)frame->addr);
142 if (ref)
143 return ref->klass;
144 else
145 return NULL;
146}
147
148java::lang::String*
149gnu::gcj::runtime::StackTrace::methodAt (jint n)
150{
151 _Jv_frame_info *frame = GET_FRAME (n);
152 _Jv_Method *meth = NULL;
153
154#ifdef INTERPRETER
155 if (frame->interp)
156 {
157 meth
158 = reinterpret_cast<_Jv_InterpMethod *> (frame->interp)
159 ->get_method();
160 }
161#endif // INTERPRETER
162
163 if (! meth)
164 {
165 gnu::gcj::runtime::MethodRef *ref
166 = getCompiledMethodRef ((gnu::gcj::RawData *)frame->addr);
167 if (ref)
168 meth = (_Jv_Method *)ref->method;
169 }
170
171 return meth
172 ? _Jv_NewStringUtf8Const (meth->name)
173 : NULL ;
174}
175
176void
177gnu::gcj::runtime::StackTrace::update(void)
178{
179 jclass klass;
180
181 while ((klass = _Jv_PopClass ()))
182 {
183 for (int i=0; i<klass->method_count; i++)
184 {
185 JvSynchronize sync (map);
186 _Jv_Method *meth = &(klass->methods[i]);
187 if (meth->ncode) // i.e. if p is not abstract
188 {
189 gnu::gcj::runtime::MethodRef *ref
190 = new gnu::gcj::runtime::MethodRef
191 ((gnu::gcj::RawData *)meth, klass);
192 map->put ((java::lang::Object*)(meth->ncode), ref);
193 }
194 }
195 }
196}
197
198void
199gnu::gcj::runtime::StackTrace::finalize(void)
200{
201 if (addrs != NULL)
202 _Jv_Free (addrs);
203}
Note: See TracBrowser for help on using the repository browser.