libunwind_i.h revision 5d0f376b08126b51a001d7cdfba1ec4e0d644f54
1/* libunwind - a platform-independent unwind library
2   Copyright (C) 2001-2005 Hewlett-Packard Co
3	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5This file is part of libunwind.
6
7Permission is hereby granted, free of charge, to any person obtaining
8a copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sublicense, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice shall be
16included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25
26#ifndef IA64_LIBUNWIND_I_H
27#define IA64_LIBUNWIND_I_H
28
29/* Target-dependent definitions that are internal to libunwind but need
30   to be shared with target-independent code.  */
31
32#include "elf64.h"
33#include "mempool.h"
34
35typedef struct
36  {
37    /* no ia64-specific fast trace */
38  }
39unw_tdep_frame_t;
40
41enum ia64_pregnum
42  {
43    /* primary unat: */
44    IA64_REG_PRI_UNAT_GR,
45    IA64_REG_PRI_UNAT_MEM,
46
47    /* memory stack (order matters: see build_script() */
48    IA64_REG_PSP,			/* previous memory stack pointer */
49    /* register stack */
50    IA64_REG_BSP,			/* register stack pointer */
51    IA64_REG_BSPSTORE,
52    IA64_REG_PFS,			/* previous function state */
53    IA64_REG_RNAT,
54    /* instruction pointer: */
55    IA64_REG_IP,
56
57    /* preserved registers: */
58    IA64_REG_R4, IA64_REG_R5, IA64_REG_R6, IA64_REG_R7,
59    IA64_REG_NAT4, IA64_REG_NAT5, IA64_REG_NAT6, IA64_REG_NAT7,
60    IA64_REG_UNAT, IA64_REG_PR, IA64_REG_LC, IA64_REG_FPSR,
61    IA64_REG_B1, IA64_REG_B2, IA64_REG_B3, IA64_REG_B4, IA64_REG_B5,
62    IA64_REG_F2, IA64_REG_F3, IA64_REG_F4, IA64_REG_F5,
63    IA64_REG_F16, IA64_REG_F17, IA64_REG_F18, IA64_REG_F19,
64    IA64_REG_F20, IA64_REG_F21, IA64_REG_F22, IA64_REG_F23,
65    IA64_REG_F24, IA64_REG_F25, IA64_REG_F26, IA64_REG_F27,
66    IA64_REG_F28, IA64_REG_F29, IA64_REG_F30, IA64_REG_F31,
67    IA64_NUM_PREGS
68  };
69
70#ifdef UNW_LOCAL_ONLY
71
72typedef unw_word_t ia64_loc_t;
73
74#else /* !UNW_LOCAL_ONLY */
75
76typedef struct ia64_loc
77  {
78    unw_word_t w0, w1;
79  }
80ia64_loc_t;
81
82#endif /* !UNW_LOCAL_ONLY */
83
84#include "script.h"
85
86#define ABI_UNKNOWN			0
87#define ABI_LINUX			1
88#define ABI_HPUX			2
89#define ABI_FREEBSD			3
90#define ABI_OPENVMS			4
91#define ABI_NSK				5	/* Tandem/HP Non-Stop Kernel */
92#define ABI_WINDOWS			6
93
94struct unw_addr_space
95  {
96    struct unw_accessors acc;
97    int big_endian;
98    int abi;	/* abi < 0 => unknown, 0 => SysV, 1 => HP-UX, 2 => Windows */
99    unw_caching_policy_t caching_policy;
100#ifdef HAVE_ATOMIC_OPS_H
101    AO_t cache_generation;
102#else
103    uint32_t cache_generation;
104#endif
105    unw_word_t dyn_generation;
106    unw_word_t dyn_info_list_addr;	/* (cached) dyn_info_list_addr */
107#ifndef UNW_REMOTE_ONLY
108    unsigned long long shared_object_removals;
109#endif
110
111    struct ia64_script_cache global_cache;
112   };
113
114/* Note: The ABI numbers in the ABI-markers (.unwabi directive) are
115   not the same as the above ABI numbers.  */
116#define ABI_MARKER_OLD_LINUX_SIGTRAMP	((0 << 8) | 's')
117#define ABI_MARKER_OLD_LINUX_INTERRUPT	((0 << 8) | 'i')
118#define ABI_MARKER_HP_UX_SIGTRAMP	((1 << 8) | 1)
119#define ABI_MARKER_LINUX_SIGTRAMP	((3 << 8) | 's')
120#define ABI_MARKER_LINUX_INTERRUPT	((3 << 8) | 'i')
121
122struct cursor
123  {
124    void *as_arg;		/* argument to address-space callbacks */
125    unw_addr_space_t as;	/* reference to per-address-space info */
126
127    /* IP, CFM, and predicate cache (these are always equal to the
128       values stored in ip_loc, cfm_loc, and pr_loc,
129       respectively).  */
130    unw_word_t ip;		/* instruction pointer value */
131    unw_word_t cfm;		/* current frame mask */
132    unw_word_t pr;		/* current predicate values */
133
134    /* current frame info: */
135    unw_word_t bsp;		/* backing store pointer value */
136    unw_word_t sp;		/* stack pointer value */
137    unw_word_t psp;		/* previous sp value */
138    ia64_loc_t cfm_loc;		/* cfm save location (or NULL) */
139    ia64_loc_t ec_loc;		/* ar.ec save location (usually cfm_loc) */
140    ia64_loc_t loc[IA64_NUM_PREGS];
141
142    unw_word_t eh_args[4];	/* exception handler arguments */
143    unw_word_t sigcontext_addr;	/* address of sigcontext or 0 */
144    unw_word_t sigcontext_off;	/* sigcontext-offset relative to signal sp */
145
146    short hint;
147    short prev_script;
148
149    uint8_t nat_bitnr[4];	/* NaT bit numbers for r4-r7 */
150    uint16_t abi_marker;	/* abi_marker for current frame (if any) */
151    uint16_t last_abi_marker;	/* last abi_marker encountered so far */
152    uint8_t eh_valid_mask;
153
154    unsigned int pi_valid :1;		/* is proc_info valid? */
155    unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
156    unw_proc_info_t pi;		/* info about current procedure */
157
158    /* In case of stack-discontiguities, such as those introduced by
159       signal-delivery on an alternate signal-stack (see
160       sigaltstack(2)), we use the following data-structure to keep
161       track of the register-backing-store areas across on which the
162       current frame may be backed up.  Since there are at most 96
163       stacked registers and since we only have to track the current
164       frame and only areas that are not empty, this puts an upper
165       limit on the # of backing-store areas we have to track.
166
167       Note that the rbs-area indexed by rbs_curr identifies the
168       rbs-area that was in effect at the time AR.BSP had the value
169       c->bsp.  However, this rbs area may not actually contain the
170       value in the register that c->bsp corresponds to because that
171       register may not have gotten spilled until much later, when a
172       possibly different rbs-area might have been in effect
173       already.  */
174    uint8_t rbs_curr;		/* index of curr. rbs-area (contains c->bsp) */
175    uint8_t rbs_left_edge;	/* index of inner-most valid rbs-area */
176    struct rbs_area
177      {
178	unw_word_t end;
179	unw_word_t size;
180	ia64_loc_t rnat_loc;
181      }
182    rbs_area[96 + 2];	/* 96 stacked regs + 1 extra stack on each side... */
183};
184
185struct ia64_global_unwind_state
186  {
187    pthread_mutex_t lock;		/* global data lock */
188
189    volatile char init_done;
190
191    /* Table of registers that prologues can save (and order in which
192       they're saved).  */
193    const unsigned char save_order[8];
194
195    /*
196     * uc_addr() may return pointers to these variables.  We need to
197     * make sure they don't get written via ia64_put() or
198     * ia64_putfp().  To make it possible to test for these variables
199     * quickly, we collect them in a single sub-structure.
200     */
201    struct
202      {
203	unw_word_t  r0;			/* r0 is byte-order neutral */
204	unw_fpreg_t f0;			/* f0 is byte-order neutral */
205	unw_fpreg_t f1_le, f1_be;	/* f1 is byte-order dependent */
206      }
207    read_only;
208    unw_fpreg_t nat_val_le, nat_val_be;
209    unw_fpreg_t int_val_le, int_val_be;
210
211    struct mempool reg_state_pool;
212    struct mempool labeled_state_pool;
213
214# if UNW_DEBUG
215    const char *preg_name[IA64_NUM_PREGS];
216# endif
217  };
218
219#define tdep_getcontext_trace           unw_getcontext
220#define tdep_init_done			unw.init_done
221#define tdep_init			UNW_OBJ(init)
222/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
223   tdep_search_unwind_table.  */
224#define tdep_search_unwind_table	unw_search_ia64_unwind_table
225#define tdep_find_unwind_table	ia64_find_unwind_table
226#define tdep_find_proc_info		UNW_OBJ(find_proc_info)
227#define tdep_uc_addr			UNW_OBJ(uc_addr)
228#define tdep_get_elf_image		UNW_ARCH_OBJ(get_elf_image)
229#define tdep_access_reg			UNW_OBJ(access_reg)
230#define tdep_access_fpreg		UNW_OBJ(access_fpreg)
231#define tdep_fetch_frame(c,ip,n)	do {} while(0)
232#define tdep_cache_frame(c,rs)		do {} while(0)
233#define tdep_reuse_frame(c,rs)		do {} while(0)
234#define tdep_stash_frame(c,rs)		do {} while(0)
235#define tdep_trace(cur,addr,n)		(-UNW_ENOINFO)
236#define tdep_get_as(c)			((c)->as)
237#define tdep_get_as_arg(c)		((c)->as_arg)
238#define tdep_get_ip(c)			((c)->ip)
239#define tdep_big_endian(as)		((c)->as->big_endian != 0)
240
241#ifndef UNW_LOCAL_ONLY
242# define tdep_put_unwind_info		UNW_OBJ(put_unwind_info)
243#endif
244
245/* This can't be an UNW_ARCH_OBJ() because we need separate
246   unw.initialized flags for the local-only and generic versions of
247   the library.  Also, if we wanted to have a single, shared global
248   data structure, we couldn't declare "unw" as HIDDEN/PROTECTED.  */
249#define unw				UNW_OBJ(data)
250
251extern void tdep_init (void);
252extern int tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip,
253				unw_proc_info_t *pi, int need_unwind_info,
254				void *arg);
255extern void tdep_put_unwind_info (unw_addr_space_t as,
256				  unw_proc_info_t *pi, void *arg);
257extern void *tdep_uc_addr (ucontext_t *uc, unw_regnum_t regnum,
258			   uint8_t *nat_bitnr);
259extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
260			       unsigned long *segbase, unsigned long *mapoff,
261			       char *path, size_t pathlen);
262extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
263			    unw_word_t *valp, int write);
264extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
265			      unw_fpreg_t *valp, int write);
266
267extern struct ia64_global_unwind_state unw;
268
269/* In user-level, we have no reasonable way of determining the base of
270   an arbitrary backing-store.  We default to half the
271   address-space.  */
272#define rbs_get_base(c,bspstore,rbs_basep)				\
273	(*(rbs_basep) = (bspstore) - (((unw_word_t) 1) << 63), 0)
274
275#endif /* IA64_LIBUNWIND_I_H */
276