// 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);
*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 */
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];
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
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]
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;
{
#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
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));
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);
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;
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,
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);
-##--------------------------------------------------------------------##
-##--- 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
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:
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 ---*/
+/*--------------------------------------------------------------------*/
#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