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