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, ®ion->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