This jumbo-checkin is the Full Virtualization checkin.  This eliminates
Valgrind's dependency on the dynamic linker for getting started, and
instead takes things into its own hands.

This checkin doesn't add much in the way of new functionality, but it
is the basis for all future work on Valgrind.  It allows us much more
flexibility in implementation, and well as increasing the reliability
of Valgrind by protecting it more from its clients.

This patch requires some changes to tools to update them to the changes
in the tool API, but they are straightforward.  See the posting "Heads
up: Full Virtualization" on valgrind-developers for a more complete
description of this change and its effects on you.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2118 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/memcheck/Makefile.am b/memcheck/Makefile.am
index 3463d2c..9f92680 100644
--- a/memcheck/Makefile.am
+++ b/memcheck/Makefile.am
@@ -4,19 +4,25 @@
 all_includes = -I$(top_srcdir)/include
 
 AM_CPPFLAGS = $(all_includes) -DVG_LIBDIR="\"$(libdir)"\"
-AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer \
+AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O2 -fomit-frame-pointer \
 		@PREFERRED_STACK_BOUNDARY@ -g
 AM_CCASFLAGS = $(all_includes)
 
 valdir = $(libdir)/valgrind
+inplacedir = $(top_srcdir)/.in_place
 
-val_PROGRAMS = vgskin_memcheck.so
+val_PROGRAMS = vgskin_memcheck.so vgpreload_memcheck.so
+
+vgpreload_memcheck_so_SOURCES = \
+	mac_replace_strmem.c
+vgpreload_memcheck_so_LDADD = $(top_srcdir)/coregrind/vg_replace_malloc.o
+vgpreload_memcheck_so_DEPENDENCIES = $(top_srcdir)/coregrind/vg_replace_malloc.o
+vgpreload_memcheck_so_LDFLAGS = -shared -Wl,-z,interpose,-z,initfirst
 
 vgskin_memcheck_so_SOURCES = \
 	mac_leakcheck.c \
 	mac_malloc_wrappers.c \
 	mac_needs.c \
-	mac_replace_strmem.c \
 	mc_main.c \
 	mc_clientreqs.c \
 	mc_errcontext.c \
@@ -24,7 +30,6 @@
 	mc_translate.c \
 	mc_helpers.S
 vgskin_memcheck_so_LDFLAGS = -shared
-vgskin_memcheck_so_LDADD = ../coregrind/vg_replace_malloc.o
 
 mcincludedir = $(includedir)/valgrind
 
@@ -38,3 +43,7 @@
 
 mac_replace_strmem.o: CFLAGS += -fno-omit-frame-pointer
 
+all-local:
+	mkdir -p $(inplacedir)
+	-rm -f $(addprefix $(inplacedir)/,$(val_PROGRAMS))
+	ln -f -s $(addprefix $(top_srcdir)/$(subdir)/,$(val_PROGRAMS)) $(inplacedir)
diff --git a/memcheck/mac_leakcheck.c b/memcheck/mac_leakcheck.c
index a596612..a11e128 100644
--- a/memcheck/mac_leakcheck.c
+++ b/memcheck/mac_leakcheck.c
@@ -311,10 +311,7 @@
       where the .bss segment has been put.  If you can, drop me a
       line.  
    */
-   if (VG_(within_stack)(a))                      return;
-   if (VG_(within_m_state_static_OR_threads)(a))  return;
-   if (a == (Addr)(&lc_min_mallocd_addr))         return;
-   if (a == (Addr)(&lc_max_mallocd_addr))         return;
+   if (!VG_(is_client_addr)(a))			  return;
 
    /* OK, let's get on and do something Useful for a change. */
 
diff --git a/memcheck/mac_replace_strmem.c b/memcheck/mac_replace_strmem.c
index 6ae5800..12560f6 100644
--- a/memcheck/mac_replace_strmem.c
+++ b/memcheck/mac_replace_strmem.c
@@ -31,8 +31,26 @@
 */
 
 #include "mc_include.h"
+#include "memcheck.h"
 #include "valgrind.h"
 
+static Addr record_overlap_error;
+
+static int init_done;
+
+/* Startup hook - called as init section */
+static void init(void) __attribute__((constructor));
+static void init(void) 
+{
+   if (init_done)
+      return;
+
+   VALGRIND_MAGIC_SEQUENCE(record_overlap_error, 0,
+			   _VG_USERREQ__MEMCHECK_GET_RECORD_OVERLAP,
+			   0, 0, 0, 0);
+   init_done = 1;
+}
+
 /* ---------------------------------------------------------------------
    The normal versions of these functions are hyper-optimised, which fools
    Memcheck and cause spurious value warnings.  So we replace them with
@@ -80,7 +98,8 @@
    OverlapExtra extra = {
       .src = (Addr)src, .dst = (Addr)dst, .len = -1,
    };
-   VALGRIND_NON_SIMD_CALL2( MAC_(record_overlap_error), s, &extra );
+   init();
+   VALGRIND_NON_SIMD_CALL2( record_overlap_error, s, &extra );
 }
 
 static __inline__
@@ -90,7 +109,8 @@
    OverlapExtra extra = {
       .src = (Addr)src, .dst = (Addr)dst, .len = n,
    };
-   VALGRIND_NON_SIMD_CALL2( MAC_(record_overlap_error), s, &extra );
+   init();
+   VALGRIND_NON_SIMD_CALL2( record_overlap_error, s, &extra );
 }
 
 char* strrchr ( const char* s, int c )
diff --git a/memcheck/mc_clientreqs.c b/memcheck/mc_clientreqs.c
index ddfb05d..e8c078c 100644
--- a/memcheck/mc_clientreqs.c
+++ b/memcheck/mc_clientreqs.c
@@ -232,6 +232,10 @@
                    ( tid, arg[1], arg[2], arg[3], True /* set them */ );
          break;
 
+      case _VG_USERREQ__MEMCHECK_GET_RECORD_OVERLAP:
+	 *ret = (Addr)MAC_(record_overlap_error);
+	 break;
+
       default:
          if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
             return True;
diff --git a/memcheck/mc_from_ucode.c b/memcheck/mc_from_ucode.c
index e1f2877..6cfe815 100644
--- a/memcheck/mc_from_ucode.c
+++ b/memcheck/mc_from_ucode.c
@@ -246,16 +246,16 @@
                                         R_EBP, reg );
          break;
       case 2: 
-         VG_(emit_movzwl_offregmem_reg) ( VG_(shadow_reg_offset)(arch),
+         VG_(emit_movzwl_offregmem_reg) ( False, VG_(shadow_reg_offset)(arch),
                                           R_EBP, reg );
          VG_(emit_nonshiftopv_lit_reg) ( False, 4, OR, 0xFFFF0000, reg );
          break;
       case 1: 
          if (arch < 4) {
-            VG_(emit_movzbl_offregmem_reg) ( VG_(shadow_reg_offset)(arch),
+            VG_(emit_movzbl_offregmem_reg) ( False, VG_(shadow_reg_offset)(arch),
                                              R_EBP, reg );
          } else {
-            VG_(emit_movzbl_offregmem_reg) ( VG_(shadow_reg_offset)(arch-4)+1,
+            VG_(emit_movzbl_offregmem_reg) ( False, VG_(shadow_reg_offset)(arch-4)+1,
                                              R_EBP, reg );
          }
          VG_(emit_nonshiftopv_lit_reg) ( False, 4, OR, 0xFFFFFF00, reg );
diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c
index 8b46797..8f3fbc8 100644
--- a/memcheck/mc_main.c
+++ b/memcheck/mc_main.c
@@ -34,8 +34,6 @@
 #include "memcheck.h"   /* for client requests */
 //#include "vg_profile.c"
 
-VG_DETERMINE_INTERFACE_VERSION
-
 /* Define to debug the mem audit system. */
 /* #define VG_DEBUG_MEMORY */
 
@@ -118,7 +116,6 @@
 static SecMap* primary_map[ /*65536*/ 262144 ];
 static SecMap  distinguished_secondary_map;
 
-
 static void init_shadow_memory ( void )
 {
    Int i;
@@ -157,7 +154,7 @@
       although this isn't important, so the following assert is
       spurious. */
    sk_assert(0 == (sizeof(SecMap) % VKI_BYTES_PER_PAGE));
-   map = VG_(get_memory_from_mmap)( sizeof(SecMap), caller );
+   map = (SecMap *)VG_(shadow_alloc)(sizeof(SecMap));
 
    for (i = 0; i < 8192; i++)
       map->abits[i] = VGM_BYTE_INVALID; /* Invalid address */
@@ -1671,6 +1668,7 @@
    VG_(needs_extended_UCode)      ();
    VG_(needs_syscall_wrapper)     ();
    VG_(needs_sanity_checks)       ();
+   VG_(needs_shadow_memory)       ();
 
    MAC_( new_mem_heap)             = & mc_new_mem_heap;
    MAC_( ban_mem_heap)             = & MC_(make_noaccess);
@@ -1678,45 +1676,45 @@
    MAC_( die_mem_heap)             = & MC_(make_noaccess);
    MAC_(check_noaccess)            = & MC_(check_noaccess);
 
-   VG_(track_new_mem_startup)      ( & mc_new_mem_startup );
-   VG_(track_new_mem_stack_signal) ( & MC_(make_writable) );
-   VG_(track_new_mem_brk)          ( & MC_(make_writable) );
-   VG_(track_new_mem_mmap)         ( & mc_set_perms );
+   VG_(init_new_mem_startup)      ( & mc_new_mem_startup );
+   VG_(init_new_mem_stack_signal) ( & MC_(make_writable) );
+   VG_(init_new_mem_brk)          ( & MC_(make_writable) );
+   VG_(init_new_mem_mmap)         ( & mc_set_perms );
    
-   VG_(track_copy_mem_remap)       ( & mc_copy_address_range_state );
-   VG_(track_change_mem_mprotect)  ( & mc_set_perms );
+   VG_(init_copy_mem_remap)       ( & mc_copy_address_range_state );
+   VG_(init_change_mem_mprotect)  ( & mc_set_perms );
       
-   VG_(track_die_mem_stack_signal) ( & MC_(make_noaccess) ); 
-   VG_(track_die_mem_brk)          ( & MC_(make_noaccess) );
-   VG_(track_die_mem_munmap)       ( & MC_(make_noaccess) ); 
+   VG_(init_die_mem_stack_signal) ( & MC_(make_noaccess) ); 
+   VG_(init_die_mem_brk)          ( & MC_(make_noaccess) );
+   VG_(init_die_mem_munmap)       ( & MC_(make_noaccess) ); 
 
-   VG_(track_new_mem_stack_4)      ( & MAC_(new_mem_stack_4)  );
-   VG_(track_new_mem_stack_8)      ( & MAC_(new_mem_stack_8)  );
-   VG_(track_new_mem_stack_12)     ( & MAC_(new_mem_stack_12) );
-   VG_(track_new_mem_stack_16)     ( & MAC_(new_mem_stack_16) );
-   VG_(track_new_mem_stack_32)     ( & MAC_(new_mem_stack_32) );
-   VG_(track_new_mem_stack)        ( & MAC_(new_mem_stack)    );
+   VG_(init_new_mem_stack_4)      ( & MAC_(new_mem_stack_4)  );
+   VG_(init_new_mem_stack_8)      ( & MAC_(new_mem_stack_8)  );
+   VG_(init_new_mem_stack_12)     ( & MAC_(new_mem_stack_12) );
+   VG_(init_new_mem_stack_16)     ( & MAC_(new_mem_stack_16) );
+   VG_(init_new_mem_stack_32)     ( & MAC_(new_mem_stack_32) );
+   VG_(init_new_mem_stack)        ( & MAC_(new_mem_stack)    );
 
-   VG_(track_die_mem_stack_4)      ( & MAC_(die_mem_stack_4)  );
-   VG_(track_die_mem_stack_8)      ( & MAC_(die_mem_stack_8)  );
-   VG_(track_die_mem_stack_12)     ( & MAC_(die_mem_stack_12) );
-   VG_(track_die_mem_stack_16)     ( & MAC_(die_mem_stack_16) );
-   VG_(track_die_mem_stack_32)     ( & MAC_(die_mem_stack_32) );
-   VG_(track_die_mem_stack)        ( & MAC_(die_mem_stack)    );
+   VG_(init_die_mem_stack_4)      ( & MAC_(die_mem_stack_4)  );
+   VG_(init_die_mem_stack_8)      ( & MAC_(die_mem_stack_8)  );
+   VG_(init_die_mem_stack_12)     ( & MAC_(die_mem_stack_12) );
+   VG_(init_die_mem_stack_16)     ( & MAC_(die_mem_stack_16) );
+   VG_(init_die_mem_stack_32)     ( & MAC_(die_mem_stack_32) );
+   VG_(init_die_mem_stack)        ( & MAC_(die_mem_stack)    );
    
-   VG_(track_ban_mem_stack)        ( & MC_(make_noaccess) );
+   VG_(init_ban_mem_stack)        ( & MC_(make_noaccess) );
 
-   VG_(track_pre_mem_read)         ( & mc_check_is_readable );
-   VG_(track_pre_mem_read_asciiz)  ( & mc_check_is_readable_asciiz );
-   VG_(track_pre_mem_write)        ( & mc_check_is_writable );
-   VG_(track_post_mem_write)       ( & MC_(make_readable) );
+   VG_(init_pre_mem_read)         ( & mc_check_is_readable );
+   VG_(init_pre_mem_read_asciiz)  ( & mc_check_is_readable_asciiz );
+   VG_(init_pre_mem_write)        ( & mc_check_is_writable );
+   VG_(init_post_mem_write)       ( & MC_(make_readable) );
 
-   VG_(track_post_regs_write_init)             ( & mc_post_regs_write_init );
-   VG_(track_post_reg_write_syscall_return)    ( & mc_post_reg_write );
-   VG_(track_post_reg_write_deliver_signal)    ( & mc_post_reg_write );
-   VG_(track_post_reg_write_pthread_return)    ( & mc_post_reg_write );
-   VG_(track_post_reg_write_clientreq_return)  ( & mc_post_reg_write );
-   VG_(track_post_reg_write_clientcall_return) ( & mc_post_reg_write_clientcall );
+   VG_(init_post_regs_write_init)             ( & mc_post_regs_write_init );
+   VG_(init_post_reg_write_syscall_return)    ( & mc_post_reg_write );
+   VG_(init_post_reg_write_deliver_signal)    ( & mc_post_reg_write );
+   VG_(init_post_reg_write_pthread_return)    ( & mc_post_reg_write );
+   VG_(init_post_reg_write_clientreq_return)  ( & mc_post_reg_write );
+   VG_(init_post_reg_write_clientcall_return) ( & mc_post_reg_write_clientcall );
 
    /* Three compact slots taken up by stack memory helpers */
    VG_(register_compact_helper)((Addr) & MC_(helper_value_check4_fail));
@@ -1760,6 +1758,8 @@
    }
 }
 
+VG_DETERMINE_INTERFACE_VERSION(SK_(pre_clo_init), 9./8)
+
 /*--------------------------------------------------------------------*/
 /*--- end                                                mc_main.c ---*/
 /*--------------------------------------------------------------------*/
diff --git a/memcheck/memcheck.h b/memcheck/memcheck.h
index 5dc7c80..58284a0 100644
--- a/memcheck/memcheck.h
+++ b/memcheck/memcheck.h
@@ -89,7 +89,10 @@
       VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE,
 
       VG_USERREQ__GET_VBITS,
-      VG_USERREQ__SET_VBITS
+      VG_USERREQ__SET_VBITS,
+
+      /* This is just for memcheck's internal use - don't use it */
+      _VG_USERREQ__MEMCHECK_GET_RECORD_OVERLAP = VG_USERREQ_SKIN_BASE('M','C')+256,
    } Vg_MemCheckClientRequest;
 
 
diff --git a/memcheck/tests/badjump.stderr.exp b/memcheck/tests/badjump.stderr.exp
index 2bec474..a01f6ec 100644
--- a/memcheck/tests/badjump.stderr.exp
+++ b/memcheck/tests/badjump.stderr.exp
@@ -6,7 +6,7 @@
  Address 0x........ is not stack'd, malloc'd or free'd
 
 Process terminating with default action of signal 11 (SIGSEGV): dumping core
- Address not mapped to object at address 0x........
+ Access not within mapped region at address 0x........
    at 0x........: ???
    by 0x........: __libc_start_main (...libc...)
    by 0x........: ...
diff --git a/memcheck/tests/fprw.vgtest b/memcheck/tests/fprw.vgtest
index a5dfb42..6dfbf0c 100644
--- a/memcheck/tests/fprw.vgtest
+++ b/memcheck/tests/fprw.vgtest
@@ -1,2 +1,2 @@
-vgopts: --single-step=yes -q
+vgopts: -q
 prog:   fprw
diff --git a/memcheck/tests/nanoleak.supp b/memcheck/tests/nanoleak.supp
index 6c87853..584c93e 100644
--- a/memcheck/tests/nanoleak.supp
+++ b/memcheck/tests/nanoleak.supp
@@ -3,6 +3,5 @@
    Addrcheck,Memcheck:Leak
    fun:malloc
    fun:main
-   fun:__libc_start_main
 }
 
diff --git a/memcheck/tests/sigaltstack.c b/memcheck/tests/sigaltstack.c
index f310df5..279e315 100644
--- a/memcheck/tests/sigaltstack.c
+++ b/memcheck/tests/sigaltstack.c
@@ -26,6 +26,7 @@
   fprintf(stderr,"setting sigaction\n");
   act.sa_flags=SA_ONSTACK;
   act.sa_handler=&sig_handler;
+  sigemptyset(&act.sa_mask);
   res = sigaction(SIGUSR1,&act,0);
   fprintf(stderr, "res = %d\n", res);
   fprintf(stderr, "raising the signal\n");
diff --git a/memcheck/tests/sigaltstack.stderr.exp b/memcheck/tests/sigaltstack.stderr.exp
index 6c0b2fc..b95833f 100644
--- a/memcheck/tests/sigaltstack.stderr.exp
+++ b/memcheck/tests/sigaltstack.stderr.exp
@@ -1,8 +1,5 @@
 calling sigaltstack, stack base is 0x........
 setting sigaction
-Syscall param sigaction(act) contains uninitialised or unaddressable byte(s)
-   at 0x........: __libc_sigaction (...libc...)
- Address 0x........ is on thread 1's stack
 res = 0
 raising the signal
 caught signal, local var is on 0x........
diff --git a/memcheck/tests/threadederrno.c b/memcheck/tests/threadederrno.c
index bc05be5..d924ca4 100644
--- a/memcheck/tests/threadederrno.c
+++ b/memcheck/tests/threadederrno.c
@@ -2,22 +2,20 @@
 #include <pthread.h>
 #include <stdio.h>
 #include <errno.h>
-
+#include <string.h>
 
 
 void* thr2 ( void* v )
 {
   FILE* f = fopen("bogus2", "r");
-  printf("f2 = %p, errno2 = %d\n", f, errno);
-  perror("wurble2");
+  printf("f2 = %p, errno2 = %d (%s)\n", f, errno, strerror(errno));
   return NULL;
 }
 
 void* thr3 ( void* v )
 {
   FILE* f = fopen("bogus3", "r");
-  printf("f3 = %p, errno3 = %d\n", f, errno);
-  perror("wurble3");
+  printf("f3 = %p, errno3 = %d (%s)\n", f, errno, strerror(errno));
   return NULL;
 }
 
@@ -29,8 +27,7 @@
   pthread_create(&tid2, NULL, &thr2, NULL);
   pthread_create(&tid3, NULL, &thr3, NULL);
   f = fopen("bogus", "r");
-  printf("f1 = %p, errno1 = %d\n", f, errno);
-  perror("wurble1");
+  printf("f1 = %p, errno1 = %d (%s)\n", f, errno, strerror(errno));
   pthread_join(tid2, NULL);
   pthread_join(tid3, NULL);
   return 0;
diff --git a/memcheck/tests/threadederrno.stderr.exp b/memcheck/tests/threadederrno.stderr.exp
index 99cd1a3..e69de29 100644
--- a/memcheck/tests/threadederrno.stderr.exp
+++ b/memcheck/tests/threadederrno.stderr.exp
@@ -1,3 +0,0 @@
-wurble1: No such file or directory
-wurble2: No such file or directory
-wurble3: No such file or directory
diff --git a/memcheck/tests/threadederrno.stdout.exp b/memcheck/tests/threadederrno.stdout.exp
index a05dec2..c68b951 100644
--- a/memcheck/tests/threadederrno.stdout.exp
+++ b/memcheck/tests/threadederrno.stdout.exp
@@ -1,3 +1,3 @@
-f1 = (nil), errno1 = 2
-f2 = (nil), errno2 = 2
-f3 = (nil), errno3 = 2
+f1 = (nil), errno1 = 2 (No such file or directory)
+f2 = (nil), errno2 = 2 (No such file or directory)
+f3 = (nil), errno3 = 2 (No such file or directory)
diff --git a/memcheck/tests/zeropage.stderr.exp b/memcheck/tests/zeropage.stderr.exp
index e69de29..d3e3f43 100644
--- a/memcheck/tests/zeropage.stderr.exp
+++ b/memcheck/tests/zeropage.stderr.exp
@@ -0,0 +1,3 @@
+Warning: client syscall mmap2 tried to modify addresses 0x........-0x........
+Warning: client syscall mmap2 tried to modify addresses 0x........-0x........
+Warning: client syscall mmap2 tried to modify addresses 0x........-0x........