1
0
Fork 0
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:
Lassi Tuura 2011-03-22 11:30:21 +01:00 committed by Arun Sharma
parent f643684978
commit 28f33c8ce0
4 changed files with 43 additions and 9 deletions

View file

@ -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])

View file

@ -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);

View file

@ -71,6 +71,8 @@ tdep_init (void)
dwarf_init ();
tdep_init_mem_validate ();
#ifndef UNW_REMOTE_ONLY
x86_64_local_addr_space_init ();
#endif

View file

@ -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;