1ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux/* libunwind - a platform-independent unwind library
2ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux   Copyright (C) 2001-2005 Hewlett-Packard Co
3ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux   Copyright (C) 2013 Linaro Limited
5ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
6ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxThis file is part of libunwind.
7ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
8ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxPermission is hereby granted, free of charge, to any person obtaining
9ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxa copy of this software and associated documentation files (the
10ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux"Software"), to deal in the Software without restriction, including
11ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxwithout limitation the rights to use, copy, modify, merge, publish,
12ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxdistribute, sublicense, and/or sell copies of the Software, and to
13ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxpermit persons to whom the Software is furnished to do so, subject to
14ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxthe following conditions:
15ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
16ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxThe above copyright notice and this permission notice shall be
17ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxincluded in all copies or substantial portions of the Software.
18ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
19ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
26ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
27ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#ifndef AARCH64_LIBUNWIND_I_H
28ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define AARCH64_LIBUNWIND_I_H
29ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
30ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux/* Target-dependent definitions that are internal to libunwind but need
31ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux   to be shared with target-independent code.  */
32ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
33ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#include <stdlib.h>
34ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#include <libunwind.h>
35ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
36ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#include "elf64.h"
377d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris/* ANDROID support update. */
387d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris#include "map_info.h"
397d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris/* End of ANDROID update. */
40ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#include "mempool.h"
41ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#include "dwarf.h"
42ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
43ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxtypedef struct
44ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  {
45ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    /* no aarch64-specific fast trace */
46ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  }
47ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxunw_tdep_frame_t;
48ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
49ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#ifdef UNW_LOCAL_ONLY
50ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
51ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxtypedef unw_word_t aarch64_loc_t;
52ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
53ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#else /* !UNW_LOCAL_ONLY */
54ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
55ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxtypedef struct aarch64_loc
56ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  {
57ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    unw_word_t w0, w1;
58ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  }
59ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxaarch64_loc_t;
60ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
61ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#endif /* !UNW_LOCAL_ONLY */
62ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
63ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxstruct unw_addr_space
64ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  {
65ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    struct unw_accessors acc;
66ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    int big_endian;
67ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    unw_caching_policy_t caching_policy;
68ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#ifdef HAVE_ATOMIC_OPS_H
69ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    AO_t cache_generation;
70ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#else
71ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    uint32_t cache_generation;
72ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#endif
73ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    unw_word_t dyn_generation;          /* see dyn-common.h */
74ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    unw_word_t dyn_info_list_addr;	/* (cached) dyn_info_list_addr */
75ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    struct dwarf_rs_cache global_cache;
76ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    struct unw_debug_frame_list *debug_frames;
777d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris    /* ANDROID support update. */
787d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris    struct map_info *map_list;
797d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris    /* End of ANDROID update. */
80ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux   };
81ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
82ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxstruct cursor
83ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  {
84ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    struct dwarf_cursor dwarf;          /* must be first */
85ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    enum
86ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      {
87ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        AARCH64_SCF_NONE,
88ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        AARCH64_SCF_LINUX_RT_SIGFRAME,
89ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      }
90ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    sigcontext_format;
91ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    unw_word_t sigcontext_addr;
92ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    unw_word_t sigcontext_sp;
93ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    unw_word_t sigcontext_pc;
94ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  };
95ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
96ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define DWARF_GET_LOC(l)        ((l).val)
97ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
98ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#ifdef UNW_LOCAL_ONLY
99ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_NULL_LOC         DWARF_LOC (0, 0)
100ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_IS_NULL_LOC(l)   (DWARF_GET_LOC (l) == 0)
101ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_LOC(r, t)        ((dwarf_loc_t) { .val = (r) })
102ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_IS_REG_LOC(l)    0
103ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_REG_LOC(c,r)     (DWARF_LOC((unw_word_t)                      \
104ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                 tdep_uc_addr((c)->as_arg, (r)), 0))
105ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_MEM_LOC(c,m)     DWARF_LOC ((m), 0)
106ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_FPREG_LOC(c,r)   (DWARF_LOC((unw_word_t)                      \
107ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                 tdep_uc_addr((c)->as_arg, (r)), 0))
108ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
109ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxstatic inline int
110ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxdwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
111ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{
112f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris/* ANDROID support update. */
113f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris  unw_fpreg_t *addr = (unw_fpreg_t *) (uintptr_t) DWARF_GET_LOC (loc);
114f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris  if (!addr || !map_local_is_readable ((unw_word_t) (uintptr_t) addr))
115ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return -1;
116f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris
117f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris  *val = *addr;
118ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  return 0;
119f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris/* End of ANDROID update. */
120ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux}
121ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
122ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxstatic inline int
123ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxdwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
124ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{
125f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris/* ANDROID support update. */
126f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris  unw_fpreg_t *addr = (unw_fpreg_t *) (uintptr_t) DWARF_GET_LOC (loc);
127f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris  if (!addr || !map_local_is_writable ((unw_word_t) (uintptr_t) addr))
128ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return -1;
129f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris
130f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris  *addr = val;
131ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  return 0;
132f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris/* End of ANDROID update. */
133ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux}
134ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
135ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxstatic inline int
136ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxdwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
137ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{
138f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris/* ANDROID support update. */
139ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (!DWARF_GET_LOC (loc))
140ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return -1;
141f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris  return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
142f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris				   0, c->as_arg);
143f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris/* End of ANDROID update. */
144ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux}
145ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
146ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxstatic inline int
147ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxdwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
148ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{
149f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris/* ANDROID support update. */
150ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (!DWARF_GET_LOC (loc))
151ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return -1;
152f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris  return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
153f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris				   1, c->as_arg);
154f622936d6c5239b3d5ccafdf38189cec8bca55c0Christopher Ferris/* End of ANDROID update. */
155ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux}
156ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
157ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#else /* !UNW_LOCAL_ONLY */
158ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_LOC_TYPE_FP      (1 << 0)
159ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_LOC_TYPE_REG     (1 << 1)
160ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_NULL_LOC         DWARF_LOC (0, 0)
161ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_IS_NULL_LOC(l)                                           \
162ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; })
163ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_LOC(r, t)        ((dwarf_loc_t) { .val = (r), .type = (t) })
164ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_IS_REG_LOC(l)    (((l).type & DWARF_LOC_TYPE_REG) != 0)
165ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_IS_FP_LOC(l)     (((l).type & DWARF_LOC_TYPE_FP) != 0)
166ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_REG_LOC(c,r)     DWARF_LOC((r), DWARF_LOC_TYPE_REG)
167ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_MEM_LOC(c,m)     DWARF_LOC ((m), 0)
168ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define DWARF_FPREG_LOC(c,r)   DWARF_LOC((r), (DWARF_LOC_TYPE_REG      \
169ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                                | DWARF_LOC_TYPE_FP))
170ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
171ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxstatic inline int
172ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxdwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
173ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{
174ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  char *valp = (char *) &val;
175ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  unw_word_t addr;
176ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  int ret;
177ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
178ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (DWARF_IS_NULL_LOC (loc))
179ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return -UNW_EBADREG;
180ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
181ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (DWARF_IS_REG_LOC (loc))
182ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
183ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                       val, 0, c->as_arg);
184ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
185ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  addr = DWARF_GET_LOC (loc);
186ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
187ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                       0, c->as_arg)) < 0)
188ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return ret;
189ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
190ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0,
191ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                   c->as_arg);
192ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux}
193ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
194ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxstatic inline int
195ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxdwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val)
196ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{
197ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  char *valp = (char *) &val;
198ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  unw_word_t addr;
199ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  int ret;
200ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
201ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (DWARF_IS_NULL_LOC (loc))
202ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return -UNW_EBADREG;
203ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
204ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (DWARF_IS_REG_LOC (loc))
205ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc),
206ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                       &val, 1, c->as_arg);
207ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
208ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  addr = DWARF_GET_LOC (loc);
209ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp,
210ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                       1, c->as_arg)) < 0)
211ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return ret;
212ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
213ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1,
214ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                   1, c->as_arg);
215ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux}
216ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
217ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxstatic inline int
218ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxdwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
219ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{
220ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (DWARF_IS_NULL_LOC (loc))
221ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return -UNW_EBADREG;
222ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
223ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  /* If a code-generator were to save a value of type unw_word_t in a
224ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux     floating-point register, we would have to support this case.  I
225ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux     suppose it could happen with MMX registers, but does it really
226ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux     happen?  */
227ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  assert (!DWARF_IS_FP_LOC (loc));
228ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
229ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (DWARF_IS_REG_LOC (loc))
230ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val,
231ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                     0, c->as_arg);
232ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  else
233ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
234ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                     0, c->as_arg);
235ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux}
236ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
237ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxstatic inline int
238ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxdwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
239ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{
240ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (DWARF_IS_NULL_LOC (loc))
241ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return -UNW_EBADREG;
242ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
243ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  /* If a code-generator were to save a value of type unw_word_t in a
244ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux     floating-point register, we would have to support this case.  I
245ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux     suppose it could happen with MMX registers, but does it really
246ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux     happen?  */
247ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  assert (!DWARF_IS_FP_LOC (loc));
248ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
249ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (DWARF_IS_REG_LOC (loc))
250ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val,
251ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                     1, c->as_arg);
252ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  else
253ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
254ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                     1, c->as_arg);
255ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux}
256ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
257ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#endif /* !UNW_LOCAL_ONLY */
258ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
259ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
260ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
261ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_getcontext_trace           unw_getcontext
262ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_init_done			UNW_OBJ(init_done)
263ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_init			UNW_OBJ(init)
264ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
265ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux   tdep_search_unwind_table.  */
266ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_search_unwind_table	dwarf_search_unwind_table
267ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_find_unwind_table	        dwarf_find_unwind_table
268ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_uc_addr			UNW_OBJ(uc_addr)
269ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_get_elf_image		UNW_ARCH_OBJ(get_elf_image)
270ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_access_reg			UNW_OBJ(access_reg)
271ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_access_fpreg		UNW_OBJ(access_fpreg)
272ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_fetch_frame(c,ip,n)	do {} while(0)
273ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_cache_frame(c,rs)		do {} while(0)
274ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_reuse_frame(c,rs)		do {} while(0)
275ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_stash_frame(c,rs)		do {} while(0)
276ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_trace(cur,addr,n)		(-UNW_ENOINFO)
277ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
278ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#ifdef UNW_LOCAL_ONLY
279ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define tdep_find_proc_info(c,ip,n)                            \
280ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n),      \
281ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                       (c)->as_arg)
282ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define tdep_put_unwind_info(as,pi,arg)                \
283ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        dwarf_put_unwind_info((as), (pi), (arg))
284ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#else
285ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define tdep_find_proc_info(c,ip,n)                                    \
286ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n),    \
287ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux                                       (c)->as_arg)
288ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux# define tdep_put_unwind_info(as,pi,arg)                \
289ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        (*(as)->acc.put_unwind_info)((as), (pi), (arg))
290ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#endif
291ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
292ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_get_as(c)                  ((c)->dwarf.as)
293ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_get_as_arg(c)              ((c)->dwarf.as_arg)
294ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_get_ip(c)                  ((c)->dwarf.ip)
295ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#define tdep_big_endian(as)             ((as)->big_endian)
296ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
297ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxextern int tdep_init_done;
298ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
299ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxextern void tdep_init (void);
300ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxextern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
301ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux				     unw_dyn_info_t *di, unw_proc_info_t *pi,
302ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux				     int need_unwind_info, void *arg);
303ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxextern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg);
30416b95a68caaa7e021209e2cd6a877ae1e558f740Christopher Ferris/* ANDROID support update. */
305f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisextern int tdep_get_elf_image (unw_addr_space_t as, struct elf_image *ei,
306f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris			       pid_t pid, unw_word_t ip,
307f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris			       unsigned long *segbase, unsigned long *mapoff,
308f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris			       char **path);
30916b95a68caaa7e021209e2cd6a877ae1e558f740Christopher Ferris/* End of ANDROID update. */
310ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxextern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
311ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux			    unw_word_t *valp, int write);
312ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxextern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
313ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux			      unw_fpreg_t *valp, int write);
314ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
315ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#endif /* AARCH64_LIBUNWIND_I_H */
316