libunwind_i.h revision 5d0f376b08126b51a001d7cdfba1ec4e0d644f54
1/* libunwind - a platform-independent unwind library
2   Copyright (C) 2006-2007 IBM
3   Contributed by
4     Corey Ashford <cjashfor@us.ibm.com>
5     Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
6
7   Copied from libunwind-x86_64.h, modified slightly for building
8   frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com>
9   Will be replaced when libunwind is ready on ppc64 platform.
10
11This file is part of libunwind.
12
13Permission is hereby granted, free of charge, to any person obtaining
14a copy of this software and associated documentation files (the
15"Software"), to deal in the Software without restriction, including
16without limitation the rights to use, copy, modify, merge, publish,
17distribute, sublicense, and/or sell copies of the Software, and to
18permit persons to whom the Software is furnished to do so, subject to
19the following conditions:
20
21The above copyright notice and this permission notice shall be
22included in all copies or substantial portions of the Software.
23
24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
31
32#ifndef PPC64_LIBUNWIND_I_H
33#define PPC64_LIBUNWIND_I_H
34
35/* Target-dependent definitions that are internal to libunwind but need
36   to be shared with target-independent code.  */
37
38#include <stdlib.h>
39#include <libunwind.h>
40
41#include "elf64.h"
42#include "mempool.h"
43#include "dwarf.h"
44
45typedef struct
46  {
47    /* no ppc64-specific fast trace */
48  }
49unw_tdep_frame_t;
50
51struct unw_addr_space
52{
53  struct unw_accessors acc;
54  unw_caching_policy_t caching_policy;
55#ifdef HAVE_ATOMIC_OPS_H
56  AO_t cache_generation;
57#else
58  uint32_t cache_generation;
59#endif
60  unw_word_t dyn_generation;	/* see dyn-common.h */
61  unw_word_t dyn_info_list_addr;	/* (cached) dyn_info_list_addr */
62  struct dwarf_rs_cache global_cache;
63  struct unw_debug_frame_list *debug_frames;
64  int validate;
65};
66
67struct cursor
68{
69  struct dwarf_cursor dwarf;	/* must be first */
70
71  /* Format of sigcontext structure and address at which it is
72     stored: */
73  enum
74  {
75    PPC_SCF_NONE,		/* no signal frame encountered */
76    PPC_SCF_LINUX_RT_SIGFRAME	/* POSIX ucontext_t */
77  }
78  sigcontext_format;
79  unw_word_t sigcontext_addr;
80};
81
82#define DWARF_GET_LOC(l)	((l).val)
83
84#ifdef UNW_LOCAL_ONLY
85# define DWARF_NULL_LOC		DWARF_LOC (0, 0)
86# define DWARF_IS_NULL_LOC(l)	(DWARF_GET_LOC (l) == 0)
87# define DWARF_LOC(r, t)	((dwarf_loc_t) { .val = (r) })
88# define DWARF_IS_REG_LOC(l)	0
89# define DWARF_IS_FP_LOC(l)	0
90# define DWARF_IS_V_LOC(l)	0
91# define DWARF_MEM_LOC(c,m)	DWARF_LOC ((m), 0)
92# define DWARF_REG_LOC(c,r)	(DWARF_LOC((unw_word_t)			     \
93				 tdep_uc_addr((c)->as_arg, (r)), 0))
94# define DWARF_FPREG_LOC(c,r)	(DWARF_LOC((unw_word_t)			     \
95				 tdep_uc_addr((c)->as_arg, (r)), 0))
96# define DWARF_VREG_LOC(c,r)	(DWARF_LOC((unw_word_t)			     \
97				 tdep_uc_addr((c)->as_arg, (r)), 0))
98#else /* !UNW_LOCAL_ONLY */
99
100# define DWARF_LOC_TYPE_FP	(1 << 0)
101# define DWARF_LOC_TYPE_REG	(1 << 1)
102# define DWARF_LOC_TYPE_V	(1 << 2)
103# define DWARF_NULL_LOC		DWARF_LOC (0, 0)
104# define DWARF_IS_NULL_LOC(l)						\
105		({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
106# define DWARF_LOC(r, t)	((dwarf_loc_t) { .val = (r), .type = (t) })
107# define DWARF_IS_REG_LOC(l)	(((l).type & DWARF_LOC_TYPE_REG) != 0)
108# define DWARF_IS_FP_LOC(l)	(((l).type & DWARF_LOC_TYPE_FP) != 0)
109# define DWARF_IS_V_LOC(l)	(((l).type & DWARF_LOC_TYPE_V) != 0)
110# define DWARF_MEM_LOC(c,m)	DWARF_LOC ((m), 0)
111# define DWARF_REG_LOC(c,r)	DWARF_LOC((r), DWARF_LOC_TYPE_REG)
112# define DWARF_FPREG_LOC(c,r)	DWARF_LOC((r), (DWARF_LOC_TYPE_REG	\
113						| DWARF_LOC_TYPE_FP))
114# define DWARF_VREG_LOC(c,r)	DWARF_LOC((r), (DWARF_LOC_TYPE_REG	\
115						| DWARF_LOC_TYPE_V))
116
117#endif /* !UNW_LOCAL_ONLY */
118
119static inline int
120dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
121{
122  unw_word_t *valp = (unw_word_t *) val;
123  unw_word_t addr;
124  int ret;
125
126  if (DWARF_IS_NULL_LOC (loc))
127    return -UNW_EBADREG;
128
129  assert (DWARF_IS_V_LOC (loc));
130  assert (!DWARF_IS_FP_LOC (loc));
131
132  if (DWARF_IS_REG_LOC (loc))
133    return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
134				      val, 0, c->as_arg);
135
136  addr = DWARF_GET_LOC (loc);
137
138  if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
139				       0, c->as_arg)) < 0)
140    return ret;
141
142  return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg);
143}
144
145static inline int
146dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
147{
148  unw_word_t *valp = (unw_word_t *) & val;
149  unw_word_t addr;
150  int ret;
151
152  if (DWARF_IS_NULL_LOC (loc))
153    return -UNW_EBADREG;
154
155  assert (DWARF_IS_V_LOC (loc));
156  assert (!DWARF_IS_FP_LOC (loc));
157
158  if (DWARF_IS_REG_LOC (loc))
159    return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
160				      &val, 1, c->as_arg);
161
162  addr = DWARF_GET_LOC (loc);
163  if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp,
164				       1, c->as_arg)) < 0)
165    return ret;
166
167  return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg);
168}
169
170static inline int
171dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val)
172{
173  unw_word_t *valp = (unw_word_t *) val;
174  unw_word_t addr;
175
176  if (DWARF_IS_NULL_LOC (loc))
177    return -UNW_EBADREG;
178
179  assert (DWARF_IS_FP_LOC (loc));
180  assert (!DWARF_IS_V_LOC (loc));
181
182  if (DWARF_IS_REG_LOC (loc))
183    return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
184				       val, 0, c->as_arg);
185
186  addr = DWARF_GET_LOC (loc);
187  return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg);
188
189}
190
191static inline int
192dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
193{
194  unw_word_t *valp = (unw_word_t *) & val;
195  unw_word_t addr;
196
197  if (DWARF_IS_NULL_LOC (loc))
198    return -UNW_EBADREG;
199
200  assert (DWARF_IS_FP_LOC (loc));
201  assert (!DWARF_IS_V_LOC (loc));
202
203  if (DWARF_IS_REG_LOC (loc))
204    return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
205				       &val, 1, c->as_arg);
206
207  addr = DWARF_GET_LOC (loc);
208
209  return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 1, c->as_arg);
210}
211
212static inline int
213dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t * val)
214{
215  if (DWARF_IS_NULL_LOC (loc))
216    return -UNW_EBADREG;
217
218  /* If a code-generator were to save a value of type unw_word_t in a
219     floating-point register, we would have to support this case.  I
220     suppose it could happen with MMX registers, but does it really
221     happen?  */
222  assert (!DWARF_IS_FP_LOC (loc));
223  assert (!DWARF_IS_V_LOC (loc));
224
225  if (DWARF_IS_REG_LOC (loc))
226    return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
227				     0, c->as_arg);
228  else
229    return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
230				     0, c->as_arg);
231}
232
233static inline int
234dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
235{
236  if (DWARF_IS_NULL_LOC (loc))
237    return -UNW_EBADREG;
238
239  /* If a code-generator were to save a value of type unw_word_t in a
240     floating-point register, we would have to support this case.  I
241     suppose it could happen with MMX registers, but does it really
242     happen?  */
243  assert (!DWARF_IS_FP_LOC (loc));
244  assert (!DWARF_IS_V_LOC (loc));
245
246  if (DWARF_IS_REG_LOC (loc))
247    return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
248				     1, c->as_arg);
249  else
250    return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
251				     1, c->as_arg);
252}
253
254#define tdep_getcontext_trace           unw_getcontext
255#define tdep_init_done			UNW_OBJ(init_done)
256#define tdep_init			UNW_OBJ(init)
257/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
258   tdep_search_unwind_table.  */
259#define tdep_search_unwind_table	dwarf_search_unwind_table
260#define tdep_find_unwind_table		dwarf_find_unwind_table
261#define tdep_uc_addr			UNW_ARCH_OBJ(uc_addr)
262#define tdep_get_elf_image		UNW_ARCH_OBJ(get_elf_image)
263#define tdep_access_reg			UNW_OBJ(access_reg)
264#define tdep_access_fpreg		UNW_OBJ(access_fpreg)
265#define tdep_fetch_frame(c,ip,n)	do {} while(0)
266#define tdep_cache_frame(c,rs)		do {} while(0)
267#define tdep_reuse_frame(c,rs)		do {} while(0)
268#define tdep_stash_frame(c,rs)		do {} while(0)
269#define tdep_trace(cur,addr,n)		(-UNW_ENOINFO)
270#define tdep_get_func_addr		UNW_OBJ(get_func_addr)
271
272#ifdef UNW_LOCAL_ONLY
273# define tdep_find_proc_info(c,ip,n)				\
274	dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n),	\
275				       (c)->as_arg)
276# define tdep_put_unwind_info(as,pi,arg)		\
277	dwarf_put_unwind_info((as), (pi), (arg))
278#else
279# define tdep_find_proc_info(c,ip,n)					\
280	(*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n),	\
281				       (c)->as_arg)
282# define tdep_put_unwind_info(as,pi,arg)			\
283	(*(as)->acc.put_unwind_info)((as), (pi), (arg))
284#endif
285
286extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip,
287				      int need_unwind_info);
288
289#define tdep_get_as(c)			((c)->dwarf.as)
290#define tdep_get_as_arg(c)		((c)->dwarf.as_arg)
291#define tdep_get_ip(c)			((c)->dwarf.ip)
292#define tdep_big_endian(as)		1
293
294extern int tdep_init_done;
295
296extern void tdep_init (void);
297extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
298				     unw_dyn_info_t * di,
299				     unw_proc_info_t * pi,
300				     int need_unwind_info, void *arg);
301extern void *tdep_uc_addr (ucontext_t * uc, int reg);
302extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
303			       unsigned long *segbase, unsigned long *mapoff,
304			       char *path, size_t pathlen);
305extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
306			    unw_word_t * valp, int write);
307extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
308			      unw_fpreg_t * valp, int write);
309extern int tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr,
310			       unw_word_t *entry_point);
311
312#endif /* PPC64_LIBUNWIND_I_H */
313