• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /* Add For Cache MAP And ELF */
34 #include "map_info.h"
35 /* Add For Cache MAP And ELF */
36 #include "mempool.h"
37 #include <stdatomic.h>
38 
39 typedef struct
40   {
41     /* no ia64-specific fast trace */
42   }
43 unw_tdep_frame_t;
44 
45 enum ia64_pregnum
46   {
47     /* primary unat: */
48     IA64_REG_PRI_UNAT_GR,
49     IA64_REG_PRI_UNAT_MEM,
50 
51     /* memory stack (order matters: see build_script() */
52     IA64_REG_PSP,                       /* previous memory stack pointer */
53     /* register stack */
54     IA64_REG_BSP,                       /* register stack pointer */
55     IA64_REG_BSPSTORE,
56     IA64_REG_PFS,                       /* previous function state */
57     IA64_REG_RNAT,
58     /* instruction pointer: */
59     IA64_REG_IP,
60 
61     /* preserved registers: */
62     IA64_REG_R4, IA64_REG_R5, IA64_REG_R6, IA64_REG_R7,
63     IA64_REG_NAT4, IA64_REG_NAT5, IA64_REG_NAT6, IA64_REG_NAT7,
64     IA64_REG_UNAT, IA64_REG_PR, IA64_REG_LC, IA64_REG_FPSR,
65     IA64_REG_B1, IA64_REG_B2, IA64_REG_B3, IA64_REG_B4, IA64_REG_B5,
66     IA64_REG_F2, IA64_REG_F3, IA64_REG_F4, IA64_REG_F5,
67     IA64_REG_F16, IA64_REG_F17, IA64_REG_F18, IA64_REG_F19,
68     IA64_REG_F20, IA64_REG_F21, IA64_REG_F22, IA64_REG_F23,
69     IA64_REG_F24, IA64_REG_F25, IA64_REG_F26, IA64_REG_F27,
70     IA64_REG_F28, IA64_REG_F29, IA64_REG_F30, IA64_REG_F31,
71     IA64_NUM_PREGS
72   };
73 
74 #ifdef UNW_LOCAL_ONLY
75 
76 typedef unw_word_t ia64_loc_t;
77 
78 #else /* !UNW_LOCAL_ONLY */
79 
80 typedef struct ia64_loc
81   {
82     unw_word_t w0, w1;
83   }
84 ia64_loc_t;
85 
86 #endif /* !UNW_LOCAL_ONLY */
87 
88 #include "script.h"
89 
90 #define ABI_UNKNOWN                     0
91 #define ABI_LINUX                       1
92 #define ABI_HPUX                        2
93 #define ABI_FREEBSD                     3
94 #define ABI_OPENVMS                     4
95 #define ABI_NSK                         5       /* Tandem/HP Non-Stop Kernel */
96 #define ABI_WINDOWS                     6
97 
98 struct unw_addr_space
99   {
100     struct unw_accessors acc;
101     int big_endian;
102     int abi;    /* abi < 0 => unknown, 0 => SysV, 1 => HP-UX, 2 => Windows */
103     unw_caching_policy_t caching_policy;
104     _Atomic 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;
109 #endif
110 
111     struct ia64_script_cache global_cache;
112 
113     /* Add For Cache MAP And ELF */
114     struct map_info *map_list;
115     /* Add For Cache MAP And ELF */
116    };
117 
118 /* Note: The ABI numbers in the ABI-markers (.unwabi directive) are
119    not the same as the above ABI numbers.  */
120 #define ABI_MARKER_OLD_LINUX_SIGTRAMP   ((0 << 8) | 's')
121 #define ABI_MARKER_OLD_LINUX_INTERRUPT  ((0 << 8) | 'i')
122 #define ABI_MARKER_HP_UX_SIGTRAMP       ((1 << 8) | 1)
123 #define ABI_MARKER_LINUX_SIGTRAMP       ((3 << 8) | 's')
124 #define ABI_MARKER_LINUX_INTERRUPT      ((3 << 8) | 'i')
125 
126 struct cursor
127   {
128     void *as_arg;               /* argument to address-space callbacks */
129     unw_addr_space_t as;        /* reference to per-address-space info */
130 
131     /* IP, CFM, and predicate cache (these are always equal to the
132        values stored in ip_loc, cfm_loc, and pr_loc,
133        respectively).  */
134     unw_word_t ip;              /* instruction pointer value */
135     unw_word_t cfm;             /* current frame mask */
136     unw_word_t pr;              /* current predicate values */
137 
138     /* current frame info: */
139     unw_word_t bsp;             /* backing store pointer value */
140     unw_word_t sp;              /* stack pointer value */
141     unw_word_t psp;             /* previous sp value */
142     ia64_loc_t cfm_loc;         /* cfm save location (or NULL) */
143     ia64_loc_t ec_loc;          /* ar.ec save location (usually cfm_loc) */
144     ia64_loc_t loc[IA64_NUM_PREGS];
145 
146     unw_word_t eh_args[4];      /* exception handler arguments */
147     unw_word_t sigcontext_addr; /* address of sigcontext or 0 */
148     unw_word_t sigcontext_off;  /* sigcontext-offset relative to signal sp */
149 
150     short hint;
151     short prev_script;
152 
153     uint8_t nat_bitnr[4];       /* NaT bit numbers for r4-r7 */
154     uint16_t abi_marker;        /* abi_marker for current frame (if any) */
155     uint16_t last_abi_marker;   /* last abi_marker encountered so far */
156     uint8_t eh_valid_mask;
157 
158     unsigned int pi_valid :1;           /* is proc_info valid? */
159     unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
160     unw_proc_info_t pi;         /* info about current procedure */
161 
162     /* In case of stack-discontiguities, such as those introduced by
163        signal-delivery on an alternate signal-stack (see
164        sigaltstack(2)), we use the following data-structure to keep
165        track of the register-backing-store areas across on which the
166        current frame may be backed up.  Since there are at most 96
167        stacked registers and since we only have to track the current
168        frame and only areas that are not empty, this puts an upper
169        limit on the # of backing-store areas we have to track.
170 
171        Note that the rbs-area indexed by rbs_curr identifies the
172        rbs-area that was in effect at the time AR.BSP had the value
173        c->bsp.  However, this rbs area may not actually contain the
174        value in the register that c->bsp corresponds to because that
175        register may not have gotten spilled until much later, when a
176        possibly different rbs-area might have been in effect
177        already.  */
178     uint8_t rbs_curr;           /* index of curr. rbs-area (contains c->bsp) */
179     uint8_t rbs_left_edge;      /* index of inner-most valid rbs-area */
180     struct rbs_area
181       {
182         unw_word_t end;
183         unw_word_t size;
184         ia64_loc_t rnat_loc;
185       }
186     rbs_area[96 + 2];   /* 96 stacked regs + 1 extra stack on each side... */
187 };
188 
189 struct ia64_global_unwind_state
190   {
191     pthread_mutex_t lock;               /* global data lock */
192 
193     volatile char init_done;
194 
195     /* Table of registers that prologues can save (and order in which
196        they're saved).  */
197     const unsigned char save_order[8];
198 
199     /*
200      * uc_addr() may return pointers to these variables.  We need to
201      * make sure they don't get written via ia64_put() or
202      * ia64_putfp().  To make it possible to test for these variables
203      * quickly, we collect them in a single sub-structure.
204      */
205     struct
206       {
207         unw_word_t  r0;                 /* r0 is byte-order neutral */
208         unw_fpreg_t f0;                 /* f0 is byte-order neutral */
209         unw_fpreg_t f1_le, f1_be;       /* f1 is byte-order dependent */
210       }
211     read_only;
212     unw_fpreg_t nat_val_le, nat_val_be;
213     unw_fpreg_t int_val_le, int_val_be;
214 
215     struct mempool reg_state_pool;
216     struct mempool labeled_state_pool;
217 
218 # if UNW_DEBUG
219     const char *preg_name[IA64_NUM_PREGS];
220 # endif
221   };
222 
223 #define tdep_getcontext_trace           unw_getcontext
224 #define tdep_init_done                  unw.init_done
225 #define tdep_init                       UNW_OBJ(init)
226 /* Platforms that support UNW_INFO_FORMAT_TABLE need to define
227    tdep_search_unwind_table.  */
228 #define tdep_search_unwind_table        unw_search_ia64_unwind_table
229 #define tdep_find_unwind_table  ia64_find_unwind_table
230 #define tdep_find_proc_info             UNW_OBJ(find_proc_info)
231 #define tdep_uc_addr                    UNW_OBJ(uc_addr)
232 #define tdep_get_elf_image              UNW_ARCH_OBJ(get_elf_image)
233 #define tdep_get_exe_image_path         UNW_ARCH_OBJ(get_exe_image_path)
234 #define tdep_access_reg                 UNW_OBJ(access_reg)
235 #define tdep_access_fpreg               UNW_OBJ(access_fpreg)
236 #define tdep_fetch_frame(c,ip,n)        do {} while(0)
237 #define tdep_cache_frame(c)             0
238 #define tdep_reuse_frame(c,frame)       do {} while(0)
239 #define tdep_stash_frame(c,rs)          do {} while(0)
240 #define tdep_trace(cur,addr,n)          (-UNW_ENOINFO)
241 #define tdep_get_as(c)                  ((c)->as)
242 #define tdep_get_as_arg(c)              ((c)->as_arg)
243 #define tdep_get_ip(c)                  ((c)->ip)
244 #define tdep_big_endian(as)             ((c)->as->big_endian != 0)
245 
246 #ifndef UNW_LOCAL_ONLY
247 # define tdep_put_unwind_info           UNW_OBJ(put_unwind_info)
248 #endif
249 
250 /* This can't be an UNW_ARCH_OBJ() because we need separate
251    unw.initialized flags for the local-only and generic versions of
252    the library.  Also, if we wanted to have a single, shared global
253    data structure, we couldn't declare "unw" as HIDDEN.  */
254 #define unw                             UNW_OBJ(data)
255 
256 extern void tdep_init (void);
257 extern int tdep_find_unwind_table (struct elf_dyn_info *edi,
258                                    unw_addr_space_t as, char *path,
259                                    unw_word_t segbase, unw_word_t mapoff,
260                                    unw_word_t ip);
261 extern int tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip,
262                                 unw_proc_info_t *pi, int need_unwind_info,
263                                 void *arg);
264 extern void tdep_put_unwind_info (unw_addr_space_t as,
265                                   unw_proc_info_t *pi, void *arg);
266 extern void *tdep_uc_addr (ucontext_t *uc, unw_regnum_t regnum,
267                            uint8_t *nat_bitnr);
268 /* Add For Cache MAP And ELF */
269 extern struct map_info *tdep_get_elf_image (unw_addr_space_t as, pid_t pid,
270 					    unw_word_t ip);
271 /* Add For Cache MAP And ELF */
272 extern void tdep_get_exe_image_path (char *path);
273 extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
274                             unw_word_t *valp, int write);
275 extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
276                               unw_fpreg_t *valp, int write);
277 
278 extern struct ia64_global_unwind_state unw;
279 
280 /* In user-level, we have no reasonable way of determining the base of
281    an arbitrary backing-store.  We default to half the
282    address-space.  */
283 #define rbs_get_base(c,bspstore,rbs_basep)                              \
284         (*(rbs_basep) = (bspstore) - (((unw_word_t) 1) << 63), 0)
285 
286 #endif /* IA64_LIBUNWIND_I_H */
287