Simplify the implementation of m_trampoline and the stuff that refers
to it.  Now there are no more offsets and no copying of code into the
stack.  We just redirect directly to entry points in m_syscalls.S.

This will mess up pointercheck, since the redirect targets are now in
Valgrind's address space, not the client's.  But pointercheck is hosed
anyway, and I'd rather back off to something simple whilst ppc32 is
stabilised.  When the address space management stuff is overhauled
then pointercheck may or may not get reinstated, and if it does then
the trampoline stuff will need revisiting.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3977 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index 4f97134..aa1c912 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -824,14 +824,12 @@
    // decide where stack goes!
    VG_(clstk_end) = VG_(client_end);
 
-   VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
-
    /* cl_esp is the client's stack pointer */
    cl_esp = VG_(clstk_end) - stacksize;
    cl_esp = VG_ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
 
    /* base of the string table (aligned) */
-   stringbase = strtab = (char *)(VG_(client_trampoline_code) 
+   stringbase = strtab = (char *)(VG_(clstk_end) 
                          - VG_ROUNDUP(stringsize, sizeof(int)));
 
    VG_(clstk_base) = VG_PGROUNDDN(cl_esp);
@@ -980,14 +978,6 @@
    *auxv = *orig_auxv;
    vg_assert(auxv->a_type == AT_NULL);
 
-// XXX: what architectures is this necessary for?  x86 yes, PPC no, others ?
-// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
-#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
-   /* --- trampoline page --- */
-   VG_(memcpy)( (void *)VG_(client_trampoline_code),
-                &VG_(trampoline_code_start), VG_(trampoline_code_length) );
-#endif
-
    vg_assert((strtab-stringbase) == stringsize);
 
    /* We know the initial ESP is pointing at argc/argv */
@@ -1480,20 +1470,6 @@
      config_error("Please use absolute paths in "
                   "./configure --prefix=... or --libdir=...");
 
-// XXX: what architectures is this necessary for?  x86 yes, PPC no, others ?
-#if defined(VGP_x86_linux)
-   {
-      UInt* auxp;
-      for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
-         switch(auxp[0]) {
-         case AT_SYSINFO:
-            auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
-            break;
-         }
-      } 
-   }
-#endif
-
    for (i = 1; i < vg_argc; i++) {
 
       Char* arg = vg_argv[i];
@@ -2577,23 +2553,6 @@
    sp_at_startup___global_arg = sp_at_startup;
    VG_(parse_procselfmaps) ( build_segment_map_callback );  /* everything */
    sp_at_startup___global_arg = 0;
-   
-#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
-   //--------------------------------------------------------------
-   // Protect client trampoline page (which is also sysinfo stuff)
-   //   p: segment stuff   [otherwise get seg faults...]
-   //--------------------------------------------------------------
-   {
-      Segment *seg;
-      VG_(mprotect)( (void *)VG_(client_trampoline_code),
-		     VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
-
-      /* Make sure this segment isn't treated as stack */
-      seg = VG_(find_segment)(VG_(client_trampoline_code));
-      if (seg)
-	 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
-   }
-#endif
 
    //==============================================================
    // Can use VG_(map)() after segments set up
@@ -2693,7 +2652,7 @@
    VG_(init_tt_tc)();
 
    //--------------------------------------------------------------
-   // Read debug info to find glibc entry points to intercept
+   // Initialise the redirect table.
    //   p: parse_procselfmaps? [XXX for debug info?]
    //   p: init_tt_tc [so it can call VG_(search_transtab) safely]
    //--------------------------------------------------------------
@@ -2701,6 +2660,19 @@
    VG_(setup_code_redirect_table)();
 
    //--------------------------------------------------------------
+   // Tell the tool about permissions in our handwritten assembly
+   // helpers.
+   //   p: init tool             [for 'new_mem_startup']
+   //--------------------------------------------------------------
+   VG_(debugLog)(1, "main", "Tell tool about permissions for asm helpers\n");
+   VG_TRACK( new_mem_startup,
+             (Addr)&VG_(trampoline_stuff_start),
+             &VG_(trampoline_stuff_end) - &VG_(trampoline_stuff_start),
+             False, /* readable? */
+             False, /* writable? */
+             True   /* executable? */ );
+
+   //--------------------------------------------------------------
    // Verbosity message
    //   p: end_rdtsc_calibration [so startup message is printed first]
    //--------------------------------------------------------------
diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
index 7c61ec3..4c6d8ff 100644
--- a/coregrind/m_redir.c
+++ b/coregrind/m_redir.c
@@ -295,7 +295,8 @@
    else          redir->from_lib  = NULL;
    if (from_sym) redir->from_sym  = VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
    else          redir->from_sym  = NULL;
-                 redir->from_addr = from_addr;
+   
+   redir->from_addr = from_addr;
 
    vg_assert(0 != to_addr);
    redir->to_addr = to_addr;
@@ -379,18 +380,30 @@
 {
 #if defined(VGP_x86_linux)
    /* Redirect _dl_sysinfo_int80, which is glibc's default system call
-      routine, to the routine in our trampoline page so that the
-      special sysinfo unwind hack in m_stacktrace.c will kick in.  */
-   add_redirect_sym_to_addr("soname:ld-linux.so.2", "_dl_sysinfo_int80",
-                            VG_(client_trampoline_code)+VG_(tramp_syscall_offset));
+      routine, to our copy so that the special sysinfo unwind hack in
+      m_stacktrace.c will kick in.  */
+   add_redirect_sym_to_addr(
+      "soname:ld-linux.so.2", "_dl_sysinfo_int80",
+      (Addr)&VG_(x86_linux_REDIR_FOR__dl_sysinfo_int80)
+   );
+
 #elif defined(VGP_amd64_linux)
+
    /* Redirect vsyscalls to local versions */
-   add_redirect_addr_to_addr(0xFFFFFFFFFF600000ULL,
-                             VG_(client_trampoline_code)+VG_(tramp_gettimeofday_offset));
-   add_redirect_addr_to_addr(0xFFFFFFFFFF600400ULL,
-                             VG_(client_trampoline_code)+VG_(tramp_time_offset));
+   add_redirect_addr_to_addr(
+      0xFFFFFFFFFF600000ULL,
+      (Addr)&VG_(amd64_linux_REDIR_FOR_vgettimeofday) 
+   );
+
+   add_redirect_addr_to_addr( 
+      0xFFFFFFFFFF600000ULL,
+      (Addr)&VG_(amd64_linux_REDIR_FOR_vtime) 
+   );
+
 #elif defined(VGP_ppc32_linux)
-//CAB: TODO
+
+   //CAB: TODO
+
 #else
 #  error Unknown platform
 #endif
diff --git a/coregrind/m_sigframe/sigframe-amd64-linux.c b/coregrind/m_sigframe/sigframe-amd64-linux.c
index 80983b0..22a725a 100644
--- a/coregrind/m_sigframe/sigframe-amd64-linux.c
+++ b/coregrind/m_sigframe/sigframe-amd64-linux.c
@@ -459,8 +459,7 @@
    if (flags & VKI_SA_RESTORER)
       frame->retaddr = (Addr)restorer;
    else
-      frame->retaddr
-         = VG_(client_trampoline_code)+VG_(tramp_rt_sigreturn_offset);
+      frame->retaddr = (Addr)&VG_(amd64_linux_SUBST_FOR_rt_sigreturn);
 
    VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t));
 
diff --git a/coregrind/m_sigframe/sigframe-x86-linux.c b/coregrind/m_sigframe/sigframe-x86-linux.c
index 2ca201d..27d4d37 100644
--- a/coregrind/m_sigframe/sigframe-x86-linux.c
+++ b/coregrind/m_sigframe/sigframe-x86-linux.c
@@ -484,8 +484,7 @@
    if (flags & VKI_SA_RESTORER)
       frame->retaddr = (Addr)restorer;
    else
-      frame->retaddr
-         = VG_(client_trampoline_code)+VG_(tramp_sigreturn_offset);
+      frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_sigreturn);
 
    synth_ucontext(tst->tid, siginfo, mask, &uc, &frame->fpstate);
 
@@ -531,8 +530,7 @@
    if (flags & VKI_SA_RESTORER)
       frame->retaddr = (Addr)restorer;
    else
-      frame->retaddr 
-         = VG_(client_trampoline_code)+VG_(tramp_rt_sigreturn_offset);
+      frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_rt_sigreturn);
 
    frame->psigInfo = (Addr)&frame->sigInfo;
    frame->puContext = (Addr)&frame->uContext;
diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c
index 9b086c7..0c07c7d 100644
--- a/coregrind/m_stacktrace.c
+++ b/coregrind/m_stacktrace.c
@@ -175,7 +175,7 @@
    Addr sp                 = VG_(get_SP)(tid);
    Addr stack_highest_word = VG_(threads)[tid].client_stack_highest_word;
 
-#if defined(VGP_x86_linux)
+#  if defined(VGP_x86_linux)
    /* Nasty little hack to deal with sysinfo syscalls - if libc is
       using the sysinfo page for syscalls (the TLS version does), then
       ip will always appear to be in that page when doing a syscall,
@@ -184,13 +184,14 @@
       off the stack so that ip is placed within the library function
       calling the syscall.  This makes stack backtraces much more
       useful.  */
-   if (ip >= VG_(client_trampoline_code)+VG_(tramp_syscall_offset) &&
-       ip < VG_(client_trampoline_code)+VG_(trampoline_code_length) &&
-       VG_(is_addressable)(sp, sizeof(Addr), VKI_PROT_READ)) {
+   if (ip >= (Addr)&VG_(trampoline_stuff_start) 
+       && ip < (Addr)&VG_(trampoline_stuff_end)
+       &&  VG_(is_addressable)(sp, sizeof(Addr), VKI_PROT_READ)) {
       ip = *(Addr *)sp;
       sp += sizeof(Addr);
    }
-#endif
+#  endif
+
    if (0)
       VG_(printf)("tid %d: stack_highest=%p ip=%p sp=%p fp=%p\n",
 		  tid, stack_highest_word, ip, sp, fp);
diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S
index 85742f4..7dacb3a 100644
--- a/coregrind/m_trampoline.S
+++ b/coregrind/m_trampoline.S
@@ -1,7 +1,7 @@
 
-##--------------------------------------------------------------------##
-##--- Trampoline code page stuff.                   m_trampoline.S ---##
-##--------------------------------------------------------------------##
+/*--------------------------------------------------------------------*/
+/*--- Trampoline code page stuff.                   m_trampoline.S ---*/
+/*--------------------------------------------------------------------*/
 
 /*
   This file is part of Valgrind, a dynamic binary instrumentation
@@ -32,23 +32,18 @@
 #include "vki_unistd.h"
 
 /* ------------------ SIMULATED CPU HELPERS ------------------ */
-/* Stubs for returns which we want to catch.
-   This code isn't used in-place.  It is copied into the client address
-   space at an arbitary address.  Therefore, this code must be completely
-   position-independent.
+/* 
+   Replacements for some functions to do with vsyscalls and signals.
+   This code runs on the simulated CPU.
 */
-.global VG_(client_trampoline_code)
-.global VG_(trampoline_code_start)
-.global VG_(trampoline_code_length)
-.global VG_(tramp_sigreturn_offset)
-.global VG_(tramp_rt_sigreturn_offset)
-.global VG_(tramp_syscall_offset)
-.global VG_(tramp_gettimeofday_offset)
-.global VG_(tramp_time_offset)
-	
-VG_(trampoline_code_start):
+
 #if defined(VGP_x86_linux)
-    sigreturn_start:
+
+.global VG_(trampoline_stuff_start)
+VG_(trampoline_stuff_start):
+
+.global VG_(x86_linux_SUBST_FOR_sigreturn)
+VG_(x86_linux_SUBST_FOR_sigreturn):
         /* This is a very specific sequence which GDB uses to
            recognize signal handler frames. */
         popl    %eax
@@ -56,47 +51,58 @@
         int     $0x80
         ud2
 
-    rt_sigreturn_start:
+.global VG_(x86_linux_SUBST_FOR_rt_sigreturn)
+VG_(x86_linux_SUBST_FOR_rt_sigreturn):
         /* Likewise for rt signal frames */
         movl    $__NR_rt_sigreturn, %eax
         int     $0x80
         ud2
 
-	# We can point our sysinfo stuff here
-	.align 16
-    syscall_start:	
+.global VG_(x86_linux_REDIR_FOR__dl_sysinfo_int80)
+VG_(x86_linux_REDIR_FOR__dl_sysinfo_int80):
+	/* We can point our sysinfo stuff here */
 	int	$0x80
 	ret
+	
+.global VG_(trampoline_stuff_end)
+VG_(trampoline_stuff_end):
 
-    gettimeofday_start:
-    time_start:
-	/* unused on x86 */
+	
+#else
+#if defined(VGP_amd64_linux)
 
-#elif defined(VGP_amd64_linux)
-    rt_sigreturn_start:
-        /* Likewise for rt signal frames */
+
+.global VG_(trampoline_stuff_start)
+VG_(trampoline_stuff_start):
+
+.global VG_(amd64_linux_SUBST_FOR_rt_sigreturn)
+VG_(amd64_linux_SUBST_FOR_rt_sigreturn):
+        /* This is a very specific sequence which GDB uses to
+           recognize signal handler frames. */
         movq    $__NR_rt_sigreturn, %rax
         syscall
         ud2
 
-        .align 16
-    gettimeofday_start:
+.global VG_(amd64_linux_REDIR_FOR_vgettimeofday)
+VG_(amd64_linux_REDIR_FOR_vgettimeofday):
         movq    $__NR_gettimeofday, %rax
         syscall
         ret
 
-        .align 16
-    time_start:
+.global VG_(amd64_linux_REDIR_FOR_vtime)
+VG_(amd64_linux_REDIR_FOR_vtime):
         movq    $__NR_time, %rax
         syscall
         ret
 
-	.align 16
-    sigreturn_start:
-    syscall_start:
-	/* unused on amd64 */
+.global VG_(trampoline_stuff_end)
+VG_(trampoline_stuff_end):
 
-#elif defined(VGP_ppc32_linux)
+
+#else
+#if defined(VGP_ppc32_linux)
+
+	
 // CAB: TODO
 // Not yet used, just keeping the compiler quiet
 sigreturn_start:
@@ -106,31 +112,18 @@
 time_start:
 
 #else
-#	error Unknown platform
+#  error Unknown platform
+
 #endif
+#endif
+#endif
+
 tramp_code_end:
-			
-.data
-VG_(client_trampoline_code):
-	.long 0
-VG_(trampoline_code_length):
-	.long tramp_code_end - VG_(trampoline_code_start)
-VG_(tramp_sigreturn_offset):
-	.long sigreturn_start - VG_(trampoline_code_start)
-VG_(tramp_rt_sigreturn_offset):
-        .long rt_sigreturn_start - VG_(trampoline_code_start)
-VG_(tramp_syscall_offset):
-	.long syscall_start - VG_(trampoline_code_start)
-VG_(tramp_gettimeofday_offset):
-	.long gettimeofday_start - VG_(trampoline_code_start)
-VG_(tramp_time_offset):
-	.long time_start - VG_(trampoline_code_start)
-.text
 
 
 /* Let the linker know we don't need an executable stack */
 .section .note.GNU-stack,"",@progbits
 		
-##--------------------------------------------------------------------##
-##--- end                                                          ---##
-##--------------------------------------------------------------------##
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h
index 5ba36c5..f217417 100644
--- a/coregrind/pub_core_trampoline.h
+++ b/coregrind/pub_core_trampoline.h
@@ -32,24 +32,32 @@
 #define __PUB_CORE_TRAMPOLINE_H
 
 //--------------------------------------------------------------------
-// PURPOSE: This module defines our trampoline code page, which we copy
-// over the client's, for arcane signal return and syscall purposes...
+// PURPOSE: This module defines a few replacement functions for Linux
+// vsyscalls, which we can't implement directly.  It also contains
+// stubs for signal returns.  Note, all the code within runs on the
+// simulated CPU.  The vsyscall stubs are gotten to by use of the 
+// redirect mechanism.
 //--------------------------------------------------------------------
 
-extern Addr VG_(client_trampoline_code);
+/* These two delimit our handwritten assembly code, so we can tell
+   tools which track memory that this area should be regarded as
+   readable, at least.  Otherwise Memcheck complains we're jumping to
+   invalid addresses. */
 
-// Platform-specifics aren't neatly factored out here, since some of the
-// constants are not used on all platforms.  But it's non-obvious how
-// to do it better.
+extern void VG_(trampoline_stuff_start);
+extern void VG_(trampoline_stuff_end);
 
-extern const Char VG_(trampoline_code_start);      // x86 + amd64
-extern const Int  VG_(trampoline_code_length);     // x86 + amd64
+#if defined(VGP_x86_linux)
+extern void VG_(x86_linux_SUBST_FOR_sigreturn);
+extern void VG_(x86_linux_SUBST_FOR_rt_sigreturn);
+extern void VG_(x86_linux_REDIR_FOR__dl_sysinfo_int80);
+#endif
 
-extern const Int  VG_(tramp_sigreturn_offset);     // x86
-extern const Int  VG_(tramp_rt_sigreturn_offset);  // x86 + amd64
-extern const Int  VG_(tramp_syscall_offset);       // x86
-extern const Int  VG_(tramp_gettimeofday_offset);  // amd64
-extern const Int  VG_(tramp_time_offset);          // amd64
+#if defined(VGP_amd64_linux)
+extern void VG_(amd64_linux_SUBST_FOR_rt_sigreturn);
+extern void VG_(amd64_linux_REDIR_FOR_vgettimeofday);
+extern void VG_(amd64_linux_REDIR_FOR_vtime);
+#endif
  
 #endif   // __PUB_CORE_TRAMPOLINE_H