libunwind-devel
[Top][All Lists]
Advanced

[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++) {



reply via email to

[Prev in Thread] Current Thread [Next in Thread]