javaprims.h (_Jv_uintptr_t): New typedef similar to uintptr_t in C99.
* gcj/javaprims.h (_Jv_uintptr_t): New typedef similar to uintptr_t in C99. * include/java-stack.h: Include stdlib.h. (_Jv_AddrInfo): New structure to hold address information. * include/posix.h (_Jv_platform_dladdr): Declare. * include/win32.h (_Jv_platform_dladdr): Declare. (backtrace): Remove declaration. * posix.cc: Include dlfcn.h if available. Include java-stack.h. (_Jv_platform_dladdr): Define. * win32.cc: Include string.h. Include java-stack.h. (backtrace): Remove. (_Jv_platform_dladdr): Define. * sysdep/i386/backtrace.h (fallback_backtrace): Check that a potential frame pointer value is 32-bit word-aligned. Use operand of the CALL instruction calling the current function to find its starting address. * stacktrace.cc: Do not include dlfcn.h. Include platform.h. (_Jv_StackTrace::getLineNumberForFrame): Use _Jv_platform_dladdr() instead of dladdr(). (_Jv_StackTrace::GetStackTraceElements): Use nCodeMap even for Windows. (_Jv_StackTrace::GetClassContext): Use fallback_backtrace() for targets with SJLJ exceptions instead of using _Unwind_Backtrace(). (_Jv_StackTrace::GetFirstNonSystemClassLoader): Likewise. From-SVN: r115069
This commit is contained in:
parent
6150b60261
commit
3379268423
@ -1,3 +1,28 @@
|
||||
2006-06-29 Ranjit Mathew <rmathew@gcc.gnu.org>
|
||||
|
||||
* gcj/javaprims.h (_Jv_uintptr_t): New typedef similar to uintptr_t in
|
||||
C99.
|
||||
* include/java-stack.h: Include stdlib.h.
|
||||
(_Jv_AddrInfo): New structure to hold address information.
|
||||
* include/posix.h (_Jv_platform_dladdr): Declare.
|
||||
* include/win32.h (_Jv_platform_dladdr): Declare.
|
||||
(backtrace): Remove declaration.
|
||||
* posix.cc: Include dlfcn.h if available. Include java-stack.h.
|
||||
(_Jv_platform_dladdr): Define.
|
||||
* win32.cc: Include string.h. Include java-stack.h.
|
||||
(backtrace): Remove.
|
||||
(_Jv_platform_dladdr): Define.
|
||||
* sysdep/i386/backtrace.h (fallback_backtrace): Check that a potential
|
||||
frame pointer value is 32-bit word-aligned. Use operand of the CALL
|
||||
instruction calling the current function to find its starting address.
|
||||
* stacktrace.cc: Do not include dlfcn.h. Include platform.h.
|
||||
(_Jv_StackTrace::getLineNumberForFrame): Use _Jv_platform_dladdr()
|
||||
instead of dladdr().
|
||||
(_Jv_StackTrace::GetStackTraceElements): Use nCodeMap even for Windows.
|
||||
(_Jv_StackTrace::GetClassContext): Use fallback_backtrace() for
|
||||
targets with SJLJ exceptions instead of using _Unwind_Backtrace().
|
||||
(_Jv_StackTrace::GetFirstNonSystemClassLoader): Likewise.
|
||||
|
||||
2006-06-27 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* java/io/OutputStreamWriter.java (writeChars): Use a 'do' loop.
|
||||
|
@ -624,6 +624,10 @@ typedef unsigned short _Jv_ushort __attribute__((__mode__(__HI__)));
|
||||
typedef unsigned int _Jv_uint __attribute__((__mode__(__SI__)));
|
||||
typedef unsigned int _Jv_ulong __attribute__((__mode__(__DI__)));
|
||||
|
||||
// The type to use when treating a pointer as an integer. Similar to
|
||||
// uintptr_t in C99.
|
||||
typedef unsigned int _Jv_uintptr_t __attribute__((__mode__(__pointer__)));
|
||||
|
||||
class _Jv_Utf8Const
|
||||
{
|
||||
_Jv_ushort hash;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// java-stack.h - Definitions for unwinding & inspecting the call stack.
|
||||
|
||||
/* Copyright (C) 2005 Free Software Foundation
|
||||
/* Copyright (C) 2005, 2006 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
@ -11,6 +11,7 @@ details. */
|
||||
#ifndef __JV_STACKTRACE_H__
|
||||
#define __JV_STACKTRACE_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unwind.h>
|
||||
|
||||
#include <gcj/cni.h>
|
||||
@ -126,5 +127,35 @@ public:
|
||||
|
||||
};
|
||||
|
||||
// Information about a given address.
|
||||
struct _Jv_AddrInfo
|
||||
{
|
||||
// File name of the defining module.
|
||||
const char *file_name;
|
||||
|
||||
// Base address of the loaded module.
|
||||
void *base;
|
||||
|
||||
// Name of the nearest symbol.
|
||||
const char *sym_name;
|
||||
|
||||
// Address of the nearest symbol.
|
||||
void *sym_addr;
|
||||
|
||||
~_Jv_AddrInfo (void)
|
||||
{
|
||||
// On systems with a real dladdr(), the file and symbol names given by
|
||||
// _Jv_platform_dladdr() are not dynamically allocated. On Windows,
|
||||
// they are.
|
||||
|
||||
#ifdef WIN32
|
||||
if (file_name)
|
||||
free ((void *)file_name);
|
||||
|
||||
if (sym_name)
|
||||
free ((void *)sym_name);
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __JV_STACKTRACE_H__ */
|
||||
|
@ -194,4 +194,11 @@ _Jv_pipe (int filedes[2])
|
||||
return ::pipe (filedes);
|
||||
}
|
||||
|
||||
// Forward declaration. See java-stack.h for definition.
|
||||
struct _Jv_AddrInfo;
|
||||
|
||||
// Given an address, determine the executable or shared object that defines
|
||||
// it and the nearest named symbol.
|
||||
extern int _Jv_platform_dladdr (const void *addr, _Jv_AddrInfo *info);
|
||||
|
||||
#endif /* __JV_POSIX_H__ */
|
||||
|
@ -11,7 +11,7 @@ details. */
|
||||
#ifndef __JV_WIN32_H__
|
||||
#define __JV_WIN32_H__
|
||||
|
||||
// Enable UNICODE Support.?
|
||||
// Enable UNICODE support?
|
||||
|
||||
#ifdef MINGW_LIBGCJ_UNICODE
|
||||
#define UNICODE
|
||||
@ -175,8 +175,11 @@ _Jv_platform_usleep (unsigned long usecs)
|
||||
}
|
||||
#endif /* JV_HASH_SYNCHRONIZATION */
|
||||
|
||||
/* Store up to SIZE return address of the current program state in
|
||||
ARRAY and return the exact number of values stored. */
|
||||
extern int backtrace (void **__array, int __size);
|
||||
// Forward declaration. See java-stack.h for definition.
|
||||
struct _Jv_AddrInfo;
|
||||
|
||||
// Given an address, determine the executable or shared object that defines
|
||||
// it and the nearest named symbol.
|
||||
extern int _Jv_platform_dladdr (const void *addr, _Jv_AddrInfo *info);
|
||||
|
||||
#endif /* __JV_WIN32_H__ */
|
||||
|
@ -17,7 +17,12 @@ details. */
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <jvm.h>
|
||||
#include <java-stack.h>
|
||||
#include <java/lang/Thread.h>
|
||||
#include <java/io/InterruptedIOException.h>
|
||||
#include <java/util/Properties.h>
|
||||
@ -203,3 +208,31 @@ _Jv_select (int n, fd_set *readfds, fd_set *writefds,
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Given an address, find the object that defines it and the nearest
|
||||
// defined symbol to that address. Returns 0 if no object defines this
|
||||
// address.
|
||||
int
|
||||
_Jv_platform_dladdr (const void *addr, _Jv_AddrInfo *info)
|
||||
{
|
||||
int ret_val = 0;
|
||||
|
||||
#if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
|
||||
Dl_info addr_info;
|
||||
ret_val = dladdr (addr, &addr_info);
|
||||
if (ret_val != 0)
|
||||
{
|
||||
info->file_name = addr_info.dli_fname;
|
||||
info->base = addr_info.dli_fbase;
|
||||
info->sym_name = addr_info.dli_sname;
|
||||
info->sym_addr = addr_info.dli_saddr;
|
||||
}
|
||||
#else
|
||||
info->file_name = NULL;
|
||||
info->base = NULL;
|
||||
info->sym_name = NULL;
|
||||
info->sym_addr = NULL;
|
||||
#endif
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
@ -9,16 +9,13 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include <config.h>
|
||||
#include <platform.h>
|
||||
|
||||
#include <jvm.h>
|
||||
#include <gcj/cni.h>
|
||||
#include <java-interp.h>
|
||||
#include <java-stack.h>
|
||||
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <java/lang/Class.h>
|
||||
@ -184,41 +181,36 @@ _Jv_StackTrace::getLineNumberForFrame(_Jv_StackFrame *frame, NameFinder *finder,
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// Use dladdr() to determine in which binary the address IP resides.
|
||||
#if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
|
||||
Dl_info info;
|
||||
|
||||
// Use _Jv_platform_dladdr() to determine in which binary the address IP
|
||||
// resides.
|
||||
_Jv_AddrInfo info;
|
||||
jstring binaryName = NULL;
|
||||
const char *argv0 = _Jv_GetSafeArg(0);
|
||||
|
||||
void *ip = frame->ip;
|
||||
_Unwind_Ptr offset = 0;
|
||||
|
||||
if (dladdr (ip, &info))
|
||||
if (_Jv_platform_dladdr (ip, &info))
|
||||
{
|
||||
if (info.dli_fname)
|
||||
binaryName = JvNewStringUTF (info.dli_fname);
|
||||
if (info.file_name)
|
||||
binaryName = JvNewStringUTF (info.file_name);
|
||||
else
|
||||
return;
|
||||
|
||||
if (*methodName == NULL && info.dli_sname)
|
||||
*methodName = JvNewStringUTF (info.dli_sname);
|
||||
if (*methodName == NULL && info.sym_name)
|
||||
*methodName = JvNewStringUTF (info.sym_name);
|
||||
|
||||
// addr2line expects relative addresses for shared libraries.
|
||||
if (strcmp (info.dli_fname, argv0) == 0)
|
||||
if (strcmp (info.file_name, argv0) == 0)
|
||||
offset = (_Unwind_Ptr) ip;
|
||||
else
|
||||
offset = (_Unwind_Ptr) ip - (_Unwind_Ptr) info.dli_fbase;
|
||||
offset = (_Unwind_Ptr) ip - (_Unwind_Ptr) info.base;
|
||||
|
||||
//printf ("linenum ip: %p\n", ip);
|
||||
//printf ("%s: 0x%x\n", info.dli_fname, offset);
|
||||
//offset -= sizeof(void *);
|
||||
|
||||
// The unwinder gives us the return address. In order to get the right
|
||||
// line number for the stack trace, roll it back a little.
|
||||
offset -= 1;
|
||||
|
||||
// printf ("%s: 0x%x\n", info.dli_fname, offset);
|
||||
|
||||
finder->lookup (binaryName, (jlong) offset);
|
||||
*sourceFileName = finder->getSourceFile();
|
||||
*lineNum = finder->getLineNum();
|
||||
@ -234,7 +226,6 @@ _Jv_StackTrace::getLineNumberForFrame(_Jv_StackFrame *frame, NameFinder *finder,
|
||||
*sourceFileName = t->toString();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Look up class and method info for the given stack frame, setting
|
||||
@ -283,7 +274,7 @@ _Jv_StackTrace::GetStackTraceElements (_Jv_StackTrace *trace,
|
||||
{
|
||||
ArrayList *list = new ArrayList ();
|
||||
|
||||
#ifdef SJLJ_EXCEPTIONS
|
||||
#if defined (SJLJ_EXCEPTIONS) && ! defined (WIN32)
|
||||
// We can't use the nCodeMap without unwinder support. Instead,
|
||||
// fake the method name by giving the IP in hex - better than nothing.
|
||||
jstring hex = JvNewStringUTF ("0x");
|
||||
@ -302,7 +293,7 @@ _Jv_StackTrace::GetStackTraceElements (_Jv_StackTrace *trace,
|
||||
list->add (element);
|
||||
}
|
||||
|
||||
#else /* SJLJ_EXCEPTIONS */
|
||||
#else /* SJLJ_EXCEPTIONS && !WIN32 */
|
||||
|
||||
//JvSynchronized (ncodeMap);
|
||||
UpdateNCodeMap ();
|
||||
@ -370,7 +361,7 @@ _Jv_StackTrace::GetStackTraceElements (_Jv_StackTrace *trace,
|
||||
}
|
||||
|
||||
finder->close();
|
||||
#endif /* SJLJ_EXCEPTIONS */
|
||||
#endif /* SJLJ_EXCEPTIONS && !WIN32 */
|
||||
|
||||
JArray<Object *> *array = JvNewObjectArray (list->size (),
|
||||
&StackTraceElement::class$, NULL);
|
||||
@ -472,7 +463,13 @@ _Jv_StackTrace::GetClassContext (jclass checkClass)
|
||||
//JvSynchronized (ncodeMap);
|
||||
UpdateNCodeMap ();
|
||||
|
||||
#ifdef SJLJ_EXCEPTIONS
|
||||
// The Unwind interface doesn't work with the SJLJ exception model.
|
||||
// Fall back to a platform-specific unwinder.
|
||||
fallback_backtrace (&state);
|
||||
#else /* SJLJ_EXCEPTIONS */
|
||||
_Unwind_Backtrace (UnwindTraceFn, &state);
|
||||
#endif /* SJLJ_EXCEPTIONS */
|
||||
|
||||
// Count the number of Java frames on the stack.
|
||||
int jframe_count = 0;
|
||||
@ -543,7 +540,13 @@ _Jv_StackTrace::GetFirstNonSystemClassLoader ()
|
||||
//JvSynchronized (ncodeMap);
|
||||
UpdateNCodeMap ();
|
||||
|
||||
#ifdef SJLJ_EXCEPTIONS
|
||||
// The Unwind interface doesn't work with the SJLJ exception model.
|
||||
// Fall back to a platform-specific unwinder.
|
||||
fallback_backtrace (&state);
|
||||
#else /* SJLJ_EXCEPTIONS */
|
||||
_Unwind_Backtrace (UnwindTraceFn, &state);
|
||||
#endif /* SJLJ_EXCEPTIONS */
|
||||
|
||||
if (state.trace_data)
|
||||
return (ClassLoader *) state.trace_data;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// backtrace.h - Fallback backtrace implementation. i386 implementation.
|
||||
|
||||
/* Copyright (C) 2005 Free Software Foundation
|
||||
/* Copyright (C) 2005, 2006 Free Software Foundation
|
||||
|
||||
This file is part of libgcj.
|
||||
|
||||
@ -22,19 +22,44 @@ fallback_backtrace (_Jv_UnwindState *state)
|
||||
{
|
||||
register void *_ebp __asm__ ("ebp");
|
||||
register void *_esp __asm__ ("esp");
|
||||
unsigned int *rfp;
|
||||
_Jv_uintptr_t *rfp;
|
||||
|
||||
int i = state->pos;
|
||||
for (rfp = *(unsigned int**)_ebp;
|
||||
for (rfp = *(_Jv_uintptr_t **)_ebp;
|
||||
rfp && i < state->length;
|
||||
rfp = *(unsigned int **)rfp)
|
||||
rfp = *(_Jv_uintptr_t **)rfp)
|
||||
{
|
||||
int diff = *rfp - (unsigned int)rfp;
|
||||
if ((void*)rfp < _esp || diff > 4 * 1024 || diff < 0)
|
||||
/* Sanity checks to eliminate dubious-looking frame pointer chains.
|
||||
The frame pointer should be a 32-bit word-aligned stack address.
|
||||
Since the stack grows downwards on x86, the frame pointer must have
|
||||
a value greater than the current value of the stack pointer, it
|
||||
should not be below the supposed next frame pointer and it should
|
||||
not be too far off from the supposed next frame pointer. */
|
||||
int diff = *rfp - (_Jv_uintptr_t)rfp;
|
||||
if (((_Jv_uintptr_t)rfp & 0x00000003) != 0 || (void*)rfp < _esp
|
||||
|| diff > 4 * 1024 || diff < 0)
|
||||
break;
|
||||
|
||||
/* Use the return address in the calling function stored just before
|
||||
the current frame pointer to locate the address operand part of the
|
||||
"CALL <XYZ>" instruction in the calling function that called this
|
||||
function. */
|
||||
void *ip = (void*)(rfp[1] - 4);
|
||||
|
||||
/* Verify that the instruction at this position is a "CALL <XYZ>" and
|
||||
use its operand to determine the starting address of the function
|
||||
that this function had called. 0xE8 is the opcode for this CALL
|
||||
instruction variant. */
|
||||
if (*(unsigned char *)((_Jv_uintptr_t)ip - 1) == 0xE8 && i > state->pos
|
||||
&& state->frames[i-1].type == frame_native)
|
||||
{
|
||||
state->frames[i-1].start_ip
|
||||
= (void *)((_Jv_uintptr_t)ip + 4 + *(_Jv_uintptr_t *)ip);
|
||||
}
|
||||
|
||||
state->frames[i].type = frame_native;
|
||||
state->frames[i].ip = (void*)(rfp[1]-4);
|
||||
state->frames[i].ip = ip;
|
||||
|
||||
i++;
|
||||
}
|
||||
state->pos = i;
|
||||
|
@ -12,8 +12,11 @@ details. */
|
||||
#include <platform.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <java-stack.h>
|
||||
|
||||
#include <java/lang/ArithmeticException.h>
|
||||
#include <java/lang/UnsupportedOperationException.h>
|
||||
#include <java/io/IOException.h>
|
||||
@ -442,28 +445,6 @@ _Jv_platform_initProperties (java::util::Properties* newprops)
|
||||
}
|
||||
}
|
||||
|
||||
/* Store up to SIZE return address of the current program state in
|
||||
ARRAY and return the exact number of values stored. */
|
||||
int
|
||||
backtrace (void **__array, int __size)
|
||||
{
|
||||
register void *_ebp __asm__ ("ebp");
|
||||
register void *_esp __asm__ ("esp");
|
||||
unsigned int *rfp;
|
||||
|
||||
int i=0;
|
||||
for (rfp = *(unsigned int**)_ebp;
|
||||
rfp && i < __size;
|
||||
rfp = *(unsigned int **)rfp)
|
||||
{
|
||||
int diff = *rfp - (unsigned int)rfp;
|
||||
if ((void*)rfp < _esp || diff > 4 * 1024 || diff < 0) break;
|
||||
|
||||
__array[i++] = (void*)(rfp[1]-4);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
_Jv_pipe (int filedes[2])
|
||||
{
|
||||
@ -477,3 +458,42 @@ _Jv_platform_close_on_exec (HANDLE h)
|
||||
// no effect under Win9X.
|
||||
SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0);
|
||||
}
|
||||
|
||||
// Given an address, find the object that defines it and the nearest
|
||||
// defined symbol to that address. Returns 0 if no object defines this
|
||||
// address.
|
||||
int
|
||||
_Jv_platform_dladdr (const void *addr, _Jv_AddrInfo *info)
|
||||
{
|
||||
// Since we do not have dladdr() on Windows, we use a trick involving
|
||||
// VirtualQuery() to find the module (EXE or DLL) that contains a given
|
||||
// address. This was taken from Matt Pietrek's "Under the Hood" column
|
||||
// for the April 1997 issue of Microsoft Systems Journal.
|
||||
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
if (!VirtualQuery (addr, &mbi, sizeof (mbi)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
HMODULE hMod = (HMODULE) mbi.AllocationBase;
|
||||
|
||||
char moduleName[MAX_PATH];
|
||||
|
||||
// FIXME: We explicitly use the ANSI variant of the function here.
|
||||
if (!GetModuleFileNameA (hMod, moduleName, sizeof (moduleName)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *file_name = (char *)(malloc (strlen (moduleName) + 1));
|
||||
strcpy (file_name, moduleName);
|
||||
info->file_name = file_name;
|
||||
|
||||
// FIXME.
|
||||
info->base = NULL;
|
||||
info->sym_name = NULL;
|
||||
info->sym_addr = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user