mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-26 17:17:39 +01:00
dwarf: Avoid a leak for a no-cache failure in create_state_record_for.
Avoid a duplicate copy for a cache miss.
This commit is contained in:
parent
24ac32b480
commit
3775cdd997
1 changed files with 23 additions and 49 deletions
|
@ -874,46 +874,19 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
uncached_dwarf_find_save_locs (struct dwarf_cursor *c)
|
|
||||||
{
|
|
||||||
dwarf_state_record_t sr;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if ((ret = fetch_proc_info (c, c->ip, 1)) < 0)
|
|
||||||
{
|
|
||||||
put_unwind_info (c, &c->pi);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ret = create_state_record_for (c, &sr, c->ip)) < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if ((ret = apply_reg_state (c, &sr.rs_current)) < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
put_unwind_info (c, &c->pi);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The function finds the saved locations and applies the register
|
/* The function finds the saved locations and applies the register
|
||||||
state as well. */
|
state as well. */
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
dwarf_find_save_locs (struct dwarf_cursor *c)
|
dwarf_find_save_locs (struct dwarf_cursor *c)
|
||||||
{
|
{
|
||||||
dwarf_state_record_t sr;
|
dwarf_state_record_t sr;
|
||||||
dwarf_reg_state_t *rs, rs_copy;
|
dwarf_reg_state_t *rs;
|
||||||
struct dwarf_rs_cache *cache;
|
struct dwarf_rs_cache *cache;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
intrmask_t saved_mask;
|
intrmask_t saved_mask;
|
||||||
|
|
||||||
if (c->as->caching_policy == UNW_CACHE_NONE)
|
if ((cache = get_rs_cache(c->as, &saved_mask)) &&
|
||||||
return uncached_dwarf_find_save_locs (c);
|
(rs = rs_lookup(cache, c)))
|
||||||
|
|
||||||
cache = get_rs_cache(c->as, &saved_mask);
|
|
||||||
rs = rs_lookup(cache, c);
|
|
||||||
|
|
||||||
if (rs)
|
|
||||||
{
|
{
|
||||||
/* update hint; no locking needed: single-word writes are atomic */
|
/* update hint; no locking needed: single-word writes are atomic */
|
||||||
cache->buckets[c->prev_rs].hint = rs - cache->buckets + 1;
|
cache->buckets[c->prev_rs].hint = rs - cache->buckets + 1;
|
||||||
|
@ -921,31 +894,32 @@ dwarf_find_save_locs (struct dwarf_cursor *c)
|
||||||
c->hint = rs->hint;
|
c->hint = rs->hint;
|
||||||
c->ret_addr_column = rs->ret_addr_column;
|
c->ret_addr_column = rs->ret_addr_column;
|
||||||
c->use_prev_instr = ! rs->signal_frame;
|
c->use_prev_instr = ! rs->signal_frame;
|
||||||
|
memcpy (&sr.rs_current, rs, sizeof (*rs));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((ret = fetch_proc_info (c, c->ip, 1)) < 0 ||
|
ret = fetch_proc_info (c, c->ip, 1);
|
||||||
(ret = create_state_record_for (c, &sr, c->ip)) < 0)
|
if (ret >= 0)
|
||||||
{
|
ret = create_state_record_for (c, &sr, c->ip);
|
||||||
put_rs_cache (c->as, cache, &saved_mask);
|
|
||||||
put_unwind_info (c, &c->pi);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
rs = rs_new (cache, c);
|
|
||||||
memcpy(rs, &sr.rs_current, offsetof(struct dwarf_reg_state, ip));
|
|
||||||
cache->buckets[c->prev_rs].hint = rs - cache->buckets;
|
|
||||||
c->prev_rs = rs - cache->buckets;
|
|
||||||
c->hint = rs->hint = 0;
|
|
||||||
|
|
||||||
put_unwind_info (c, &c->pi);
|
put_unwind_info (c, &c->pi);
|
||||||
|
|
||||||
|
if (cache && ret >= 0)
|
||||||
|
{
|
||||||
|
rs = rs_new (cache, c);
|
||||||
|
memcpy(rs, &sr.rs_current, offsetof(struct dwarf_reg_state, ip));
|
||||||
|
cache->buckets[c->prev_rs].hint = rs - cache->buckets;
|
||||||
|
c->prev_rs = rs - cache->buckets;
|
||||||
|
c->hint = rs->hint = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (&rs_copy, rs, sizeof (rs_copy));
|
if (cache)
|
||||||
put_rs_cache (c->as, cache, &saved_mask);
|
put_rs_cache (c->as, cache, &saved_mask);
|
||||||
|
if (ret < 0)
|
||||||
tdep_reuse_frame (c, &rs_copy);
|
return ret;
|
||||||
if ((ret = apply_reg_state (c, &rs_copy)) < 0)
|
if (cache)
|
||||||
|
tdep_reuse_frame (c, rs);
|
||||||
|
if ((ret = apply_reg_state (c, &sr.rs_current)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue