1f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris/* libunwind - a platform-independent unwind library
2f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris   Copyright (C) 2014 The Android Open Source Project
3f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
4f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisThis file is part of libunwind.
5f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
6f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisPermission is hereby granted, free of charge, to any person obtaining
7f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisa copy of this software and associated documentation files (the
8f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris"Software"), to deal in the Software without restriction, including
9f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferriswithout limitation the rights to use, copy, modify, merge, publish,
10f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisdistribute, sublicense, and/or sell copies of the Software, and to
11f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrispermit persons to whom the Software is furnished to do so, subject to
12f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferristhe following conditions:
13f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
14f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisThe above copyright notice and this permission notice shall be
15f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisincluded in all copies or substantial portions of the Software.
16f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
17f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
24f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
25f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris#define UNW_LOCAL_ONLY
26f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris#include <libunwind.h>
27f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris#include "libunwind_i.h"
28f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
29f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris/* Global to hold the map for all local unwinds. */
30f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisextern struct map_info *local_map_list;
31f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisextern lock_rdwr_var (local_rdwr_lock);
32f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
33965cd6944d33fd7a2ef7c4f4cb8f3c8e420d93ccChristopher Ferrisstatic pthread_once_t local_rdwr_lock_init = PTHREAD_ONCE_INIT;
34965cd6944d33fd7a2ef7c4f4cb8f3c8e420d93ccChristopher Ferris
35965cd6944d33fd7a2ef7c4f4cb8f3c8e420d93ccChristopher Ferrisstatic void
36965cd6944d33fd7a2ef7c4f4cb8f3c8e420d93ccChristopher Ferrismap_local_init_once (void)
37965cd6944d33fd7a2ef7c4f4cb8f3c8e420d93ccChristopher Ferris{
38965cd6944d33fd7a2ef7c4f4cb8f3c8e420d93ccChristopher Ferris  lock_rdwr_init (&local_rdwr_lock);
39965cd6944d33fd7a2ef7c4f4cb8f3c8e420d93ccChristopher Ferris}
40965cd6944d33fd7a2ef7c4f4cb8f3c8e420d93ccChristopher Ferris
41f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisHIDDEN void
42f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrismap_local_init (void)
43f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris{
44965cd6944d33fd7a2ef7c4f4cb8f3c8e420d93ccChristopher Ferris  pthread_once (&local_rdwr_lock_init, map_local_init_once);
45f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris}
46f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
47f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisstatic void
48f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrismove_cached_elf_data (struct map_info *old_list, struct map_info *new_list)
49f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris{
50f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  while (old_list)
51f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    {
52f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      if (old_list->ei.image == NULL)
53f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        {
54f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          old_list = old_list->next;
55f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          continue;
56f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        }
57f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      /* Both lists are in order, so it's not necessary to scan through
58f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris         from the beginning of new_list each time looking for a match to
59f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris         the current map. As we progress, simply start from the last element
60f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris         in new_list we checked. */
61f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      while (new_list && old_list->start <= new_list->start)
62f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        {
63f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          if (old_list->start == new_list->start
64f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris              && old_list->end == new_list->end)
65f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris            {
66f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris              /* No need to do any lock, the entire local_map_list is locked
67f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris                 at this point. */
68f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris              new_list->ei.size = old_list->ei.size;
69f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris              new_list->ei.image = old_list->ei.image;
70f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris              old_list->ei.size = 0;
71f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris              old_list->ei.image = NULL;
72f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris              /* Don't bother breaking out of the loop, the next while check
73f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris                 is guaranteed to fail, causing us to break out of the loop
74f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris                 after advancing to the next map element. */
75f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris            }
76f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          new_list = new_list->next;
77f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        }
78f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      old_list = old_list->next;
79f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    }
80f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris}
81f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
82f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris/* In order to cache as much as possible while unwinding the local process,
83f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris   we gather a map of the process before starting. If the cache is missing
84f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris   a map, or a map exists but doesn't have the "expected_flags" set, then
85f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris   check if the cache needs to be regenerated.
86f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris   While regenerating the list, grab a write lock to avoid any readers using
87f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris   the list while it's being modified. */
88f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisstatic int
89f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisrebuild_if_necessary (unw_word_t addr, int expected_flags)
90f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris{
91f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  struct map_info *map;
92f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  struct map_info *new_list;
93f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  int ret_value = -1;
94f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  intrmask_t saved_mask;
95f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
96f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  new_list = map_create_list (getpid());
97f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  map = map_find_from_addr (new_list, addr);
98f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  if (map && (expected_flags == 0 || (map->flags & expected_flags)))
99f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    {
100f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      /* Get a write lock on local_map_list since it's going to be modified. */
101f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      lock_rdwr_wr_acquire (&local_rdwr_lock, saved_mask);
102f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
103f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      /* Just in case another thread rebuilt the map, check to see if the
104f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris         ip with expected_flags is in local_map_list. If not, the assumption
105f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris         is that new_list is newer than local_map_list because the map only
106f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris         gets new maps with new permissions. If this is not true, then it
107f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris         would be necessary to regenerate the list one more time. */
108f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      ret_value = 0;
109f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      map = map_find_from_addr (local_map_list, addr);
110f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      if (!map || (expected_flags != 0 && !(map->flags & expected_flags)))
111f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        {
112f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          /* Move any cached items to the new list. */
113f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          move_cached_elf_data (local_map_list, new_list);
114f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          map = local_map_list;
115f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          local_map_list = new_list;
116f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          new_list = map;
117f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        }
118f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
119f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      lock_rdwr_release (&local_rdwr_lock, saved_mask);
120f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    }
121f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
122f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  map_destroy_list (new_list);
123f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
124f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  return ret_value;
125f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris}
126f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
127f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisstatic int
128f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisis_flag_set (unw_word_t addr, int flag)
129f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris{
130f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  struct map_info *map;
131f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  int ret = 0;
132f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  intrmask_t saved_mask;
133f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
134f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  lock_rdwr_rd_acquire (&local_rdwr_lock, saved_mask);
135f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  map = map_find_from_addr (local_map_list, addr);
136f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  if (map != NULL)
137f360ccc06f3f086f41cf6ba4036b52571ed2a54fChristopher Ferris    {
138f360ccc06f3f086f41cf6ba4036b52571ed2a54fChristopher Ferris      if (map->flags & MAP_FLAGS_DEVICE_MEM)
139f360ccc06f3f086f41cf6ba4036b52571ed2a54fChristopher Ferris        {
140f360ccc06f3f086f41cf6ba4036b52571ed2a54fChristopher Ferris          lock_rdwr_release (&local_rdwr_lock, saved_mask);
141f360ccc06f3f086f41cf6ba4036b52571ed2a54fChristopher Ferris          return 0;
142f360ccc06f3f086f41cf6ba4036b52571ed2a54fChristopher Ferris        }
143f360ccc06f3f086f41cf6ba4036b52571ed2a54fChristopher Ferris      ret = map->flags & flag;
144f360ccc06f3f086f41cf6ba4036b52571ed2a54fChristopher Ferris    }
145f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  lock_rdwr_release (&local_rdwr_lock, saved_mask);
146f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
147f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  if (!ret && rebuild_if_necessary (addr, flag) == 0)
148f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    {
149f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      return 1;
150f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    }
151f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  return ret;
152f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris}
153f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
154f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisPROTECTED int
155f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrismap_local_is_readable (unw_word_t addr)
156f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris{
157f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  return is_flag_set (addr, PROT_READ);
158f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris}
159f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
160f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisPROTECTED int
161f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrismap_local_is_writable (unw_word_t addr)
162f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris{
163f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  return is_flag_set (addr, PROT_WRITE);
164f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris}
165f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
166f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher FerrisPROTECTED int
167f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrislocal_get_elf_image (struct elf_image *ei, unw_word_t ip,
168f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris                     unsigned long *segbase, unsigned long *mapoff, char **path)
169f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris{
170f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  struct map_info *map;
171f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  intrmask_t saved_mask;
1720fa05b02d01da95b0b266e9b5660a9364d85e98bChristopher Ferris  int return_value = -UNW_ENOINFO;
173f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
174f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  lock_rdwr_rd_acquire (&local_rdwr_lock, saved_mask);
175f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  map = map_find_from_addr (local_map_list, ip);
176f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  if (!map)
177f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    {
178f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      lock_rdwr_release (&local_rdwr_lock, saved_mask);
179f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      if (rebuild_if_necessary (ip, 0) < 0)
180f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        return -UNW_ENOINFO;
181f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
182f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      lock_rdwr_rd_acquire (&local_rdwr_lock, saved_mask);
183f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      map = map_find_from_addr (local_map_list, ip);
184f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    }
185f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
1860fa05b02d01da95b0b266e9b5660a9364d85e98bChristopher Ferris  if (map && elf_map_cached_image (map, ip) == 0)
187f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    {
188f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      *ei = map->ei;
189f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      *segbase = map->start;
190f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      *mapoff = map->offset;
191f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      if (path != NULL)
192f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        {
193f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          if (map->path)
194f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris            *path = strdup(map->path);
195f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          else
196f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris            *path = NULL;
197f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        }
1980fa05b02d01da95b0b266e9b5660a9364d85e98bChristopher Ferris      return_value = 0;
199f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    }
200f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  lock_rdwr_release (&local_rdwr_lock, saved_mask);
201f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
2020fa05b02d01da95b0b266e9b5660a9364d85e98bChristopher Ferris  return return_value;
203f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris}
204bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris
205bb754471703e806d83d0e6670955dc1d399690b3Christopher FerrisPROTECTED char *
206bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferrismap_local_get_image_name (unw_word_t ip)
207bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris{
208bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  struct map_info *map;
209bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  intrmask_t saved_mask;
210bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  char *image_name = NULL;
211bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris
212bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  lock_rdwr_rd_acquire (&local_rdwr_lock, saved_mask);
213bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  map = map_find_from_addr (local_map_list, ip);
214bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  if (!map)
215bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris    {
216bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris      lock_rdwr_release (&local_rdwr_lock, saved_mask);
217bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris      if (rebuild_if_necessary (ip, 0) < 0)
218bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris        return NULL;
219bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris
220bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris      lock_rdwr_rd_acquire (&local_rdwr_lock, saved_mask);
221bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris      map = map_find_from_addr (local_map_list, ip);
222bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris    }
223bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  if (map)
224bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris    image_name = strdup (map->path);
225bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  lock_rdwr_release (&local_rdwr_lock, saved_mask);
226bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris
227bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris  return image_name;
228bb754471703e806d83d0e6670955dc1d399690b3Christopher Ferris}
229