1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2025-01-08 18:33:42 +01:00

Identify signal frames by augmentation attribute.

This commit is contained in:
Lassi Tuura 2010-04-20 23:13:09 +02:00 committed by Arun Sharma
parent 250382c56d
commit dac2d001af
13 changed files with 117 additions and 9 deletions

View file

@ -247,6 +247,7 @@ typedef struct dwarf_reg_state
unsigned short lru_chain; /* used for least-recently-used chain */
unsigned short coll_chain; /* used for hash collisions */
unsigned short hint; /* hint for next rs to try (or -1) */
unsigned short signal_frame; /* optional machine-dependent signal info */
}
dwarf_reg_state_t;
@ -266,6 +267,7 @@ typedef struct dwarf_cie_info
uint8_t lsda_encoding;
unsigned int sized_augmentation : 1;
unsigned int have_abi_marker : 1;
unsigned int signal_frame : 1;
}
dwarf_cie_info_t;

View file

@ -217,6 +217,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
#define tdep_access_reg UNW_OBJ(access_reg)
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
#define tdep_fetch_frame(c,ip,n) do {} while(0)
#define tdep_cache_frame(c,rs) do {} while(0)
#define tdep_reuse_frame(c,rs) do {} while(0)
#ifdef UNW_LOCAL_ONLY
# define tdep_find_proc_info(c,ip,n) \

View file

@ -224,6 +224,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
#define tdep_access_reg UNW_OBJ(access_reg)
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
#define tdep_fetch_frame(c,ip,n) do {} while(0)
#define tdep_cache_frame(c,rs) do {} while(0)
#define tdep_reuse_frame(c,rs) do {} while(0)
#ifdef UNW_LOCAL_ONLY
# define tdep_find_proc_info(c,ip,n) \

View file

@ -220,6 +220,9 @@ struct ia64_global_unwind_state
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
#define tdep_access_reg UNW_OBJ(access_reg)
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
#define tdep_fetch_frame(c,ip,n) do {} while(0)
#define tdep_cache_frame(c,rs) do {} while(0)
#define tdep_reuse_frame(c,rs) do {} while(0)
#define tdep_get_as(c) ((c)->as)
#define tdep_get_as_arg(c) ((c)->as_arg)
#define tdep_get_ip(c) ((c)->ip)

View file

@ -279,6 +279,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
#define tdep_access_reg UNW_OBJ(access_reg)
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
#define tdep_fetch_frame(c,ip,n) do {} while(0)
#define tdep_cache_frame(c,rs) do {} while(0)
#define tdep_reuse_frame(c,rs) do {} while(0)
#ifdef UNW_LOCAL_ONLY
# define tdep_find_proc_info(c,ip,n) \

View file

@ -256,6 +256,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
#define tdep_access_reg UNW_OBJ(access_reg)
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
#define tdep_fetch_frame(c,ip,n) do {} while(0)
#define tdep_cache_frame(c,rs) do {} while(0)
#define tdep_reuse_frame(c,rs) do {} while(0)
#define tdep_get_func_addr UNW_OBJ(get_func_addr)
#ifdef UNW_LOCAL_ONLY

View file

@ -256,6 +256,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
#define tdep_access_reg UNW_OBJ(access_reg)
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
#define tdep_fetch_frame(c,ip,n) do {} while(0)
#define tdep_cache_frame(c,rs) do {} while(0)
#define tdep_reuse_frame(c,rs) do {} while(0)
#define tdep_get_func_addr UNW_OBJ(get_func_addr)
#ifdef UNW_LOCAL_ONLY

View file

@ -240,6 +240,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
#define tdep_access_reg UNW_OBJ(access_reg)
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
#define tdep_fetch_frame(c,ip,n) do {} while(0)
#define tdep_cache_frame(c,rs) do {} while(0)
#define tdep_reuse_frame(c,rs) do {} while(0)
#ifdef UNW_LOCAL_ONLY
# define tdep_find_proc_info(c,ip,n) \

View file

@ -163,6 +163,15 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
#define tdep_access_reg UNW_OBJ(access_reg)
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
#if __linux__
# define tdep_fetch_frame UNW_OBJ(fetch_frame)
# define tdep_cache_frame UNW_OBJ(cache_frame)
# define tdep_reuse_frame UNW_OBJ(reuse_frame)
#else
# define tdep_fetch_frame(c,ip,n) do {} while(0)
# define tdep_cache_frame(c,rs) do {} while(0)
# define tdep_reuse_frame(c,rs) do {} while(0)
#endif
#ifdef UNW_LOCAL_ONLY
# define tdep_find_proc_info(c,ip,n) \
@ -196,5 +205,14 @@ extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg,
unw_word_t *valp, int write);
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
unw_fpreg_t *valp, int write);
#if __linux__
extern void tdep_fetch_frame (struct dwarf_cursor *c, unw_word_t ip,
int need_unwind_info);
extern void tdep_cache_frame (struct dwarf_cursor *c,
struct dwarf_reg_state *rs);
extern void tdep_reuse_frame (struct dwarf_cursor *c,
struct dwarf_reg_state *rs);
#endif
#endif /* X86_64_LIBUNWIND_I_H */

View file

@ -187,6 +187,9 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
break;
case 'S':
/* This is a signal frame. */
dci->signal_frame = 1;
/* Temporarily set it to one so dwarf_parse_fde() knows that
it should fetch the actual ABI/TAG pair from the FDE. */
dci->have_abi_marker = 1;

View file

@ -400,6 +400,11 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
c->pi_valid = 1;
c->pi_is_dynamic = dynamic;
/* Let system/machine-dependent code determine frame-specific attributes. */
if (ret >= 0)
tdep_fetch_frame (c, ip, need_unwind_info);
return ret;
}
@ -604,6 +609,8 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
rs->hint = 0;
rs->ip = c->ip;
rs->ret_addr_column = c->ret_addr_column;
rs->signal_frame = 0;
tdep_cache_frame (c, rs);
return rs;
}
@ -818,6 +825,8 @@ dwarf_find_save_locs (struct dwarf_cursor *c)
memcpy (&rs_copy, rs, sizeof (rs_copy));
put_rs_cache (c->as, cache, &saved_mask);
tdep_reuse_frame (c, &rs_copy);
if ((ret = apply_reg_state (c, &rs_copy)) < 0)
return ret;

View file

@ -30,10 +30,59 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <sys/syscall.h>
HIDDEN void
tdep_fetch_frame (struct dwarf_cursor *dw, unw_word_t ip, int need_unwind_info)
{
struct cursor *c = (struct cursor *) dw;
assert(! need_unwind_info || dw->pi_valid);
assert(! need_unwind_info || dw->pi.unwind_info);
if (dw->pi_valid
&& dw->pi.unwind_info
&& ((struct dwarf_cie_info *) dw->pi.unwind_info)->signal_frame)
{
c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME;
c->sigcontext_addr = dw->cfa;
}
else
{
c->sigcontext_format = X86_64_SCF_NONE;
c->sigcontext_addr = 0;
}
Debug(15, "fetch frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n",
dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr);
}
HIDDEN void
tdep_cache_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
{
struct cursor *c = (struct cursor *) dw;
rs->signal_frame = c->sigcontext_format;
Debug(15, "cache frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n",
dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr);
}
HIDDEN void
tdep_reuse_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
{
struct cursor *c = (struct cursor *) dw;
c->sigcontext_format = rs->signal_frame;
if (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME)
c->sigcontext_addr = dw->cfa;
else
c->sigcontext_addr = 0;
Debug(15, "reuse frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n",
dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr);
}
PROTECTED int
unw_is_signal_frame (unw_cursor_t *cursor)
{
struct cursor *c = (struct cursor *) cursor;
return c->sigcontext_format != X86_64_SCF_NONE;
#if 0
unw_word_t w0, w1, ip;
unw_addr_space_t as;
unw_accessors_t *a;
@ -57,20 +106,24 @@ unw_is_signal_frame (unw_cursor_t *cursor)
return 0;
w1 &= 0xff;
return (w0 == 0x0f0000000fc0c748 && w1 == 0x05);
#endif
}
PROTECTED int
unw_handle_signal_frame (unw_cursor_t *cursor)
{
/* Should not get here because we now use kernel-provided dwarf
information for the signal trampoline and dwarf_step() works.
Hence dwarf_step() should never call this function. Maybe
restore old non-dwarf signal handling here, but then the
gating on unw_is_signal_frame() needs to be removed. */
struct cursor *c = (struct cursor *) cursor;
int ret;
unw_word_t ucontext = c->dwarf.cfa;
Debug(1, "signal frame, skip over trampoline\n");
c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME;
c->sigcontext_addr = c->dwarf.cfa;
Debug(1, "old format signal frame? format=%d addr=0x%lx cfa=0x%lx\n",
c->sigcontext_format, c->sigcontext_addr, c->dwarf.cfa);
assert(c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME);
assert(c->sigcontext_addr == c->dwarf.cfa);
assert(0);
#if 0
struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa);
if (ret < 0)
@ -96,8 +149,9 @@ unw_handle_signal_frame (unw_cursor_t *cursor)
c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0);
#endif
return 0;
return 1;
}
#ifndef UNW_REMOTE_ONLY

View file

@ -38,6 +38,7 @@ unw_step (unw_cursor_t *cursor)
c, (unsigned long long) c->dwarf.ip);
/* Try DWARF-based unwinding... */
c->sigcontext_format = X86_64_SCF_NONE;
ret = dwarf_step (&c->dwarf);
if (ret < 0 && ret != -UNW_ENOINFO)