From: Julian Seward Date: Tue, 21 Jun 2005 01:41:34 +0000 (+0000) Subject: Simplify the implementation of m_trampoline and the stuff that refers X-Git-Tag: svn/VALGRIND_3_0_0~341 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b36f48842a52b089fd883b34791e4b533ad18c4b;p=thirdparty%2Fvalgrind.git 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 --- diff --git a/coregrind/m_main.c b/coregrind/m_main.c index 4f97134572..aa1c91280e 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -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] diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c index 7c61ec308d..4c6d8ff079 100644 --- a/coregrind/m_redir.c +++ b/coregrind/m_redir.c @@ -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 diff --git a/coregrind/m_sigframe/sigframe-amd64-linux.c b/coregrind/m_sigframe/sigframe-amd64-linux.c index 80983b0d94..22a725af4c 100644 --- a/coregrind/m_sigframe/sigframe-amd64-linux.c +++ b/coregrind/m_sigframe/sigframe-amd64-linux.c @@ -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)); diff --git a/coregrind/m_sigframe/sigframe-x86-linux.c b/coregrind/m_sigframe/sigframe-x86-linux.c index 2ca201d36e..27d4d377bc 100644 --- a/coregrind/m_sigframe/sigframe-x86-linux.c +++ b/coregrind/m_sigframe/sigframe-x86-linux.c @@ -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; diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index 9b086c789d..0c07c7d8e2 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -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); diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S index 85742f44b2..7dacb3ab6f 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 @@ 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 ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h index 5ba36c5d13..f217417656 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