1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2025-01-10 11:13:43 +01:00

Merge branch 'master' into freebsd

This commit is contained in:
Konstantin Belousov 2010-05-02 16:29:02 +03:00
commit b73c618a31
38 changed files with 228 additions and 102 deletions

View file

@ -169,6 +169,12 @@ if test x$enable_block_signals = xyes; then
AC_DEFINE([CONFIG_BLOCK_SIGNALS], [], [Block signals before mutex operations])
fi
AC_ARG_ENABLE(conservative_checks,
[ --enable-conservative-checks Validate all memory addresses before use],
[enable_conservative_checks=$enableval], [enable_conservative_checks=yes])
if test x$enable_conservative_checks = xyes; then
CPPFLAGS="${CPPFLAGS} -DCONSERVATIVE_CHECKS"
fi
LIBUNWIND___THREAD

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;
@ -293,6 +295,7 @@ typedef struct dwarf_cursor
dwarf_loc_t loc[DWARF_NUM_PRESERVED_REGS];
unsigned int use_prev_instr :1; /* use previous (= call) or current (= signal) instruction? */
unsigned int pi_valid :1; /* is proc_info valid? */
unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */
unw_proc_info_t pi; /* info about current procedure */

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

@ -47,7 +47,7 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
c->dwarf.as = unw_local_addr_space;
c->dwarf.as_arg = uc;
return common_init (c);
return common_init (c, 1);
}
#endif /* !UNW_REMOTE_ONLY */

View file

@ -40,6 +40,6 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
c->dwarf.as = as;
c->dwarf.as_arg = as_arg;
return common_init (c);
return common_init (c, 0);
#endif /* !UNW_LOCAL_ONLY */
}

View file

@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
static inline int
common_init (struct cursor *c)
common_init (struct cursor *c, unsigned use_prev_instr)
{
int ret, i;
@ -62,6 +62,7 @@ common_init (struct cursor *c)
c->dwarf.args_size = 0;
c->dwarf.ret_addr_column = 0;
c->dwarf.use_prev_instr = use_prev_instr;
c->dwarf.pi_valid = 0;
c->dwarf.pi_is_dynamic = 0;
c->dwarf.hint = 0;

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;
@ -293,7 +296,7 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
}
Debug (15, "looking for CIE at address %x\n", (int) cie_addr);
Debug (15, "looking for CIE at address %lx\n", (long) cie_addr);
if ((ret = parse_cie (as, a, cie_addr, pi, &dci, base, arg)) < 0)
return ret;

View file

@ -275,7 +275,7 @@ locate_debug_info (unw_addr_space_t as, struct dl_phdr_info *info,
for (w = as->debug_frames; w; w = w->next)
{
Debug (4, "checking %p: %x-%x\n", w, (int)w->start, (int)w->end);
Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end);
if (addr >= w->start && addr < w->end)
return w;
}
@ -316,7 +316,7 @@ locate_debug_info (unw_addr_space_t as, struct dl_phdr_info *info,
end = hdrlimit;
}
Debug (4, "calculated bounds of %x-%x for '%s'\n", (int)start, (int)end,
Debug (4, "calculated bounds of %lx-%lx for '%s'\n", (long)start, (long)end,
name);
err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space);
@ -667,8 +667,8 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr)
NULL);
if (err == 0)
{
Debug (15, "start_ip = %x, end_ip = %x\n",
(int) this_pi.start_ip, (int) this_pi.end_ip);
Debug (15, "start_ip = %lx, end_ip = %lx\n",
(long) this_pi.start_ip, (long) this_pi.end_ip);
debug_frame_tab_append (tab,
item_start - (unw_word_t) (uintptr_t) buf,
this_pi.start_ip);
@ -771,7 +771,7 @@ lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip)
{
mid = (lo + hi) / 2;
e = table + mid;
Debug (1, "e->start_ip_offset = %x\n", (int) e->start_ip_offset);
Debug (1, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset);
if (rel_ip < e->start_ip_offset)
hi = mid;
else
@ -897,8 +897,8 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
}
if (!e)
{
Debug (1, "IP %x inside range %x-%x, but no explicit unwind info found\n",
(int) ip, (int) di->start_ip, (int) di->end_ip);
Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n",
(long) ip, (long) di->start_ip, (long) di->end_ip);
/* IP is inside this table's range, but there is no explicit
unwind info. */
return -UNW_ENOINFO;
@ -909,9 +909,9 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
fde_addr = e->fde_offset + debug_frame_base;
else
fde_addr = e->fde_offset + segbase;
Debug (1, "e->fde_offset = %x, segbase = %x, debug_frame_base = %x, "
"fde_addr = %x\n", (int) e->fde_offset, (int) segbase,
(int) debug_frame_base, (int) fde_addr);
Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, "
"fde_addr = %lx\n", (long) e->fde_offset, (long) segbase,
(long) debug_frame_base, (long) fde_addr);
if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi,
need_unwind_info,
debug_frame_base, arg)) < 0)

View file

@ -76,7 +76,10 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
a = unw_get_accessors (as);
curr_ip = c->pi.start_ip;
while (curr_ip < ip && *addr < end_addr)
/* Process everything up to and including the current 'ip',
including all the DW_CFA_advance_loc instructions. See
'c->use_prev_instr' use in 'fetch_proc_info' for details. */
while (curr_ip <= ip && *addr < end_addr)
{
if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0)
return ret;
@ -381,7 +384,23 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
{
int ret, dynamic = 1;
--ip;
/* The 'ip' can point either to the previous or next instruction
depending on what type of frame we have: normal call or a place
to resume execution (e.g. after signal frame).
For a normal call frame we need to back up so we point within the
call itself; this is important because a) the call might be the
very last instruction of the function and the edge of the FDE,
and b) so that run_cfi_program() runs locations up to the call
but not more.
For execution resume, we need to do the exact opposite and look
up using the current 'ip' value. That is where execution will
continue, and it's important we get this right, as 'ip' could be
right at the function entry and hence FDE edge, or at instruction
that manipulates CFA (push/pop). */
if (c->use_prev_instr)
--ip;
if (c->pi_valid && !need_unwind_info)
return 0;
@ -400,6 +419,19 @@ 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);
/* Update use_prev_instr for the next frame. */
if (need_unwind_info)
{
assert(c->pi.unwind_info);
struct dwarf_cie_info *dci = c->pi.unwind_info;
c->use_prev_instr = ! dci->signal_frame;
}
return ret;
}
@ -604,6 +636,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;
}
@ -743,13 +777,20 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
break;
}
}
c->cfa = cfa;
ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip);
if (ret < 0)
return ret;
c->ip = ip;
/* XXX: check for ip to be code_aligned */
c->cfa = cfa;
/* DWARF spec says undefined return address location means end of stack. */
if (DWARF_IS_NULL_LOC (c->loc[c->ret_addr_column]))
c->ip = 0;
else
{
ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip);
if (ret < 0)
return ret;
c->ip = ip;
}
/* XXX: check for ip to be code_aligned */
if (c->ip == prev_ip && c->cfa == prev_cfa)
{
Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
@ -796,7 +837,10 @@ dwarf_find_save_locs (struct dwarf_cursor *c)
rs = rs_lookup(cache, c);
if (rs)
c->ret_addr_column = rs->ret_addr_column;
{
c->ret_addr_column = rs->ret_addr_column;
c->use_prev_instr = ! rs->signal_frame;
}
else
{
if ((ret = fetch_proc_info (c, c->ip, 1)) < 0 ||
@ -818,6 +862,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

@ -48,7 +48,7 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
c->dwarf.as = unw_local_addr_space;
c->dwarf.as_arg = uc;
return common_init (c);
return common_init (c, 1);
}
#endif /* !UNW_REMOTE_ONLY */

View file

@ -41,6 +41,6 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
c->dwarf.as = as;
c->dwarf.as_arg = as_arg;
return common_init (c);
return common_init (c, 0);
#endif /* !UNW_LOCAL_ONLY */
}

View file

@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
static inline int
common_init (struct cursor *c)
common_init (struct cursor *c, unsigned use_prev_instr)
{
int ret;
@ -40,5 +40,7 @@ common_init (struct cursor *c)
ret = hppa_get (c, HPPA_REG_LOC (c, UNW_HPPA_SP), &c->sp);
if (ret < 0)
return ret;
c->dwarf.use_prev_instr = use_prev_instr;
return 0;
}

View file

@ -47,7 +47,7 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
c->dwarf.as = unw_local_addr_space;
c->dwarf.as_arg = uc;
return common_init (c);
return common_init (c, 1);
}
#endif /* !UNW_REMOTE_ONLY */

View file

@ -40,6 +40,6 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
c->dwarf.as = as;
c->dwarf.as_arg = as_arg;
return common_init (c);
return common_init (c, 0);
#endif /* !UNW_LOCAL_ONLY */
}

View file

@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
static inline int
common_init (struct cursor *c)
common_init (struct cursor *c, unsigned use_prev_instr)
{
int ret, i;
@ -47,6 +47,7 @@ common_init (struct cursor *c)
c->dwarf.args_size = 0;
c->dwarf.ret_addr_column = 0;
c->dwarf.use_prev_instr = use_prev_instr;
c->dwarf.pi_valid = 0;
c->dwarf.pi_is_dynamic = 0;
c->dwarf.hint = 0;

View file

@ -56,9 +56,9 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
c->dwarf.as = unw_local_addr_space;
c->dwarf.as_arg = uc;
#ifdef UNW_TARGET_PPC64
return common_init_ppc64 (c);
return common_init_ppc64 (c, 1);
#else
return common_init_ppc32 (c);
return common_init_ppc32 (c, 1);
#endif
}

View file

@ -50,9 +50,9 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
c->dwarf.as_arg = as_arg;
#ifdef UNW_TARGET_PPC64
return common_init_ppc64(c);
return common_init_ppc64 (c, 0);
#elif UNW_TARGET_PPC32
return common_init_ppc32 (c);
return common_init_ppc32 (c, 0);
#else
#error init_remote :: NO VALID PPC ARCH!
#endif

View file

@ -30,7 +30,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/* Here is the "common" init, for remote and local debuging" */
static inline int
common_init_ppc32 (struct cursor *c)
common_init_ppc32 (struct cursor *c, unsigned use_prev_instr)
{
int ret;
int i;
@ -62,6 +62,7 @@ common_init_ppc32 (struct cursor *c)
c->dwarf.args_size = 0;
c->dwarf.ret_addr_column = 0;
c->dwarf.use_prev_instr = use_prev_instr;
c->dwarf.pi_valid = 0;
c->dwarf.pi_is_dynamic = 0;
c->dwarf.hint = 0;

View file

@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
static inline int
common_init_ppc64 (struct cursor *c)
common_init_ppc64 (struct cursor *c, unsigned use_prev_instr)
{
int ret;
int i;
@ -72,6 +72,7 @@ common_init_ppc64 (struct cursor *c)
c->dwarf.args_size = 0;
c->dwarf.ret_addr_column = 0;
c->dwarf.use_prev_instr = use_prev_instr;
c->dwarf.pi_valid = 0;
c->dwarf.pi_is_dynamic = 0;
c->dwarf.hint = 0;

View file

@ -50,7 +50,7 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
c->dwarf.as_arg = c;
c->uc = uc;
c->validate = 0;
return common_init (c);
return common_init (c, 1);
}
#endif /* !UNW_REMOTE_ONLY */

View file

@ -51,6 +51,6 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
c->dwarf.as_arg = as_arg;
c->uc = 0;
}
return common_init (c);
return common_init (c, 0);
#endif /* !UNW_LOCAL_ONLY */
}

View file

@ -27,6 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
.global _Ux86_getcontext
.type _Ux86_getcontext, @function
_Ux86_getcontext:
.cfi_startproc
pushl %eax
mov 8(%esp),%eax /* ucontext_t* */
popl FREEBSD_UC_MCONTEXT_EAX_OFF(%eax)
@ -97,6 +98,7 @@ _Ux86_getcontext:
xorl %eax, %eax
ret
.cfi_endproc
.size _Ux86_getcontext, . - _Ux86_getcontext
/* We do not need executable stack. */

View file

@ -36,6 +36,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
.global _Ux86_getcontext
.type _Ux86_getcontext, @function
_Ux86_getcontext:
.cfi_startproc
mov 4(%esp),%eax /* ucontext_t* */
/* EAX is not preserved. */
@ -66,6 +67,7 @@ _Ux86_getcontext:
xor %eax, %eax
ret
.cfi_endproc
.size _Ux86_getcontext, . - _Ux86_getcontext
/* We do not need executable stack. */

View file

@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
static inline int
common_init (struct cursor *c)
common_init (struct cursor *c, unsigned use_prev_instr)
{
int ret, i;
@ -59,6 +59,7 @@ common_init (struct cursor *c)
c->dwarf.args_size = 0;
c->dwarf.ret_addr_column = 0;
c->dwarf.use_prev_instr = use_prev_instr;
c->dwarf.pi_valid = 0;
c->dwarf.pi_is_dynamic = 0;
c->dwarf.hint = 0;

View file

@ -51,8 +51,12 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
c->dwarf.as = unw_local_addr_space;
c->dwarf.as_arg = c;
c->uc = uc;
#if CONSERVATIVE_CHECKS
c->validate = 1;
#else
c->validate = 0;
return common_init (c);
#endif
return common_init (c, 1);
}
#endif /* !UNW_REMOTE_ONLY */

View file

@ -52,6 +52,6 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
c->dwarf.as_arg = as_arg;
c->uc = 0;
}
return common_init (c);
return common_init (c, 0);
#endif /* !UNW_LOCAL_ONLY */
}

View file

@ -30,74 +30,76 @@ 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;
unw_word_t w0, w1, ip;
unw_addr_space_t as;
unw_accessors_t *a;
void *arg;
int ret;
as = c->dwarf.as;
a = unw_get_accessors (as);
arg = c->dwarf.as_arg;
/* Check if RIP points at sigreturn sequence.
on x86_64 Linux that is (see libc.so):
48 c7 c0 0f 00 00 00 mov $0xf,%rax
0f 05 syscall
66 data16
*/
ip = c->dwarf.ip;
if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
|| (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0)
return 0;
w1 &= 0xff;
return (w0 == 0x0f0000000fc0c748 && w1 == 0x05);
return c->sigcontext_format != X86_64_SCF_NONE;
}
PROTECTED int
unw_handle_signal_frame (unw_cursor_t *cursor)
{
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;
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)
{
Debug (2, "returning %d\n", ret);
return ret;
}
c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0);
c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0);
c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0);
c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0);
c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0);
c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0);
c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0);
c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0);
c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0);
c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0);
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);
return 0;
#if UNW_DEBUG /* To silence compiler warnings */
/* 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. */
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);
#endif
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)
@ -85,6 +86,11 @@ unw_step (unw_cursor_t *cursor)
return 0;
}
}
else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP]))
{
for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
c->dwarf.loc[i] = DWARF_NULL_LOC;
}
else
{
unw_word_t rbp;
@ -92,7 +98,8 @@ unw_step (unw_cursor_t *cursor)
ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp);
if (ret < 0)
{
Debug (2, "returning %d\n", ret);
Debug (2, "returning %d [RBP=0x%lx]\n", ret,
DWARF_GET_LOC (c->dwarf.loc[RBP]));
return ret;
}

View file

@ -37,6 +37,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
.global _Ux86_64_getcontext
.type _Ux86_64_getcontext, @function
_Ux86_64_getcontext:
.cfi_startproc
/* Callee saved: RBX, RBP, R12-R15 */
movq %r12, UC_MCONTEXT_GREGS_R12(%rdi)
@ -70,7 +71,9 @@ _Ux86_64_getcontext:
/* Save rflags and segment registers, so that sigreturn(2)
does not complain. */
pushfq
.cfi_adjust_cfa_offset 8
popq UC_MCONTEXT_RFLAGS(%rdi)
.cfi_adjust_cfa_offset -8
movl $0, UC_MCONTEXT_FLAGS(%rdi)
movw %cs, UC_MCONTEXT_CS(%rdi)
movw %ss, UC_MCONTEXT_SS(%rdi)
@ -95,6 +98,7 @@ _Ux86_64_getcontext:
xorq %rax, %rax
retq
.cfi_endproc
.size _Ux86_64_getcontext, . - _Ux86_64_getcontext
/* We do not need executable stack. */

View file

@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "unwind_i.h"
static inline int
common_init (struct cursor *c)
common_init (struct cursor *c, unsigned use_prev_instr)
{
int ret;
@ -64,6 +64,7 @@ common_init (struct cursor *c)
c->dwarf.args_size = 0;
c->dwarf.ret_addr_column = RIP;
c->dwarf.use_prev_instr = use_prev_instr;
c->dwarf.pi_valid = 0;
c->dwarf.pi_is_dynamic = 0;
c->dwarf.hint = 0;

View file

@ -1,2 +1,2 @@
#!/bin/sh
./test-ptrace -c -n -t ./mapper
./test-ptrace -c -n -t ./mapper $*