]> git.ipfire.org Git - thirdparty/gcc.git/blame - libjava/sysdep/i386/backtrace.h
cygming.h (TARGET_USE_JCR_SECTION): Enable.
[thirdparty/gcc.git] / libjava / sysdep / i386 / backtrace.h
CommitLineData
18744d9b
BM
1// backtrace.h - Fallback backtrace implementation. i386 implementation.
2
33792684 3/* Copyright (C) 2005, 2006 Free Software Foundation
18744d9b
BM
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11#ifndef __SYSDEP_BACKTRACE_H__
12#define __SYSDEP_BACKTRACE_H__
13
14#include <java-stack.h>
15
6a92b6c7
DK
16#ifdef __CYGWIN__
17/* To allow this to link as a DLL. */
18#define MAIN_FUNC dll_crt0__FP11per_process
19extern "C" int MAIN_FUNC () __declspec(dllimport);
20#else /* !__CYGWIN__ */
21#define MAIN_FUNC main
22extern int MAIN_FUNC (int, char **);
23#endif /* ?__CYGWIN__ */
18744d9b 24
38b19a92
RM
25/* The context used to keep track of our position while unwinding through
26 the call stack. */
27struct _Unwind_Context
28{
29 /* The starting address of the method. */
30 _Jv_uintptr_t meth_addr;
31
32 /* The return address in the method. */
33 _Jv_uintptr_t ret_addr;
34};
35
36#ifdef SJLJ_EXCEPTIONS
37
38#undef _Unwind_GetIPInfo
39#define _Unwind_GetIPInfo(ctx,ip_before_insn) \
40 (*(ip_before_insn) = 1, (ctx)->ret_addr)
41
42#undef _Unwind_GetRegionStart
43#define _Unwind_GetRegionStart(ctx) \
44 ((ctx)->meth_addr)
45
46#undef _Unwind_Backtrace
47#define _Unwind_Backtrace(trace_fn,state_ptr) \
48 (fallback_backtrace (trace_fn, state_ptr))
49
50#endif /* SJLJ_EXCEPTIONS */
51
52/* Unwind through the call stack calling TRACE_FN with STATE for each stack
53 frame. Returns the reason why the unwinding was stopped. */
54_Unwind_Reason_Code
55fallback_backtrace (_Unwind_Trace_Fn trace_fn, _Jv_UnwindState *state)
18744d9b 56{
c6d0959c
RM
57 register _Jv_uintptr_t *_ebp __asm__ ("ebp");
58 register _Jv_uintptr_t _esp __asm__ ("esp");
59 _Jv_uintptr_t rfp;
38b19a92 60 _Unwind_Context ctx;
18744d9b 61
38b19a92 62 for (rfp = *_ebp; rfp; rfp = *(_Jv_uintptr_t *)rfp)
18744d9b 63 {
33792684
RM
64 /* Sanity checks to eliminate dubious-looking frame pointer chains.
65 The frame pointer should be a 32-bit word-aligned stack address.
66 Since the stack grows downwards on x86, the frame pointer must have
67 a value greater than the current value of the stack pointer, it
68 should not be below the supposed next frame pointer and it should
69 not be too far off from the supposed next frame pointer. */
c6d0959c
RM
70 int diff = *(_Jv_uintptr_t *)rfp - rfp;
71 if ((rfp & 0x00000003) != 0 || rfp < _esp
33792684 72 || diff > 4 * 1024 || diff < 0)
18744d9b
BM
73 break;
74
c6d0959c
RM
75 /* Get the return address in the calling function. This is stored on
76 the stack just before the value of the old frame pointer. */
38b19a92 77 ctx.ret_addr = *(_Jv_uintptr_t *)(rfp + sizeof (_Jv_uintptr_t));
c6d0959c
RM
78
79 /* Try to locate a "pushl %ebp; movl %esp, %ebp" function prologue
80 by scanning backwards at even addresses below the return address.
d58b0443
RM
81 This instruction sequence is encoded either as 0x55 0x89 0xE5 or as
82 0x55 0x8B 0xEC. We give up if we do not find this sequence even
83 after scanning 1024K of memory.
c6d0959c
RM
84 FIXME: This is not robust and will probably give us false positives,
85 but this is about the best we can do if we do not have DWARF-2 unwind
86 information based exception handling. */
38b19a92
RM
87 ctx.meth_addr = (_Jv_uintptr_t)NULL;
88 _Jv_uintptr_t scan_addr = (ctx.ret_addr & 0xFFFFFFFE) - 2;
c6d0959c
RM
89 _Jv_uintptr_t limit_addr
90 = (scan_addr > 1024 * 1024) ? (scan_addr - 1024 * 1024) : 2;
91 for ( ; scan_addr >= limit_addr; scan_addr -= 2)
33792684 92 {
c6d0959c 93 unsigned char *scan_bytes = (unsigned char *)scan_addr;
d58b0443
RM
94 if (scan_bytes[0] == 0x55
95 && ((scan_bytes[1] == 0x89 && scan_bytes[2] == 0xE5)
96 || (scan_bytes[1] == 0x8B && scan_bytes[2] == 0xEC)))
c6d0959c 97 {
38b19a92 98 ctx.meth_addr = scan_addr;
c6d0959c
RM
99 break;
100 }
33792684
RM
101 }
102
38b19a92
RM
103 /* Now call the unwinder callback function. */
104 if (trace_fn != NULL)
105 (*trace_fn) (&ctx, state);
33792684 106
38b19a92
RM
107 /* No need to unwind beyond _Jv_RunMain(), _Jv_ThreadStart or
108 main(). */
109 void *jv_runmain
110 = (void *)(void (*)(JvVMInitArgs *, jclass, const char *, int,
111 const char **, bool))_Jv_RunMain;
112 if (ctx.meth_addr == (_Jv_uintptr_t)jv_runmain
113 || ctx.meth_addr == (_Jv_uintptr_t)_Jv_ThreadStart
6a92b6c7 114 || (ctx.meth_addr - (_Jv_uintptr_t)MAIN_FUNC) < 16)
38b19a92 115 break;
18744d9b 116 }
38b19a92
RM
117
118 return _URC_NO_REASON;
18744d9b
BM
119}
120#endif