2bea8301e9ddb63d388149e949c6e530d8fd2151
[platform/upstream/libunwind.git] / include / tdep-ia64 / libunwind_i.h
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
5 This file is part of libunwind.
6
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:
14
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
17
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.  */
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
35 typedef struct
36   {
37     /* no ia64-specific fast trace */
38   }
39 unw_tdep_frame_t;
40
41 enum 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
72 typedef unw_word_t ia64_loc_t;
73
74 #else /* !UNW_LOCAL_ONLY */
75
76 typedef struct ia64_loc
77   {
78     unw_word_t w0, w1;
79   }
80 ia64_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
94 struct 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
122 struct 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
185 struct 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
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,
255                                    unw_word_t ip);
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,
258                                 void *arg);
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,
262                            uint8_t *nat_bitnr);
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);
270
271 extern struct ia64_global_unwind_state unw;
272
273 /* In user-level, we have no reasonable way of determining the base of
274    an arbitrary backing-store.  We default to half the
275    address-space.  */
276 #define rbs_get_base(c,bspstore,rbs_basep)                              \
277         (*(rbs_basep) = (bspstore) - (((unw_word_t) 1) << 63), 0)
278
279 #endif /* IA64_LIBUNWIND_I_H */