1588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm/* libunwind - a platform-independent unwind library
2588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm   Copyright (C) 2002 Hewlett-Packard Co
3e6b9f350f78ecd9ef3b8a3e721f9435c94fc2562David Mosberger-Tang   Copyright (C) 2007 David Mosberger-Tang
4e6b9f350f78ecd9ef3b8a3e721f9435c94fc2562David Mosberger-Tang	Contributed by David Mosberger-Tang <dmosberger@gmail.com>
5588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
6588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmThis file is part of libunwind.
7588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
8588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmPermission is hereby granted, free of charge, to any person obtaining
9588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidma copy of this software and associated documentation files (the
10588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm"Software"), to deal in the Software without restriction, including
11588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmwithout limitation the rights to use, copy, modify, merge, publish,
12588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmdistribute, sublicense, and/or sell copies of the Software, and to
13588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmpermit persons to whom the Software is furnished to do so, subject to
14588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmthe following conditions:
15588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
16588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmThe above copyright notice and this permission notice shall be
17588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmincluded in all copies or substantial portions of the Software.
18588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
19588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
26588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
27ee99dbec879212406d813b1bae56b988b4ab1e00Konstantin Belousov#ifdef HAVE_CONFIG_H
28ee99dbec879212406d813b1bae56b988b4ab1e00Konstantin Belousov#include <config.h>
29ee99dbec879212406d813b1bae56b988b4ab1e00Konstantin Belousov#endif
30ee99dbec879212406d813b1bae56b988b4ab1e00Konstantin Belousov
31588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm#include <stdlib.h>
32588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm#include <string.h>
33588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
34588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm#include "unwind_i.h"
35588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
36588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm#ifdef UNW_REMOTE_ONLY
37588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
38588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm/* unw_local_addr_space is a NULL pointer in this case.  */
39588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmPROTECTED unw_addr_space_t unw_local_addr_space;
40588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
41588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm#else /* !UNW_REMOTE_ONLY */
42588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
43588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmstatic struct unw_addr_space local_addr_space;
44588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
45588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmPROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space;
46588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
47588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm# ifdef UNW_LOCAL_ONLY
48588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
49588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmHIDDEN void *
50588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmtdep_uc_addr (ucontext_t *uc, int reg)
51588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm{
520dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov  return x86_r_uc_addr (uc, reg);
53588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm}
54588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
55588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm# endif /* UNW_LOCAL_ONLY */
56588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
57588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmHIDDEN unw_dyn_info_list_t _U_dyn_info_list;
58588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
59588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm/* XXX fix me: there is currently no way to locate the dyn-info list
60588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm       by a remote unwinder.  On ia64, this is done via a special
61588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm       unwind-table entry.  Perhaps something similar can be done with
62588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm       DWARF2 unwind info.  */
63588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
64588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmstatic void
65588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmput_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
66588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm{
67588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  /* it's a no-op */
68588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm}
69588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
70588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmstatic int
71588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmget_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
72588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm			void *arg)
73588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm{
74588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
75588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  return 0;
76588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm}
77588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
78efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris/* ANDROID support update. */
79efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris#ifndef PAGE_SIZE
80ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma#define PAGE_SIZE 4096
81efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris#endif
82efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris/* End of ANDROID update. */
83efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
84ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma#define PAGE_START(a)	((a) & ~(PAGE_SIZE-1))
85ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma
86ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma/* Cache of already validated addresses */
87ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma#define NLGA 4
88ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharmastatic unw_word_t last_good_addr[NLGA];
89ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharmastatic int lga_victim;
90ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma
91ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharmastatic int
92ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharmavalidate_mem (unw_word_t addr)
93ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma{
94ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  int i, victim;
95ee99dbec879212406d813b1bae56b988b4ab1e00Konstantin Belousov#ifdef HAVE_MINCORE
9699e60be5a4c8bc9076d1b11e89a06f85d9da7b88Arun Sharma  unsigned char mvec[2]; /* Unaligned access may cross page boundary */
97ee99dbec879212406d813b1bae56b988b4ab1e00Konstantin Belousov#endif
9899e60be5a4c8bc9076d1b11e89a06f85d9da7b88Arun Sharma  size_t len;
9999e60be5a4c8bc9076d1b11e89a06f85d9da7b88Arun Sharma
10099e60be5a4c8bc9076d1b11e89a06f85d9da7b88Arun Sharma  if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr))
10199e60be5a4c8bc9076d1b11e89a06f85d9da7b88Arun Sharma    len = PAGE_SIZE;
10299e60be5a4c8bc9076d1b11e89a06f85d9da7b88Arun Sharma  else
10399e60be5a4c8bc9076d1b11e89a06f85d9da7b88Arun Sharma    len = PAGE_SIZE * 2;
104ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma
105ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  addr = PAGE_START(addr);
106ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma
1070cf76ed0b54f4b64d3a0575a1c85ef8617d4278dPaul Pluzhnikov  if (addr == 0)
1080cf76ed0b54f4b64d3a0575a1c85ef8617d4278dPaul Pluzhnikov    return -1;
1090cf76ed0b54f4b64d3a0575a1c85ef8617d4278dPaul Pluzhnikov
110ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  for (i = 0; i < NLGA; i++)
111ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma    {
112ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma      if (last_good_addr[i] && (addr == last_good_addr[i]))
113ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma	return 0;
114ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma    }
115ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma
116ee99dbec879212406d813b1bae56b988b4ab1e00Konstantin Belousov#ifdef HAVE_MINCORE
11799e60be5a4c8bc9076d1b11e89a06f85d9da7b88Arun Sharma  if (mincore ((void *) addr, len, mvec) == -1)
118ee99dbec879212406d813b1bae56b988b4ab1e00Konstantin Belousov#else
11999e60be5a4c8bc9076d1b11e89a06f85d9da7b88Arun Sharma  if (msync ((void *) addr, len, MS_ASYNC) == -1)
120ee99dbec879212406d813b1bae56b988b4ab1e00Konstantin Belousov#endif
121ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma    return -1;
122ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma
123ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  victim = lga_victim;
124ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  for (i = 0; i < NLGA; i++) {
125ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma    if (!last_good_addr[victim]) {
126ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma      last_good_addr[victim++] = addr;
127ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma      return 0;
128ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma    }
129ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma    victim = (victim + 1) % NLGA;
130ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  }
131ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma
132ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  /* All slots full. Evict the victim. */
133ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  last_good_addr[victim] = addr;
134ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  victim = (victim + 1) % NLGA;
135ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  lga_victim = victim;
136ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma
137ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  return 0;
138ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma}
139ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma
140588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmstatic int
141588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmaccess_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
142588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm	    void *arg)
143588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm{
144588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  if (write)
145588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    {
1467d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris      /* ANDROID support update. */
147cdf9ee587b78148c5d48dae1b5ea72ec8df64c96Christopher Ferris#ifdef UNW_LOCAL_ONLY
14818cf8168ef34750ffae6451bded31ff06d2d2763Christopher Ferris      if (map_local_is_writable (addr, sizeof(unw_word_t)))
1497d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris        {
150cdf9ee587b78148c5d48dae1b5ea72ec8df64c96Christopher Ferris#endif
1517d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          Debug (16, "mem[%x] <- %x\n", addr, *val);
1527d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          *(unw_word_t *) addr = *val;
153cdf9ee587b78148c5d48dae1b5ea72ec8df64c96Christopher Ferris#ifdef UNW_LOCAL_ONLY
1547d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris        }
1557d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris      else
1567d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris        {
1577d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          Debug (16, "Unwritable memory mem[%x] <- %x\n", addr, *val);
1587d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          return -1;
1597d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris        }
160cdf9ee587b78148c5d48dae1b5ea72ec8df64c96Christopher Ferris#endif
1617d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris      /* End of ANDROID update. */
162588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    }
163588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  else
164588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    {
16576a0b9f6a9813311ddfd59aaa580339f36a2c510Christopher Ferris      /* ANDROID support update. */
16676a0b9f6a9813311ddfd59aaa580339f36a2c510Christopher Ferris#ifdef CONSERVATIVE_CHECKS
16776a0b9f6a9813311ddfd59aaa580339f36a2c510Christopher Ferris      if (validate_mem(addr))
168ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma        return -1;
16976a0b9f6a9813311ddfd59aaa580339f36a2c510Christopher Ferris#endif
17076a0b9f6a9813311ddfd59aaa580339f36a2c510Christopher Ferris      /* End of ANDROID update. */
17176a0b9f6a9813311ddfd59aaa580339f36a2c510Christopher Ferris
1727d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris      /* ANDROID support update. */
173cdf9ee587b78148c5d48dae1b5ea72ec8df64c96Christopher Ferris#ifdef UNW_LOCAL_ONLY
17418cf8168ef34750ffae6451bded31ff06d2d2763Christopher Ferris      if (map_local_is_readable (addr, sizeof(unw_word_t)))
1757d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris        {
176cdf9ee587b78148c5d48dae1b5ea72ec8df64c96Christopher Ferris#endif
1777d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          *val = *(unw_word_t *) addr;
1787d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          Debug (16, "mem[%x] -> %x\n", addr, *val);
179cdf9ee587b78148c5d48dae1b5ea72ec8df64c96Christopher Ferris#ifdef UNW_LOCAL_ONLY
1807d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris        }
1817d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris      else
1827d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris        {
1837d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          Debug (16, "Unreadable memory mem[%x] -> XXX\n", addr);
1847d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          return -1;
1857d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris        }
186cdf9ee587b78148c5d48dae1b5ea72ec8df64c96Christopher Ferris#endif
1877d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris      /* End of ANDROID update. */
188588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    }
189588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  return 0;
190588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm}
191588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
192588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmstatic int
193588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmaccess_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
194588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm	    void *arg)
195588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm{
196588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  unw_word_t *addr;
197ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  ucontext_t *uc = ((struct cursor *)arg)->uc;
198588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
199588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  if (unw_is_fpreg (reg))
200588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    goto badreg;
201588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
2020dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov  if (!(addr = x86_r_uc_addr (uc, reg)))
203588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    goto badreg;
204588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
205588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  if (write)
206588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    {
207588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm      *(unw_word_t *) addr = *val;
208588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm      Debug (12, "%s <- %x\n", unw_regname (reg), *val);
209588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    }
210588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  else
211588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    {
212588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm      *val = *(unw_word_t *) addr;
213588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm      Debug (12, "%s -> %x\n", unw_regname (reg), *val);
214588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    }
215588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  return 0;
216588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
217588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm badreg:
218588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  Debug (1, "bad register number %u\n", reg);
219588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  return -UNW_EBADREG;
220588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm}
221588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
222588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmstatic int
223588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmaccess_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
224588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm	      int write, void *arg)
225588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm{
226ff0ae70cc3c3c1498724deed519cd18dde6c1e80Arun Sharma  ucontext_t *uc = ((struct cursor *)arg)->uc;
227588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  unw_fpreg_t *addr;
228588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
229588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  if (!unw_is_fpreg (reg))
230588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    goto badreg;
231588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
2320dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov  if (!(addr = x86_r_uc_addr (uc, reg)))
233588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    goto badreg;
234588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
235588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  if (write)
236588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    {
237588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm      Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg),
238588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm	     ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
239588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm      *(unw_fpreg_t *) addr = *val;
240588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    }
241588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  else
242588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    {
243588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm      *val = *(unw_fpreg_t *) addr;
244588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm      Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg),
245588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm	     ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]);
246588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm    }
247588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  return 0;
248588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
249588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm badreg:
250588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  Debug (1, "bad register number %u\n", reg);
251588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  /* attempt to access a non-preserved register */
252588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  return -UNW_EBADREG;
253588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm}
254588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
255588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmstatic int
256588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmget_static_proc_name (unw_addr_space_t as, unw_word_t ip,
257588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm		      char *buf, size_t buf_len, unw_word_t *offp,
258588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm		      void *arg)
259588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm{
260ae38b20031a02d3f6f56a8315c1f097ae5293c56Christopher Ferris  return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp, arg);
261588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm}
262588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
263849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferrisstatic int
264849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferrisaccess_mem_unrestricted (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
265849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris                         int write, void *arg)
266849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris{
267849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris  if (write)
268849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris    return -1;
269849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris
270849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris  *val = *(unw_word_t *) addr;
271849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris  Debug (16, "mem[%x] -> %x\n", addr, *val);
272849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris  return 0;
273849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris}
274849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris
275849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris// This initializes just enough of the address space to call the
276849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris// access memory function.
277849a547fb4de698b95c14806ddb3fcad8aa26331Christopher FerrisPROTECTED void
278849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferrisunw_local_access_addr_space_init (unw_addr_space_t as)
279849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris{
280849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris  memset (as, 0, sizeof (*as));
281849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris  as->acc.access_mem = access_mem_unrestricted;
282849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris}
283849a547fb4de698b95c14806ddb3fcad8aa26331Christopher Ferris
284588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmHIDDEN void
285588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidmx86_local_addr_space_init (void)
286588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm{
287588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  memset (&local_addr_space, 0, sizeof (local_addr_space));
288588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
289588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  local_addr_space.acc.find_proc_info = dwarf_find_proc_info;
290588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  local_addr_space.acc.put_unwind_info = put_unwind_info;
291588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
292588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  local_addr_space.acc.access_mem = access_mem;
293588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  local_addr_space.acc.access_reg = access_reg;
294588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  local_addr_space.acc.access_fpreg = access_fpreg;
295588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  local_addr_space.acc.resume = x86_local_resume;
296588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  local_addr_space.acc.get_proc_name = get_static_proc_name;
297588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm  unw_flush_cache (&local_addr_space, 0, 0);
298f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
299f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  map_local_init ();
300588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm}
301588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm
302588192d3015512656c39232cdde53cae24ff0fd0homeip.net!davidm#endif /* !UNW_REMOTE_ONLY */
303