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:
parent
250382c56d
commit
dac2d001af
13 changed files with 117 additions and 9 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue