mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-30 02:27:38 +01:00
(desc_alias): New function.
(parse_dynamic): Handle UNW_DYN_ALIAS via desc_dynamic(). (Logical change 1.201)
This commit is contained in:
parent
835bb9110b
commit
93d627ef87
1 changed files with 45 additions and 10 deletions
|
@ -744,6 +744,48 @@ lookup_preg (int regnum, int memory, struct ia64_state_record *sr)
|
||||||
return sr->curr.reg + preg;
|
return sr->curr.reg + preg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* An alias directive inside a region of length RLEN is interpreted to
|
||||||
|
mean that the region behaves exactly like the first RLEN
|
||||||
|
instructions at the aliased IP. RLEN=0 implies that the current
|
||||||
|
state matches exactly that of the aliased IP. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
desc_alias (unw_dyn_op_t *op, struct cursor *c, struct ia64_state_record *sr)
|
||||||
|
{
|
||||||
|
struct ia64_state_record orig_sr = *sr;
|
||||||
|
int i, ret, when, rlen = sr->region_len;
|
||||||
|
unw_word_t new_ip;
|
||||||
|
|
||||||
|
when = MIN(sr->when_target, rlen - 1);
|
||||||
|
new_ip = op->val + ((when / 3) * 16 + (when % 3));
|
||||||
|
|
||||||
|
if ((ret = ia64_fetch_proc_info (c, new_ip, 1)) < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((ret = create_state_record_for (c, sr, new_ip)) < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
sr->first_region = orig_sr.first_region;
|
||||||
|
sr->done = 0;
|
||||||
|
sr->any_spills |= orig_sr.any_spills;
|
||||||
|
sr->in_body = orig_sr.in_body;
|
||||||
|
sr->region_start = orig_sr.region_start;
|
||||||
|
sr->region_len = orig_sr.region_len;
|
||||||
|
if (sr->when_sp_restored != IA64_WHEN_NEVER)
|
||||||
|
sr->when_sp_restored = op->when + MIN (orig_sr.when_sp_restored, rlen - 1);
|
||||||
|
sr->epilogue_count = orig_sr.epilogue_count;
|
||||||
|
sr->when_target = orig_sr.when_target;
|
||||||
|
|
||||||
|
for (i = 0; i < IA64_NUM_PREGS; ++i)
|
||||||
|
if (sr->curr.reg[i].when != IA64_WHEN_NEVER)
|
||||||
|
sr->curr.reg[i].when = op->when + MIN (sr->curr.reg[i].when, rlen - 1);
|
||||||
|
|
||||||
|
ia64_free_state_record (sr);
|
||||||
|
sr->labeled_states = orig_sr.labeled_states;
|
||||||
|
sr->curr.next = orig_sr.curr.next;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
parse_dynamic (struct cursor *c, struct ia64_state_record *sr)
|
parse_dynamic (struct cursor *c, struct ia64_state_record *sr)
|
||||||
{
|
{
|
||||||
|
@ -751,10 +793,10 @@ parse_dynamic (struct cursor *c, struct ia64_state_record *sr)
|
||||||
unw_dyn_proc_info_t *proc = &di->u.pi;
|
unw_dyn_proc_info_t *proc = &di->u.pi;
|
||||||
unw_dyn_region_info_t *r;
|
unw_dyn_region_info_t *r;
|
||||||
struct ia64_reg_info *ri;
|
struct ia64_reg_info *ri;
|
||||||
unw_word_t val, new_ip;
|
|
||||||
enum ia64_where where;
|
enum ia64_where where;
|
||||||
unw_dyn_op_t *op;
|
|
||||||
int32_t when, len;
|
int32_t when, len;
|
||||||
|
unw_dyn_op_t *op;
|
||||||
|
unw_word_t val;
|
||||||
int memory, ret;
|
int memory, ret;
|
||||||
int8_t qp;
|
int8_t qp;
|
||||||
|
|
||||||
|
@ -861,15 +903,8 @@ parse_dynamic (struct cursor *c, struct ia64_state_record *sr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNW_DYN_ALIAS:
|
case UNW_DYN_ALIAS:
|
||||||
while (sr->curr.next)
|
if ((ret = desc_alias (op, c, sr)) < 0)
|
||||||
pop (sr);
|
|
||||||
new_ip = op->val + ((sr->when_target / 3) * 16
|
|
||||||
+ (sr->when_target % 3));
|
|
||||||
ret = ia64_fetch_proc_info (c, new_ip, 1);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
ia64_free_state_record (sr);
|
|
||||||
return create_state_record_for (c, sr, new_ip);
|
|
||||||
|
|
||||||
case UNW_DYN_STOP:
|
case UNW_DYN_STOP:
|
||||||
goto end_of_ops;
|
goto end_of_ops;
|
||||||
|
|
Loading…
Reference in a new issue