1f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm/* libunwind - a platform-independent unwind library 287081cebabb0525d4e3085cfdc3f751fbc5c8239mostang.com!davidm Copyright (C) 2001-2005 Hewlett-Packard Co 3f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 4f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 5f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmThis file is part of libunwind. 6f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 7f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmPermission is hereby granted, free of charge, to any person obtaining 8f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidma copy of this software and associated documentation files (the 9f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm"Software"), to deal in the Software without restriction, including 10f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmwithout limitation the rights to use, copy, modify, merge, publish, 11f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmdistribute, sublicense, and/or sell copies of the Software, and to 12f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmpermit persons to whom the Software is furnished to do so, subject to 13f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmthe following conditions: 14f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 15f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmThe above copyright notice and this permission notice shall be 16f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmincluded in all copies or substantial portions of the Software. 17f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 18f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 22f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 25f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 26f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm#include "offsets.h" 27f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm#include "unwind_i.h" 28f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 29f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmstatic inline int 3026fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidmlinux_sigtramp (struct cursor *c, ia64_loc_t prev_cfm_loc, 3126fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm unw_word_t *num_regsp) 32f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm{ 33f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm#if defined(UNW_LOCAL_ONLY) && !defined(__linux) 34f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return -UNW_EINVAL; 35f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm#else 36f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm unw_word_t sc_addr; 37f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm int ret; 38f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 39f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if ((ret = ia64_get (c, IA64_LOC_ADDR (c->sp + 0x10 40f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm + LINUX_SIGFRAME_ARG2_OFF, 0), 41f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm &sc_addr)) < 0) 42f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 43f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 44f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->sigcontext_addr = sc_addr; 45f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 46f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (!IA64_IS_REG_LOC (c->loc[IA64_REG_IP]) 47f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm && IA64_GET_ADDR (c->loc[IA64_REG_IP]) == sc_addr + LINUX_SC_BR_OFF + 8) 48f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm { 49f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* Linux kernels before 2.4.19 and 2.5.10 had buggy 50f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm unwind info for sigtramp. Fix it up here. */ 51f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_IP] = IA64_LOC_ADDR (sc_addr + LINUX_SC_IP_OFF, 0); 52f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->cfm_loc = IA64_LOC_ADDR (sc_addr + LINUX_SC_CFM_OFF, 0); 53f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm } 54f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 55f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* do what can't be described by unwind directives: */ 56f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_PFS] = IA64_LOC_ADDR (sc_addr + LINUX_SC_AR_PFS_OFF, 0); 5726fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm c->ec_loc = prev_cfm_loc; 58f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm *num_regsp = c->cfm & 0x7f; /* size of frame */ 59f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return 0; 60f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm#endif 61f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm} 62f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 63f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmstatic inline int 6426fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidmlinux_interrupt (struct cursor *c, ia64_loc_t prev_cfm_loc, 6526fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm unw_word_t *num_regsp, int marker) 66f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm{ 676675be4926ff3989da0542ed19c55ab3a01df010hp.com!davidm#if defined(UNW_LOCAL_ONLY) && !(defined(__linux) && defined(__KERNEL__)) 68f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return -UNW_EINVAL; 69f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm#else 70f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm unw_word_t sc_addr, num_regs; 71f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm ia64_loc_t pfs_loc; 72f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 73f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm sc_addr = c->sigcontext_addr = c->sp + 0x10; 74f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 75f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if ((c->pr & (1UL << LINUX_PT_P_NONSYS)) != 0) 76f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm num_regs = c->cfm & 0x7f; 77f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm else 78f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm num_regs = 0; 79f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 80f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* do what can't be described by unwind directives: */ 81f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (marker == ABI_MARKER_OLD_LINUX_INTERRUPT) 82f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm pfs_loc = IA64_LOC_ADDR (sc_addr + LINUX_OLD_PT_PFS_OFF, 0); 83f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm else 84f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm pfs_loc = IA64_LOC_ADDR (sc_addr + LINUX_PT_PFS_OFF, 0); 85f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_PFS] = pfs_loc; 8626fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm c->ec_loc = prev_cfm_loc; 87f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm *num_regsp = num_regs; /* size of frame */ 88f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return 0; 89f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm#endif 90f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm} 91f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 92f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmstatic inline int 9326fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidmhpux_sigtramp (struct cursor *c, ia64_loc_t prev_cfm_loc, 9426fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm unw_word_t *num_regsp) 95f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm{ 96f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm#if defined(UNW_LOCAL_ONLY) && !defined(__hpux) 97f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return -UNW_EINVAL; 98f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm#else 99f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm unw_word_t sc_addr, bsp, bspstore; 100f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm ia64_loc_t sc_loc; 101f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm int ret, i; 102f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 103f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* HP-UX passes the address of ucontext_t in r32: */ 104f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if ((ret = ia64_get_stacked (c, 32, &sc_loc, NULL)) < 0) 105f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 106f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if ((ret = ia64_get (c, sc_loc, &sc_addr)) < 0) 107f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 108f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 109f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->sigcontext_addr = sc_addr; 110f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 111f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* Now mark all (preserved) registers as coming from the 112f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm signal context: */ 113f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->cfm_loc = IA64_LOC_UC_REG (UNW_IA64_CFM, sc_addr); 114f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_PRI_UNAT_MEM] = IA64_NULL_LOC; 115f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_PSP] = IA64_LOC_UC_REG (UNW_IA64_GR + 12, sc_addr); 116f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_BSP] = IA64_LOC_UC_REG (UNW_IA64_AR_BSP, sc_addr); 117f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_BSPSTORE] = IA64_LOC_UC_REG (UNW_IA64_AR_BSPSTORE, sc_addr); 118f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_PFS] = IA64_LOC_UC_REG (UNW_IA64_AR_PFS, sc_addr); 119f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_RNAT] = IA64_LOC_UC_REG (UNW_IA64_AR_RNAT, sc_addr); 120f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_IP] = IA64_LOC_UC_REG (UNW_IA64_IP, sc_addr); 121f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_R4] = IA64_LOC_UC_REG (UNW_IA64_GR + 4, sc_addr); 122f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_R5] = IA64_LOC_UC_REG (UNW_IA64_GR + 5, sc_addr); 123f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_R6] = IA64_LOC_UC_REG (UNW_IA64_GR + 6, sc_addr); 124f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_R7] = IA64_LOC_UC_REG (UNW_IA64_GR + 7, sc_addr); 125f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_NAT4] = IA64_LOC_UC_REG (UNW_IA64_NAT + 4, sc_addr); 126f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_NAT5] = IA64_LOC_UC_REG (UNW_IA64_NAT + 5, sc_addr); 127f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_NAT6] = IA64_LOC_UC_REG (UNW_IA64_NAT + 6, sc_addr); 128f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_NAT7] = IA64_LOC_UC_REG (UNW_IA64_NAT + 7, sc_addr); 129f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_UNAT] = IA64_LOC_UC_REG (UNW_IA64_AR_UNAT, sc_addr); 130f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_PR] = IA64_LOC_UC_REG (UNW_IA64_PR, sc_addr); 131f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_LC] = IA64_LOC_UC_REG (UNW_IA64_AR_LC, sc_addr); 132f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_FPSR] = IA64_LOC_UC_REG (UNW_IA64_AR_FPSR, sc_addr); 133f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_B1] = IA64_LOC_UC_REG (UNW_IA64_BR + 1, sc_addr); 134f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_B2] = IA64_LOC_UC_REG (UNW_IA64_BR + 2, sc_addr); 135f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_B3] = IA64_LOC_UC_REG (UNW_IA64_BR + 3, sc_addr); 136f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_B4] = IA64_LOC_UC_REG (UNW_IA64_BR + 4, sc_addr); 137f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_B5] = IA64_LOC_UC_REG (UNW_IA64_BR + 5, sc_addr); 138f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_F2] = IA64_LOC_UC_REG (UNW_IA64_FR + 2, sc_addr); 139f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_F3] = IA64_LOC_UC_REG (UNW_IA64_FR + 3, sc_addr); 140f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_F4] = IA64_LOC_UC_REG (UNW_IA64_FR + 4, sc_addr); 141f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_F5] = IA64_LOC_UC_REG (UNW_IA64_FR + 5, sc_addr); 142f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm for (i = 0; i < 16; ++i) 143f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_F16 + i] = IA64_LOC_UC_REG (UNW_IA64_FR + 16 + i, sc_addr); 144f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 145f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->pi.flags |= UNW_PI_FLAG_IA64_RBS_SWITCH; 146f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 147f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* update the CFM cache: */ 148f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if ((ret = ia64_get (c, c->cfm_loc, &c->cfm)) < 0) 149f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 150f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* update the PSP cache: */ 151f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if ((ret = ia64_get (c, c->loc[IA64_REG_PSP], &c->psp)) < 0) 152f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 153f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 154f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if ((ret = ia64_get (c, c->loc[IA64_REG_BSP], &bsp)) < 0 155f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm || (ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &bspstore)) < 0) 156f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 157f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (bspstore < bsp) 158f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* Dirty partition got spilled into the ucontext_t structure 159f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm itself. We'll need to access it via uc_access(3). */ 160f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm rbs_switch (c, bsp, bspstore, IA64_LOC_UC_ADDR (bsp | 0x1f8, 0)); 161f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 16226fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm c->ec_loc = prev_cfm_loc; 16326fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm 16426fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm *num_regsp = 0; 165f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return 0; 166f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm#endif 167f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm} 168f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 169f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 170f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmstatic inline int 171f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmcheck_rbs_switch (struct cursor *c) 172f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm{ 173f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm unw_word_t saved_bsp, saved_bspstore, loadrs, ndirty; 174f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm int ret = 0; 175f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 176f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm saved_bsp = c->bsp; 177f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (c->pi.flags & UNW_PI_FLAG_IA64_RBS_SWITCH) 178f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm { 179f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* Got ourselves a frame that has saved ar.bspstore, ar.bsp, 180f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm and ar.rnat, so we're all set for rbs-switching: */ 181f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if ((ret = ia64_get (c, c->loc[IA64_REG_BSP], &saved_bsp)) < 0 182f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm || (ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &saved_bspstore))) 183f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 184f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm } 185f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm else if ((c->abi_marker == ABI_MARKER_LINUX_SIGTRAMP 186f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm || c->abi_marker == ABI_MARKER_OLD_LINUX_SIGTRAMP) 187f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm && !IA64_IS_REG_LOC (c->loc[IA64_REG_BSP]) 188f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm && (IA64_GET_ADDR (c->loc[IA64_REG_BSP]) 189f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm == c->sigcontext_addr + LINUX_SC_AR_BSP_OFF)) 190f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm { 191f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* When Linux delivers a signal on an alternate stack, it 192f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm does things a bit differently from what the unwind 193f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm conventions allow us to describe: instead of saving 194f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm ar.rnat, ar.bsp, and ar.bspstore, it saves the former two 195f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm plus the "loadrs" value. Because of this, we need to 196f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm detect & record a potential rbs-area switch 197f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm manually... */ 198f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 199f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* If ar.bsp has been saved already AND the current bsp is 200f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm not equal to the saved value, then we know for sure that 201f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm we're past the point where the backing store has been 202f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm switched (and before the point where it's restored). */ 203f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if ((ret = ia64_get (c, IA64_LOC_ADDR (c->sigcontext_addr 204f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm + LINUX_SC_AR_BSP_OFF, 0), 205f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm &saved_bsp) < 0) 206f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm || (ret = ia64_get (c, IA64_LOC_ADDR (c->sigcontext_addr 207f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm + LINUX_SC_LOADRS_OFF, 0), 208f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm &loadrs) < 0)) 209f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 210f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm loadrs >>= 16; 21187081cebabb0525d4e3085cfdc3f751fbc5c8239mostang.com!davidm ndirty = rse_num_regs (c->bsp - loadrs, c->bsp); 21287081cebabb0525d4e3085cfdc3f751fbc5c8239mostang.com!davidm saved_bspstore = rse_skip_regs (saved_bsp, -ndirty); 213f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm } 214f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 215f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (saved_bsp == c->bsp) 216f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return 0; 217f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 218f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return rbs_switch (c, saved_bsp, saved_bspstore, c->loc[IA64_REG_RNAT]); 219f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm} 220f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 221f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmstatic inline int 222f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmupdate_frame_state (struct cursor *c) 223f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm{ 224f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm unw_word_t prev_ip, prev_sp, prev_bsp, ip, num_regs; 22526fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm ia64_loc_t prev_cfm_loc; 226f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm int ret; 227f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 22826fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm prev_cfm_loc = c->cfm_loc; 229f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm prev_ip = c->ip; 230f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm prev_sp = c->sp; 231f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm prev_bsp = c->bsp; 232f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 233f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* Update the IP cache (do this first: if we reach the end of the 234f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm frame-chain, the rest of the info may not be valid/useful 235f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm anymore. */ 236f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm ret = ia64_get (c, c->loc[IA64_REG_IP], &ip); 237f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (ret < 0) 238f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 239f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->ip = ip; 240f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 241f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if ((ip & 0xc) != 0) 242f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm { 243f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* don't let obviously bad addresses pollute the cache */ 244f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm Debug (1, "rejecting bad ip=0x%lx\n", (long) c->ip); 245f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return -UNW_EINVALIDIP; 246f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm } 247f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 248f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->cfm_loc = c->loc[IA64_REG_PFS]; 249f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* update the CFM cache: */ 250f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm ret = ia64_get (c, c->cfm_loc, &c->cfm); 251f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (ret < 0) 252f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 253f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 25426fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm /* Normally, AR.EC is stored in the CFM save-location. That 25526fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm save-location contains the full function-state as defined by 25626fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm AR.PFS. However, interruptions only save the frame-marker, not 25726fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm any other info in CFM. Instead, AR.EC gets saved on the first 25826fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm call by the interruption-handler. Thus, interruption-related 25926fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm frames need to track the _previous_ CFM save-location since 26026fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm that's were AR.EC is saved. We support this by setting ec_loc to 26126fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm cfm_loc by default and giving frames marked with an ABI-marker 26226fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm the chance to override this value with prev_cfm_loc. */ 26326fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm c->ec_loc = c->cfm_loc; 26426fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm 265f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm num_regs = 0; 266f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (unlikely (c->abi_marker)) 267f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm { 268f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->last_abi_marker = c->abi_marker; 2696675be4926ff3989da0542ed19c55ab3a01df010hp.com!davidm switch (ia64_get_abi_marker (c)) 270f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm { 271f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm case ABI_MARKER_LINUX_SIGTRAMP: 272f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm case ABI_MARKER_OLD_LINUX_SIGTRAMP: 2736675be4926ff3989da0542ed19c55ab3a01df010hp.com!davidm ia64_set_abi (c, ABI_LINUX); 27426fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm if ((ret = linux_sigtramp (c, prev_cfm_loc, &num_regs)) < 0) 275f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 276f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm break; 277f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 278f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm case ABI_MARKER_OLD_LINUX_INTERRUPT: 279f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm case ABI_MARKER_LINUX_INTERRUPT: 2806675be4926ff3989da0542ed19c55ab3a01df010hp.com!davidm ia64_set_abi (c, ABI_LINUX); 28126fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm if ((ret = linux_interrupt (c, prev_cfm_loc, &num_regs, 28226fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm c->abi_marker)) < 0) 283f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 284f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm break; 285f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 286f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm case ABI_MARKER_HP_UX_SIGTRAMP: 2876675be4926ff3989da0542ed19c55ab3a01df010hp.com!davidm ia64_set_abi (c, ABI_HPUX); 28826fdb45d764982fc6847f07caf42e56a343d410dhp.com!davidm if ((ret = hpux_sigtramp (c, prev_cfm_loc, &num_regs)) < 0) 289f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 290f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm break; 291f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 292f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm default: 293f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm Debug (1, "unknown ABI marker: ABI=%u, context=%u\n", 294f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->abi_marker >> 8, c->abi_marker & 0xff); 295f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return -UNW_EINVAL; 296f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm } 297f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm Debug (12, "sigcontext_addr=%lx (ret=%d)\n", 298f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm (unsigned long) c->sigcontext_addr, ret); 299f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 300f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->sigcontext_off = c->sigcontext_addr - c->sp; 301f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 302f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* update the IP cache: */ 303f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if ((ret = ia64_get (c, c->loc[IA64_REG_IP], &ip)) < 0) 304f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 305f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->ip = ip; 306f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (ip == 0) 307f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* end of frame-chain reached */ 308f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return 0; 309f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm } 310f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm else 311f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm num_regs = (c->cfm >> 7) & 0x7f; /* size of locals */ 312f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 313f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (!IA64_IS_NULL_LOC (c->loc[IA64_REG_BSP])) 314f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm { 315f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm ret = check_rbs_switch (c); 316f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (ret < 0) 317f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 318f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm } 319f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 32087081cebabb0525d4e3085cfdc3f751fbc5c8239mostang.com!davidm c->bsp = rse_skip_regs (c->bsp, -num_regs); 321f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 322f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->sp = c->psp; 323f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->abi_marker = 0; 324f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 325f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (c->ip == prev_ip && c->sp == prev_sp && c->bsp == prev_bsp) 326f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm { 327ec53de82ec7c00adb56c9e8b1b03d489a69c494bArun Sharma Dprintf ("%s: ip, sp, and bsp unchanged; stopping here (ip=0x%lx)\n", 328f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm __FUNCTION__, (long) ip); 329f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return -UNW_EBADFRAME; 330f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm } 331f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 332f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* as we unwind, the saved ar.unat becomes the primary unat: */ 333f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->loc[IA64_REG_PRI_UNAT_MEM] = c->loc[IA64_REG_UNAT]; 334f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 335f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm /* restore the predicates: */ 336f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm ret = ia64_get (c, c->loc[IA64_REG_PR], &c->pr); 337f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm if (ret < 0) 338f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return ret; 339f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 340f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm c->pi_valid = 0; 341f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm return 0; 342f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm} 343f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 344f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 345f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmPROTECTED int 346f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidmunw_step (unw_cursor_t *cursor) 347f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm{ 348f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm struct cursor *c = (struct cursor *) cursor; 349f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm int ret; 350f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 35187081cebabb0525d4e3085cfdc3f751fbc5c8239mostang.com!davidm Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->ip); 352f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 35387081cebabb0525d4e3085cfdc3f751fbc5c8239mostang.com!davidm if ((ret = ia64_find_save_locs (c)) >= 0 35487081cebabb0525d4e3085cfdc3f751fbc5c8239mostang.com!davidm && (ret = update_frame_state (c)) >= 0) 35587081cebabb0525d4e3085cfdc3f751fbc5c8239mostang.com!davidm ret = (c->ip == 0) ? 0 : 1; 356f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm 3576675be4926ff3989da0542ed19c55ab3a01df010hp.com!davidm Debug (2, "returning %d (ip=0x%016lx)\n", ret, (unsigned long) c->ip); 35887081cebabb0525d4e3085cfdc3f751fbc5c8239mostang.com!davidm return ret; 359f1734db27381d83b4c2f9395d55cef37a766bcd2homeip.net!davidm} 360