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