I have been testing recent versions of libunwind on Centos 5.2 (x86_64),
and it appears that mincore(2) does not do what we want. That is,
msync(2) and mincore(2) do not give the same results.
While tracking this down, I noticed a longer-standing problem in
validate_mem() having to do with unaligned access that straddles pages.
In practice I wouldn't be surprised if this bug is never triggered,
but fixing it seems worthwhile nonetheless. Following is a partial
patch, but it doesn't actually fix the problem. Can anyone shed some
light on whether mincore(2) is viable on Linux? If not I'll try to come
up with a more sophisticated autoconf test for mincore(2).
Thanks,
Jason
diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c
index 14614f1..7942c39 100644
--- a/src/x86_64/Ginit.c
+++ b/src/x86_64/Ginit.c
@@ -33,6 +33,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
+#ifdef HAVE_MINCORE
+#include <errno.h>
+#endif
#include "unwind_i.h"
@@ -93,6 +96,12 @@ validate_mem (unw_word_t addr)
#ifdef HAVE_MINCORE
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))
+ len = PAGE_SIZE;
+ else
+ len = PAGE_SIZE * 2;
addr = PAGE_START(addr);
@@ -106,11 +115,21 @@ validate_mem (unw_word_t addr)
}
#ifdef HAVE_MINCORE
- if (mincore ((void *) addr, sizeof (unw_word_t), mvec) == -1)
+ while (1)
+ {
+ if (mincore ((void *) addr, len, mvec) == 0)
+ break;
+ switch (errno)
+ {
+ case EAGAIN: break;
+ case ENOMEM: return -1;
+ case EFAULT: case EINVAL: default: abort ();
+ }
+ }
#else
- if (msync ((void *) addr, sizeof (unw_word_t), MS_ASYNC) == -1)
-#endif
+ if (msync ((void *) addr, len, MS_ASYNC) == -1)
return -1;
+#endif
victim = lga_victim;
for (i = 0; i < NLGA; i++) {
_______________________________________________
Libunwind-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/libunwind-devel