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>
5 This file is part of libunwind.
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
26 #ifndef IA64_LIBUNWIND_I_H
27 #define IA64_LIBUNWIND_I_H
29 /* Target-dependent definitions that are internal to libunwind but need
30 to be shared with target-independent code. */
37 /* no ia64-specific fast trace */
45 IA64_REG_PRI_UNAT_MEM
,
47 /* memory stack (order matters: see build_script() */
48 IA64_REG_PSP
, /* previous memory stack pointer */
50 IA64_REG_BSP
, /* register stack pointer */
52 IA64_REG_PFS
, /* previous function state */
54 /* instruction pointer: */
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
,
72 typedef unw_word_t ia64_loc_t
;
74 #else /* !UNW_LOCAL_ONLY */
76 typedef struct ia64_loc
82 #endif /* !UNW_LOCAL_ONLY */
91 #define ABI_NSK 5 /* Tandem/HP Non-Stop Kernel */
96 struct unw_accessors acc
;
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
;
103 uint32_t cache_generation
;
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
;
111 struct ia64_script_cache global_cache
;
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')
124 void *as_arg
; /* argument to address-space callbacks */
125 unw_addr_space_t as
; /* reference to per-address-space info */
127 /* IP, CFM, and predicate cache (these are always equal to the
128 values stored in ip_loc, cfm_loc, and pr_loc,
130 unw_word_t ip
; /* instruction pointer value */
131 unw_word_t cfm
; /* current frame mask */
132 unw_word_t pr
; /* current predicate values */
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
];
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 */
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
;
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 */
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.
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
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 */
182 rbs_area
[96 + 2]; /* 96 stacked regs + 1 extra stack on each side... */
185 struct ia64_global_unwind_state
187 pthread_mutex_t lock
; /* global data lock */
189 volatile char init_done
;
191 /* Table of registers that prologues can save (and order in which
193 const unsigned char save_order
[8];
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.
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 */
208 unw_fpreg_t nat_val_le
, nat_val_be
;
209 unw_fpreg_t int_val_le
, int_val_be
;
211 struct mempool reg_state_pool
;
212 struct mempool labeled_state_pool
;
215 const char *preg_name
[IA64_NUM_PREGS
];
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)
241 #ifndef UNW_LOCAL_ONLY
242 # define tdep_put_unwind_info UNW_OBJ(put_unwind_info)
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)
251 extern void tdep_init (void);
252 extern int tdep_find_unwind_table (struct elf_dyn_info
*edi
,
253 unw_addr_space_t as
, char *path
,
254 unw_word_t segbase
, unw_word_t mapoff
,
256 extern int tdep_find_proc_info (unw_addr_space_t as
, unw_word_t ip
,
257 unw_proc_info_t
*pi
, int need_unwind_info
,
259 extern void tdep_put_unwind_info (unw_addr_space_t as
,
260 unw_proc_info_t
*pi
, void *arg
);
261 extern void *tdep_uc_addr (ucontext_t
*uc
, unw_regnum_t regnum
,
263 extern int tdep_get_elf_image (struct elf_image
*ei
, pid_t pid
, unw_word_t ip
,
264 unsigned long *segbase
, unsigned long *mapoff
,
265 char *path
, size_t pathlen
);
266 extern int tdep_access_reg (struct cursor
*c
, unw_regnum_t reg
,
267 unw_word_t
*valp
, int write
);
268 extern int tdep_access_fpreg (struct cursor
*c
, unw_regnum_t reg
,
269 unw_fpreg_t
*valp
, int write
);
271 extern struct ia64_global_unwind_state unw
;
273 /* In user-level, we have no reasonable way of determining the base of
274 an arbitrary backing-store. We default to half the
276 #define rbs_get_base(c,bspstore,rbs_basep) \
277 (*(rbs_basep) = (bspstore) - (((unw_word_t) 1) << 63), 0)
279 #endif /* IA64_LIBUNWIND_I_H */