]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Simplify the implementation of m_trampoline and the stuff that refers
authorJulian Seward <jseward@acm.org>
Tue, 21 Jun 2005 01:41:34 +0000 (01:41 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 21 Jun 2005 01:41:34 +0000 (01:41 +0000)
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

coregrind/m_main.c
coregrind/m_redir.c
coregrind/m_sigframe/sigframe-amd64-linux.c
coregrind/m_sigframe/sigframe-x86-linux.c
coregrind/m_stacktrace.c
coregrind/m_trampoline.S
coregrind/pub_core_trampoline.h

index 4f97134572e3e704f53e7cae3cf21abca8bf6d91..aa1c91280ef55d20752b199d3c15e6be14b10f6a 100644 (file)
@@ -824,14 +824,12 @@ static Addr setup_client_stack(void* init_sp,
    // 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 @@ static Addr setup_client_stack(void* init_sp,
    *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 @@ static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
      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 @@ int main(int argc, char **argv, char **envp)
    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,13 +2652,26 @@ int main(int argc, char **argv, char **envp)
    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]
    //--------------------------------------------------------------
    VG_(debugLog)(1, "main", "Initialise redirects\n");
    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]
index 7c61ec308ddbfc7be84f13e56739f2e9e0c7ea30..4c6d8ff079def31608ef17233137de742607c6e8 100644 (file)
@@ -295,7 +295,8 @@ static void add_redirect_X_to_addr(
    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 @@ void VG_(setup_code_redirect_table) ( void )
 {
 #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
index 80983b0d947ed154c6be27b1884cd03b4e100c69..22a725af4c2713660dcd55f20a08a4a8d61d4df6 100644 (file)
@@ -459,8 +459,7 @@ static Addr build_rt_sigframe(ThreadState *tst,
    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));
 
index 2ca201d36e7e9d222fbb4e491a9496c10b7c855d..27d4d377bc0c66263a952764537d46e4f365717b 100644 (file)
@@ -484,8 +484,7 @@ static Addr build_sigframe(ThreadState *tst,
    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 @@ static Addr build_rt_sigframe(ThreadState *tst,
    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;
index 9b086c789db6d4a87d20a37e8643cf619877642d..0c07c7d8e2ef22f3d25474ea2892f4f36b4427d8 100644 (file)
@@ -175,7 +175,7 @@ UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips )
    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 @@ UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips )
       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);
index 85742f44b29e032d73ed77529d51954efdd6903b..7dacb3ab6f64127d2129707536a57783f727192a 100644 (file)
@@ -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
 #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 @@ VG_(trampoline_code_start):
         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):
+
+
+#else
+#if defined(VGP_ppc32_linux)
 
-#elif defined(VGP_ppc32_linux)
+       
 // CAB: TODO
 // Not yet used, just keeping the compiler quiet
 sigreturn_start:
@@ -106,31 +112,18 @@ gettimeofday_start:
 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                                                          ---*/
+/*--------------------------------------------------------------------*/
index 5ba36c5d13378be1a162db3615076bde4c1dff9a..f2174176562360ffb70578792c314465dc74a16d 100644 (file)
 #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