4d5c703ec0
* gnu/gcj/runtime/NameFinder.java (remove_interpreter): New field. (sanitizeStack): Correctly reset unknown and interpreter counters, detect interpreter runtime frames. (demangleInterpreterMethod): New method. * gnu/gcj/runtime/natNameFinder.cc (lookupInterp): Use new method. * java/lang/natVMThrowable.cc (fillInStackTrace): Change order of filling in addrs[]. From-SVN: r56741
114 lines
3.2 KiB
C++
114 lines
3.2 KiB
C++
// natNameFinder.cc - native helper methods for NameFinder.java
|
|
|
|
/* Copyright (C) 2002 Free Software Foundation, 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 Mark Wielaard (mark@klomp.org)
|
|
* Based on the old name-finder.cc by Andrew Haley <aph@cygnus.com>.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <gcj/cni.h>
|
|
#include <jvm.h>
|
|
#include <java/lang/String.h>
|
|
#include <java/lang/StackTraceElement.h>
|
|
#include <java/lang/StringBuffer.h>
|
|
#include <java-interp.h>
|
|
|
|
#include <gnu/gcj/runtime/NameFinder.h>
|
|
|
|
#ifdef HAVE_DLFCN_H
|
|
#include <dlfcn.h>
|
|
#endif
|
|
|
|
java::lang::String*
|
|
gnu::gcj::runtime::NameFinder::getExecutable (void)
|
|
{
|
|
return JvNewStringLatin1 (_Jv_ThisExecutable ());
|
|
}
|
|
|
|
java::lang::String*
|
|
gnu::gcj::runtime::NameFinder::getAddrAsString(RawData* addrs, jint n)
|
|
{
|
|
_Jv_frame_info *p = (_Jv_frame_info *) addrs;
|
|
typedef unsigned word_t __attribute ((mode (word)));
|
|
word_t w = (word_t) p[n].addr;
|
|
int digits = sizeof (void *) * 2;
|
|
char hex[digits+5];
|
|
|
|
strcpy (hex, "0x");
|
|
for (int i = digits - 1; i >= 0; i--)
|
|
{
|
|
int digit = w % 16;
|
|
|
|
w /= 16;
|
|
hex[i+2] = digit > 9 ? 'a' + digit - 10 : '0' + digit;
|
|
}
|
|
hex [digits+2] = 0;
|
|
|
|
return JvNewStringLatin1(hex);
|
|
}
|
|
|
|
java::lang::StackTraceElement*
|
|
gnu::gcj::runtime::NameFinder::dladdrLookup(RawData* addrs, jint n)
|
|
{
|
|
#if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
|
|
extern char **_Jv_argv;
|
|
char name[1024];
|
|
char file_name[1024];
|
|
_Jv_frame_info *stack = (_Jv_frame_info *) addrs;
|
|
void* p = stack[n].addr;
|
|
Dl_info dl_info;
|
|
|
|
if (dladdr (p, &dl_info))
|
|
{
|
|
if (dl_info.dli_fname)
|
|
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. */
|
|
if (dl_info.dli_fname != NULL
|
|
&& dl_info.dli_sname != NULL
|
|
&& (_Jv_argv == NULL || strcmp (file_name, _Jv_argv[0]) != 0))
|
|
return createStackTraceElement (JvNewStringLatin1 (name),
|
|
JvNewStringLatin1 (file_name));
|
|
}
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
java::lang::StackTraceElement *
|
|
gnu::gcj::runtime::NameFinder::lookupInterp(RawData* addrs, jint n)
|
|
{
|
|
#ifdef INTERPRETER
|
|
_Jv_frame_info *stack = (_Jv_frame_info *) addrs;
|
|
if (stack[n].interp == NULL)
|
|
return NULL;
|
|
|
|
_Jv_InterpMethod *meth
|
|
= reinterpret_cast<_Jv_InterpMethod *> (stack[n].interp);
|
|
java::lang::StringBuffer *sb = new java::lang::StringBuffer();
|
|
sb->append(_Jv_NewStringUtf8Const(meth->self->name));
|
|
sb->append(_Jv_NewStringUtf8Const(meth->self->signature));
|
|
// FIXME: source file name and line number can be found from
|
|
// bytecode debug information. But currently we don't keep that
|
|
// around.
|
|
// FIXME: is using the defining class correct here?
|
|
java::lang::String *className = meth->defining_class->getName();
|
|
java::lang::String *methodName
|
|
= demangleInterpreterMethod(sb->toString(), className);
|
|
return new java::lang::StackTraceElement(NULL, -1,
|
|
className, methodName, false);
|
|
#else // INTERPRETER
|
|
return NULL;
|
|
#endif // INTERPRETER
|
|
}
|