OSDN Git Service

* include/jvm.h (struct _Jv_frame_info): New structure.
[pf3gnuchains/gcc-fork.git] / libjava / gnu / gcj / runtime / natNameFinder.cc
1 // natNameFinder.cc - native helper methods for NameFinder.java
2
3 /* Copyright (C) 2002  Free Software Foundation, Inc
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 /**
12  * @author Mark Wielaard (mark@klomp.org)
13  * Based on the old name-finder.cc by Andrew Haley <aph@cygnus.com>.
14  */
15
16 #include <config.h>
17
18 #include <gcj/cni.h>
19 #include <jvm.h>
20 #include <java/lang/String.h>
21 #include <java/lang/StackTraceElement.h>
22 #include <java/lang/StringBuffer.h>
23 #include <java-interp.h>
24
25 #include <gnu/gcj/runtime/NameFinder.h>
26
27 #ifdef HAVE_DLFCN_H
28 #include <dlfcn.h>
29 #endif
30
31 java::lang::String*
32 gnu::gcj::runtime::NameFinder::getExecutable (void)
33 {
34   return JvNewStringLatin1 (_Jv_ThisExecutable ());
35 }
36
37 java::lang::String*
38 gnu::gcj::runtime::NameFinder::getAddrAsString(RawData* addrs, jint n)
39 {
40   _Jv_frame_info *p = (_Jv_frame_info *) addrs;
41   typedef unsigned word_t __attribute ((mode (word)));
42   word_t w = (word_t) p[n].addr;
43   int digits = sizeof (void *) * 2;
44   char hex[digits+5];
45
46   strcpy (hex, "0x");
47   for (int i = digits - 1; i >= 0; i--)
48     {
49       int digit = w % 16;
50
51       w /= 16;
52       hex[i+2] = digit > 9 ? 'a' + digit - 10 : '0' + digit;
53     }
54   hex [digits+2] = 0;
55
56   return JvNewStringLatin1(hex);
57 }
58
59 java::lang::StackTraceElement*
60 gnu::gcj::runtime::NameFinder::dladdrLookup(RawData* addrs, jint n)
61 {
62 #if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
63   extern char **_Jv_argv;
64   char name[1024];
65   char file_name[1024];
66   _Jv_frame_info *stack = (_Jv_frame_info *) addrs;
67   void* p = stack[n].addr;
68   Dl_info dl_info;
69    
70   if (dladdr (p, &dl_info))
71     {
72       if (dl_info.dli_fname)
73         strncpy (file_name, dl_info.dli_fname, sizeof file_name);
74       if (dl_info.dli_sname)
75         strncpy (name, dl_info.dli_sname, sizeof name);
76      
77      /* Don't trust dladdr() if the address is from the main program. */
78      if (dl_info.dli_fname != NULL
79          && dl_info.dli_sname != NULL
80          && (_Jv_argv == NULL || strcmp (file_name, _Jv_argv[0]) != 0))
81        return createStackTraceElement (JvNewStringLatin1 (name),
82                                        JvNewStringLatin1 (file_name));
83     }
84 #endif
85   return NULL;
86 }
87
88 java::lang::StackTraceElement *
89 gnu::gcj::runtime::NameFinder::lookupInterp(RawData* addrs, jint n)
90 {
91 #ifdef INTERPRETER
92   _Jv_frame_info *stack = (_Jv_frame_info *) addrs;
93   if (stack[n].interp == NULL)
94     return NULL;
95
96   _Jv_InterpMethod *meth
97     = reinterpret_cast<_Jv_InterpMethod *> (stack[n].interp);
98   // FIXME: demangle.
99   java::lang::StringBuffer *sb = new java::lang::StringBuffer();
100   sb->append(_Jv_NewStringUtf8Const(meth->self->name));
101   sb->append(_Jv_NewStringUtf8Const(meth->self->signature));
102   // FIXME: source file name and line number can be found from
103   // bytecode debug information.  But currently we don't keep that
104   // around.
105   // FIXME: is using the defining class correct here?
106   return new java::lang::StackTraceElement(NULL, -1,
107                                            meth->defining_class->getName(),
108                                            sb->toString(), false);
109 #else // INTERPRETER
110   return NULL;
111 #endif // INTERPRETER
112 }