mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-14 12:18:12 +01:00
In dwarf_reg_states_table_iterate, the rs stack has to persist from
one run_cfi_program call to the next, so pull the stack out of run_cfi_program and make the caller responsible for cleanup at the end.
This commit is contained in:
parent
bb61e0bc2b
commit
2b692db23f
1 changed files with 30 additions and 13 deletions
|
@ -80,14 +80,21 @@ pop_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
|
||||||
free_reg_state (old_rs);
|
free_reg_state (old_rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
empty_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
|
||||||
|
{
|
||||||
|
while (*rs_stack)
|
||||||
|
pop_rstate_stack(rs_stack);
|
||||||
|
}
|
||||||
|
|
||||||
/* Run a CFI program to update the register state. */
|
/* Run a CFI program to update the register state. */
|
||||||
static int
|
static int
|
||||||
run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
||||||
unw_word_t *ip, unw_word_t end_ip,
|
unw_word_t *ip, unw_word_t end_ip,
|
||||||
unw_word_t *addr, unw_word_t end_addr,
|
unw_word_t *addr, unw_word_t end_addr,
|
||||||
|
dwarf_stackable_reg_state_t **rs_stack,
|
||||||
struct dwarf_cie_info *dci)
|
struct dwarf_cie_info *dci)
|
||||||
{
|
{
|
||||||
dwarf_stackable_reg_state_t *rs_stack = NULL;
|
|
||||||
unw_addr_space_t as;
|
unw_addr_space_t as;
|
||||||
void *arg;
|
void *arg;
|
||||||
|
|
||||||
|
@ -263,25 +270,27 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_remember_state:
|
case DW_CFA_remember_state:
|
||||||
if (push_rstate_stack(&rs_stack) < 0)
|
if (push_rstate_stack(rs_stack) < 0)
|
||||||
{
|
{
|
||||||
Debug (1, "Out of memory in DW_CFA_remember_state\n");
|
Debug (1, "Out of memory in DW_CFA_remember_state\n");
|
||||||
ret = -UNW_ENOMEM;
|
ret = -UNW_ENOMEM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memcpy (rs_stack->state.reg, sr->rs_current.reg, sizeof (rs_stack->state.reg));
|
memcpy ((*rs_stack)->state.reg, sr->rs_current.reg,
|
||||||
|
sizeof (dwarf_reg_state_t))
|
||||||
Debug (15, "CFA_remember_state\n");
|
Debug (15, "CFA_remember_state\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_restore_state:
|
case DW_CFA_restore_state:
|
||||||
if (!rs_stack)
|
if (!*rs_stack)
|
||||||
{
|
{
|
||||||
Debug (1, "register-state stack underflow\n");
|
Debug (1, "register-state stack underflow\n");
|
||||||
ret = -UNW_EINVAL;
|
ret = -UNW_EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memcpy (&sr->rs_current.reg, &rs_stack->state.reg, sizeof (rs_stack->state.reg));
|
memcpy (&sr->rs_current.reg, &(*rs_stack)->state.reg,
|
||||||
pop_rstate_stack(&rs_stack);
|
sizeof (dwarf_reg_state_t));
|
||||||
|
pop_rstate_stack(rs_stack);
|
||||||
Debug (15, "CFA_restore_state\n");
|
Debug (15, "CFA_restore_state\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -412,9 +421,6 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the register-state stack, if not empty already. */
|
|
||||||
while (rs_stack)
|
|
||||||
pop_rstate_stack(&rs_stack);
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -517,8 +523,12 @@ setup_fde (struct dwarf_cursor *c, dwarf_state_record_t *sr)
|
||||||
c->ret_addr_column = dci->ret_addr_column;
|
c->ret_addr_column = dci->ret_addr_column;
|
||||||
unw_word_t addr = dci->cie_instr_start;
|
unw_word_t addr = dci->cie_instr_start;
|
||||||
unw_word_t curr_ip = 0;
|
unw_word_t curr_ip = 0;
|
||||||
if ((ret = run_cfi_program (c, sr, &curr_ip, ~(unw_word_t) 0, &addr,
|
dwarf_stackable_reg_state_t *rs_stack = NULL;
|
||||||
dci->cie_instr_end, dci)) < 0)
|
ret = run_cfi_program (c, sr, &curr_ip, ~(unw_word_t) 0, &addr,
|
||||||
|
dci->cie_instr_end,
|
||||||
|
&rs_stack, dci);
|
||||||
|
empty_rstate_stack(&rs_stack);
|
||||||
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial));
|
memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial));
|
||||||
|
@ -532,7 +542,11 @@ parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
|
||||||
struct dwarf_cie_info *dci = c->pi.unwind_info;
|
struct dwarf_cie_info *dci = c->pi.unwind_info;
|
||||||
unw_word_t addr = dci->fde_instr_start;
|
unw_word_t addr = dci->fde_instr_start;
|
||||||
unw_word_t curr_ip = c->pi.start_ip;
|
unw_word_t curr_ip = c->pi.start_ip;
|
||||||
if ((ret = run_cfi_program (c, sr, &curr_ip, ip, &addr, dci->fde_instr_end, dci)) < 0)
|
dwarf_stackable_reg_state_t *rs_stack = NULL;
|
||||||
|
ret = run_cfi_program (c, sr, &curr_ip, ip, &addr, dci->fde_instr_end,
|
||||||
|
&rs_stack, dci);
|
||||||
|
empty_rstate_stack(&rs_stack);
|
||||||
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -985,13 +999,16 @@ dwarf_reg_states_table_iterate(struct dwarf_cursor *c,
|
||||||
struct dwarf_cie_info *dci = c->pi.unwind_info;
|
struct dwarf_cie_info *dci = c->pi.unwind_info;
|
||||||
unw_word_t addr = dci->fde_instr_start;
|
unw_word_t addr = dci->fde_instr_start;
|
||||||
unw_word_t curr_ip = c->pi.start_ip;
|
unw_word_t curr_ip = c->pi.start_ip;
|
||||||
|
dwarf_stackable_reg_state_t *rs_stack = NULL;
|
||||||
while (ret >= 0 && curr_ip < c->pi.end_ip && addr < dci->fde_instr_end)
|
while (ret >= 0 && curr_ip < c->pi.end_ip && addr < dci->fde_instr_end)
|
||||||
{
|
{
|
||||||
unw_word_t prev_ip = curr_ip;
|
unw_word_t prev_ip = curr_ip;
|
||||||
ret = run_cfi_program (c, &sr, &curr_ip, prev_ip, &addr, dci->fde_instr_end, dci);
|
ret = run_cfi_program (c, &sr, &curr_ip, prev_ip, &addr, dci->fde_instr_end,
|
||||||
|
&rs_stack, dci);
|
||||||
if (ret >= 0 && prev_ip < curr_ip)
|
if (ret >= 0 && prev_ip < curr_ip)
|
||||||
ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), prev_ip, curr_ip);
|
ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), prev_ip, curr_ip);
|
||||||
}
|
}
|
||||||
|
empty_rstate_stack(&rs_stack);
|
||||||
#if defined(NEED_LAST_IP)
|
#if defined(NEED_LAST_IP)
|
||||||
if (ret >= 0 && curr_ip < c->pi.last_ip)
|
if (ret >= 0 && curr_ip < c->pi.last_ip)
|
||||||
/* report the dead zone after the procedure ends */
|
/* report the dead zone after the procedure ends */
|
||||||
|
|
Loading…
Reference in a new issue