1e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm/* libunwind - a platform-independent unwind library
207b01ad205162a93dab42722caaa4dbb7ba43b3fhp.com!davidm   Copyright (C) 2001-2002, 2005 Hewlett-Packard Co
3e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
5e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmThis file is part of libunwind.
6e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
7e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmPermission is hereby granted, free of charge, to any person obtaining
8e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidma copy of this software and associated documentation files (the
9e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm"Software"), to deal in the Software without restriction, including
10e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmwithout limitation the rights to use, copy, modify, merge, publish,
11e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmdistribute, sublicense, and/or sell copies of the Software, and to
12e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmpermit persons to whom the Software is furnished to do so, subject to
13e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmthe following conditions:
14e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
15e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmThe above copyright notice and this permission notice shall be
16e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmincluded in all copies or substantial portions of the Software.
17e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
18e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
26e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm#include <stdlib.h>
27e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
2807b01ad205162a93dab42722caaa4dbb7ba43b3fhp.com!davidm#include "libunwind_i.h"
29e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm#include "remote.h"
30e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
31e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmstatic void
32e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmfree_regions (unw_dyn_region_info_t *region)
33e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm{
34e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (region->next)
35e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    free_regions (region->next);
36e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  free (region);
37e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm}
38e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
39e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmstatic int
40e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmintern_op (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
41e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	   unw_dyn_op_t *op, void *arg)
42e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm{
43e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  int ret;
44e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
45e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if ((ret = fetch8 (as, a, addr, &op->tag, arg)) < 0
46e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      || (ret = fetch8 (as, a, addr, &op->qp, arg)) < 0
47e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      || (ret = fetch16 (as, a, addr, &op->reg, arg)) < 0
48e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      || (ret = fetch32 (as, a, addr, &op->when, arg)) < 0
49e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      || (ret = fetchw  (as, a, addr, &op->val, arg)) < 0)
50e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    return ret;
51e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  return 0;
52e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm}
53e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
54e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmstatic int
55e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmintern_regions (unw_addr_space_t as, unw_accessors_t *a,
56e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm		unw_word_t *addr, unw_dyn_region_info_t **regionp, void *arg)
57e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm{
58e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  uint32_t insn_count, op_count, i;
59e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  unw_dyn_region_info_t *region;
60e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  unw_word_t next_addr;
61e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  int ret;
62e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
63e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  *regionp = NULL;
64e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
65e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (!*addr)
66e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    return 0;	/* NULL region-list */
67e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
68e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if ((ret = fetchw (as, a, addr, &next_addr, arg)) < 0
69e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      || (ret = fetch32 (as, a, addr, (int32_t *) &insn_count, arg)) < 0
70e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      || (ret = fetch32 (as, a, addr, (int32_t *) &op_count, arg)) < 0)
71e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    return ret;
72e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
73e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  region = calloc (1, _U_dyn_region_info_size (op_count));
74e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (!region)
75e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    {
76e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      ret = -UNW_ENOMEM;
77e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      goto out;
78e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    }
79e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
80e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  region->insn_count = insn_count;
81e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  region->op_count = op_count;
82e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  for (i = 0; i < op_count; ++i)
83e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    if ((ret = intern_op (as, a, addr, region->op + i, arg)) < 0)
84e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      goto out;
85e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
86e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (next_addr)
87e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    if ((ret = intern_regions (as, a, &next_addr, &region->next, arg)) < 0)
88e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      goto out;
89e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
90e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  *regionp = region;
91e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  return 0;
92e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
93e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm out:
94e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (region)
95e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    free_regions (region);
96e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  return ret;
97e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm}
98e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
99e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmstatic int
100e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmintern_array (unw_addr_space_t as, unw_accessors_t *a,
101e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      unw_word_t *addr, unw_word_t table_len, unw_word_t **table_data,
102e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      void *arg)
103e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm{
104e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  unw_word_t i, *data = calloc (table_len, WSIZE);
105e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  int ret = 0;
106e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
107e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (!data)
108e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    {
109e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      ret = -UNW_ENOMEM;
110e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      goto out;
111e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    }
112e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
113e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  for (i = 0; i < table_len; ++i)
114e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    if (fetchw (as, a, addr, data + i, arg) < 0)
115e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      goto out;
116e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
117e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  *table_data = data;
118e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  return 0;
119e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
120e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm out:
121e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (data)
122e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    free (data);
123e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  return ret;
124e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm}
125e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
126e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmstatic void
127e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmfree_dyn_info (unw_dyn_info_t *di)
128e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm{
129e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  switch (di->format)
130e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    {
131e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    case UNW_INFO_FORMAT_DYNAMIC:
132e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      if (di->u.pi.regions)
133e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	{
134e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  free_regions (di->u.pi.regions);
135e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  di->u.pi.regions = NULL;
136e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	}
137e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      break;
138e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
139e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    case UNW_INFO_FORMAT_TABLE:
140e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      if (di->u.ti.table_data)
141e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	{
142e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  free (di->u.ti.table_data);
143e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  di->u.ti.table_data = NULL;
144e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	}
145e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      break;
146e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
147e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    case UNW_INFO_FORMAT_REMOTE_TABLE:
148e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    default:
149e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      break;
150e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    }
151e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm}
152e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
153e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmstatic int
154e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmintern_dyn_info (unw_addr_space_t as, unw_accessors_t *a,
155e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm		 unw_word_t *addr, unw_dyn_info_t *di, void *arg)
156e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm{
157e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  unw_word_t first_region;
158e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  int ret;
159e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
160e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  switch (di->format)
161e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    {
162e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    case UNW_INFO_FORMAT_DYNAMIC:
163e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      if ((ret = fetchw (as, a, addr, &di->u.pi.name_ptr, arg)) < 0
164e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  || (ret = fetchw (as, a, addr, &di->u.pi.handler, arg)) < 0
165e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  || (ret = fetch32 (as, a, addr,
166e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm			     (int32_t *) &di->u.pi.flags, arg)) < 0)
167e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	goto out;
168e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      *addr += 4;	/* skip over pad0 */
169e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      if ((ret = fetchw (as, a, addr, &first_region, arg)) < 0
170e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  || (ret = intern_regions (as, a, &first_region, &di->u.pi.regions,
171e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm				    arg)) < 0)
172e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	goto out;
173e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      break;
174e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
175e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    case UNW_INFO_FORMAT_TABLE:
176e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      if ((ret = fetchw (as, a, addr, &di->u.ti.name_ptr, arg)) < 0
177e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  || (ret = fetchw (as, a, addr, &di->u.ti.segbase, arg)) < 0
178e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  || (ret = fetchw (as, a, addr, &di->u.ti.table_len, arg)) < 0
179e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  || (ret = intern_array (as, a, addr, di->u.ti.table_len,
180e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm				  &di->u.ti.table_data, arg)) < 0)
181e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	goto out;
182e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      break;
183e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
184e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    case UNW_INFO_FORMAT_REMOTE_TABLE:
185e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      if ((ret = fetchw (as, a, addr, &di->u.rti.name_ptr, arg)) < 0
186e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  || (ret = fetchw (as, a, addr, &di->u.rti.segbase, arg)) < 0
187e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  || (ret = fetchw (as, a, addr, &di->u.rti.table_len, arg)) < 0
188e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  || (ret = fetchw (as, a, addr, &di->u.rti.table_data, arg)) < 0)
189e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	goto out;
190e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      break;
191e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
192e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    default:
193e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      ret = -UNW_ENOINFO;
194e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      goto out;
195e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    }
196e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  return 0;
197e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
198e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm out:
199e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  free_dyn_info (di);
200e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  return ret;
201e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm}
202e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
203e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmHIDDEN int
204e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmunwi_dyn_remote_find_proc_info (unw_addr_space_t as, unw_word_t ip,
205e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm				unw_proc_info_t *pi,
206e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm				int need_unwind_info, void *arg)
207e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm{
208e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  unw_accessors_t *a = unw_get_accessors (as);
209e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  unw_word_t dyn_list_addr, addr, next_addr, gen1, gen2, start_ip, end_ip;
210e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  unw_dyn_info_t *di = NULL;
211e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  int ret;
212e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
213e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (as->dyn_info_list_addr)
214e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    dyn_list_addr = as->dyn_info_list_addr;
215e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  else
216e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    {
217e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      if ((*a->get_dyn_info_list_addr) (as, &dyn_list_addr, arg) < 0)
218e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	return -UNW_ENOINFO;
219e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      if (as->caching_policy != UNW_CACHE_NONE)
220e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	as->dyn_info_list_addr = dyn_list_addr;
221e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    }
222e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
223e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  do
224e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    {
225e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      addr = dyn_list_addr;
226e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
227e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      ret = -UNW_ENOINFO;
228e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
229e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      if (fetchw (as, a, &addr, &gen1, arg) < 0
230e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  || fetchw (as, a, &addr, &next_addr, arg) < 0)
231e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	return ret;
232e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
233e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      for (addr = next_addr; addr != 0; addr = next_addr)
234e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	{
235e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  if (fetchw (as, a, &addr, &next_addr, arg) < 0)
236e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	    goto recheck;	/* only fail if generation # didn't change */
237e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
238e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  addr += WSIZE;	/* skip over prev_addr */
239e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
240e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  if (fetchw (as, a, &addr, &start_ip, arg) < 0
241e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      || fetchw (as, a, &addr, &end_ip, arg) < 0)
242e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	    goto recheck;	/* only fail if generation # didn't change */
243e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
244e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	  if (ip >= start_ip && ip < end_ip)
245e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	    {
246e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      if (!di)
247e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm		di = calloc (1, sizeof (*di));
248e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
249e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      di->start_ip = start_ip;
250e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      di->end_ip = end_ip;
251e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
252e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      if (fetchw (as, a, &addr, &di->gp, arg) < 0
253e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm		  || fetch32 (as, a, &addr, &di->format, arg) < 0)
254e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm		goto recheck;	/* only fail if generation # didn't change */
255e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
256e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      addr += 4;	/* skip over padding */
257e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
258e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      if (need_unwind_info
259e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm		  && intern_dyn_info (as, a, &addr, di, arg) < 0)
260e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm		goto recheck;	/* only fail if generation # didn't change */
261e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
262e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      if (unwi_extract_dynamic_proc_info (as, ip, pi, di,
263e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm						  need_unwind_info, arg) < 0)
264e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm		{
265e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm		  free_dyn_info (di);
266e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm		  goto recheck;	/* only fail if generation # didn't change */
267e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm		}
268e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      ret = 0;	/* OK, found it */
269e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	      break;
270e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	    }
271e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	}
272e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
273e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      /* Re-check generation number to ensure the data we have is
274e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	 consistent.  */
275e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    recheck:
276e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      addr = dyn_list_addr;
277e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm      if (fetchw (as, a, &addr, &gen2, arg) < 0)
278e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm	return ret;
279e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    }
280e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  while (gen1 != gen2);
281e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
282e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (ret < 0 && di)
283e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    free (di);
284e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
285e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  return ret;
286e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm}
287e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
288e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmHIDDEN void
289e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmunwi_dyn_remote_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi,
290e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm				 void *arg)
291e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm{
292e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (!pi->unwind_info)
293e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    return;
294e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
295e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  free_dyn_info (pi->unwind_info);
296e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  free (pi->unwind_info);
297e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  pi->unwind_info = NULL;
298e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm}
299e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
300e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm/* Returns 1 if the cache is up-to-date or -1 if the cache contained
301e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm   stale data and had to be flushed.  */
302e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
303e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmHIDDEN int
304e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidmunwi_dyn_validate_cache (unw_addr_space_t as, void *arg)
305e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm{
306e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  unw_word_t addr, gen;
307e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  unw_accessors_t *a;
308e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
309e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (!as->dyn_info_list_addr)
310e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    /* If we don't have the dyn_info_list_addr, we don't have anything
311e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm       in the cache.  */
312e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    return 0;
313e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
314e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  a = unw_get_accessors (as);
315e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  addr = as->dyn_info_list_addr;
316e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
317e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (fetchw (as, a, &addr, &gen, arg) < 0)
318e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    return 1;
319e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
320e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  if (gen == as->dyn_generation)
321e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm    return 1;
322e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm
323e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  unw_flush_cache (as, 0, 0);
324e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  as->dyn_generation = gen;
325e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm  return -1;
326e11aa4383c8f0df359cc9c631f4383153f529a27hp.com!davidm}
327