1122715Sbde/* Header file for the ARM EABI unwinder
2122715Sbde   Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
3122715Sbde   Contributed by Paul Brook
4122715Sbde
5122715Sbde   This file is free software; you can redistribute it and/or modify it
685909Simp   under the terms of the GNU General Public License as published by the
788893Simp   Free Software Foundation; either version 2, or (at your option) any
888893Simp   later version.
988969Simp
1085909Simp   In addition to the permissions in the GNU General Public License, the
11115572Sphk   Free Software Foundation gives you unlimited permission to link the
12115572Sphk   compiled version of this file into combinations with other programs,
13115572Sphk   and to distribute those combinations without any restriction coming
14115572Sphk   from the use of this file.  (The General Public License restrictions
15124108Simp   do apply in other respects; for example, they cover modification of
16115572Sphk   the file, and distribution when not linked into a combine
17111211Sru   executable.)
1885909Simp
19111802Sru   This file is distributed in the hope that it will be useful, but
20111802Sru   WITHOUT ANY WARRANTY; without even the implied warranty of
21111211Sru   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22111211Sru   General Public License for more details.
23111211Sru
24111211Sru   You should have received a copy of the GNU General Public License
25111802Sru   along with this program; see the file COPYING.  If not, write to
26111802Sru   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27111211Sru   Boston, MA 02110-1301, USA.  */
28111211Sru
2985909Simp/* Language-independent unwinder header public defines.  This contains both
30137596Simp   ABI defined objects, and GNU support routines.  */
31147155Simp
32151732Sru#ifndef UNWIND_ARM_H
33137596Simp#define UNWIND_ARM_H
34147011Smux
35142424Simp#define __ARM_EABI_UNWINDER__ 1
36142413Simp
37137596Simp#ifdef __cplusplus
38147011Smuxextern "C" {
39137596Simp#endif
40137596Simp  typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
41137596Simp  typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
42137596Simp  typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
43111211Sru  typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__)));
44111211Sru  typedef _Unwind_Word _uw;
45111211Sru  typedef unsigned _uw64 __attribute__((mode(__DI__)));
46111211Sru  typedef unsigned _uw16 __attribute__((mode(__HI__)));
47155427Sru  typedef unsigned _uw8 __attribute__((mode(__QI__)));
48111802Sru
49111802Sru  typedef enum
50111766Sru    {
51111211Sru      _URC_OK = 0,       /* operation completed successfully */
52111766Sru      _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
53111766Sru      _URC_END_OF_STACK = 5,
54111211Sru      _URC_HANDLER_FOUND = 6,
55111211Sru      _URC_INSTALL_CONTEXT = 7,
56111211Sru      _URC_CONTINUE_UNWIND = 8,
57111211Sru      _URC_FAILURE = 9   /* unspecified failure of some kind */
58111211Sru    }
59111211Sru  _Unwind_Reason_Code;
60111211Sru
61111211Sru  typedef enum
62151636Simp    {
63151636Simp      _US_VIRTUAL_UNWIND_FRAME = 0,
64151636Simp      _US_UNWIND_FRAME_STARTING = 1,
65151636Simp      _US_UNWIND_FRAME_RESUME = 2,
66151750Sru      _US_ACTION_MASK = 3,
67151750Sru      _US_FORCE_UNWIND = 8,
68151731Sru      _US_END_OF_STACK = 16
69151750Sru    }
70151731Sru  _Unwind_State;
71151646Sru
72151646Sru  /* Provided only for for compatibility with existing code.  */
73116252Sgrog  typedef int _Unwind_Action;
74123965Sbde#define _UA_SEARCH_PHASE	1
75116252Sgrog#define _UA_CLEANUP_PHASE	2
76123965Sbde#define _UA_HANDLER_FRAME	4
77123965Sbde#define _UA_FORCE_UNWIND	8
78135611Sphk#define _UA_END_OF_STACK	16
79124776Sru#define _URC_NO_REASON 	_URC_OK
80116252Sgrog
81123965Sbde  typedef struct _Unwind_Control_Block _Unwind_Control_Block;
8285909Simp  typedef struct _Unwind_Context _Unwind_Context;
83124776Sru  typedef _uw _Unwind_EHT_Header;
8485909Simp
85151636Simp
8685909Simp  /* UCB: */
8785909Simp
8885909Simp  struct _Unwind_Control_Block
89125775Sru    {
90125775Sru      unsigned  exception_class __attribute__((__mode__(__DI__)));
91125775Sru      void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
9285909Simp      /* Unwinder cache, private fields for the unwinder's use */
93159560Scognet      struct
94159560Scognet	{
95159560Scognet	  _uw reserved1;  /* Forced unwind stop fn, 0 if not forced */
96159560Scognet	  _uw reserved2;  /* Personality routine address */
97159560Scognet	  _uw reserved3;  /* Saved callsite address */
98159560Scognet	  _uw reserved4;  /* Forced unwind stop arg */
99159560Scognet	  _uw reserved5;
100159560Scognet	}
101159560Scognet      unwinder_cache;
10285909Simp      /* Propagation barrier cache (valid after phase 1): */
103116691Sru      struct
104131129Simp	{
10585909Simp	  _uw sp;
10685909Simp	  _uw bitpattern[5];
107116341Smarkm	}
108116341Smarkm      barrier_cache;
10985909Simp      /* Cleanup cache (preserved over cleanup): */
110102082Sbde      struct
111102082Sbde	{
112102082Sbde	  _uw bitpattern[4];
113102082Sbde	}
11485909Simp      cleanup_cache;
11595844Sobrien      /* Pr cache (for pr's benefit): */
11685909Simp      struct
11785909Simp	{
11885909Simp	  _uw fnstart;			/* function start address */
11985909Simp	  _Unwind_EHT_Header *ehtp;	/* pointer to EHT entry header word */
120151750Sru	  _uw additional;		/* additional data */
121151731Sru	  _uw reserved1;
122145416Sru	}
123123965Sbde      pr_cache;
124163332Sru      long long int :0;	/* Force alignment to 8-byte boundary */
12585909Simp    };
126116341Smarkm
127123965Sbde  /* Virtual Register Set*/
128123965Sbde
12992491Smarkm  typedef enum
13085909Simp    {
13185909Simp      _UVRSC_CORE = 0,      /* integer register */
13285909Simp      _UVRSC_VFP = 1,       /* vfp */
13385909Simp      _UVRSC_FPA = 2,       /* fpa */
13485909Simp      _UVRSC_WMMXD = 3,     /* Intel WMMX data register */
135161283Sdes      _UVRSC_WMMXC = 4      /* Intel WMMX control register */
136123966Sbde    }
13785909Simp  _Unwind_VRS_RegClass;
13885909Simp
139123965Sbde  typedef enum
14085909Simp    {
14185909Simp      _UVRSD_UINT32 = 0,
14285909Simp      _UVRSD_VFPX = 1,
143127306Sobrien      _UVRSD_FPAX = 2,
14485909Simp      _UVRSD_UINT64 = 3,
14585909Simp      _UVRSD_FLOAT = 4,
146123985Sbde      _UVRSD_DOUBLE = 5
14785909Simp    }
14885909Simp  _Unwind_VRS_DataRepresentation;
14985909Simp
150145403Sru  typedef enum
151102073Sbde    {
15291104Sjake      _UVRSR_OK = 0,
153152964Sru      _UVRSR_NOT_IMPLEMENTED = 1,
154152964Sru      _UVRSR_FAILED = 2
155152964Sru    }
156163332Sru  _Unwind_VRS_Result;
15785909Simp
158131210Simp  /* Frame unwinding state.  */
159102073Sbde  typedef struct
160111684Sru    {
161102073Sbde      /* The current word (bytes packed msb first).  */
16285909Simp      _uw data;
16385909Simp      /* Pointer to the next word of data.  */
16485909Simp      _uw *next;
165152964Sru      /* The number of bytes left in this word.  */
166152964Sru      _uw8 bytes_left;
167152964Sru      /* The number of words pointed to by ptr.  */
168152964Sru      _uw8 words_left;
169152964Sru    }
170152964Sru  __gnu_unwind_state;
171152964Sru
172152964Sru  typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State,
173152964Sru      _Unwind_Control_Block *, _Unwind_Context *);
174152964Sru
175152964Sru  _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass,
176152964Sru                                     _uw, _Unwind_VRS_DataRepresentation,
177152964Sru                                     void *);
178152964Sru
179152964Sru  _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass,
180152964Sru                                     _uw, _Unwind_VRS_DataRepresentation,
181152964Sru                                     void *);
182152964Sru
183152964Sru  _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass,
184152964Sru                                     _uw, _Unwind_VRS_DataRepresentation);
185152964Sru
186152964Sru
187163332Sru  /* Support functions for the PR.  */
18885909Simp#define _Unwind_Exception _Unwind_Control_Block
189163332Sru  typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
19085909Simp
19185909Simp  void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
19285909Simp  _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
193123965Sbde
19491046Sluigi  /* These two should never be used.  */
195123965Sbde  _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *);
196123965Sbde  _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *);
19785909Simp
19885909Simp  /* Interface functions: */
19985909Simp  _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp);
20085909Simp  void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp);
20185909Simp  _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp);
20285909Simp
203127246Smarcel  typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
204151731Sru       (int, _Unwind_Action, _Unwind_Exception_Class,
20585909Simp	_Unwind_Control_Block *, struct _Unwind_Context *, void *);
20685909Simp  _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *,
20785909Simp					    _Unwind_Stop_Fn, void *);
20885909Simp  /* @@@ Use unwind data to perform a stack backtrace.  The trace callback
20985909Simp     is called for every stack frame in the call chain, but no cleanup
210145623Sru     actions are performed.  */
21185909Simp  typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (_Unwind_Context *, void *);
21285909Simp  _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn,
21385909Simp					void*);
21485909Simp
21585909Simp  _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
21685909Simp  void _Unwind_Complete(_Unwind_Control_Block *ucbp);
21785909Simp  void _Unwind_DeleteException (_Unwind_Exception *);
21885909Simp
219118633Sru  _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *,
22085909Simp					  _Unwind_Context *);
22185909Simp  _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *,
22285909Simp					    __gnu_unwind_state *);
223151731Sru
224151636Simp  /* Decode an R_ARM_TARGET2 relocation.  */
225151750Sru  static inline _Unwind_Word
226151636Simp  _Unwind_decode_target2 (_Unwind_Word ptr)
22785909Simp    {
22895356Sru      _Unwind_Word tmp;
22985909Simp
230151731Sru      tmp = *(_Unwind_Word *) ptr;
231151636Simp      /* Zero values are always NULL.  */
232151750Sru      if (!tmp)
233151636Simp	return 0;
23485909Simp
235144293Sphk#if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__)
23685909Simp      /* Pc-relative indirect.  */
23785909Simp      tmp += ptr;
238144293Sphk      tmp = *(_Unwind_Word *) tmp;
239116341Smarkm#elif defined(__symbian__)
240116341Smarkm      /* Absolute pointer.  Nothing more to do.  */
24185909Simp#else
242135371Sru      /* Pc-relative pointer.  */
24385909Simp      tmp += ptr;
24491512Sobrien#endif
24591512Sobrien      return tmp;
24685909Simp    }
24791512Sobrien
24891512Sobrien  static inline _Unwind_Word
249138290Sphk  _Unwind_GetGR (_Unwind_Context *context, int regno)
250138290Sphk    {
25185909Simp      _uw val;
252116691Sru      _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
253116691Sru      return val;
25485909Simp    }
255111686Sru
256#ifndef __FreeBSD__
257  /* Return the address of the instruction, not the actual IP value.  */
258#define _Unwind_GetIP(context) \
259  (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
260
261#define _Unwind_GetIPInfo(context, ip_before_insn) \
262  (*ip_before_insn = 0, _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
263#else
264  _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
265  _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
266#endif
267
268  static inline void
269  _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val)
270    {
271      _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
272    }
273
274  /* The dwarf unwinder doesn't understand arm/thumb state.  We assume the
275     landing pad uses the same instruction set as the call site.  */
276#define _Unwind_SetIP(context, val) \
277  _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1))
278
279#ifdef __cplusplus
280}   /* extern "C" */
281#endif
282
283#endif /* defined UNWIND_ARM_H */
284