summaryrefslogtreecommitdiff
path: root/libjava/sysdep
diff options
context:
space:
mode:
authorrmathew <rmathew@138bc75d-0d04-0410-961f-82ee72b054a4>2006-07-07 15:40:55 +0000
committerrmathew <rmathew@138bc75d-0d04-0410-961f-82ee72b054a4>2006-07-07 15:40:55 +0000
commitdffdaa2d109ca72205b7e509c5c89f90926a1717 (patch)
treecd5da0d97f30d4e4367bc650c3e8d8425bb458b1 /libjava/sysdep
parent94e58bad0ba224e5fbd97c293693d294f228a481 (diff)
downloadgcc-dffdaa2d109ca72205b7e509c5c89f90926a1717.tar.gz
* sysdep/i386/backtrace.h (fallback_backtrace): Scan for a function's
prologue to determine its beginning. Stop unwinding when we reach JvRunMain(). git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@115261 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/sysdep')
-rw-r--r--libjava/sysdep/i386/backtrace.h58
1 files changed, 36 insertions, 22 deletions
diff --git a/libjava/sysdep/i386/backtrace.h b/libjava/sysdep/i386/backtrace.h
index 8d46cbf1702..3b951634efb 100644
--- a/libjava/sysdep/i386/backtrace.h
+++ b/libjava/sysdep/i386/backtrace.h
@@ -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);
+ /* 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));
- /* 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].type = frame_native;
+ 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)
{
- state->frames[i-1].start_ip
- = (void *)((_Jv_uintptr_t)ip + 4 + *(_Jv_uintptr_t *)ip);
+ 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;
+ }
}
- state->frames[i].type = frame_native;
- state->frames[i].ip = ip;
+ /* No need to unwind beyond JvRunMain(). */
+ if (state->frames[i].start_ip == (void *)JvRunMain)
+ break;
i++;
}