From: Julian Seward Date: Fri, 10 May 2002 22:31:40 +0000 (+0000) Subject: Kernel 2.4 / glibc 2.2.X build fixes for recent startup changes. X-Git-Tag: svn/VALGRIND_1_0_3~205 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46111c06e3731f1bec14f0db46d0cdee6e636b5e;p=thirdparty%2Fvalgrind.git Kernel 2.4 / glibc 2.2.X build fixes for recent startup changes. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@259 --- diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c index 015b9f73b3..df895171a3 100644 --- a/coregrind/arch/x86-linux/vg_libpthread.c +++ b/coregrind/arch/x86-linux/vg_libpthread.c @@ -104,8 +104,6 @@ extern void VG_(startup) ( void ); static __inline__ void ensure_valgrind ( char* caller ) { - char* str; - int is_valgrind; VG_(startup)(); } @@ -333,7 +331,9 @@ int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) case PTHREAD_MUTEX_TIMED_NP: case PTHREAD_MUTEX_ADAPTIVE_NP: # endif +# ifdef GLIBC_2_1 case PTHREAD_MUTEX_FAST_NP: +# endif case PTHREAD_MUTEX_RECURSIVE_NP: case PTHREAD_MUTEX_ERRORCHECK_NP: attr->__mutexkind = type; diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index f280ef876c..d4622b2892 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -627,10 +627,22 @@ extern jmp_buf VG_(scheduler_jmpbuf); extern Int VG_(longjmpd_on_signal); -/* We check that the initial stack, which we can't move, is allocated - here. VG_(scheduler_init) checks this. +/* Possible places where the main stack might be based. We check that + the initial stack, which we can't move, is allocated here. + VG_(scheduler_init) checks this. Andrea Archelangi's 2.4 kernels + have been rumoured to start stacks at 0x80000000, so that too is + considered. */ -#define VG_STARTUP_STACK_MASK (Addr)0xBFF80000 +#define VG_STARTUP_STACK_BASE_1 (Addr)0xC0000000 +#define VG_STARTUP_STACK_BASE_2 (Addr)0x80000000 +#define VG_STARTUP_STACK_SMALLERTHAN 0x100000 /* 1024k */ + +#define VG_STACK_MATCHES_BASE(zzstack, zzbase) \ + ( \ + ((zzstack) & ((zzbase) - VG_STARTUP_STACK_SMALLERTHAN)) \ + == \ + ((zzbase) - VG_STARTUP_STACK_SMALLERTHAN) \ + ) /* The red-zone size which we put at the bottom (highest address) of diff --git a/coregrind/vg_kerneliface.h b/coregrind/vg_kerneliface.h index 362a553f29..a7690dd732 100644 --- a/coregrind/vg_kerneliface.h +++ b/coregrind/vg_kerneliface.h @@ -297,6 +297,24 @@ struct vki_stat { }; +/* To do with the ELF constructed by the kernel on a process' stack + just before it transfers control to the program's interpreter + (to use the ELF parlance). + Constants from /usr/src/linux-2.4.9-31/include/linux/elf.h + Logic from /usr/src/linux-2.4.9-31/fs/binfmt_elf.c + and its counterpart in the 2.2.14 kernel sources + in Red Hat 6.2. +*/ +#define VKI_AT_CLKTCK 17 /* frequency at which times() increments */ +#define VKI_AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ +#define VKI_AT_BASE 7 /* base address of interpreter */ +#define VKI_AT_PAGESZ 6 /* system page size */ +#define VKI_AT_PHNUM 5 /* number of program headers */ +#define VKI_AT_PHENT 4 /* size of program header entry */ +#define VKI_AT_PHDR 3 /* program headers for program */ + + + #endif /* ndef __VG_KERNELIFACE_H */ /*--------------------------------------------------------------------*/ diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c index 015b9f73b3..df895171a3 100644 --- a/coregrind/vg_libpthread.c +++ b/coregrind/vg_libpthread.c @@ -104,8 +104,6 @@ extern void VG_(startup) ( void ); static __inline__ void ensure_valgrind ( char* caller ) { - char* str; - int is_valgrind; VG_(startup)(); } @@ -333,7 +331,9 @@ int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) case PTHREAD_MUTEX_TIMED_NP: case PTHREAD_MUTEX_ADAPTIVE_NP: # endif +# ifdef GLIBC_2_1 case PTHREAD_MUTEX_FAST_NP: +# endif case PTHREAD_MUTEX_RECURSIVE_NP: case PTHREAD_MUTEX_ERRORCHECK_NP: attr->__mutexkind = type; diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c index 6df3e92a2d..330068db79 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -481,6 +481,15 @@ static void config_error ( Char* msg ) VG_(exit)(1); } +static void args_grok_error ( Char* msg ) +{ + VG_(shutdown_logging)(); + VG_(clo_logfile_fd) = 2; /* stderr */ + VG_(printf)("valgrind.so: When searching for " + "client's argc/argc/envp:\n\t%s\n", msg); + config_error("couldn't find client's argc/argc/envp"); +} + static void process_cmd_line_options ( void ) { @@ -488,7 +497,7 @@ static void process_cmd_line_options ( void ) UInt argc; UChar* p; UChar* str; - Int i, eventually_logfile_fd; + Int i, eventually_logfile_fd, ctr; # define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n') # define STREQ(s1,s2) (0==VG_(strcmp_ws)((s1),(s2))) @@ -532,160 +541,88 @@ static void process_cmd_line_options ( void ) VG_(startup_logging)(); - /* We look for the Linux ELF table and go down until we find the + /* (Suggested by Fabrice Bellard ... ) + We look for the Linux ELF table and go down until we find the envc & envp. It is not full proof, but these structures should change less often than the libc ones. */ { - unsigned long *sp; - int i; + UInt* sp = 0; /* bogus init to keep gcc -O happy */ + /* locate the top of the stack */ - sp = (unsigned long *)(((unsigned long)VG_(esp_at_startup) & - 0xF0000000) + 0x10000000); + if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup), + VG_STARTUP_STACK_BASE_1 )) { + sp = (UInt*)VG_STARTUP_STACK_BASE_1; + } else + if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup), + VG_STARTUP_STACK_BASE_2 )) { + sp = (UInt*)VG_STARTUP_STACK_BASE_2; + } else { + args_grok_error( + "startup %esp is not near any VG_STARTUP_STACK_BASE_*\n " + "constants defined in vg_include.h. You should investigate." + ); + } + /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in the elf interpreter table */ sp -= 2; - -#define VKI_AT_PAGESZ 6 - while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) { - /* VG_(printf)("trying %p\n", sp); */ + /* VG_(printf)("trying %p\n", sp); */ sp--; } -#define VKI_AT_BASE 7 /* base address of interpreter */ -#define VKI_AT_PAGESZ 6 /* system page size */ -#define VKI_AT_PHNUM 5 /* number of program headers */ -#define VKI_AT_PHENT 4 /* size of program header entry */ -#define VKI_AT_PHDR 3 /* program headers for program */ if (sp[2] == VKI_AT_BASE && sp[0] == VKI_AT_PAGESZ && sp[-2] == VKI_AT_PHNUM && sp[-4] == VKI_AT_PHENT && sp[-6] == VKI_AT_PHDR) { - VG_(printf)("Looks like you've got a 2.2.X kernel here.\n"); + if (0) + VG_(printf)("Looks like you've got a 2.2.X kernel here.\n"); sp -= 6; - } + } else + if (sp[2] == VKI_AT_CLKTCK + && sp[0] == VKI_AT_PAGESZ + && sp[-2] == VKI_AT_HWCAP) { + if (0) + VG_(printf)("Looks like you've got a 2.4.X kernel here.\n"); + sp -= 2; + } else + args_grok_error( + "ELF frame does not look like 2.2.X or 2.4.X.\n " + "See kernel sources linux/fs/binfmt_elf.c to make sense of this." + ); sp--; - vg_assert(*sp == 0); + if (*sp != 0) + args_grok_error("can't find NULL at end of env[]"); + /* sp now points to NULL at the end of env[] */ + ctr = 0; while (True) { sp --; if (*sp == 0) break; + if (++ctr >= 1000) + args_grok_error( + "suspiciously many (1000) env[] entries; giving up"); + } /* sp now points to NULL at the end of argv[] */ - VG_(client_envp) = sp+1; + VG_(client_envp) = (Char**)(sp+1); + ctr = 0; VG_(client_argc) = 0; while (True) { sp--; if (*sp == VG_(client_argc)) break; VG_(client_argc)++; + if (++ctr >= 1000) + args_grok_error( + "suspiciously many (1000) argv[] entries; giving up"); } - VG_(client_argv) = sp+1; - } - - -#if 0 - /* Magically find the client's argc/argv/envp. This kludge is - entirely dependent on the stack layout imposed by libc at - startup. Hence the magic offsets. Then check (heuristically) - that the results are plausible. There must be a better way to - do this ... */ - -# if 1 - /* Use this to search for the correct offsets if the tests below - barf. */ - { Int i; - VG_(printf)("startup %%esp is %p\n", VG_(esp_at_startup) ); - for (i = -10; i < 20; i++) { - Char* p = ((Char**)VG_(esp_at_startup))[i]; - VG_(printf)("%d: %p\n", i, p); - } + VG_(client_argv) = (Char**)(sp+1); } -# endif - -# if defined(GLIBC_2_2) - /* These offsets (5,6,7) are right for my RedHat 7.2 (glibc-2.2.4) - box. */ - - VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [5] ); - VG_(client_argv) = (Char**)( ((void**)VG_(esp_at_startup)) [6] ); - VG_(client_envp) = (Char**)( ((void**)VG_(esp_at_startup)) [7] ); - - if ( ((UInt)VG_(client_argc)) > 0 && - ((UInt)VG_(client_argc)) < 10000 && - (Addr)VG_(client_argv) >= 0x8000000 && - (Addr)VG_(client_envp) >= 0x8000000) - goto argc_argv_envp_OK; - - /* If that's no good, try some other offsets discovered by KDE - folks on 8 Feb 02: - For glibc > 2.2.4 the offset 9/10/11 did the trick. Coolo found - out those, on I think a Caldera 3.1 with glibc 2.2.4 -- the same - offsets worked for on a debian sid with glibc 2.2.5. */ - - VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [9] ); - VG_(client_argv) = (Char**)( ((void**)VG_(esp_at_startup)) [10] ); - VG_(client_envp) = (Char**)( ((void**)VG_(esp_at_startup)) [11] ); - - if ( ((UInt)VG_(client_argc)) > 0 && - ((UInt)VG_(client_argc)) < 10000 && - (Addr)VG_(client_argv) >= 0x8000000 && - (Addr)VG_(client_envp) >= 0x8000000) - goto argc_argv_envp_OK; - -# endif /* defined(GLIBC_2_2) */ - -# if defined(GLIBC_2_1) - /* Doesn't look promising. Try offsets for RedHat 6.2 - (glibc-2.1.3) instead. In this case, the argv and envp vectors - are actually on the stack (bizarrely). */ - - VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [4] ); - VG_(client_argv) = (Char**) & ( ((void**)VG_(esp_at_startup)) [5] ); - VG_(client_envp) - = (Char**) & ( ((void**)VG_(esp_at_startup)) [6 + VG_(client_argc)] ); - - if ( ((UInt)VG_(client_argc)) > 0 && - ((UInt)VG_(client_argc)) < 10000 && - (Addr)VG_(client_argv) >= 0x8000000 && - (Addr)VG_(client_envp) >= 0x8000000) - goto argc_argv_envp_OK; - - /* Here's yet another variant, from (irc.kde.org). */ - - VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [9] ); - VG_(client_argv) = (Char**) & ( ((void**)VG_(esp_at_startup)) [10] ); - VG_(client_envp) - = (Char**) & ( ((void**)VG_(esp_at_startup)) [11 + VG_(client_argc)] ); - - if ( ((UInt)VG_(client_argc)) > 0 && - ((UInt)VG_(client_argc)) < 10000 && - (Addr)VG_(client_argv) >= 0x8000000 && - (Addr)VG_(client_envp) >= 0x8000000) - goto argc_argv_envp_OK; -# endif /* defined(GLIBC_2_1) */ - -# if !defined(GLIBC_2_2) && !defined(GLIBC_2_1) - config_error("autoconf/configure detected neither glibc 2.1.X nor 2.2.X"); -# endif - - /* VG_(printf)("%d %p %p\n", VG_(client_argc), VG_(client_argv), - VG_(client_envp)); - */ - /* We're hosed. Give up :-( */ - config_error( - "Can't get plausible values for client's argc/argv/envp.\n\t" - "You may be able to fix this; see process_cmd_line_options()\n\t" - "in vg_main.c" - ); - /* NOTREACHED */ - - argc_argv_envp_OK: -#endif /* Now that VG_(client_envp) has been set, we can extract the args for Valgrind itself. Copy into global var so that we don't have to diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index 54dc30b8ff..79056e7edf 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -524,9 +524,15 @@ void VG_(scheduler_init) ( void ) ThreadId tid_main; startup_esp = VG_(baseBlock)[VGOFF_(m_esp)]; - if ((startup_esp & VG_STARTUP_STACK_MASK) != VG_STARTUP_STACK_MASK) { - VG_(printf)("%%esp at startup = %p is not near %p; aborting\n", - (void*)startup_esp, (void*)VG_STARTUP_STACK_MASK); + + if (VG_STACK_MATCHES_BASE(startup_esp, VG_STARTUP_STACK_BASE_1) + || VG_STACK_MATCHES_BASE(startup_esp, VG_STARTUP_STACK_BASE_2)) { + /* Jolly good! */ + } else { + VG_(printf)("%%esp at startup = %p is not near %p or %p; aborting\n", + (void*)startup_esp, + (void*)VG_STARTUP_STACK_BASE_1, + (void*)VG_STARTUP_STACK_BASE_2 ); VG_(panic)("unexpected %esp at startup"); } @@ -1922,7 +1928,9 @@ void do_pthread_mutex_lock( ThreadId tid, case PTHREAD_MUTEX_TIMED_NP: case PTHREAD_MUTEX_ADAPTIVE_NP: # endif +# ifdef GLIBC_2_1 case PTHREAD_MUTEX_FAST_NP: +# endif case PTHREAD_MUTEX_RECURSIVE_NP: case PTHREAD_MUTEX_ERRORCHECK_NP: if (mutex->__m_count >= 0) break; @@ -2016,7 +2024,9 @@ void do_pthread_mutex_unlock ( ThreadId tid, case PTHREAD_MUTEX_TIMED_NP: case PTHREAD_MUTEX_ADAPTIVE_NP: # endif +# ifdef GLIBC_2_1 case PTHREAD_MUTEX_FAST_NP: +# endif case PTHREAD_MUTEX_RECURSIVE_NP: case PTHREAD_MUTEX_ERRORCHECK_NP: if (mutex->__m_count >= 0) break; @@ -2234,7 +2244,9 @@ void do_pthread_cond_wait ( ThreadId tid, case PTHREAD_MUTEX_TIMED_NP: case PTHREAD_MUTEX_ADAPTIVE_NP: # endif +# ifdef GLIBC_2_1 case PTHREAD_MUTEX_FAST_NP: +# endif case PTHREAD_MUTEX_RECURSIVE_NP: case PTHREAD_MUTEX_ERRORCHECK_NP: if (mutex->__m_count >= 0) break; diff --git a/vg_include.h b/vg_include.h index f280ef876c..d4622b2892 100644 --- a/vg_include.h +++ b/vg_include.h @@ -627,10 +627,22 @@ extern jmp_buf VG_(scheduler_jmpbuf); extern Int VG_(longjmpd_on_signal); -/* We check that the initial stack, which we can't move, is allocated - here. VG_(scheduler_init) checks this. +/* Possible places where the main stack might be based. We check that + the initial stack, which we can't move, is allocated here. + VG_(scheduler_init) checks this. Andrea Archelangi's 2.4 kernels + have been rumoured to start stacks at 0x80000000, so that too is + considered. */ -#define VG_STARTUP_STACK_MASK (Addr)0xBFF80000 +#define VG_STARTUP_STACK_BASE_1 (Addr)0xC0000000 +#define VG_STARTUP_STACK_BASE_2 (Addr)0x80000000 +#define VG_STARTUP_STACK_SMALLERTHAN 0x100000 /* 1024k */ + +#define VG_STACK_MATCHES_BASE(zzstack, zzbase) \ + ( \ + ((zzstack) & ((zzbase) - VG_STARTUP_STACK_SMALLERTHAN)) \ + == \ + ((zzbase) - VG_STARTUP_STACK_SMALLERTHAN) \ + ) /* The red-zone size which we put at the bottom (highest address) of diff --git a/vg_kerneliface.h b/vg_kerneliface.h index 362a553f29..a7690dd732 100644 --- a/vg_kerneliface.h +++ b/vg_kerneliface.h @@ -297,6 +297,24 @@ struct vki_stat { }; +/* To do with the ELF constructed by the kernel on a process' stack + just before it transfers control to the program's interpreter + (to use the ELF parlance). + Constants from /usr/src/linux-2.4.9-31/include/linux/elf.h + Logic from /usr/src/linux-2.4.9-31/fs/binfmt_elf.c + and its counterpart in the 2.2.14 kernel sources + in Red Hat 6.2. +*/ +#define VKI_AT_CLKTCK 17 /* frequency at which times() increments */ +#define VKI_AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ +#define VKI_AT_BASE 7 /* base address of interpreter */ +#define VKI_AT_PAGESZ 6 /* system page size */ +#define VKI_AT_PHNUM 5 /* number of program headers */ +#define VKI_AT_PHENT 4 /* size of program header entry */ +#define VKI_AT_PHDR 3 /* program headers for program */ + + + #endif /* ndef __VG_KERNELIFACE_H */ /*--------------------------------------------------------------------*/ diff --git a/vg_libpthread.c b/vg_libpthread.c index 015b9f73b3..df895171a3 100644 --- a/vg_libpthread.c +++ b/vg_libpthread.c @@ -104,8 +104,6 @@ extern void VG_(startup) ( void ); static __inline__ void ensure_valgrind ( char* caller ) { - char* str; - int is_valgrind; VG_(startup)(); } @@ -333,7 +331,9 @@ int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) case PTHREAD_MUTEX_TIMED_NP: case PTHREAD_MUTEX_ADAPTIVE_NP: # endif +# ifdef GLIBC_2_1 case PTHREAD_MUTEX_FAST_NP: +# endif case PTHREAD_MUTEX_RECURSIVE_NP: case PTHREAD_MUTEX_ERRORCHECK_NP: attr->__mutexkind = type; diff --git a/vg_main.c b/vg_main.c index 6df3e92a2d..330068db79 100644 --- a/vg_main.c +++ b/vg_main.c @@ -481,6 +481,15 @@ static void config_error ( Char* msg ) VG_(exit)(1); } +static void args_grok_error ( Char* msg ) +{ + VG_(shutdown_logging)(); + VG_(clo_logfile_fd) = 2; /* stderr */ + VG_(printf)("valgrind.so: When searching for " + "client's argc/argc/envp:\n\t%s\n", msg); + config_error("couldn't find client's argc/argc/envp"); +} + static void process_cmd_line_options ( void ) { @@ -488,7 +497,7 @@ static void process_cmd_line_options ( void ) UInt argc; UChar* p; UChar* str; - Int i, eventually_logfile_fd; + Int i, eventually_logfile_fd, ctr; # define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n') # define STREQ(s1,s2) (0==VG_(strcmp_ws)((s1),(s2))) @@ -532,160 +541,88 @@ static void process_cmd_line_options ( void ) VG_(startup_logging)(); - /* We look for the Linux ELF table and go down until we find the + /* (Suggested by Fabrice Bellard ... ) + We look for the Linux ELF table and go down until we find the envc & envp. It is not full proof, but these structures should change less often than the libc ones. */ { - unsigned long *sp; - int i; + UInt* sp = 0; /* bogus init to keep gcc -O happy */ + /* locate the top of the stack */ - sp = (unsigned long *)(((unsigned long)VG_(esp_at_startup) & - 0xF0000000) + 0x10000000); + if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup), + VG_STARTUP_STACK_BASE_1 )) { + sp = (UInt*)VG_STARTUP_STACK_BASE_1; + } else + if (VG_STACK_MATCHES_BASE( VG_(esp_at_startup), + VG_STARTUP_STACK_BASE_2 )) { + sp = (UInt*)VG_STARTUP_STACK_BASE_2; + } else { + args_grok_error( + "startup %esp is not near any VG_STARTUP_STACK_BASE_*\n " + "constants defined in vg_include.h. You should investigate." + ); + } + /* we locate: NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE) in the elf interpreter table */ sp -= 2; - -#define VKI_AT_PAGESZ 6 - while (sp[0] != VKI_AT_PAGESZ || sp[1] != 4096) { - /* VG_(printf)("trying %p\n", sp); */ + /* VG_(printf)("trying %p\n", sp); */ sp--; } -#define VKI_AT_BASE 7 /* base address of interpreter */ -#define VKI_AT_PAGESZ 6 /* system page size */ -#define VKI_AT_PHNUM 5 /* number of program headers */ -#define VKI_AT_PHENT 4 /* size of program header entry */ -#define VKI_AT_PHDR 3 /* program headers for program */ if (sp[2] == VKI_AT_BASE && sp[0] == VKI_AT_PAGESZ && sp[-2] == VKI_AT_PHNUM && sp[-4] == VKI_AT_PHENT && sp[-6] == VKI_AT_PHDR) { - VG_(printf)("Looks like you've got a 2.2.X kernel here.\n"); + if (0) + VG_(printf)("Looks like you've got a 2.2.X kernel here.\n"); sp -= 6; - } + } else + if (sp[2] == VKI_AT_CLKTCK + && sp[0] == VKI_AT_PAGESZ + && sp[-2] == VKI_AT_HWCAP) { + if (0) + VG_(printf)("Looks like you've got a 2.4.X kernel here.\n"); + sp -= 2; + } else + args_grok_error( + "ELF frame does not look like 2.2.X or 2.4.X.\n " + "See kernel sources linux/fs/binfmt_elf.c to make sense of this." + ); sp--; - vg_assert(*sp == 0); + if (*sp != 0) + args_grok_error("can't find NULL at end of env[]"); + /* sp now points to NULL at the end of env[] */ + ctr = 0; while (True) { sp --; if (*sp == 0) break; + if (++ctr >= 1000) + args_grok_error( + "suspiciously many (1000) env[] entries; giving up"); + } /* sp now points to NULL at the end of argv[] */ - VG_(client_envp) = sp+1; + VG_(client_envp) = (Char**)(sp+1); + ctr = 0; VG_(client_argc) = 0; while (True) { sp--; if (*sp == VG_(client_argc)) break; VG_(client_argc)++; + if (++ctr >= 1000) + args_grok_error( + "suspiciously many (1000) argv[] entries; giving up"); } - VG_(client_argv) = sp+1; - } - - -#if 0 - /* Magically find the client's argc/argv/envp. This kludge is - entirely dependent on the stack layout imposed by libc at - startup. Hence the magic offsets. Then check (heuristically) - that the results are plausible. There must be a better way to - do this ... */ - -# if 1 - /* Use this to search for the correct offsets if the tests below - barf. */ - { Int i; - VG_(printf)("startup %%esp is %p\n", VG_(esp_at_startup) ); - for (i = -10; i < 20; i++) { - Char* p = ((Char**)VG_(esp_at_startup))[i]; - VG_(printf)("%d: %p\n", i, p); - } + VG_(client_argv) = (Char**)(sp+1); } -# endif - -# if defined(GLIBC_2_2) - /* These offsets (5,6,7) are right for my RedHat 7.2 (glibc-2.2.4) - box. */ - - VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [5] ); - VG_(client_argv) = (Char**)( ((void**)VG_(esp_at_startup)) [6] ); - VG_(client_envp) = (Char**)( ((void**)VG_(esp_at_startup)) [7] ); - - if ( ((UInt)VG_(client_argc)) > 0 && - ((UInt)VG_(client_argc)) < 10000 && - (Addr)VG_(client_argv) >= 0x8000000 && - (Addr)VG_(client_envp) >= 0x8000000) - goto argc_argv_envp_OK; - - /* If that's no good, try some other offsets discovered by KDE - folks on 8 Feb 02: - For glibc > 2.2.4 the offset 9/10/11 did the trick. Coolo found - out those, on I think a Caldera 3.1 with glibc 2.2.4 -- the same - offsets worked for on a debian sid with glibc 2.2.5. */ - - VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [9] ); - VG_(client_argv) = (Char**)( ((void**)VG_(esp_at_startup)) [10] ); - VG_(client_envp) = (Char**)( ((void**)VG_(esp_at_startup)) [11] ); - - if ( ((UInt)VG_(client_argc)) > 0 && - ((UInt)VG_(client_argc)) < 10000 && - (Addr)VG_(client_argv) >= 0x8000000 && - (Addr)VG_(client_envp) >= 0x8000000) - goto argc_argv_envp_OK; - -# endif /* defined(GLIBC_2_2) */ - -# if defined(GLIBC_2_1) - /* Doesn't look promising. Try offsets for RedHat 6.2 - (glibc-2.1.3) instead. In this case, the argv and envp vectors - are actually on the stack (bizarrely). */ - - VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [4] ); - VG_(client_argv) = (Char**) & ( ((void**)VG_(esp_at_startup)) [5] ); - VG_(client_envp) - = (Char**) & ( ((void**)VG_(esp_at_startup)) [6 + VG_(client_argc)] ); - - if ( ((UInt)VG_(client_argc)) > 0 && - ((UInt)VG_(client_argc)) < 10000 && - (Addr)VG_(client_argv) >= 0x8000000 && - (Addr)VG_(client_envp) >= 0x8000000) - goto argc_argv_envp_OK; - - /* Here's yet another variant, from (irc.kde.org). */ - - VG_(client_argc) = (Int) ( ((void**)VG_(esp_at_startup)) [9] ); - VG_(client_argv) = (Char**) & ( ((void**)VG_(esp_at_startup)) [10] ); - VG_(client_envp) - = (Char**) & ( ((void**)VG_(esp_at_startup)) [11 + VG_(client_argc)] ); - - if ( ((UInt)VG_(client_argc)) > 0 && - ((UInt)VG_(client_argc)) < 10000 && - (Addr)VG_(client_argv) >= 0x8000000 && - (Addr)VG_(client_envp) >= 0x8000000) - goto argc_argv_envp_OK; -# endif /* defined(GLIBC_2_1) */ - -# if !defined(GLIBC_2_2) && !defined(GLIBC_2_1) - config_error("autoconf/configure detected neither glibc 2.1.X nor 2.2.X"); -# endif - - /* VG_(printf)("%d %p %p\n", VG_(client_argc), VG_(client_argv), - VG_(client_envp)); - */ - /* We're hosed. Give up :-( */ - config_error( - "Can't get plausible values for client's argc/argv/envp.\n\t" - "You may be able to fix this; see process_cmd_line_options()\n\t" - "in vg_main.c" - ); - /* NOTREACHED */ - - argc_argv_envp_OK: -#endif /* Now that VG_(client_envp) has been set, we can extract the args for Valgrind itself. Copy into global var so that we don't have to diff --git a/vg_scheduler.c b/vg_scheduler.c index 54dc30b8ff..79056e7edf 100644 --- a/vg_scheduler.c +++ b/vg_scheduler.c @@ -524,9 +524,15 @@ void VG_(scheduler_init) ( void ) ThreadId tid_main; startup_esp = VG_(baseBlock)[VGOFF_(m_esp)]; - if ((startup_esp & VG_STARTUP_STACK_MASK) != VG_STARTUP_STACK_MASK) { - VG_(printf)("%%esp at startup = %p is not near %p; aborting\n", - (void*)startup_esp, (void*)VG_STARTUP_STACK_MASK); + + if (VG_STACK_MATCHES_BASE(startup_esp, VG_STARTUP_STACK_BASE_1) + || VG_STACK_MATCHES_BASE(startup_esp, VG_STARTUP_STACK_BASE_2)) { + /* Jolly good! */ + } else { + VG_(printf)("%%esp at startup = %p is not near %p or %p; aborting\n", + (void*)startup_esp, + (void*)VG_STARTUP_STACK_BASE_1, + (void*)VG_STARTUP_STACK_BASE_2 ); VG_(panic)("unexpected %esp at startup"); } @@ -1922,7 +1928,9 @@ void do_pthread_mutex_lock( ThreadId tid, case PTHREAD_MUTEX_TIMED_NP: case PTHREAD_MUTEX_ADAPTIVE_NP: # endif +# ifdef GLIBC_2_1 case PTHREAD_MUTEX_FAST_NP: +# endif case PTHREAD_MUTEX_RECURSIVE_NP: case PTHREAD_MUTEX_ERRORCHECK_NP: if (mutex->__m_count >= 0) break; @@ -2016,7 +2024,9 @@ void do_pthread_mutex_unlock ( ThreadId tid, case PTHREAD_MUTEX_TIMED_NP: case PTHREAD_MUTEX_ADAPTIVE_NP: # endif +# ifdef GLIBC_2_1 case PTHREAD_MUTEX_FAST_NP: +# endif case PTHREAD_MUTEX_RECURSIVE_NP: case PTHREAD_MUTEX_ERRORCHECK_NP: if (mutex->__m_count >= 0) break; @@ -2234,7 +2244,9 @@ void do_pthread_cond_wait ( ThreadId tid, case PTHREAD_MUTEX_TIMED_NP: case PTHREAD_MUTEX_ADAPTIVE_NP: # endif +# ifdef GLIBC_2_1 case PTHREAD_MUTEX_FAST_NP: +# endif case PTHREAD_MUTEX_RECURSIVE_NP: case PTHREAD_MUTEX_ERRORCHECK_NP: if (mutex->__m_count >= 0) break;