mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-12-23 03:53:43 +01:00
Auto-detect whether to use msync() or mincore() for address validation.
This commit is contained in:
parent
f643684978
commit
28f33c8ce0
4 changed files with 43 additions and 9 deletions
|
@ -223,7 +223,8 @@ 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"
|
||||
AC_DEFINE(CONSERVATIVE_CHECKS, 1,
|
||||
[Define to 1 if you want every memory access validated])
|
||||
fi
|
||||
AC_MSG_RESULT([$enable_conservative_checks])
|
||||
|
||||
|
|
|
@ -155,6 +155,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
|||
}
|
||||
|
||||
#define tdep_needs_initialization UNW_OBJ(needs_initialization)
|
||||
#define tdep_init_mem_validate UNW_OBJ(init_mem_validate)
|
||||
#define tdep_init UNW_OBJ(init)
|
||||
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
|
||||
tdep_search_unwind_table. */
|
||||
|
@ -195,6 +196,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
|||
extern int tdep_needs_initialization;
|
||||
|
||||
extern void tdep_init (void);
|
||||
extern void tdep_init_mem_validate (void);
|
||||
extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_dyn_info_t *di, unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg);
|
||||
|
|
|
@ -71,6 +71,8 @@ tdep_init (void)
|
|||
|
||||
dwarf_init ();
|
||||
|
||||
tdep_init_mem_validate ();
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
x86_64_local_addr_space_init ();
|
||||
#endif
|
||||
|
|
|
@ -81,6 +81,42 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
|
|||
#define PAGE_SIZE 4096
|
||||
#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1))
|
||||
|
||||
static int (*mem_validate_func) (void *addr, size_t len);
|
||||
static int msync_validate (void *addr, size_t len)
|
||||
{
|
||||
return msync (addr, len, MS_ASYNC);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MINCORE
|
||||
static int mincore_validate (void *addr, size_t len)
|
||||
{
|
||||
unsigned char mvec[2]; /* Unaligned access may cross page boundary */
|
||||
return mincore (addr, len, mvec);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialise memory validation method. On linux kernels <2.6.21,
|
||||
mincore() returns incorrect value for MAP_PRIVATE mappings,
|
||||
such as stacks. If mincore() was available at compile time,
|
||||
check if we can actually use it. If not, use msync() instead. */
|
||||
HIDDEN void
|
||||
tdep_init_mem_validate (void)
|
||||
{
|
||||
#ifdef HAVE_MINCORE
|
||||
unsigned char present = 1;
|
||||
if (mincore (&present, 1, &present) == 0)
|
||||
{
|
||||
Debug(1, "using mincore to validate memory\n");
|
||||
mem_validate_func = mincore_validate;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Debug(1, "using msync to validate memory\n");
|
||||
mem_validate_func = msync_validate;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cache of already validated addresses */
|
||||
#define NLGA 4
|
||||
static unw_word_t last_good_addr[NLGA];
|
||||
|
@ -90,9 +126,6 @@ static int
|
|||
validate_mem (unw_word_t addr)
|
||||
{
|
||||
int i, victim;
|
||||
#ifdef HAVE_MINCORE
|
||||
unsigned char mvec[2]; /* Unaligned access may cross page boundary */
|
||||
#endif
|
||||
size_t len;
|
||||
|
||||
if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr))
|
||||
|
@ -111,11 +144,7 @@ validate_mem (unw_word_t addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MINCORE
|
||||
if (mincore ((void *) addr, len, mvec) == -1)
|
||||
#else
|
||||
if (msync ((void *) addr, len, MS_ASYNC) == -1)
|
||||
#endif
|
||||
if (mem_validate_func ((void *) addr, len) == -1)
|
||||
return -1;
|
||||
|
||||
victim = lga_victim;
|
||||
|
|
Loading…
Reference in a new issue