A minimal set of changes to make it work on Red Hat 9, at least in the
interim.  All hats off to Graydon Hoare for this, plus to whoever
devised the LD_ASSUME_KERNEL trapdoor.

This does not provide NPTL support.  Instead it turns out we can ask
for the old LinuxThreads interface to be used (wonderful!)

Other than that we have to deal with kernels with SYSINFO pages at the
top of memory.  No big deal, apparently.

MERGE TO STABLE


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1508 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/addrcheck/ac_main.c b/addrcheck/ac_main.c
index 511c7c5..eb8a31d 100644
--- a/addrcheck/ac_main.c
+++ b/addrcheck/ac_main.c
@@ -1182,8 +1182,12 @@
 
 Bool SK_(cheap_sanity_check) ( void )
 {
-   if (IS_DISTINGUISHED_SM(primary_map[0]) && 
-       IS_DISTINGUISHED_SM(primary_map[65535]))
+   if (IS_DISTINGUISHED_SM(primary_map[0])
+       /* kludge: kernel drops a page up at top of address range for
+          magic "optimized syscalls", so we can no longer check the
+          highest page */
+       /* && IS_DISTINGUISHED_SM(primary_map[65535]) */
+      )
       return True;
    else
       return False;
diff --git a/coregrind/valgrind.in b/coregrind/valgrind.in
index 14c1409..fcdbd5b 100755
--- a/coregrind/valgrind.in
+++ b/coregrind/valgrind.in
@@ -83,6 +83,14 @@
 
 export VG_ARGS
 
+# Red Hat Linux 9 uses NPTL, which has a kernel interface 
+# unlike the linuxthreads interface valgrind expects. we can
+# tell the dynamic loader to disable this interface using
+# an environment variable.
+
+LD_ASSUME_KERNEL=2.2.5
+export LD_ASSUME_KERNEL 
+
 # A bit subtle.  The LD_PRELOAD added entry must be absolute
 # and not depend on LD_LIBRARY_PATH.  This is so that we can
 # mess with LD_LIBRARY_PATH for child processes, which makes
diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h
index f309dc1..018e88a 100644
--- a/coregrind/vg_include.h
+++ b/coregrind/vg_include.h
@@ -1320,6 +1320,11 @@
    client's argc, argv and envp are deduced. */
 extern Addr   VG_(esp_at_startup);
 
+/* Indicates presence, and holds address of client's sysinfo page, a
+   feature of some modern kernels used to provide vsyscalls, etc. */
+extern Bool VG_(sysinfo_page_exists);
+extern Addr VG_(sysinfo_page_addr);
+
 /* Remove valgrind.so and skin's .so from a LD_PRELOAD=... string so child
    processes don't get traced into.  Also mess up $libdir/valgrind so that
    our libpthread.so disappears from view. */
diff --git a/coregrind/vg_kerneliface.h b/coregrind/vg_kerneliface.h
index 7784571..67b61a5 100644
--- a/coregrind/vg_kerneliface.h
+++ b/coregrind/vg_kerneliface.h
@@ -353,6 +353,7 @@
    Logic from     /usr/src/linux-2.4.9-31/fs/binfmt_elf.c
                   and its counterpart in the 2.2.14 kernel sources 
                   in Red Hat 6.2.  */
+#define VKI_AT_SYSINFO 32   /* address of system info page */
 #define VKI_AT_CLKTCK 17    /* frequency at which times() increments */
 #define VKI_AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
 #define VKI_AT_BASE   7     /* base address of interpreter */
diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c
index a308c2b..eebdec6 100644
--- a/coregrind/vg_main.c
+++ b/coregrind/vg_main.c
@@ -496,6 +496,11 @@
 /* Holds client's %esp at the point we gained control. */
 Addr VG_(esp_at_startup);
 
+/* Indicates presence, and holds address of client's sysinfo page, a
+   feature of some modern kernels used to provide vsyscalls, etc. */
+Bool VG_(sysinfo_page_exists) = False;
+Addr VG_(sysinfo_page_addr) = 0;
+
 /* As deduced from VG_(esp_at_startup), the client's argc, argv[] and
    envp[] as extracted from the client's stack at startup-time. */
 Int    VG_(client_argc);
@@ -725,6 +730,18 @@
        if (sp[2] == VKI_AT_CLKTCK
            && sp[0] == VKI_AT_PAGESZ
            && sp[-2] == VKI_AT_HWCAP
+           && sp[-4] == VKI_AT_SYSINFO
+           && sp[-4-1] == 0) {
+          if (0)
+             VG_(printf)("Looks like you've got a 2.4.X kernel with "
+                         "a sysinfo page at %x here.\n", sp[-3]);
+	  VG_(sysinfo_page_exists) = True;
+	  VG_(sysinfo_page_addr) = sp[-3];
+          sp -= 4;
+       } else
+       if (sp[2] == VKI_AT_CLKTCK
+           && sp[0] == VKI_AT_PAGESZ
+           && sp[-2] == VKI_AT_HWCAP
            && sp[-4] == VKI_AT_USER_AUX_SEGMENT
            && sp[-4-1] == 0) {
           if (0)
diff --git a/coregrind/vg_memory.c b/coregrind/vg_memory.c
index f2429ec..7b83fa3 100644
--- a/coregrind/vg_memory.c
+++ b/coregrind/vg_memory.c
@@ -211,6 +211,15 @@
 
    /* 4 */
    VG_(init_dataseg_end_for_brk)();
+
+   /* kludge: some newer kernels place a "sysinfo" page up high, with
+      vsyscalls in it, and possibly some other stuff in the future. */
+   if (VG_(sysinfo_page_exists)) {
+      VG_(new_exe_segment)( VG_(sysinfo_page_addr), 4096 );
+      VG_TRACK( new_mem_startup, VG_(sysinfo_page_addr), 4096, 
+                True, True, True );
+     }
+
 }
 
 
diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c
index 8859aff..190e906 100644
--- a/helgrind/hg_main.c
+++ b/helgrind/hg_main.c
@@ -1872,8 +1872,12 @@
 
 Bool SK_(cheap_sanity_check) ( void )
 {
-   if (VGE_IS_DISTINGUISHED_SM(primary_map[0]) && 
-       VGE_IS_DISTINGUISHED_SM(primary_map[65535]))
+   if (VGE_IS_DISTINGUISHED_SM(primary_map[0])
+       /* kludge: kernel drops a page up at top of address range for
+          magic "optimized syscalls", so we can no longer check the
+          highest page */
+       /* && VGE_IS_DISTINGUISHED_SM(primary_map[65535]) */
+      )
       return True;
    else
       return False;
diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c
index 78779bb..2a4daaa 100644
--- a/memcheck/mc_main.c
+++ b/memcheck/mc_main.c
@@ -1349,8 +1349,12 @@
 
 Bool SK_(cheap_sanity_check) ( void )
 {
-   if (IS_DISTINGUISHED_SM(primary_map[0]) && 
-       IS_DISTINGUISHED_SM(primary_map[65535]))
+   if (IS_DISTINGUISHED_SM(primary_map[0])
+       /* kludge: kernel drops a page up at top of address range for
+          magic "optimized syscalls", so we can no longer check the
+          highest page */
+       /* && IS_DISTINGUISHED_SM(primary_map[65535]) */
+      )
       return True;
    else
       return False;