188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm/* libunwind - a platform-independent unwind library 2df3d6af467fa67e2a2127b9c49b71359982c099fhp.com!davidm Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. 388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmThis file is part of libunwind. 688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmPermission is hereby granted, free of charge, to any person obtaining 888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidma copy of this software and associated documentation files (the 988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm"Software"), to deal in the Software without restriction, including 1088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmwithout limitation the rights to use, copy, modify, merge, publish, 1188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmdistribute, sublicense, and/or sell copies of the Software, and to 1288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmpermit persons to whom the Software is furnished to do so, subject to 1388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmthe following conditions: 1488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 1588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmThe above copyright notice and this permission notice shall be 1688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmincluded in all copies or substantial portions of the Software. 1788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 1888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 2288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 2388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 2588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 2600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma#include <stddef.h> 2788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#include "dwarf_i.h" 28df3d6af467fa67e2a2127b9c49b71359982c099fhp.com!davidm#include "libunwind_i.h" 2988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 3088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool)) 3188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs)) 3288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 3388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmstatic inline int 3488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmread_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, 3588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_word_t *valp, void *arg) 3688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 3788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm int ret; 3888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 3988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_read_uleb128 (as, a, addr, valp, arg)) < 0) 4088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 4188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 4288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (*valp >= DWARF_NUM_PRESERVED_REGS) 4388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 44642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm Debug (1, "Invalid register number %u\n", (unsigned int) *valp); 4588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return -UNW_EBADREG; 4688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 4788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return 0; 4888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 4988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 5088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmstatic inline void 5188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmset_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where, 5288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_word_t val) 5388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 5488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm sr->rs_current.reg[regnum].where = where; 5588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm sr->rs_current.reg[regnum].val = val; 5688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 5788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 5888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm/* Run a CFI program to update the register state. */ 5988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmstatic int 6088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmrun_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr, 6188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_word_t ip, unw_word_t *addr, unw_word_t end_addr, 62c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm struct dwarf_cie_info *dci) 6388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 6488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_word_t curr_ip, operand = 0, regnum, val, len, fde_encoding; 6588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm dwarf_reg_state_t *rs_stack = NULL, *new_rs, *old_rs; 6688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_addr_space_t as; 6788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_accessors_t *a; 6888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm uint8_t u8, op; 6988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm uint16_t u16; 7088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm uint32_t u32; 7188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm void *arg; 7288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm int ret; 7388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 7488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm as = c->as; 7588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm arg = c->as_arg; 7646e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma if (c->pi.flags & UNW_PI_FLAG_DEBUG_FRAME) 7746e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma { 7846e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma /* .debug_frame CFI is stored in local address space. */ 7946e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma as = unw_local_addr_space; 8046e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma arg = NULL; 8146e10c5abeeb93345367a70db2af3aba4440a49eArun Sharma } 8288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm a = unw_get_accessors (as); 8388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm curr_ip = c->pi.start_ip; 8488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 85a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura /* Process everything up to and including the current 'ip', 86a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura including all the DW_CFA_advance_loc instructions. See 87a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura 'c->use_prev_instr' use in 'fetch_proc_info' for details. */ 88a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura while (curr_ip <= ip && *addr < end_addr) 8988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 9088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0) 9188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 9288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 9388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (op & DWARF_CFA_OPCODE_MASK) 9488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 9588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm operand = op & DWARF_CFA_OPERAND_MASK; 9688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm op &= ~DWARF_CFA_OPERAND_MASK; 9788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 9888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm switch ((dwarf_cfa_t) op) 9988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 10088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_advance_loc: 101c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm curr_ip += operand * dci->code_align; 102aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_advance_loc to 0x%lx\n", (long) curr_ip); 10388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 10488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 10588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_advance_loc1: 10688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_readu8 (as, a, addr, &u8, arg)) < 0) 10788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 108c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm curr_ip += u8 * dci->code_align; 109aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) curr_ip); 11088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 11188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 11288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_advance_loc2: 11388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_readu16 (as, a, addr, &u16, arg)) < 0) 11488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 115c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm curr_ip += u16 * dci->code_align; 116aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) curr_ip); 11788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 11888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 11988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_advance_loc4: 12088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_readu32 (as, a, addr, &u32, arg)) < 0) 12188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 122c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm curr_ip += u32 * dci->code_align; 123aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) curr_ip); 12488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 12588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 12688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_MIPS_advance_loc8: 12788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#ifdef UNW_TARGET_MIPS 12888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 12988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm uint64_t u64; 13088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 13188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_readu64 (as, a, addr, &u64, arg)) < 0) 13288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 133c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm curr_ip += u64 * dci->code_align; 134aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_MIPS_advance_loc8\n"); 13588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 13688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 13788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#else 13888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm Debug (1, "DW_CFA_MIPS_advance_loc8 on non-MIPS target\n"); 13988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = -UNW_EINVAL; 14088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 14188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#endif 14288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 14388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_offset: 14488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm regnum = operand; 14588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (regnum >= DWARF_NUM_PRESERVED_REGS) 14688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 14788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm Debug (1, "Invalid register number %u in DW_cfa_OFFSET\n", 148642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm (unsigned int) regnum); 14988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = -UNW_EBADREG; 15088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 15188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 15288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) 15388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 154c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); 155aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_offset r%lu at cfa+0x%lx\n", 156c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm (long) regnum, (long) (val * dci->data_align)); 15788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 15888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 15988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_offset_extended: 16088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 16188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) 16288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 163c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); 164aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n", 165c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm (long) regnum, (long) (val * dci->data_align)); 16688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 16788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 16888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_offset_extended_sf: 16988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 17088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)) 17188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 172c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); 173aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n", 174c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm (long) regnum, (long) (val * dci->data_align)); 17588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 17688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 17788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_restore: 17888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm regnum = operand; 17988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (regnum >= DWARF_NUM_PRESERVED_REGS) 18088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 18188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm Debug (1, "Invalid register number %u in DW_CFA_restore\n", 182642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm (unsigned int) regnum); 18388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = -UNW_EINVAL; 18488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 18588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 18688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum]; 187aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_restore r%lu\n", (long) regnum); 18888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 18988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 19088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_restore_extended: 19188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_read_uleb128 (as, a, addr, ®num, arg)) < 0) 19288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 19388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (regnum >= DWARF_NUM_PRESERVED_REGS) 19488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 19588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm Debug (1, "Invalid register number %u in " 196642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm "DW_CFA_restore_extended\n", (unsigned int) regnum); 19788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = -UNW_EINVAL; 19888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 19988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 20088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum]; 201aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_restore_extended r%lu\n", (long) regnum); 20288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 20388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 20488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_nop: 20588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 20688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 20788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_set_loc: 208c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm fde_encoding = dci->fde_encoding; 20988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_read_encoded_pointer (as, a, addr, fde_encoding, 21088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm &c->pi, &curr_ip, 21188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm arg)) < 0) 21288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 213aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_set_loc to 0x%lx\n", (long) curr_ip); 21488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 21588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 21688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_undefined: 21788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 21888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 21988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, regnum, DWARF_WHERE_UNDEF, 0); 220aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_undefined r%lu\n", (long) regnum); 22188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 22288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 22388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_same_value: 22488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 22588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 22688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, regnum, DWARF_WHERE_SAME, 0); 227aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_same_value r%lu\n", (long) regnum); 22888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 22988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 23088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_register: 23188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 23288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) 23388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 23488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, regnum, DWARF_WHERE_REG, val); 235aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_register r%lu to r%lu\n", (long) regnum, (long) val); 23688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 23788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 23888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_remember_state: 23988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm new_rs = alloc_reg_state (); 24088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (!new_rs) 24188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 24288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm Debug (1, "Out of memory in DW_CFA_remember_state\n"); 24388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = -UNW_ENOMEM; 24488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 24588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 24688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 24788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm memcpy (new_rs->reg, sr->rs_current.reg, sizeof (new_rs->reg)); 24888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm new_rs->next = rs_stack; 24988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm rs_stack = new_rs; 250aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_remember_state\n"); 25188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 25288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 25388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_restore_state: 25488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (!rs_stack) 25588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 25688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm Debug (1, "register-state stack underflow\n"); 25788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = -UNW_EINVAL; 25888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 25988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 26088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm memcpy (&sr->rs_current.reg, &rs_stack->reg, sizeof (rs_stack->reg)); 26188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm old_rs = rs_stack; 26288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm rs_stack = rs_stack->next; 26388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm free_reg_state (old_rs); 264aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_restore_state\n"); 26588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 26688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 26788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_def_cfa: 26888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 26988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) 27088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 27188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); 27288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */ 273aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_def_cfa r%lu+0x%lx\n", (long) regnum, (long) val); 27488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 27588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 27688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_def_cfa_sf: 27788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 27888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)) 27988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 28088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); 28188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, 282c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm val * dci->data_align); /* factored! */ 283aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_def_cfa_sf r%lu+0x%lx\n", 284c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm (long) regnum, (long) (val * dci->data_align)); 28588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 28688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 28788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_def_cfa_register: 28888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 28988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 29088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); 291aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_def_cfa_register r%lu\n", (long) regnum); 29288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 29388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 29488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_def_cfa_offset: 29588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) 29688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 29788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */ 298c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm Debug (15, "CFA_def_cfa_offset 0x%lx\n", (long) val); 29988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 30088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 30188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_def_cfa_offset_sf: 30288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0) 30388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 30488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, 305c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm val * dci->data_align); /* factored! */ 306c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm Debug (15, "CFA_def_cfa_offset_sf 0x%lx\n", 307c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm (long) (val * dci->data_align)); 30888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 30988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 31088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_def_cfa_expression: 31188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* Save the address of the DW_FORM_block for later evaluation. */ 31288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_EXPR, *addr); 31388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 31488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0) 31588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 31688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 317aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_def_cfa_expr @ 0x%lx [%lu bytes]\n", 31888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm (long) *addr, (long) len); 31988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm *addr += len; 32088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 32188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 322c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm case DW_CFA_expression: 32388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 32488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 32588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 32688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* Save the address of the DW_FORM_block for later evaluation. */ 32788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, regnum, DWARF_WHERE_EXPR, *addr); 32888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 32988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0) 33088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 33188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 332aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_expression r%lu @ 0x%lx [%lu bytes]\n", 33388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm (long) regnum, (long) addr, (long) len); 33488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm *addr += len; 33588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 33688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 33788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_GNU_args_size: 33888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) 33988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 34088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm sr->args_size = val; 341aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_GNU_args_size %lu\n", (long) val); 34288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 34388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 34488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_GNU_negative_offset_extended: 34588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* A comment in GCC says that this is obsoleted by 34688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm DW_CFA_offset_extended_sf, but that it's used by older 34788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm PowerPC code. */ 34888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) 34988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) 35088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 351c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm set_reg (sr, regnum, DWARF_WHERE_CFAREL, -(val * dci->data_align)); 352c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm Debug (15, "CFA_GNU_negative_offset_extended cfa+0x%lx\n", 353c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm (long) -(val * dci->data_align)); 35488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 35588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 35688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_GNU_window_save: 35788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#ifdef UNW_TARGET_SPARC 35888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* This is a special CFA to handle all 16 windowed registers 35988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm on SPARC. */ 36088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm for (regnum = 16; regnum < 32; ++regnum) 36188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, regnum, DWARF_WHERE_CFAREL, 36288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm (regnum - 16) * sizeof (unw_word_t)); 363aae368ace23687c4f50f575111dc0196350b2c55homeip.net!davidm Debug (15, "CFA_GNU_window_save\n"); 36488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 36588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#else 36688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* FALL THROUGH */ 36788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#endif 36888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_lo_user: 36988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DW_CFA_hi_user: 370c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm Debug (1, "Unexpected CFA opcode 0x%x\n", op); 37188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = -UNW_EINVAL; 37288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm goto fail; 37388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 37488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 37588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = 0; 37688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 37788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm fail: 37888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* Free the register-state stack, if not empty already. */ 37988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm while (rs_stack) 38088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 38188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm old_rs = rs_stack; 38288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm rs_stack = rs_stack->next; 38388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm free_reg_state (old_rs); 38488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 38588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 38688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 38788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 38888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmstatic int 38988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmfetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info) 39088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 39188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm int ret, dynamic = 1; 39288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 393a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura /* The 'ip' can point either to the previous or next instruction 394a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura depending on what type of frame we have: normal call or a place 395a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura to resume execution (e.g. after signal frame). 396a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura 397a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura For a normal call frame we need to back up so we point within the 398a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura call itself; this is important because a) the call might be the 399a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura very last instruction of the function and the edge of the FDE, 400a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura and b) so that run_cfi_program() runs locations up to the call 401a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura but not more. 402a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura 403a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura For execution resume, we need to do the exact opposite and look 404a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura up using the current 'ip' value. That is where execution will 405a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura continue, and it's important we get this right, as 'ip' could be 406a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura right at the function entry and hence FDE edge, or at instruction 407a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura that manipulates CFA (push/pop). */ 408a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura if (c->use_prev_instr) 409a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura --ip; 410c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm 41188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (c->pi_valid && !need_unwind_info) 41288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return 0; 41388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 414c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm memset (&c->pi, 0, sizeof (c->pi)); 415c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm 41688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* check dynamic info first --- it overrides everything else */ 41788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info, 41888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm c->as_arg); 41988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (ret == -UNW_ENOINFO) 42088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 42188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm dynamic = 0; 42288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = tdep_find_proc_info (c, ip, need_unwind_info)) < 0) 42388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 42488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 42588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 426545023c2072975c6b85a09d5faf2cf05db10e064Ken Werner if (c->pi.format != UNW_INFO_FORMAT_DYNAMIC 427545023c2072975c6b85a09d5faf2cf05db10e064Ken Werner && c->pi.format != UNW_INFO_FORMAT_TABLE 428545023c2072975c6b85a09d5faf2cf05db10e064Ken Werner && c->pi.format != UNW_INFO_FORMAT_REMOTE_TABLE) 429545023c2072975c6b85a09d5faf2cf05db10e064Ken Werner return -UNW_ENOINFO; 430545023c2072975c6b85a09d5faf2cf05db10e064Ken Werner 43188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm c->pi_valid = 1; 43288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm c->pi_is_dynamic = dynamic; 433dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 434dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura /* Let system/machine-dependent code determine frame-specific attributes. */ 435dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura if (ret >= 0) 436dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura tdep_fetch_frame (c, ip, need_unwind_info); 437dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 438a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura /* Update use_prev_instr for the next frame. */ 439a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura if (need_unwind_info) 440a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura { 441a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura assert(c->pi.unwind_info); 442a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura struct dwarf_cie_info *dci = c->pi.unwind_info; 443a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura c->use_prev_instr = ! dci->signal_frame; 444a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura } 445a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura 44688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 44788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 44888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 44988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmstatic int 45088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmparse_dynamic (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr) 45188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 45288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm Debug (1, "Not yet implemented\n"); 45388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#if 0 45488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* Don't forget to set the ret_addr_column! */ 45588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm c->ret_addr_column = XXX; 45688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#endif 45788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return -UNW_ENOINFO; 45888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 45988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 46088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmstatic inline void 46188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmput_unwind_info (struct dwarf_cursor *c, unw_proc_info_t *pi) 46288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 46388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (c->pi_is_dynamic) 46488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg); 4653b8254d3b911193d1270bed6e941f56479ef5a85Matt Fischer else if (pi->unwind_info && pi->format == UNW_INFO_FORMAT_TABLE) 466c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm { 467c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm mempool_free (&dwarf_cie_info_pool, pi->unwind_info); 468c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm pi->unwind_info = NULL; 469c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm } 47088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 47188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 47288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmstatic inline int 47388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmparse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr) 47488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 475c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm struct dwarf_cie_info *dci; 47688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_word_t addr; 47788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm int ret; 47888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 479c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm dci = c->pi.unwind_info; 480c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm c->ret_addr_column = dci->ret_addr_column; 48188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 482c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm addr = dci->cie_instr_start; 48388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = run_cfi_program (c, sr, ~(unw_word_t) 0, &addr, 484c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm dci->cie_instr_end, dci)) < 0) 48588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 48688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 48788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial)); 48888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 489c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm addr = dci->fde_instr_start; 490c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm if ((ret = run_cfi_program (c, sr, ip, &addr, dci->fde_instr_end, dci)) < 0) 49188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 49288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 49388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return 0; 49488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 49588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 49600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharmastatic inline void 49700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharmaflush_rs_cache (struct dwarf_rs_cache *cache) 49800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma{ 49900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma int i; 50000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 50100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->lru_head = DWARF_UNW_CACHE_SIZE - 1; 50200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->lru_tail = 0; 50300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 50400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma for (i = 0; i < DWARF_UNW_CACHE_SIZE; ++i) 50500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma { 50600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (i > 0) 50700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->buckets[i].lru_chain = (i - 1); 50800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->buckets[i].coll_chain = -1; 50900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->buckets[i].ip = 0; 5105e59e93d049b9c6261c0db456edb7ab323618b6cArun Sharma cache->buckets[i].valid = 0; 51100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma } 51200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma for (i = 0; i<DWARF_UNW_HASH_SIZE; ++i) 51300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->hash[i] = -1; 51400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma} 51500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 5164312719cbc30dfa9e188b24e85185c325e671d00Arun Sharmastatic inline struct dwarf_rs_cache * 5174312719cbc30dfa9e188b24e85185c325e671d00Arun Sharmaget_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp) 51800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma{ 51900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma struct dwarf_rs_cache *cache = &as->global_cache; 5204312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma unw_caching_policy_t caching = as->caching_policy; 5214312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma 5224312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma if (caching == UNW_CACHE_NONE) 5234312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma return NULL; 5244312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma 5254312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma if (likely (caching == UNW_CACHE_GLOBAL)) 5264312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma { 527e61c6f69c30d85584ece5250b8b82b03898384f5Tommi Rantala Debug (16, "acquiring lock\n"); 52884d4150668d83a98420cc91e00026159c3d74a81Paul Pluzhnikov lock_acquire (&cache->lock, *saved_maskp); 5294312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma } 5304312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma 53100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation)) 53200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma { 53300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma flush_rs_cache (cache); 53400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->generation = as->cache_generation; 53500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma } 53600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 53700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma return cache; 53800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma} 53900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 5404312719cbc30dfa9e188b24e85185c325e671d00Arun Sharmastatic inline void 5414312719cbc30dfa9e188b24e85185c325e671d00Arun Sharmaput_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache, 5424312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma intrmask_t *saved_maskp) 5434312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma{ 5444312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma assert (as->caching_policy != UNW_CACHE_NONE); 5454312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma 5464312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma Debug (16, "unmasking signals/interrupts and releasing lock\n"); 5474312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma if (likely (as->caching_policy == UNW_CACHE_GLOBAL)) 54884d4150668d83a98420cc91e00026159c3d74a81Paul Pluzhnikov lock_release (&cache->lock, *saved_maskp); 5494312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma} 5504312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma 5517d471b144013924f8d80e532a693fb77dbe73c2bTommi Rantalastatic inline unw_hash_index_t CONST_ATTR 55200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharmahash (unw_word_t ip) 55300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma{ 55400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma /* based on (sqrt(5)/2-1)*2^64 */ 55500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL) 55600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 55755fe524775b47f16589e3fc8f28ccffe5e88a048Arun Sharma return ip * magic >> ((sizeof(unw_word_t) * 8) - DWARF_LOG_UNW_HASH_SIZE); 55800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma} 55900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 56000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharmastatic inline long 56100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharmacache_match (dwarf_reg_state_t *rs, unw_word_t ip) 56200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma{ 5635e59e93d049b9c6261c0db456edb7ab323618b6cArun Sharma if (rs->valid && (ip == rs->ip)) 56400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma return 1; 56500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma return 0; 56600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma} 56700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 56800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharmastatic dwarf_reg_state_t * 56900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharmars_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c) 57000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma{ 57100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma dwarf_reg_state_t *rs = cache->buckets + c->hint; 57200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma unsigned short index; 57300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma unw_word_t ip; 57400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 57500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma ip = c->ip; 57600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 57700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (cache_match (rs, ip)) 57800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma return rs; 57900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 58000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma index = cache->hash[hash (ip)]; 58100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (index >= DWARF_UNW_CACHE_SIZE) 582890e23eb9d3ffd9be2a025189a21794b5ed0e0ffTommi Rantala return NULL; 58300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 58400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma rs = cache->buckets + index; 58500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma while (1) 58600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma { 58700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (cache_match (rs, ip)) 58800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma { 58900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma /* update hint; no locking needed: single-word writes are atomic */ 59000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma c->hint = cache->buckets[c->prev_rs].hint = 59100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma (rs - cache->buckets); 59200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma return rs; 59300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma } 59400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (rs->coll_chain >= DWARF_UNW_HASH_SIZE) 595890e23eb9d3ffd9be2a025189a21794b5ed0e0ffTommi Rantala return NULL; 59600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma rs = cache->buckets + rs->coll_chain; 59700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma } 59800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma} 59900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 60000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharmastatic inline dwarf_reg_state_t * 601c5dc3c150a4fab2962f8d32f78d80ce857e662a5Arun Sharmars_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c) 60200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma{ 60300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma dwarf_reg_state_t *rs, *prev, *tmp; 60400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma unw_hash_index_t index; 60500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma unsigned short head; 60600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 60700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma head = cache->lru_head; 60800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma rs = cache->buckets + head; 60900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->lru_head = rs->lru_chain; 61000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 61100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma /* re-insert rs at the tail of the LRU chain: */ 61200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->buckets[cache->lru_tail].lru_chain = head; 61300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->lru_tail = head; 61400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 61500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma /* remove the old rs from the hash table (if it's there): */ 61600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (rs->ip) 61700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma { 61800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma index = hash (rs->ip); 61900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma tmp = cache->buckets + cache->hash[index]; 620890e23eb9d3ffd9be2a025189a21794b5ed0e0ffTommi Rantala prev = NULL; 62100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma while (1) 62200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma { 62300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (tmp == rs) 62400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma { 62500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (prev) 62600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma prev->coll_chain = tmp->coll_chain; 62700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma else 62800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->hash[index] = tmp->coll_chain; 62900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma break; 63000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma } 63100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma else 63200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma prev = tmp; 63300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (tmp->coll_chain >= DWARF_UNW_CACHE_SIZE) 63400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma /* old rs wasn't in the hash-table */ 63500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma break; 63600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma tmp = cache->buckets + tmp->coll_chain; 63700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma } 63800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma } 63900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 64000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma /* enter new rs in the hash table */ 641c5dc3c150a4fab2962f8d32f78d80ce857e662a5Arun Sharma index = hash (c->ip); 64200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma rs->coll_chain = cache->hash[index]; 64300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma cache->hash[index] = rs - cache->buckets; 64400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 64500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma rs->hint = 0; 646c5dc3c150a4fab2962f8d32f78d80ce857e662a5Arun Sharma rs->ip = c->ip; 6475e59e93d049b9c6261c0db456edb7ab323618b6cArun Sharma rs->valid = 1; 648c5dc3c150a4fab2962f8d32f78d80ce857e662a5Arun Sharma rs->ret_addr_column = c->ret_addr_column; 649dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura rs->signal_frame = 0; 650dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura tdep_cache_frame (c, rs); 65100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 65200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma return rs; 65300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma} 65400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 65588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmstatic int 65688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmcreate_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr, 65788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_word_t ip) 65888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 65988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm int i, ret; 66088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 66188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm assert (c->pi_valid); 66288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 663c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm memset (sr, 0, sizeof (*sr)); 664c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i) 66588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm set_reg (sr, i, DWARF_WHERE_SAME, 0); 66688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 66788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm switch (c->pi.format) 66888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 669c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm case UNW_INFO_FORMAT_TABLE: 670c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm case UNW_INFO_FORMAT_REMOTE_TABLE: 67188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = parse_fde (c, ip, sr); 67288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 67388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 67488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case UNW_INFO_FORMAT_DYNAMIC: 67588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = parse_dynamic (c, ip, sr); 67688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 67788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 67888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm default: 67988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm Debug (1, "Unexpected unwind-info format %d\n", c->pi.format); 68088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm ret = -UNW_EINVAL; 68188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 68288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 68388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 68488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 68588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmstatic inline int 68688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmeval_location_expr (struct dwarf_cursor *c, unw_addr_space_t as, 68788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_accessors_t *a, unw_word_t addr, 68888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm dwarf_loc_t *locp, void *arg) 68988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 69088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm int ret, is_register; 69188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_word_t len, val; 69288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 69388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* read the length of the expression: */ 69488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_read_uleb128 (as, a, &addr, &len, arg)) < 0) 69588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 69688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 69788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* evaluate the expression: */ 69888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = dwarf_eval_expr (c, &addr, len, &val, &is_register)) < 0) 69988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 70088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 70188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (is_register) 70288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm *locp = DWARF_REG_LOC (c, dwarf_to_unw_regnum (val)); 70388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm else 70488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm *locp = DWARF_MEM_LOC (c, val); 70588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 70688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return 0; 70788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 70888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 70988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmstatic int 71088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmapply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) 71188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 71200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma unw_word_t regnum, addr, cfa, ip; 71300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma unw_word_t prev_ip, prev_cfa; 71488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_addr_space_t as; 71588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm dwarf_loc_t cfa_loc; 71688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm unw_accessors_t *a; 71788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm int i, ret; 71888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm void *arg; 71988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 72000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma prev_ip = c->ip; 72100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma prev_cfa = c->cfa; 72200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 72388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm as = c->as; 72488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm arg = c->as_arg; 72588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm a = unw_get_accessors (as); 72688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 727c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm /* Evaluate the CFA first, because it may be referred to by other 72888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm expressions. */ 72988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 73088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG) 73188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 73288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* CFA is equal to [reg] + offset: */ 73388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 734642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm /* As a special-case, if the stack-pointer is the CFA and the 735642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm stack-pointer wasn't saved, popping the CFA implicitly pops 736642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm the stack-pointer as well. */ 737642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm if ((rs->reg[DWARF_CFA_REG_COLUMN].val == UNW_TDEP_SP) 738d7089547e2d13c2ae5f9ad896dc4bc5dc796fb0bArun Sharma && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg)) 739642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm && (rs->reg[UNW_TDEP_SP].where == DWARF_WHERE_SAME)) 740642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm cfa = c->cfa; 741642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm else 742642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm { 743642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm regnum = dwarf_to_unw_regnum (rs->reg[DWARF_CFA_REG_COLUMN].val); 744642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0) 745642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm return ret; 746642607dbaab4a55959c6ddb7f6853b2d28d935f7homeip.net!davidm } 74788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm cfa += rs->reg[DWARF_CFA_OFF_COLUMN].val; 74888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 74988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm else 75088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 75188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* CFA is equal to EXPR: */ 75288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 75388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm assert (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_EXPR); 75488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 75588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm addr = rs->reg[DWARF_CFA_REG_COLUMN].val; 75688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0) 75788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 758c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm /* the returned location better be a memory location... */ 759c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm if (DWARF_IS_REG_LOC (cfa_loc)) 760c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm return -UNW_EBADFRAME; 761c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm cfa = DWARF_GET_LOC (cfa_loc); 76288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 76388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 76488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) 76588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 76688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm switch ((dwarf_where_t) rs->reg[i].where) 76788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm { 76888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DWARF_WHERE_UNDEF: 76988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm c->loc[i] = DWARF_NULL_LOC; 77088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 77188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 77288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DWARF_WHERE_SAME: 77388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 77488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 77588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DWARF_WHERE_CFAREL: 77688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm c->loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg[i].val); 77788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 77888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 77988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DWARF_WHERE_REG: 78088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm c->loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg[i].val)); 78188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 78288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 78388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm case DWARF_WHERE_EXPR: 78488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm addr = rs->reg[i].val; 78569e300e8f6f5e9b136a70d5f3ca80fb8deac6666Jiri Olsa if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0) 78688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return ret; 78788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm break; 78888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 78988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm } 7904c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura 791c14371409aea0c3f90cdd00f529b347d8a5954f4mostang.com!davidm c->cfa = cfa; 7924c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura /* DWARF spec says undefined return address location means end of stack. */ 7934c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura if (DWARF_IS_NULL_LOC (c->loc[c->ret_addr_column])) 7944c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura c->ip = 0; 7954c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura else 7964c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura { 7974c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip); 7984c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura if (ret < 0) 7994c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura return ret; 8004c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura c->ip = ip; 8014c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura } 80200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 8034c553ceb2c3fcde6248b05953abc34e162917c4aLassi Tuura /* XXX: check for ip to be code_aligned */ 80400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (c->ip == prev_ip && c->cfa == prev_cfa) 80500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma { 806ec53de82ec7c00adb56c9e8b1b03d489a69c494bArun Sharma Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", 80700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma __FUNCTION__, (long) c->ip); 80800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma return -UNW_EBADFRAME; 80900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma } 8109e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura 8119e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura if (c->stash_frames) 8129e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura tdep_stash_frame (c, rs); 8139e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura 81400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma return 0; 81500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma} 81600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 81700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharmastatic int 81800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharmauncached_dwarf_find_save_locs (struct dwarf_cursor *c) 81900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma{ 82000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma dwarf_state_record_t sr; 82100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma int ret; 82200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 82300db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if ((ret = fetch_proc_info (c, c->ip, 1)) < 0) 824f92ecb61273bf58f9372f96868a9b8fb4d920ad4Arun Sharma { 825f92ecb61273bf58f9372f96868a9b8fb4d920ad4Arun Sharma put_unwind_info (c, &c->pi); 826f92ecb61273bf58f9372f96868a9b8fb4d920ad4Arun Sharma return ret; 827f92ecb61273bf58f9372f96868a9b8fb4d920ad4Arun Sharma } 82800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 82900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if ((ret = create_state_record_for (c, &sr, c->ip)) < 0) 830d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris { 831d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris /* ANDROID support update. */ 832d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris put_unwind_info (c, &c->pi); 833d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris /* End of ANDROID update. */ 834d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris return ret; 835d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris } 83600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 83700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if ((ret = apply_reg_state (c, &sr.rs_current)) < 0) 838d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris { 839d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris /* ANDROID support update. */ 840d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris put_unwind_info (c, &c->pi); 841d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris /* End of ANDROID update. */ 842d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris return ret; 843d3bf49b06c7d56b371fe49f13490f7e548a8455aChristopher Ferris } 84400db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 84500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma put_unwind_info (c, &c->pi); 84688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return 0; 84788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 84888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 84960b7af702ac56265798ec7202e05f0439c992360Arun Sharma/* The function finds the saved locations and applies the register 85060b7af702ac56265798ec7202e05f0439c992360Arun Sharma state as well. */ 85188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmHIDDEN int 85288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmdwarf_find_save_locs (struct dwarf_cursor *c) 85388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 8545f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#if defined(CONSERVE_STACK) 8555f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris dwarf_reg_state_t *rs_copy; 8565f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#else 8575f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris dwarf_reg_state_t rs_copy_stack; 8585f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris dwarf_reg_state_t *rs_copy = &rs_copy_stack; 8595f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#endif 8605f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris dwarf_reg_state_t *rs; 86100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma struct dwarf_rs_cache *cache; 8624312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma int ret = 0; 8634312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma intrmask_t saved_mask; 86488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 86500db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (c->as->caching_policy == UNW_CACHE_NONE) 86600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma return uncached_dwarf_find_save_locs (c); 86700db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 8684312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma cache = get_rs_cache(c->as, &saved_mask); 86900db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma rs = rs_lookup(cache, c); 87000db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 87100db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma if (rs) 872a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura { 873a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura c->ret_addr_column = rs->ret_addr_column; 874a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura c->use_prev_instr = ! rs->signal_frame; 875a9dce3c06e6ffcb83957e734d960505415118f00Lassi Tuura } 8762648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov else 8772648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov { 8785f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#if !defined(CONSERVE_STACK) 8795f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris dwarf_state_record_t sr_stack; 8805f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris dwarf_state_record_t *sr = &sr_stack; 8815f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#else 8825f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris dwarf_state_record_t *sr = (dwarf_state_record_t*)malloc(sizeof(dwarf_state_record_t)); 8835f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris 8845f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris if (sr == NULL) 8855f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris return -UNW_ENOMEM; 8865f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#endif 8875f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris 8882648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov if ((ret = fetch_proc_info (c, c->ip, 1)) < 0 || 8895f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris (ret = create_state_record_for (c, sr, c->ip)) < 0) 8902648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov { 891f92ecb61273bf58f9372f96868a9b8fb4d920ad4Arun Sharma put_rs_cache (c->as, cache, &saved_mask); 892f92ecb61273bf58f9372f96868a9b8fb4d920ad4Arun Sharma put_unwind_info (c, &c->pi); 8935f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#if defined(CONSERVE_STACK) 8945f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris free(sr); 8955f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#endif 8962648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov return ret; 8972648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov } 89800db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 8992648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov rs = rs_new (cache, c); 9005f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris memcpy(rs, &sr->rs_current, offsetof(struct dwarf_reg_state, ip)); 9012648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov cache->buckets[c->prev_rs].hint = rs - cache->buckets; 90200db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharma 9032648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov c->hint = rs->hint; 9042648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov c->prev_rs = rs - cache->buckets; 9053dfde7a3f089cf5c36ff7ed14d8d31034b5eafb8Arun Sharma 9062648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov put_unwind_info (c, &c->pi); 9075f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris 9085f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#if defined(CONSERVE_STACK) 9095f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris free(sr); 9105f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#endif 9112648a77f0499b2aeb3d624a1b44d2f1d2dd01835Paul Pluzhnikov } 9124312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma 9135f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#if defined(CONSERVE_STACK) 9145f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris rs_copy = (dwarf_reg_state_t*)malloc(sizeof(dwarf_reg_state_t)); 9155f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris if (rs_copy == NULL) 9165f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris return -UNW_ENOMEM; 9175f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#endif 9185f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris 9195f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris memcpy (rs_copy, rs, sizeof (*rs_copy)); 9204312719cbc30dfa9e188b24e85185c325e671d00Arun Sharma put_rs_cache (c->as, cache, &saved_mask); 921dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 9225f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris tdep_reuse_frame (c, rs_copy); 9235f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris ret = apply_reg_state (c, rs_copy); 92488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 9255f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#if defined(CONSERVE_STACK) 9265f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris free(rs_copy); 9275f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris#endif 9285f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris 9295f0e55ca7540d58e8c02dd67e1a062cad285f6c8Christopher Ferris return ret; 93088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 93188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 93288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm/* The proc-info must be valid for IP before this routine can be 93388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm called. */ 93488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmHIDDEN int 93588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmdwarf_create_state_record (struct dwarf_cursor *c, dwarf_state_record_t *sr) 93688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 93788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return create_state_record_for (c, sr, c->ip); 93888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 93988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm 94088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmHIDDEN int 94188160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidmdwarf_make_proc_info (struct dwarf_cursor *c) 94288160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm{ 94388160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#if 0 94488160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm if (c->as->caching_policy == UNW_CACHE_NONE 94588160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm || get_cached_proc_info (c) < 0) 94688160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm#endif 94788160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm /* Lookup it up the slow way... */ 94888160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return fetch_proc_info (c, c->ip, 0); 94988160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm return 0; 95088160e0f66447d25bdc4cd0024912e08175b4f58homeip.net!davidm} 951