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:
commit
b73c618a31
38 changed files with 228 additions and 102 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#!/bin/sh
|
||||
./test-ptrace -c -n -t ./mapper
|
||||
./test-ptrace -c -n -t ./mapper $*
|
||||
|
|
Loading…
Reference in a new issue