Remove the AT_SYSINFO and AT_SYSINFO_EHDR values if the sysinfo page
is in one of our reserved ranges.

diff --git a/loader/preloader.c b/loader/preloader.c
index 7bdf83d..1af59fd 100644
--- a/loader/preloader.c
+++ b/loader/preloader.c
@@ -282,17 +282,6 @@
     return dest;
 }
 
-static inline void *wld_memmove( void *dest, const void *src, size_t len )
-{
-    const char *s = src;
-    char *d = dest;
-    int i;
-
-    if (d < s) for (i = 0; i < len; i++) d[i] = s[i];
-    else for (i = len - 1; i >= 0; i--) d[i] = s[i];
-    return dest;
-}
-
 /*
  * wld_printf - just the basics
  *
@@ -377,6 +366,8 @@
         NAME(AT_PHENT),
         NAME(AT_PHNUM),
         NAME(AT_PLATFORM),
+        NAME(AT_SYSINFO),
+        NAME(AT_SYSINFO_EHDR),
         NAME(AT_UID),
         { 0, NULL }
     };
@@ -398,13 +389,28 @@
  *
  * Set the new auxiliary values
  */
-static void set_auxiliary_values( ElfW(auxv_t) *av, const ElfW(auxv_t) *new_av, void **stack )
+static void set_auxiliary_values( ElfW(auxv_t) *av, const ElfW(auxv_t) *new_av,
+                                  const ElfW(auxv_t) *delete_av, void **stack )
 {
-    int i, j, av_count = 0, new_count = 0;
+    int i, j, av_count = 0, new_count = 0, delete_count = 0;
+    char *src, *dst;
 
     /* count how many aux values we have already */
     while (av[av_count].a_type != AT_NULL) av_count++;
 
+    /* delete unwanted values */
+    for (j = 0; delete_av[j].a_type != AT_NULL; j++)
+    {
+        for (i = 0; i < av_count; i++) if (av[i].a_type == delete_av[j].a_type)
+        {
+            av[i].a_type = av[av_count-1].a_type;
+            av[i].a_un.a_val = av[av_count-1].a_un.a_val;
+            av[--av_count].a_type = AT_NULL;
+            delete_count++;
+            break;
+        }
+    }
+
     /* count how many values we have in new_av that aren't in av */
     for (j = 0; new_av[j].a_type != AT_NULL; j++)
     {
@@ -412,13 +418,20 @@
         if (i == av_count) new_count++;
     }
 
-    if (new_count)  /* need to make room for the extra values */
+    src = (char *)*stack;
+    dst = src - (new_count - delete_count) * sizeof(*av);
+    if (new_count > delete_count)   /* need to make room for the extra values */
     {
-        char *new_stack = (char *)*stack - new_count * sizeof(*av);
-        wld_memmove( new_stack, *stack, (char *)(av + av_count) - (char *)*stack );
-        *stack = new_stack;
-        av -= new_count;
+        int len = (char *)(av + av_count + 1) - src;
+        for (i = 0; i < len; i++) dst[i] = src[i];
     }
+    else if (new_count < delete_count)  /* get rid of unused values */
+    {
+        int len = (char *)(av + av_count + 1) - dst;
+        for (i = len - 1; i >= 0; i--) dst[i] = src[i];
+    }
+    *stack = dst;
+    av -= (new_count - delete_count);
 
     /* now set the values */
     for (j = 0; new_av[j].a_type != AT_NULL; j++)
@@ -803,6 +816,28 @@
     fatal_error( "invalid WINEPRELOADRESERVE value '%s'\n", str );
 }
 
+/*
+ *  is_in_preload_range
+ *
+ * Check if address of the given aux value is in one of the reserved ranges
+ */
+static int is_in_preload_range( const ElfW(auxv_t) *av, int type )
+{
+    int i;
+
+    while (av->a_type != type && av->a_type != AT_NULL) av++;
+
+    if (av->a_type == type)
+    {
+        for (i = 0; preload_info[i].size; i++)
+        {
+            if ((char *)av->a_un.a_ptr >= (char *)preload_info[i].addr &&
+                (char *)av->a_un.a_ptr < (char *)preload_info[i].addr + preload_info[i].size)
+                return 1;
+        }
+    }
+    return 0;
+}
 
 /*
  *  wld_start
@@ -816,7 +851,7 @@
     int i, *pargc;
     char **argv, **p;
     char *interp, *reserve = NULL;
-    ElfW(auxv_t) new_av[11], *av;
+    ElfW(auxv_t) new_av[12], delete_av[3], *av;
     struct wld_link_map main_binary_map, ld_so_map;
     struct wine_preload_info **wine_main_preload_info;
 
@@ -879,13 +914,20 @@
     SET_NEW_AV( 8, AT_EUID, get_auxiliary( av, AT_EUID, wld_geteuid() ) );
     SET_NEW_AV( 9, AT_GID, get_auxiliary( av, AT_GID, wld_getgid() ) );
     SET_NEW_AV(10, AT_EGID, get_auxiliary( av, AT_EGID, wld_getegid() ) );
+    SET_NEW_AV(11, AT_NULL, 0 );
 #undef SET_NEW_AV
 
+    i = 0;
+    /* delete sysinfo values if addresses conflict */
+    if (is_in_preload_range( av, AT_SYSINFO )) delete_av[i++].a_type = AT_SYSINFO;
+    if (is_in_preload_range( av, AT_SYSINFO_EHDR )) delete_av[i++].a_type = AT_SYSINFO_EHDR;
+    delete_av[i].a_type = AT_NULL;
+
     /* get rid of first argument */
     pargc[1] = pargc[0] - 1;
     *stack = pargc + 1;
 
-    set_auxiliary_values( av, new_av, stack );
+    set_auxiliary_values( av, new_av, delete_av, stack );
 
 #ifdef DUMP_AUX_INFO
     wld_printf("new stack = %x\n", *stack);