From b39a007b536d82a2478cd90dac6d1598d552c77b Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Sun, 2 Aug 2009 12:21:31 +0000 Subject: [PATCH] Reinstating a heavily modified version of r10402. This is to do with #190429. This patch (originally from Jakub Jelinek) makes the redir of strlen in ld.so on amd64-linux ld.so mandatory, but only for glibc 2.10 and above. For glibc-2.2 (our earliest supported version) to glibc-2.9 it is still optional. Also, makes more verbose, the message that is printed if a mandatory ld.so redirection on Linux cannot be set up. Is believed to fix #190429. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10689 --- coregrind/m_redir.c | 63 +++++++++++++++++++++++---------- coregrind/m_trampoline.S | 33 ++++++++++++++++- coregrind/pub_core_trampoline.h | 1 + 3 files changed, 77 insertions(+), 20 deletions(-) diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c index a63a556a6b..fd7d046ce5 100644 --- a/coregrind/m_redir.c +++ b/coregrind/m_redir.c @@ -223,8 +223,8 @@ typedef HChar* from_fnpatt; /* from fnname pattern */ Addr to_addr; /* where redirecting to */ Bool isWrap; /* wrap or replacement? */ - const HChar* mandatory; /* non-NULL ==> abort V and print the - string if from_sopatt is loaded but + HChar** mandatory; /* non-NULL ==> abort V and print the + strings if from_sopatt is loaded but from_fnpatt cannot be found */ /* VARIABLE PARTS -- used transiently whilst processing redirections */ Bool mark; /* set if spec requires further processing */ @@ -555,6 +555,7 @@ void generate_and_add_actives ( break; } if (sp) { + HChar** strp; HChar* v = "valgrind: "; vg_assert(sp->mark); vg_assert(!sp->done); @@ -581,8 +582,11 @@ void generate_and_add_actives ( v, VG_(DebugInfo_get_soname)(di)); VG_(printf)( "%s\n", v); - VG_(printf)( - "%s%s\n", v, sp->mandatory); + + for (strp = sp->mandatory; *strp; strp++) + VG_(printf)( + "%s%s\n", v, *strp); + VG_(printf)( "%s\n", v); VG_(printf)( @@ -809,7 +813,7 @@ static void add_hardwired_active ( Addr from, Addr to ) __attribute__((unused)) /* not used on all platforms */ static void add_hardwired_spec ( HChar* sopatt, HChar* fnpatt, Addr to_addr, - const HChar* const mandatory ) + HChar** mandatory ) { Spec* spec = dinfo_zalloc("redir.ahs.1", sizeof(Spec)); vg_assert(spec); @@ -838,6 +842,18 @@ static void add_hardwired_spec ( HChar* sopatt, HChar* fnpatt, } +__attribute__((unused)) /* not used on all platforms */ +static const HChar* complain_about_stripped_glibc_ldso[] += { "Possible fixes: (1, short term): install glibc's debuginfo", + "package on this machine. (2, longer term): ask the packagers", + "for your Linux distribution to please in future ship a non-", + "stripped ld.so (or whatever the dynamic linker .so is called)", + "that exports the above-named function using the standard", + "calling conventions for this platform.", + NULL + }; + + /* Initialise the redir system, and create the initial Spec list and for amd64-linux a couple of permanent active mappings. The initial Specs are not converted into Actives yet, on the (checked) @@ -880,11 +896,26 @@ void VG_(redir_initialise) ( void ) (Addr)&VG_(amd64_linux_REDIR_FOR_vtime) ); -# elif defined(VGP_ppc32_linux) - { - static const HChar croakage[] - = "Possible fix: install glibc's debuginfo package on this machine."; + /* If we're using memcheck, use these intercepts right from + the start, otherwise ld.so makes a lot of noise. */ + if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { + add_hardwired_spec( + "ld-linux-x86-64.so.2", "strlen", + (Addr)&VG_(amd64_linux_REDIR_FOR_strlen), +# if defined(GLIBC_2_2) || defined(GLIBC_2_3) || defined(GLIBC_2_4) \ + || defined(GLIBC_2_5) || defined(GLIBC_2_6) || defined(GLIBC_2_7) \ + || defined(GLIBC_2_8) || defined(GLIBC_2_9) + NULL +# else + /* for glibc-2.10 and later, this is mandatory - can't sanely + continue without it */ + complain_about_stripped_glibc_ldso +# endif + ); + } + +# elif defined(VGP_ppc32_linux) /* If we're using memcheck, use these intercepts right from the start, otherwise ld.so makes a lot of noise. */ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { @@ -893,7 +924,7 @@ void VG_(redir_initialise) ( void ) add_hardwired_spec( "ld.so.1", "strlen", (Addr)&VG_(ppc32_linux_REDIR_FOR_strlen), - croakage + complain_about_stripped_glibc_ldso ); add_hardwired_spec( "ld.so.1", "strcmp", @@ -908,13 +939,8 @@ void VG_(redir_initialise) ( void ) /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */ ); } - } # elif defined(VGP_ppc64_linux) - { - static const HChar croakage[] - = "Possible fix: install glibc's debuginfo package on this machine."; - /* If we're using memcheck, use these intercepts right from the start, otherwise ld.so makes a lot of noise. */ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { @@ -923,7 +949,7 @@ void VG_(redir_initialise) ( void ) add_hardwired_spec( "ld64.so.1", "strlen", (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strlen) ), - croakage + complain_about_stripped_glibc_ldso ); add_hardwired_spec( @@ -933,7 +959,6 @@ void VG_(redir_initialise) ( void ) /* glibc-2.5 (FC6, ppc64) seems fine without it */ ); } - } # elif defined(VGP_ppc32_aix5) /* nothing so far */ @@ -955,11 +980,11 @@ void VG_(redir_initialise) ( void ) (Addr)&VG_(darwin_REDIR_FOR_strcpy), NULL); add_hardwired_spec("dyld", "strlcat", (Addr)&VG_(darwin_REDIR_FOR_strlcat), NULL); -#if defined(VGP_amd64_darwin) +# if defined(VGP_amd64_darwin) // DDD: #warning fixme rdar://6166275 add_hardwired_spec("dyld", "arc4random", (Addr)&VG_(darwin_REDIR_FOR_arc4random), NULL); -#endif +# endif } # else diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S index 8b3487ef9f..256666bdf4 100644 --- a/coregrind/m_trampoline.S +++ b/coregrind/m_trampoline.S @@ -168,7 +168,29 @@ VG_(amd64_linux_REDIR_FOR_vtime): .LfnE3: .size VG_(amd64_linux_REDIR_FOR_vtime), .-.LfnB3 -/* A CIE for the above two functions, followed by their FDEs */ +/* There's no particular reason that this needs to be handwritten + assembly, but since that's what this file contains, here's a + simple strlen implementation (written in C and compiled by gcc.) +*/ +.global VG_(amd64_linux_REDIR_FOR_strlen) +.type VG_(amd64_linux_REDIR_FOR_strlen), @function +VG_(amd64_linux_REDIR_FOR_strlen): +.LfnB4: + xorl %eax, %eax + cmpb $0, (%rdi) + movq %rdi, %rdx + je .L41 +.L40: addq $1, %rdx + cmpb $0, (%rdx) + jne .L40 + movq %rdx, %rax + subq %rdi, %rax +.L41: ret +.LfnE4: +.size VG_(amd64_linux_REDIR_FOR_strlen), .-VG_(amd64_linux_REDIR_FOR_strlen) + + +/* A CIE for the above three functions, followed by their FDEs */ .section .eh_frame,"a",@progbits .Lframe1: .long .LEcie1-.LScie1 @@ -206,6 +228,15 @@ VG_(amd64_linux_REDIR_FOR_vtime): .uleb128 0x0 .align 8 .LEfde3: +.LSfde4: + .long .LEfde4-.LASfde4 +.LASfde4: + .long .LASfde4-.Lframe1 + .long .LfnB4 + .long .LfnE4-.LfnB4 + .uleb128 0x0 + .align 8 +.LEfde4: .previous .global VG_(trampoline_stuff_end) diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h index c8c6520744..31c591cb94 100644 --- a/coregrind/pub_core_trampoline.h +++ b/coregrind/pub_core_trampoline.h @@ -66,6 +66,7 @@ extern Char* VG_(x86_linux_REDIR_FOR_index) ( const Char*, Int ); 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); +extern UInt VG_(amd64_linux_REDIR_FOR_strlen)( void* ); #endif #if defined(VGP_ppc32_linux) -- 2.47.3