138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm/* libunwind - a platform-independent unwind library 27f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm Copyright (C) 2003-2005 Hewlett-Packard Co 338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmThis file is part of libunwind. 638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmPermission is hereby granted, free of charge, to any person obtaining 838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidma copy of this software and associated documentation files (the 938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm"Software"), to deal in the Software without restriction, including 1038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmwithout limitation the rights to use, copy, modify, merge, publish, 1138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmdistribute, sublicense, and/or sell copies of the Software, and to 1238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmpermit persons to whom the Software is furnished to do so, subject to 1338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmthe following conditions: 1438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 1538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmThe above copyright notice and this permission notice shall be 1638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmincluded in all copies or substantial portions of the Software. 1738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 1838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 2238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 2338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 2538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 2638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm/* Logically, we like to think of the stack as a contiguous region of 2738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmmemory. Unfortunately, this logical view doesn't work for the 2838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmregister backing store, because the RSE is an asynchronous engine and 2938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmbecause UNIX/Linux allow for stack-switching via sigaltstack(2). 3038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmSpecifically, this means that any given stacked register may or may 3138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmnot be backed up by memory in the current stack. If not, then the 3238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmbacking memory may be found in any of the "more inner" (younger) 3338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmstacks. The routines in this file help manage the discontiguous 3438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmnature of the register backing store. The routines are completely 3538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmindependent of UNIX/Linux, but each stack frame that switches the 3638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmbacking store is expected to reserve 4 words for use by libunwind. For 3738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmexample, in the Linux sigcontext, sc_fr[0] and sc_fr[1] serve this 3838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmpurpose. */ 3938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 4038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm#include "unwind_i.h" 4138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 4296407911ee56be584395c491cffa2f4824647911hp.com!davidm#if UNW_DEBUG 4396407911ee56be584395c491cffa2f4824647911hp.com!davidm 4496407911ee56be584395c491cffa2f4824647911hp.com!davidmHIDDEN const char * 4596407911ee56be584395c491cffa2f4824647911hp.com!davidmia64_strloc (ia64_loc_t loc) 4696407911ee56be584395c491cffa2f4824647911hp.com!davidm{ 4796407911ee56be584395c491cffa2f4824647911hp.com!davidm static char buf[128]; 4896407911ee56be584395c491cffa2f4824647911hp.com!davidm 4996407911ee56be584395c491cffa2f4824647911hp.com!davidm if (IA64_IS_NULL_LOC (loc)) 5096407911ee56be584395c491cffa2f4824647911hp.com!davidm return "<null>"; 5196407911ee56be584395c491cffa2f4824647911hp.com!davidm 5296407911ee56be584395c491cffa2f4824647911hp.com!davidm buf[0] = '\0'; 5396407911ee56be584395c491cffa2f4824647911hp.com!davidm 5496407911ee56be584395c491cffa2f4824647911hp.com!davidm if (IA64_IS_MEMSTK_NAT (loc)) 5596407911ee56be584395c491cffa2f4824647911hp.com!davidm strcat (buf, "memstk_nat("); 5696407911ee56be584395c491cffa2f4824647911hp.com!davidm if (IA64_IS_UC_LOC (loc)) 5796407911ee56be584395c491cffa2f4824647911hp.com!davidm strcat (buf, "uc("); 5896407911ee56be584395c491cffa2f4824647911hp.com!davidm if (IA64_IS_FP_LOC (loc)) 5996407911ee56be584395c491cffa2f4824647911hp.com!davidm strcat (buf, "fp("); 6096407911ee56be584395c491cffa2f4824647911hp.com!davidm 6196407911ee56be584395c491cffa2f4824647911hp.com!davidm if (IA64_IS_REG_LOC (loc)) 6296407911ee56be584395c491cffa2f4824647911hp.com!davidm sprintf (buf + strlen (buf), "%s", unw_regname (IA64_GET_REG (loc))); 6396407911ee56be584395c491cffa2f4824647911hp.com!davidm else 6496407911ee56be584395c491cffa2f4824647911hp.com!davidm sprintf (buf + strlen (buf), "0x%llx", 6596407911ee56be584395c491cffa2f4824647911hp.com!davidm (unsigned long long) IA64_GET_ADDR (loc)); 6696407911ee56be584395c491cffa2f4824647911hp.com!davidm 6796407911ee56be584395c491cffa2f4824647911hp.com!davidm if (IA64_IS_FP_LOC (loc)) 6896407911ee56be584395c491cffa2f4824647911hp.com!davidm strcat (buf, ")"); 6996407911ee56be584395c491cffa2f4824647911hp.com!davidm if (IA64_IS_UC_LOC (loc)) 7096407911ee56be584395c491cffa2f4824647911hp.com!davidm strcat (buf, ")"); 7196407911ee56be584395c491cffa2f4824647911hp.com!davidm if (IA64_IS_MEMSTK_NAT (loc)) 7296407911ee56be584395c491cffa2f4824647911hp.com!davidm strcat (buf, ")"); 7396407911ee56be584395c491cffa2f4824647911hp.com!davidm 7496407911ee56be584395c491cffa2f4824647911hp.com!davidm return buf; 7596407911ee56be584395c491cffa2f4824647911hp.com!davidm} 7696407911ee56be584395c491cffa2f4824647911hp.com!davidm 7796407911ee56be584395c491cffa2f4824647911hp.com!davidm#endif /* UNW_DEBUG */ 7896407911ee56be584395c491cffa2f4824647911hp.com!davidm 7938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmHIDDEN int 8038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmrbs_switch (struct cursor *c, 8138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm unw_word_t saved_bsp, unw_word_t saved_bspstore, 8238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm ia64_loc_t saved_rnat_loc) 8338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm{ 8438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm struct rbs_area *rbs = &c->rbs_area[c->rbs_curr]; 8519e3bf3ea675ea64dbe23730e2600ae99ab0b187hp.com!davidm unw_word_t lo, ndirty, rbs_base; 8619e3bf3ea675ea64dbe23730e2600ae99ab0b187hp.com!davidm int ret; 8738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 88f20eb7ea72c517e53165d86e1be4d421d1f7bf22hp.com!davidm Debug (10, "(left=%u, curr=%u)\n", c->rbs_left_edge, c->rbs_curr); 8938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 9038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm /* Calculate address "lo" at which the backing store starts: */ 917f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm ndirty = rse_num_regs (saved_bspstore, saved_bsp); 927f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm lo = rse_skip_regs (c->bsp, -ndirty); 9338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 9438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm rbs->size = (rbs->end - lo); 9538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 9638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm /* If the previously-recorded rbs-area is empty we don't need to 9738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm track it and we can simply overwrite it... */ 9838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm if (rbs->size) 9938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm { 100f20eb7ea72c517e53165d86e1be4d421d1f7bf22hp.com!davidm Debug (10, "inner=[0x%lx-0x%lx)\n", 10138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm (long) (rbs->end - rbs->size), (long) rbs->end); 10238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 1037f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm c->rbs_curr = (c->rbs_curr + 1) % ARRAY_SIZE (c->rbs_area); 10438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm rbs = c->rbs_area + c->rbs_curr; 10538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 10638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm if (c->rbs_curr == c->rbs_left_edge) 1077f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm c->rbs_left_edge = (c->rbs_left_edge + 1) % ARRAY_SIZE (c->rbs_area); 10838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm } 10919e3bf3ea675ea64dbe23730e2600ae99ab0b187hp.com!davidm 11019e3bf3ea675ea64dbe23730e2600ae99ab0b187hp.com!davidm if ((ret = rbs_get_base (c, saved_bspstore, &rbs_base)) < 0) 11119e3bf3ea675ea64dbe23730e2600ae99ab0b187hp.com!davidm return ret; 11219e3bf3ea675ea64dbe23730e2600ae99ab0b187hp.com!davidm 11338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm rbs->end = saved_bspstore; 11419e3bf3ea675ea64dbe23730e2600ae99ab0b187hp.com!davidm rbs->size = saved_bspstore - rbs_base; 11538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm rbs->rnat_loc = saved_rnat_loc; 11638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 11738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm c->bsp = saved_bsp; 11838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 11919e3bf3ea675ea64dbe23730e2600ae99ab0b187hp.com!davidm Debug (10, "outer=[0x%llx-0x%llx), rnat@%s\n", (long long) rbs_base, 12038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm (long long) rbs->end, ia64_strloc (rbs->rnat_loc)); 12138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm return 0; 12238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm} 12338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 12438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmHIDDEN int 12538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmrbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip, 12638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm ia64_loc_t *locp, ia64_loc_t *rnat_locp) 12738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm{ 12838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm unw_word_t nregs, bsp = c->bsp, curr = c->rbs_curr, n; 12938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm unw_word_t left_edge = c->rbs_left_edge; 13038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm#if UNW_DEBUG 13138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm int reg = 32 + regs_to_skip; 13238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm#endif 13338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 13438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm while (!rbs_contains (&c->rbs_area[curr], bsp)) 13538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm { 13638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm if (curr == left_edge) 13738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm { 13838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm Debug (1, "could not find register r%d!\n", reg); 13938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm return -UNW_EBADREG; 14038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm } 14138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 1427f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm n = rse_num_regs (c->rbs_area[curr].end, bsp); 1437f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) % ARRAY_SIZE (c->rbs_area); 1447f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm bsp = rse_skip_regs (c->rbs_area[curr].end - c->rbs_area[curr].size, n); 14538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm } 14638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 14738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm while (1) 14838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm { 1497f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm nregs = rse_num_regs (bsp, c->rbs_area[curr].end); 15038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 15138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm if (regs_to_skip < nregs) 15238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm { 15338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm /* found it: */ 15438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm unw_word_t addr; 15538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 1567f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm addr = rse_skip_regs (bsp, regs_to_skip); 15738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm if (locp) 15838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm *locp = rbs_loc (c->rbs_area + curr, addr); 15938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm if (rnat_locp) 16038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm *rnat_locp = rbs_get_rnat_loc (c->rbs_area + curr, addr); 16138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm return 0; 16238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm } 16338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 16438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm if (curr == left_edge) 16538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm { 16638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm Debug (1, "could not find register r%d!\n", reg); 16738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm return -UNW_EBADREG; 16838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm } 16938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 17038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm regs_to_skip -= nregs; 17138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 1727f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) % ARRAY_SIZE (c->rbs_area); 17338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm bsp = c->rbs_area[curr].end - c->rbs_area[curr].size; 17438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm } 17538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm} 17638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 17796407911ee56be584395c491cffa2f4824647911hp.com!davidm#ifdef NEED_RBS_COVER_AND_FLUSH 178cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm 17938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmstatic inline int 18038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmget_rnat (struct cursor *c, struct rbs_area *rbs, unw_word_t bsp, 181cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm unw_word_t *__restrict rnatp) 18238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm{ 183cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm ia64_loc_t rnat_locp = rbs_get_rnat_loc (rbs, bsp); 184cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm 185cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm return ia64_get (c, rnat_locp, rnatp); 18638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm} 18738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 188cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm/* Simulate the effect of "cover" followed by a "flushrs" for the 189cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm target-frame. However, since the target-frame's backing store 190cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm may not have space for the registers that got spilled onto other 191cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm rbs-areas, we save those registers to DIRTY_PARTITION where 192cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm we can then load them via a single "loadrs". 193cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm 194cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm This function returns the size of the dirty-partition that was 195cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm created or a negative error-code in case of error. 19638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 19738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm Note: This does not modify the rbs_area[] structure in any way. */ 19838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidmHIDDEN int 199cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidmrbs_cover_and_flush (struct cursor *c, unw_word_t nregs, 200cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm unw_word_t *dirty_partition, unw_word_t *dirty_rnat, 201cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm unw_word_t *bspstore) 20238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm{ 203cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm unw_word_t n, src_mask, dst_mask, bsp, *dst, src_rnat, dst_rnat = 0; 204cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm unw_word_t curr = c->rbs_curr, left_edge = c->rbs_left_edge; 205cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm struct rbs_area *rbs = c->rbs_area + curr; 20638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm int ret; 20738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 208cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm bsp = c->bsp; 2097f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm c->bsp = rse_skip_regs (bsp, nregs); 21038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 211cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm if (likely (rbs_contains (rbs, bsp))) 21238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm { 213cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm /* at least _some_ registers are on rbs... */ 2147f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm n = rse_num_regs (bsp, rbs->end); 215cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm if (likely (n >= nregs)) 216cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm { 217cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm /* common case #1: all registers are on current rbs... */ 218cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm /* got lucky: _all_ registers are on rbs... */ 219cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm ia64_loc_t rnat_loc = rbs_get_rnat_loc (rbs, c->bsp); 22038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 221cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm *bspstore = c->bsp; 22238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 223cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm if (IA64_IS_REG_LOC (rnat_loc)) 224cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm { 225cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm unw_word_t rnat_addr = (unw_word_t) 226cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm tdep_uc_addr (c->as_arg, UNW_IA64_AR_RNAT, NULL); 227cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm rnat_loc = IA64_LOC_ADDR (rnat_addr, 0); 228cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm } 229cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm c->loc[IA64_REG_RNAT] = rnat_loc; 230cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm return 0; /* all done */ 231cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm } 232cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm nregs -= n; /* account for registers already on the rbs */ 23338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 2347f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm assert (rse_skip_regs (c->bsp, -nregs) == rse_skip_regs (rbs->end, 0)); 23538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm } 236cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm else 237cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm /* Earlier frames also didn't get spilled; need to "loadrs" those, 238cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm too... */ 2397f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm nregs += rse_num_regs (rbs->end, bsp); 240cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm 241cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm /* OK, we need to copy NREGS registers to the dirty partition. */ 242cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm 243cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm *bspstore = bsp = rbs->end; 244cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm c->loc[IA64_REG_RNAT] = rbs->rnat_loc; 245cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm assert (!IA64_IS_REG_LOC (rbs->rnat_loc)); 24638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 247cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm dst = dirty_partition; 248cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm 249cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm while (nregs > 0) 25038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm { 251cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm if (unlikely (!rbs_contains (rbs, bsp))) 25238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm { 253cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm /* switch to next non-empty rbs-area: */ 254cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm do 25538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm { 256cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm if (curr == left_edge) 257cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm { 258cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm Debug (0, "rbs-underflow while flushing %lu regs, " 259cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm "bsp=0x%lx, dst=0x%p\n", (unsigned long) nregs, 260cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm (unsigned long) bsp, dst); 261cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm return -UNW_EBADREG; 262cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm } 263cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm 2647f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm assert (rse_num_regs (rbs->end, bsp) == 0); 265cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm 2667f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) 2677f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm % ARRAY_SIZE (c->rbs_area); 268cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm rbs = c->rbs_area + curr; 269cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm bsp = rbs->end - rbs->size; 27038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm } 271cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm while (rbs->size == 0); 27238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 273cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm if ((ret = get_rnat (c, rbs, bsp, &src_rnat)) < 0) 274cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm return ret; 275cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm } 27638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 2777f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm if (unlikely (rse_is_rnat_slot (bsp))) 278cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm { 279cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm bsp += 8; 280cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm if ((ret = get_rnat (c, rbs, bsp, &src_rnat)) < 0) 281cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm return ret; 282cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm } 2837f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm if (unlikely (rse_is_rnat_slot ((unw_word_t) dst))) 284cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm { 285cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm *dst++ = dst_rnat; 286cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm dst_rnat = 0; 287cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm } 28838b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 2897f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm src_mask = ((unw_word_t) 1) << rse_slot_num (bsp); 2907f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm dst_mask = ((unw_word_t) 1) << rse_slot_num ((unw_word_t) dst); 29138b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 29238b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm if (src_rnat & src_mask) 29338b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm dst_rnat |= dst_mask; 29438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm else 29538b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm dst_rnat &= ~dst_mask; 29638b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 297cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm /* copy one slot: */ 298cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm if ((ret = ia64_get (c, rbs_loc (rbs, bsp), dst)) < 0) 29938b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm return ret; 30038b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm 301cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm /* advance to next slot: */ 302cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm --nregs; 303cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm bsp += 8; 304cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm ++dst; 305cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm } 3067f8b54ae5c0aae5bc2574b727946c8b9ecccc09dmostang.com!davidm if (unlikely (rse_is_rnat_slot ((unw_word_t) dst))) 307cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm { 308cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm /* The LOADRS instruction loads "the N bytes below the current 309cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm BSP" but BSP can never point to an RNaT slot so if the last 310cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm destination word happens to be an RNaT slot, we need to write 311cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm that slot now. */ 312cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm *dst++ = dst_rnat; 313cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm dst_rnat = 0; 31438b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm } 315cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm *dirty_rnat = dst_rnat; 316cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm return (char *) dst - (char *) dirty_partition; 31738b586f953d19b8d775b8165d76567f8eae5f3d7homeip.net!davidm} 318cd69bfec0c6e20fef5ea60e8f8363cb773e79065hp.com!davidm 31981f4953a1f3114dfe328a0fe6126527cd9c8c1e6mostang.com!davidm#endif /* !UNW_REMOTE_ONLY */ 320