mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2025-02-28 23:31:40 +01:00
(rbs_record_switch): Fix it so it stands a chance of working in all cases.
(rbs_underflow): Ditto. (rbs_find_stacked): Ditto. (Logical change 1.41)
This commit is contained in:
parent
eacf0e24e1
commit
d5370fb25c
1 changed files with 65 additions and 38 deletions
|
@ -44,37 +44,52 @@ rbs_record_switch (struct cursor *c,
|
||||||
unw_word_t saved_bsp, unw_word_t saved_bspstore,
|
unw_word_t saved_bsp, unw_word_t saved_bspstore,
|
||||||
unw_word_t saved_rnat_loc)
|
unw_word_t saved_rnat_loc)
|
||||||
{
|
{
|
||||||
unw_word_t ndirty, prev, last = c->rbs_wridx;
|
unw_word_t bsp, i, j, lo, ndirty, nregs, right_edge = c->rbs_right_edge;
|
||||||
|
|
||||||
debug (10, "%s: ", __FUNCTION__);
|
debug (10, "%s: (left=%u, curr=%u, right=%u)\n\t", __FUNCTION__,
|
||||||
|
c->rbs_left_edge, c->rbs_curr, c->rbs_right_edge);
|
||||||
|
|
||||||
ndirty = ia64_rse_num_regs (saved_bspstore, saved_bsp);
|
bsp = c->bsp;
|
||||||
|
|
||||||
if (ndirty == 0)
|
/* If other stacks are already pending, we need to convert "bsp" to
|
||||||
/* The last-recorded rbs-area is empty. No point in tracking it... */
|
equivalent address on the final stack. The conversion is easy
|
||||||
prev = last;
|
because we know that the low end of a stack corresponds to the
|
||||||
else
|
high end of the next stack. */
|
||||||
|
for (i = c->rbs_curr; i != right_edge; i = (i + 1) % NELEMS (c->rbs_area))
|
||||||
{
|
{
|
||||||
c->rbs_area[last].size = (c->rbs_area[last].end
|
j = (i + 1) % NELEMS (c->rbs_area);
|
||||||
- ia64_rse_skip_regs (c->bsp, -ndirty));
|
nregs = ia64_rse_num_regs (c->rbs_area[i].end - c->rbs_area[i].size, bsp);
|
||||||
debug (10, "\n\tinner=[0x%lx-0x%lx),\n\t",
|
bsp = ia64_rse_skip_regs (c->rbs_area[j].end, nregs);
|
||||||
(long) (c->rbs_area[last].end - c->rbs_area[last].size),
|
|
||||||
(long) c->rbs_area[last].end);
|
|
||||||
|
|
||||||
last = ((last + NELEMS (c->rbs_area) - 1) % NELEMS (c->rbs_area));
|
|
||||||
|
|
||||||
++c->rbs_nvalid;
|
|
||||||
if (c->rbs_nvalid > NELEMS (c->rbs_area))
|
|
||||||
c->rbs_nvalid = NELEMS (c->rbs_area);
|
|
||||||
|
|
||||||
assert (last != c->rbs_curr);
|
|
||||||
}
|
}
|
||||||
c->rbs_area[last].end = saved_bspstore;
|
|
||||||
c->rbs_area[last].size = ~(unw_word_t) 0; /* initial guess... */
|
|
||||||
c->rbs_area[last].rnat_loc = saved_rnat_loc;
|
|
||||||
|
|
||||||
debug (10, "outer=[??????????????????-0x%lx), rnat @ 0x%lx\n",
|
/* Calculate address "lo" at which the backing store starts: */
|
||||||
(long) c->rbs_area[last].end, (long) c->rbs_area[last].rnat_loc);
|
ndirty = ia64_rse_num_regs (saved_bspstore, saved_bsp);
|
||||||
|
lo = ia64_rse_skip_regs (bsp, -ndirty);
|
||||||
|
|
||||||
|
c->rbs_area[right_edge].size = (c->rbs_area[right_edge].end - lo);
|
||||||
|
|
||||||
|
/* If the previously-recorded rbs-area is empty we don't need to
|
||||||
|
track it and we can simply overwrite it... */
|
||||||
|
if (c->rbs_area[right_edge].size)
|
||||||
|
{
|
||||||
|
debug (10, "inner=[0x%lx-0x%lx)\n\t",
|
||||||
|
(long) (c->rbs_area[right_edge].end - c->rbs_area[right_edge].size),
|
||||||
|
(long) c->rbs_area[right_edge].end);
|
||||||
|
|
||||||
|
right_edge = (right_edge + 1) % NELEMS (c->rbs_area);
|
||||||
|
c->rbs_right_edge = right_edge;
|
||||||
|
|
||||||
|
assert (right_edge != c->rbs_curr);
|
||||||
|
|
||||||
|
if (right_edge == c->rbs_left_edge)
|
||||||
|
c->rbs_left_edge = (right_edge + 1) % NELEMS (c->rbs_area);
|
||||||
|
}
|
||||||
|
c->rbs_area[right_edge].end = saved_bspstore;
|
||||||
|
c->rbs_area[right_edge].size = ~(unw_word_t) 0; /* initial guess... */
|
||||||
|
c->rbs_area[right_edge].rnat_loc = saved_rnat_loc;
|
||||||
|
|
||||||
|
debug (10, "outer=[?????????????????\?-0x%lx), rnat@0x%lx\n",
|
||||||
|
(long) c->rbs_area[right_edge].end, (long) c->rbs_area[right_edge].rnat_loc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,8 +98,9 @@ rbs_underflow (struct cursor *c)
|
||||||
{
|
{
|
||||||
size_t num_regs;
|
size_t num_regs;
|
||||||
|
|
||||||
while (c->rbs_area[c->rbs_curr].end - c->bsp
|
assert (c->rbs_area[c->rbs_curr].end - c->bsp > c->rbs_area[c->rbs_curr].size);
|
||||||
> c->rbs_area[c->rbs_curr].size)
|
|
||||||
|
while (1)
|
||||||
{
|
{
|
||||||
unw_word_t old_base = (c->rbs_area[c->rbs_curr].end
|
unw_word_t old_base = (c->rbs_area[c->rbs_curr].end
|
||||||
- c->rbs_area[c->rbs_curr].size);
|
- c->rbs_area[c->rbs_curr].size);
|
||||||
|
@ -92,9 +108,19 @@ rbs_underflow (struct cursor *c)
|
||||||
/* # of register we were short on old rbs-area: */
|
/* # of register we were short on old rbs-area: */
|
||||||
num_regs = ia64_rse_num_regs (c->bsp, old_base);
|
num_regs = ia64_rse_num_regs (c->bsp, old_base);
|
||||||
|
|
||||||
c->rbs_curr = ((c->rbs_curr + NELEMS (c->rbs_area) - 1)
|
c->rbs_curr = (c->rbs_curr + 1) % NELEMS (c->rbs_area);
|
||||||
% NELEMS (c->rbs_area));
|
|
||||||
c->bsp = ia64_rse_skip_regs (c->rbs_area[c->rbs_curr].end, -num_regs);
|
c->bsp = ia64_rse_skip_regs (c->rbs_area[c->rbs_curr].end, -num_regs);
|
||||||
|
|
||||||
|
if (c->rbs_area[c->rbs_curr].end - c->bsp <= c->rbs_area[c->rbs_curr].size)
|
||||||
|
{
|
||||||
|
debug (10, "%s: [0x%016lx-0x%016lx), bsp=0x%lx\n",
|
||||||
|
__FUNCTION__, (long) (c->rbs_area[c->rbs_curr].end
|
||||||
|
- c->rbs_area[c->rbs_curr].size),
|
||||||
|
(long) c->rbs_area[c->rbs_curr].end, c->bsp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (c->rbs_curr != c->rbs_right_edge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,12 +128,10 @@ HIDDEN int
|
||||||
rbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip,
|
rbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip,
|
||||||
unw_word_t *locp, unw_word_t *rnat_locp)
|
unw_word_t *locp, unw_word_t *rnat_locp)
|
||||||
{
|
{
|
||||||
unw_word_t curr, nregs, bsp = c->bsp;
|
unw_word_t nregs, bsp = c->bsp, curr = c->rbs_curr, left_edge = c->rbs_left_edge;
|
||||||
int i;
|
int reg = 32 + regs_to_skip;
|
||||||
|
|
||||||
curr = c->rbs_curr;
|
while (1)
|
||||||
|
|
||||||
for (i = 0; i < c->rbs_nvalid; ++i)
|
|
||||||
{
|
{
|
||||||
nregs = ia64_rse_num_regs (bsp, c->rbs_area[curr].end);
|
nregs = ia64_rse_num_regs (bsp, c->rbs_area[curr].end);
|
||||||
|
|
||||||
|
@ -124,12 +148,15 @@ rbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (curr == left_edge)
|
||||||
|
{
|
||||||
|
debug (1, "%s: could not find register r%d!\n", __FUNCTION__, reg);
|
||||||
|
return -UNW_EBADREG;
|
||||||
|
}
|
||||||
|
|
||||||
regs_to_skip -= nregs;
|
regs_to_skip -= nregs;
|
||||||
|
|
||||||
curr = (curr + 1) % NELEMS (c->rbs_area);
|
curr = (curr + NELEMS (c->rbs_area) - 1) % NELEMS (c->rbs_area);
|
||||||
bsp = c->rbs_area[curr].end - c->rbs_area[curr].size;
|
bsp = c->rbs_area[curr].end - c->rbs_area[curr].size;
|
||||||
}
|
}
|
||||||
debug (1, "%s: could not find register r%d!\n",
|
|
||||||
__FUNCTION__, 32 + regs_to_skip);
|
|
||||||
return -UNW_EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue