[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Libunwind-devel] mincore(2) problems on Linux
From: |
Jason Evans |
Subject: |
[Libunwind-devel] mincore(2) problems on Linux |
Date: |
Thu, 03 Jun 2010 18:19:54 -0700 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100423 Thunderbird/3.0.4 |
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] mincore(2) problems on Linux,
Jason Evans <=