Home | History | Annotate | Download | only in ia64
      1 /* libunwind - a platform-independent unwind library
      2    Copyright (C) 2003-2005 Hewlett-Packard Co
      3 	Contributed by David Mosberger-Tang <davidm (at) hpl.hp.com>
      4 
      5 This file is part of libunwind.
      6 
      7 Permission is hereby granted, free of charge, to any person obtaining
      8 a copy of this software and associated documentation files (the
      9 "Software"), to deal in the Software without restriction, including
     10 without limitation the rights to use, copy, modify, merge, publish,
     11 distribute, sublicense, and/or sell copies of the Software, and to
     12 permit persons to whom the Software is furnished to do so, subject to
     13 the following conditions:
     14 
     15 The above copyright notice and this permission notice shall be
     16 included in all copies or substantial portions of the Software.
     17 
     18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
     25 
     26 /* Logically, we like to think of the stack as a contiguous region of
     27 memory.  Unfortunately, this logical view doesn't work for the
     28 register backing store, because the RSE is an asynchronous engine and
     29 because UNIX/Linux allow for stack-switching via sigaltstack(2).
     30 Specifically, this means that any given stacked register may or may
     31 not be backed up by memory in the current stack.  If not, then the
     32 backing memory may be found in any of the "more inner" (younger)
     33 stacks.  The routines in this file help manage the discontiguous
     34 nature of the register backing store.  The routines are completely
     35 independent of UNIX/Linux, but each stack frame that switches the
     36 backing store is expected to reserve 4 words for use by libunwind. For
     37 example, in the Linux sigcontext, sc_fr[0] and sc_fr[1] serve this
     38 purpose.  */
     39 
     40 #include "unwind_i.h"
     41 
     42 #if UNW_DEBUG
     43 
     44 HIDDEN const char *
     45 ia64_strloc (ia64_loc_t loc)
     46 {
     47   static char buf[128];
     48 
     49   if (IA64_IS_NULL_LOC (loc))
     50     return "<null>";
     51 
     52   buf[0] = '\0';
     53 
     54   if (IA64_IS_MEMSTK_NAT (loc))
     55     strcat (buf, "memstk_nat(");
     56   if (IA64_IS_UC_LOC (loc))
     57     strcat (buf, "uc(");
     58   if (IA64_IS_FP_LOC (loc))
     59     strcat (buf, "fp(");
     60 
     61   if (IA64_IS_REG_LOC (loc))
     62     sprintf (buf + strlen (buf), "%s", unw_regname (IA64_GET_REG (loc)));
     63   else
     64     sprintf (buf + strlen (buf), "0x%llx",
     65 	     (unsigned long long) IA64_GET_ADDR (loc));
     66 
     67   if (IA64_IS_FP_LOC (loc))
     68     strcat (buf, ")");
     69   if (IA64_IS_UC_LOC (loc))
     70     strcat (buf, ")");
     71   if (IA64_IS_MEMSTK_NAT (loc))
     72     strcat (buf, ")");
     73 
     74   return buf;
     75 }
     76 
     77 #endif /* UNW_DEBUG */
     78 
     79 HIDDEN int
     80 rbs_switch (struct cursor *c,
     81 	    unw_word_t saved_bsp, unw_word_t saved_bspstore,
     82 	    ia64_loc_t saved_rnat_loc)
     83 {
     84   struct rbs_area *rbs = &c->rbs_area[c->rbs_curr];
     85   unw_word_t lo, ndirty, rbs_base;
     86   int ret;
     87 
     88   Debug (10, "(left=%u, curr=%u)\n", c->rbs_left_edge, c->rbs_curr);
     89 
     90   /* Calculate address "lo" at which the backing store starts:  */
     91   ndirty = rse_num_regs (saved_bspstore, saved_bsp);
     92   lo = rse_skip_regs (c->bsp, -ndirty);
     93 
     94   rbs->size = (rbs->end - lo);
     95 
     96   /* If the previously-recorded rbs-area is empty we don't need to
     97      track it and we can simply overwrite it... */
     98   if (rbs->size)
     99     {
    100       Debug (10, "inner=[0x%lx-0x%lx)\n",
    101 	     (long) (rbs->end - rbs->size), (long) rbs->end);
    102 
    103       c->rbs_curr = (c->rbs_curr + 1) % ARRAY_SIZE (c->rbs_area);
    104       rbs = c->rbs_area + c->rbs_curr;
    105 
    106       if (c->rbs_curr == c->rbs_left_edge)
    107 	c->rbs_left_edge = (c->rbs_left_edge + 1) % ARRAY_SIZE (c->rbs_area);
    108     }
    109 
    110   if ((ret = rbs_get_base (c, saved_bspstore, &rbs_base)) < 0)
    111     return ret;
    112 
    113   rbs->end = saved_bspstore;
    114   rbs->size = saved_bspstore - rbs_base;
    115   rbs->rnat_loc = saved_rnat_loc;
    116 
    117   c->bsp = saved_bsp;
    118 
    119   Debug (10, "outer=[0x%llx-0x%llx), rnat@%s\n", (long long) rbs_base,
    120 	 (long long) rbs->end, ia64_strloc (rbs->rnat_loc));
    121   return 0;
    122 }
    123 
    124 HIDDEN int
    125 rbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip,
    126 		  ia64_loc_t *locp, ia64_loc_t *rnat_locp)
    127 {
    128   unw_word_t nregs, bsp = c->bsp, curr = c->rbs_curr, n;
    129   unw_word_t left_edge = c->rbs_left_edge;
    130 #if UNW_DEBUG
    131   int reg = 32 + regs_to_skip;
    132 #endif
    133 
    134   while (!rbs_contains (&c->rbs_area[curr], bsp))
    135     {
    136       if (curr == left_edge)
    137 	{
    138 	  Debug (1, "could not find register r%d!\n", reg);
    139 	  return -UNW_EBADREG;
    140 	}
    141 
    142       n = rse_num_regs (c->rbs_area[curr].end, bsp);
    143       curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) % ARRAY_SIZE (c->rbs_area);
    144       bsp = rse_skip_regs (c->rbs_area[curr].end - c->rbs_area[curr].size, n);
    145     }
    146 
    147   while (1)
    148     {
    149       nregs = rse_num_regs (bsp, c->rbs_area[curr].end);
    150 
    151       if (regs_to_skip < nregs)
    152 	{
    153 	  /* found it: */
    154 	  unw_word_t addr;
    155 
    156 	  addr = rse_skip_regs (bsp, regs_to_skip);
    157 	  if (locp)
    158 	    *locp = rbs_loc (c->rbs_area + curr, addr);
    159 	  if (rnat_locp)
    160 	    *rnat_locp = rbs_get_rnat_loc (c->rbs_area + curr, addr);
    161 	  return 0;
    162 	}
    163 
    164       if (curr == left_edge)
    165 	{
    166 	  Debug (1, "could not find register r%d!\n", reg);
    167 	  return -UNW_EBADREG;
    168 	}
    169 
    170       regs_to_skip -= nregs;
    171 
    172       curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) % ARRAY_SIZE (c->rbs_area);
    173       bsp = c->rbs_area[curr].end - c->rbs_area[curr].size;
    174     }
    175 }
    176 
    177 #ifdef NEED_RBS_COVER_AND_FLUSH
    178 
    179 static inline int
    180 get_rnat (struct cursor *c, struct rbs_area *rbs, unw_word_t bsp,
    181 	  unw_word_t *__restrict rnatp)
    182 {
    183   ia64_loc_t rnat_locp = rbs_get_rnat_loc (rbs, bsp);
    184 
    185   return ia64_get (c, rnat_locp, rnatp);
    186 }
    187 
    188 /* Simulate the effect of "cover" followed by a "flushrs" for the
    189    target-frame.  However, since the target-frame's backing store
    190    may not have space for the registers that got spilled onto other
    191    rbs-areas, we save those registers to DIRTY_PARTITION where
    192    we can then load them via a single "loadrs".
    193 
    194    This function returns the size of the dirty-partition that was
    195    created or a negative error-code in case of error.
    196 
    197    Note: This does not modify the rbs_area[] structure in any way.  */
    198 HIDDEN int
    199 rbs_cover_and_flush (struct cursor *c, unw_word_t nregs,
    200 		     unw_word_t *dirty_partition, unw_word_t *dirty_rnat,
    201 		     unw_word_t *bspstore)
    202 {
    203   unw_word_t n, src_mask, dst_mask, bsp, *dst, src_rnat, dst_rnat = 0;
    204   unw_word_t curr = c->rbs_curr, left_edge = c->rbs_left_edge;
    205   struct rbs_area *rbs = c->rbs_area + curr;
    206   int ret;
    207 
    208   bsp = c->bsp;
    209   c->bsp = rse_skip_regs (bsp, nregs);
    210 
    211   if (likely (rbs_contains (rbs, bsp)))
    212     {
    213       /* at least _some_ registers are on rbs... */
    214       n = rse_num_regs (bsp, rbs->end);
    215       if (likely (n >= nregs))
    216 	{
    217 	  /* common case #1: all registers are on current rbs... */
    218 	  /* got lucky: _all_ registers are on rbs... */
    219 	  ia64_loc_t rnat_loc = rbs_get_rnat_loc (rbs, c->bsp);
    220 
    221 	  *bspstore = c->bsp;
    222 
    223 	  if (IA64_IS_REG_LOC (rnat_loc))
    224 	    {
    225 	      unw_word_t rnat_addr = (unw_word_t)
    226 		tdep_uc_addr (c->as_arg, UNW_IA64_AR_RNAT, NULL);
    227 	      rnat_loc = IA64_LOC_ADDR (rnat_addr, 0);
    228 	    }
    229 	  c->loc[IA64_REG_RNAT] = rnat_loc;
    230 	  return 0;	/* all done */
    231 	}
    232       nregs -= n;	/* account for registers already on the rbs */
    233 
    234       assert (rse_skip_regs (c->bsp, -nregs) == rse_skip_regs (rbs->end, 0));
    235     }
    236   else
    237     /* Earlier frames also didn't get spilled; need to "loadrs" those,
    238        too... */
    239     nregs += rse_num_regs (rbs->end, bsp);
    240 
    241   /* OK, we need to copy NREGS registers to the dirty partition.  */
    242 
    243   *bspstore = bsp = rbs->end;
    244   c->loc[IA64_REG_RNAT] = rbs->rnat_loc;
    245   assert (!IA64_IS_REG_LOC (rbs->rnat_loc));
    246 
    247   dst = dirty_partition;
    248 
    249   while (nregs > 0)
    250     {
    251       if (unlikely (!rbs_contains (rbs, bsp)))
    252 	{
    253 	  /* switch to next non-empty rbs-area: */
    254 	  do
    255 	    {
    256 	      if (curr == left_edge)
    257 		{
    258 		  Debug (0, "rbs-underflow while flushing %lu regs, "
    259 			 "bsp=0x%lx, dst=0x%p\n", (unsigned long) nregs,
    260 			 (unsigned long) bsp, dst);
    261 		  return -UNW_EBADREG;
    262 		}
    263 
    264 	      assert (rse_num_regs (rbs->end, bsp) == 0);
    265 
    266 	      curr = (curr + ARRAY_SIZE (c->rbs_area) - 1)
    267 		      % ARRAY_SIZE (c->rbs_area);
    268 	      rbs = c->rbs_area + curr;
    269 	      bsp = rbs->end - rbs->size;
    270 	    }
    271 	  while (rbs->size == 0);
    272 
    273 	  if ((ret = get_rnat (c, rbs, bsp, &src_rnat)) < 0)
    274 	    return ret;
    275 	}
    276 
    277       if (unlikely (rse_is_rnat_slot (bsp)))
    278 	{
    279 	  bsp += 8;
    280 	  if ((ret = get_rnat (c, rbs, bsp, &src_rnat)) < 0)
    281 	    return ret;
    282 	}
    283       if (unlikely (rse_is_rnat_slot ((unw_word_t) dst)))
    284 	{
    285 	  *dst++ = dst_rnat;
    286 	  dst_rnat = 0;
    287 	}
    288 
    289       src_mask = ((unw_word_t) 1) << rse_slot_num (bsp);
    290       dst_mask = ((unw_word_t) 1) << rse_slot_num ((unw_word_t) dst);
    291 
    292       if (src_rnat & src_mask)
    293 	dst_rnat |= dst_mask;
    294       else
    295 	dst_rnat &= ~dst_mask;
    296 
    297       /* copy one slot: */
    298       if ((ret = ia64_get (c, rbs_loc (rbs, bsp), dst)) < 0)
    299 	return ret;
    300 
    301       /* advance to next slot: */
    302       --nregs;
    303       bsp += 8;
    304       ++dst;
    305     }
    306   if (unlikely (rse_is_rnat_slot ((unw_word_t) dst)))
    307     {
    308       /* The LOADRS instruction loads "the N bytes below the current
    309 	 BSP" but BSP can never point to an RNaT slot so if the last
    310 	 destination word happens to be an RNaT slot, we need to write
    311 	 that slot now. */
    312       *dst++ = dst_rnat;
    313       dst_rnat = 0;
    314     }
    315   *dirty_rnat = dst_rnat;
    316   return (char *) dst - (char *) dirty_partition;
    317 }
    318 
    319 #endif /* !UNW_REMOTE_ONLY */
    320