mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-13 22:03:43 +08:00
backtrace.h (fallback_backtrace): Scan for a function's prologue to determine its beginning.
* sysdep/i386/backtrace.h (fallback_backtrace): Scan for a function's prologue to determine its beginning. Stop unwinding when we reach JvRunMain(). From-SVN: r115261
This commit is contained in:
parent
11de7ef20e
commit
c6d0959c4b
@ -1,3 +1,9 @@
|
||||
2006-07-07 Ranjit Mathew <rmathew@gcc.gnu.org>
|
||||
|
||||
* sysdep/i386/backtrace.h (fallback_backtrace): Scan for a function's
|
||||
prologue to determine its beginning. Stop unwinding when we reach
|
||||
JvRunMain().
|
||||
|
||||
2006-07-07 Gary Benson <gbenson@redhat.com>
|
||||
|
||||
* Makefile.am (BOOT_CLASS_PATH_DIR): Only contain libgcj.jar.
|
||||
|
@ -20,14 +20,14 @@ details. */
|
||||
void
|
||||
fallback_backtrace (_Jv_UnwindState *state)
|
||||
{
|
||||
register void *_ebp __asm__ ("ebp");
|
||||
register void *_esp __asm__ ("esp");
|
||||
_Jv_uintptr_t *rfp;
|
||||
register _Jv_uintptr_t *_ebp __asm__ ("ebp");
|
||||
register _Jv_uintptr_t _esp __asm__ ("esp");
|
||||
_Jv_uintptr_t rfp;
|
||||
|
||||
int i = state->pos;
|
||||
for (rfp = *(_Jv_uintptr_t **)_ebp;
|
||||
for (rfp = *_ebp;
|
||||
rfp && i < state->length;
|
||||
rfp = *(_Jv_uintptr_t **)rfp)
|
||||
rfp = *(_Jv_uintptr_t *)rfp)
|
||||
{
|
||||
/* Sanity checks to eliminate dubious-looking frame pointer chains.
|
||||
The frame pointer should be a 32-bit word-aligned stack address.
|
||||
@ -35,30 +35,44 @@ fallback_backtrace (_Jv_UnwindState *state)
|
||||
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
|
||||
int diff = *(_Jv_uintptr_t *)rfp - rfp;
|
||||
if ((rfp & 0x00000003) != 0 || 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);
|
||||
}
|
||||
/* Get the return address in the calling function. This is stored on
|
||||
the stack just before the value of the old frame pointer. */
|
||||
_Jv_uintptr_t ret_addr
|
||||
= *(_Jv_uintptr_t *)(rfp + sizeof (_Jv_uintptr_t));
|
||||
|
||||
state->frames[i].type = frame_native;
|
||||
state->frames[i].ip = ip;
|
||||
state->frames[i].ip = (void *)(ret_addr - 1);
|
||||
state->frames[i].start_ip = NULL;
|
||||
|
||||
/* Try to locate a "pushl %ebp; movl %esp, %ebp" function prologue
|
||||
by scanning backwards at even addresses below the return address.
|
||||
This instruction sequence is encoded as 0x55 0x89 0xE5. We give up
|
||||
if we do not find this sequence even after scanning 1024K of memory.
|
||||
FIXME: This is not robust and will probably give us false positives,
|
||||
but this is about the best we can do if we do not have DWARF-2 unwind
|
||||
information based exception handling. */
|
||||
_Jv_uintptr_t scan_addr = (ret_addr & 0xFFFFFFFE) - 2;
|
||||
_Jv_uintptr_t limit_addr
|
||||
= (scan_addr > 1024 * 1024) ? (scan_addr - 1024 * 1024) : 2;
|
||||
for ( ; scan_addr >= limit_addr; scan_addr -= 2)
|
||||
{
|
||||
unsigned char *scan_bytes = (unsigned char *)scan_addr;
|
||||
if (scan_bytes[0] == 0x55 && scan_bytes[1] == 0x89
|
||||
&& scan_bytes[2] == 0xE5)
|
||||
{
|
||||
state->frames[i].start_ip = (void *)scan_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No need to unwind beyond JvRunMain(). */
|
||||
if (state->frames[i].start_ip == (void *)JvRunMain)
|
||||
break;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user