Added a unit self-test -- a test program that incorporates a small part of
Valgrind itself (the files ume.c, ume_entry.c and jmp_with_stack.c).  Thus,
we are using Memcheck to check these files in a unit test setting.

I hope to do unit self-testing for many more parts of Valgrind, eventually all
the bits that can be pulled out into any kind of sensible stand-alone form.
Doing so achieves two things:

 a) it introduces unit testing into our framework (a serious shortcoming at the
    moment)
 b) it lets us use Valgrind (esp. Memcheck) on itself, to some extent

This should help reliability.  This first unit self-test isn't very exhaustive,
but it's a start.

Note that this involves something like bootstrapping, in that we are checking
parts of a Valgrind build with itself.  I don't think this will be a problem,
since we (at least, I do) tend to only run the regtests when we think the
Valgrind build is ok.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2760 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/memcheck/tests/.cvsignore b/memcheck/tests/.cvsignore
index 8f5de61..dc19631 100644
--- a/memcheck/tests/.cvsignore
+++ b/memcheck/tests/.cvsignore
@@ -21,6 +21,7 @@
 fpeflags
 fprw
 fwrite
+hello
 inits
 inline
 malloc1
@@ -49,6 +50,7 @@
 suppfree
 trivialleak
 tronical
+vgtest_ume
 weirdioctl
 *.stdout.diff
 *.stderr.diff
diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am
index e620092..9ec6929 100644
--- a/memcheck/tests/Makefile.am
+++ b/memcheck/tests/Makefile.am
@@ -75,6 +75,7 @@
 	metadata.stderr.exp metadata.stdout.exp metadata.vgtest \
 	threadederrno.stderr.exp threadederrno.stdout.exp \
 	threadederrno.vgtest \
+	vgtest_ume.stderr.exp vgtest_ume.vgtest \
 	writev.stderr.exp writev.vgtest \
 	zeropage.stderr.exp zeropage.stderr.exp2 zeropage.vgtest
 
@@ -83,14 +84,17 @@
 	badloop badrw brk brk2 buflen_check \
 	clientperm custom_alloc \
 	doublefree error_counts errs1 exitprog execve execve2 \
-	fpeflags fprw fwrite inits inline \
+	fpeflags fprw fwrite hello inits inline \
 	malloc1 malloc2 malloc3 manuel1 manuel2 manuel3 \
 	memalign_test memalign2 memcmptest mempool mmaptest \
 	nanoleak new_nothrow \
 	null_socket overlap pushfpopf \
 	realloc1 realloc2 realloc3 sigaltstack signal2 supp1 supp2 suppfree \
 	trivialleak tronical weirdioctl	\
-	mismatches new_override metadata threadederrno writev zeropage
+	mismatches new_override metadata threadederrno \
+	vgtest_ume \
+	writev zeropage
+
 
 AM_CPPFLAGS = -I$(top_srcdir)/include
 AM_CFLAGS   = $(WERROR) -Winline -Wall -Wshadow -g 
@@ -148,6 +152,7 @@
 metadata_SOURCES	= metadata.c
 threadederrno_SOURCES	= threadederrno.c
 threadederrno_LDADD	= -lpthread
+vgtest_ume_SOURCES	= vgtest_ume.c
 writev_SOURCES		= writev.c
 zeropage_SOURCES	= zeropage.c
 
@@ -156,5 +161,13 @@
 new_nothrow_SOURCES 	= new_nothrow.cpp
 new_override_SOURCES 	= new_override.cpp
 
+# Valgrind unit self-tests
+hello_SOURCES		= hello.c
+hello_LDFLAGS		= -Wl,-defsym,kickstart_base=0x50000000 \
+			  -Wl,-T,../../coregrind/${VG_ARCH}/stage2.lds
+vgtest_ume_LDADD	= ../../coregrind/ume.o \
+			  ../../coregrind/ume_entry.o \
+			  ../../coregrind/jmp_with_stack.o
+
 # must be built with these flags -- bug only occurred with them
 fpeflags.o: CFLAGS += -march=i686
diff --git a/memcheck/tests/hello.c b/memcheck/tests/hello.c
new file mode 100644
index 0000000..836b36f
--- /dev/null
+++ b/memcheck/tests/hello.c
@@ -0,0 +1,9 @@
+
+#include <stdio.h>
+
+int main(void)
+{
+    fprintf(stderr, "Hello, world!\n");
+    return 0;
+}
+
diff --git a/memcheck/tests/vgtest_ume.c b/memcheck/tests/vgtest_ume.c
new file mode 100644
index 0000000..99fb5c9
--- /dev/null
+++ b/memcheck/tests/vgtest_ume.c
@@ -0,0 +1,75 @@
+#define ELFSZ  32
+
+// This file is a unit self-test for ume.c, ume_entry.c, jmp_with_stack.c
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <elf.h>
+#include "../../coregrind/ume.h"
+
+#define STKSZ   (64*1024)
+
+static void push_auxv(unsigned char **espp, int type, void *val)
+{
+        struct ume_auxv *auxp = (struct ume_auxv *)*espp;
+        auxp--;
+        auxp->a_type = type;
+        auxp->u.a_ptr = val;
+        *espp = (unsigned char *)auxp;
+}
+
+static void push(unsigned char **espp, void *v)
+{
+        void **vp = *(void ***)espp;
+        *--vp = v;
+        *espp = (unsigned char *)vp;
+}
+
+
+int main(void)
+{
+   struct exeinfo info;
+   int err;
+   unsigned char* newstack;
+   unsigned char *esp;
+
+   info.argv     = NULL;
+   info.exe_base = 0x50000000;
+   info.exe_end  = 0x50ffffff;
+   info.map_base = 0x51000000;
+   
+   err = do_exec("hello", &info);
+   assert(0 == err);
+
+//   printf("info.exe_base=%p exe_end=%p\n", 
+//          (void*)info.exe_base, (void*)info.exe_end);
+
+   newstack = malloc(STKSZ);
+   assert(0 != newstack);
+
+   esp = newstack+STKSZ;
+
+   /* 
+      Set the new executable's stack up like the kernel would after
+      exec.
+
+      These are being pushed onto the stack, towards decreasing
+      addresses.
+    */
+   push_auxv(&esp, AT_NULL, 0);                         // auxv terminator
+   push_auxv(&esp, AT_ENTRY, (void *)info.entry);       // entrypoint of the main executable */
+   push_auxv(&esp, AT_BASE, (void *)info.interp_base);  // base address of ld-linux.so
+   push_auxv(&esp, AT_PHDR, (void *)info.phdr);         // where the ELF PHDRs are mapped
+   push_auxv(&esp, AT_PHNUM, (void*)info.phnum);        // and how many of them
+
+   push(&esp, 0);               /* no env */
+   push(&esp, 0);               /* no argv */
+   push(&esp, 0);               /* argc=0 */
+
+//   fprintf(stderr, "ume_go: %p %p\n", (void*)info.init_eip, (void*)esp);
+
+   jmp_with_stack(info.init_eip, (addr_t)esp);
+
+   return 0;
+}
diff --git a/memcheck/tests/vgtest_ume.stderr.exp b/memcheck/tests/vgtest_ume.stderr.exp
new file mode 100644
index 0000000..af5626b
--- /dev/null
+++ b/memcheck/tests/vgtest_ume.stderr.exp
@@ -0,0 +1 @@
+Hello, world!
diff --git a/memcheck/tests/vgtest_ume.vgtest b/memcheck/tests/vgtest_ume.vgtest
new file mode 100644
index 0000000..24da9a3
--- /dev/null
+++ b/memcheck/tests/vgtest_ume.vgtest
@@ -0,0 +1,2 @@
+prog: vgtest_ume
+vgopts: -q