aboutsummaryrefslogtreecommitdiff
path: root/gcc/unwind-libunwind.c
blob: 89e841759cf9013309f77e437c5bb290a62971ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/* Subroutines needed for unwinding stack frames via the libunwind API.
   Copyright (C) 2002, 2003
   Free Software Foundation, Inc.
   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>

   This file is part of GCC.

   GCC is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   GCC is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GCC; see the file COPYING.  If not, write to
   the Free Software Foundation, 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

/* As a special exception, if you link this library with other files,
   some of which are compiled with GCC, to produce an executable,
   this library does not by itself cause the resulting executable
   to be covered by the GNU General Public License.
   This exception does not however invalidate any other reasons why
   the executable file might be covered by the GNU General Public License.  */

#include "tconfig.h"
#include "tsystem.h"
#include "unwind.h"

#ifndef __USING_SJLJ_EXCEPTIONS__

#define UNW_LOCAL_ONLY

#include <libunwind.h>

typedef struct {
  _Unwind_Personality_Fn personality;
} _Unwind_FrameState;

struct _Unwind_Context {
  unw_cursor_t cursor;
};


/* First come the helper-routines that are needed by unwind.inc.  */

static _Unwind_Reason_Code
uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
  unw_proc_info_t pi;

  if (unw_step (&context->cursor) <= 0)
    return _URC_END_OF_STACK;

  unw_get_proc_info(&context->cursor, &pi);
  fs->personality = (_Unwind_Personality_Fn) pi.handler;

  return _URC_NO_REASON;
}

#define uw_update_context(context,fs)	do { ; } while (0)

static inline _Unwind_Ptr
uw_identify_context (struct _Unwind_Context *context)
{
  unw_word_t ip;
  unw_get_reg (&context->cursor, UNW_REG_IP, &ip);
  return (_Unwind_Ptr) ip;
}

#define uw_init_context(context)		\
do						\
  {						\
    unw_context_t uc;				\
    unw_getcontext (&uc);			\
    unw_init_local (&(context)->cursor, &uc);	\
  }						\
while (0)

static inline void __attribute__ ((noreturn))
uw_install_context (struct _Unwind_Context *current __attribute__ ((unused)),
		    struct _Unwind_Context *target)
{
  unw_resume (&(target)->cursor);
  abort ();
}


/* Now come the helper-routines which may be called from an exception
   handler.  The interface for these routines are defined by the C++
   ABI.  See: http://www.codesourcery.com/cxx-abi/abi-eh.html */

_Unwind_Word
_Unwind_GetGR (struct _Unwind_Context *context, int index)
{
  unw_word_t ret;

  /* Note: here we depend on the fact that general registers are
     expected to start with register number 0!  */
  unw_get_reg (&context->cursor, index, &ret);
  return ret;
}

/* Get the value of the CFA as saved in CONTEXT.  */

_Unwind_Word
_Unwind_GetCFA (struct _Unwind_Context *context)
{
  unw_word_t ret;

  unw_get_reg (&context->cursor, UNW_IA64_SP, &ret);
  return ret;
}

/* Overwrite the saved value for register REG in CONTEXT with VAL.  */

void
_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
{
  /* Note: here we depend on the fact that general registers are
     expected to start with register number 0!  */
  unw_set_reg (&context->cursor, index, val);
}

/* Retrieve the return address for CONTEXT.  */

inline _Unwind_Ptr
_Unwind_GetIP (struct _Unwind_Context *context)
{
  unw_word_t ret;

  unw_get_reg (&context->cursor, UNW_REG_IP, &ret);
  return ret;
}

/* Overwrite the return address for CONTEXT with VAL.  */

inline void
_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
{
  unw_set_reg (&context->cursor, UNW_REG_IP, val);
}

void *
_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
{
  unw_proc_info_t pi;

  unw_get_proc_info(&context->cursor, &pi);
  return (void *) pi.lsda;
}

_Unwind_Ptr
_Unwind_GetRegionStart (struct _Unwind_Context *context)
{
  unw_proc_info_t pi;

  unw_get_proc_info(&context->cursor, &pi);
  return (_Unwind_Ptr) pi.start_ip;
}

void *
_Unwind_FindEnclosingFunction (void *pc)
{
  return NULL;
}

#ifdef UNW_TARGET_IA64

_Unwind_Word
_Unwind_GetBSP (struct _Unwind_Context *context)
{
  unw_word_t ret;

  unw_get_reg (&context->cursor, UNW_IA64_BSP, &ret);
  return ret;
}

#endif

#include "unwind.inc"

#endif /* !__USING_SJLJ_EXCEPTIONS__ */