|
From: Jeremy F. <je...@go...> - 2003-11-01 00:51:15
|
CVS commit by fitzhardinge: Oops, add new files A corecheck/tests/vgprintf.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright] A corecheck/tests/vgprintf.stderr.exp 1.1 A corecheck/tests/vgprintf.stdout.exp 1.1 A corecheck/tests/vgprintf.vgtest 1.1 A tests/filter_numbers 1.1 |
|
From: Robert W. <rj...@ke...> - 2003-11-17 17:46:50
|
CVS commit by rjwalsh: Add a facility for tracking open file descriptors. Information about still open files is dumped out exit. Enabled using the --track-fds switch. A corecheck/tests/fdleak_cmsg.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright] A corecheck/tests/fdleak_cmsg.stderr.exp 1.1 A corecheck/tests/fdleak_cmsg.vgtest 1.1 A corecheck/tests/fdleak_creat.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright] A corecheck/tests/fdleak_creat.stderr.exp 1.1 A corecheck/tests/fdleak_creat.vgtest 1.1 A corecheck/tests/fdleak_dup.c 1.1 [no copyright] A corecheck/tests/fdleak_dup.stderr.exp 1.1 A corecheck/tests/fdleak_dup.vgtest 1.1 A corecheck/tests/fdleak_dup2.c 1.1 [no copyright] A corecheck/tests/fdleak_dup2.stderr.exp 1.1 A corecheck/tests/fdleak_dup2.vgtest 1.1 A corecheck/tests/fdleak_fcntl.c 1.1 [no copyright] A corecheck/tests/fdleak_fcntl.stderr.exp 1.1 A corecheck/tests/fdleak_fcntl.vgtest 1.1 A corecheck/tests/fdleak_ipv4.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright] A corecheck/tests/fdleak_ipv4.stderr.exp 1.1 A corecheck/tests/fdleak_ipv4.stdout.exp 1.1 A corecheck/tests/fdleak_ipv4.vgtest 1.1 A corecheck/tests/fdleak_open.c 1.1 [no copyright] A corecheck/tests/fdleak_open.stderr.exp 1.1 A corecheck/tests/fdleak_open.vgtest 1.1 A corecheck/tests/fdleak_pipe.c 1.1 [no copyright] A corecheck/tests/fdleak_pipe.stderr.exp 1.1 A corecheck/tests/fdleak_pipe.vgtest 1.1 A corecheck/tests/fdleak_socketpair.c 1.1 [no copyright] A corecheck/tests/fdleak_socketpair.stderr.exp 1.1 A corecheck/tests/fdleak_socketpair.vgtest 1.1 A corecheck/tests/filter_fdleak 1.1 M +23 -3 corecheck/tests/Makefile.am 1.14 M +7 -0 coregrind/vg_include.h 1.155 M +16 -0 coregrind/vg_main.c 1.122 M +88 -4 coregrind/vg_mylibc.c 1.57 M +356 -7 coregrind/vg_syscalls.c 1.56 M +9 -0 coregrind/docs/coregrind_core.html 1.17 M +39 -0 include/vg_kerneliface.h 1.6 M +14 -0 include/vg_skin.h 1.100 |
|
From: Nicholas N. <nj...@ca...> - 2003-11-20 16:21:29
|
CVS commit by nethercote: Updated all "report bugs to..." messages to point to valgrind.kde.org; also updated the docs to refer to valgrind.kde.org instead of the old website. M +1 -1 addrcheck/ac_main.c 1.55 M +3 -3 auxprogs/valgrind-listener.c 1.11 M +1 -1 cachegrind/cg_main.c 1.57 M +1 -1 cachegrind/docs/cg_techdocs.html 1.4 M +1 -1 corecheck/cc_main.c 1.17 M +0 -7 coregrind/vg_include.h 1.156 M +1 -3 coregrind/vg_intercept.c 1.25 [POSSIBLY UNSAFE: printf] M +4 -2 coregrind/vg_libpthread.c 1.140 [POSSIBLY UNSAFE: printf] M +3 -3 coregrind/vg_main.c 1.125 M +2 -2 coregrind/vg_mylibc.c 1.58 M +1 -1 coregrind/docs/coregrind_core.html 1.18 M +1 -1 helgrind/hg_main.c 1.67 M +7 -0 include/vg_skin.h 1.101 M +1 -1 lackey/lk_main.c 1.21 M +1 -1 memcheck/mc_main.c 1.42 M +1 -1 memcheck/docs/mc_techdocs.html 1.7 M +1 -1 none/nl_main.c 1.16 --- valgrind/addrcheck/ac_main.c #1.54:1.55 @@ -1279,5 +1279,5 @@ void SK_(pre_clo_init)(void) VG_(details_copyright_author)( "Copyright (C) 2002-2003, and GNU GPL'd, by Julian Seward."); - VG_(details_bug_reports_to) ("js...@ac..."); + VG_(details_bug_reports_to) (VG_BUGS_TO); VG_(details_avg_translation_sizeB) ( 135 ); --- valgrind/auxprogs/valgrind-listener.c #1.10:1.11 @@ -46,5 +46,5 @@ -/* For VG_CLO_DEFAULT_LOGPORT and VG_EMAIL_ADDR. */ +/* For VG_CLO_DEFAULT_LOGPORT and VG_BUGS_TO. */ #include "vg_include.h" @@ -65,5 +65,5 @@ static void panic ( Char* str ) "`impossible' happened:\n %s\n", str); fprintf(stderr, - "Please report this bug to: %s\n\n", VG_EMAIL_ADDR); + "Please report this bug at: %s\n\n", VG_BUGS_TO); exit(1); } @@ -76,5 +76,5 @@ static void my_assert_fail ( const Char* file, line, fn, expr ); fprintf(stderr, - "Please report this bug to: %s\n\n", VG_EMAIL_ADDR); + "Please report this bug at: %s\n\n", VG_BUGS_TO); exit(1); } --- valgrind/cachegrind/cg_main.c #1.56:1.57 @@ -2025,5 +2025,5 @@ void SK_(pre_clo_init)(void) VG_(details_copyright_author)( "Copyright (C) 2002-2003, and GNU GPL'd, by Nicholas Nethercote."); - VG_(details_bug_reports_to) ("nj...@ca..."); + VG_(details_bug_reports_to) (VG_BUGS_TO); VG_(details_avg_translation_sizeB) ( 155 ); --- valgrind/cachegrind/docs/cg_techdocs.html #1.3:1.4 @@ -34,5 +34,5 @@ <a href="mailto:nj...@ca...">nj...@ca...</a><br> <a -href="http://developer.kde.org/~sewardj">http://developer.kde.org/~sewardj</a><br> +href="http://valgrind.kde.org">http://valgrind.kde.org</a><br> <p> Copyright © 2001-2003 Nick Nethercote --- valgrind/corecheck/cc_main.c #1.16:1.17 @@ -41,5 +41,5 @@ void SK_(pre_clo_init)(void) VG_(details_copyright_author)( "Copyright (C) 2002-2003, and GNU GPL'd, by Nicholas Nethercote."); - VG_(details_bug_reports_to) ("nj...@ca..."); + VG_(details_bug_reports_to) (VG_BUGS_TO); VG_(needs_core_errors)(); --- valgrind/coregrind/vg_include.h #1.155:1.156 @@ -35,11 +35,4 @@ /* --------------------------------------------------------------------- - Where to send bug reports to. - ------------------------------------------------------------------ */ - -#define VG_EMAIL_ADDR "js...@ac..." - - -/* --------------------------------------------------------------------- Build options and table sizes. You should be able to change these options or sizes, recompile, and still have a working system. --- valgrind/coregrind/vg_intercept.c #1.24:1.25 @@ -135,7 +135,5 @@ void my_assert_fail ( const Char* expr, "valgrind", file, line, fn, expr ); cat_n_send ( "", buf ); - sprintf(buf, "Please report this bug to me at: %s\n\n", - VG_EMAIL_ADDR); - cat_n_send ( "", buf ); + sprintf(buf, "Please report this bug at: %s\n\n", VG_BUGS_TO); my_exit(1); } --- valgrind/coregrind/vg_libpthread.c #1.139:1.140 @@ -171,4 +171,6 @@ void barf ( const char* str ) strcpy(buf, "\nvalgrind's libpthread.so: "); strcat(buf, str); + strcat(buf, "\nPlease report this bug at: "); + strcat(buf, VG_BUGS_TO); strcat(buf, "\n\n"); VALGRIND_NON_SIMD_CALL2(VG_(message), Vg_UserMsg, buf); @@ -212,5 +214,5 @@ void vgPlain_unimp ( char* fn ) { cat_n_send ( "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ", fn, "" ); - barf("Please report this bug to me at: js...@ac..."); + barf("unimplemented function"); } @@ -227,5 +229,5 @@ void my_assert_fail ( const Char* expr, "valgrind", file, line, fn, expr ); cat_n_send ( "", buf, "" ); - sprintf(buf, "Please report this bug to me at: %s\n\n", VG_EMAIL_ADDR); + sprintf(buf, "Please report this bug at: %s\n\n", VG_BUGS_TO); my_exit(1); } --- valgrind/coregrind/vg_main.c #1.124:1.125 @@ -729,5 +729,5 @@ static void usage ( void ) else VG_(printf)(" (none)\n"); - VG_(printf)(usage3, VG_EMAIL_ADDR); + VG_(printf)(usage3, VG_BUGS_TO); VG_(shutdown_logging)(); @@ -1991,7 +1991,7 @@ void VG_(unimplemented) ( Char* msg ) "or because no reasonable program would behave this way,"); VG_(message)(Vg_UserMsg, - "or because nobody has yet needed it. In any case, let me know"); + "or because nobody has yet needed it. In any case, let us know at"); VG_(message)(Vg_UserMsg, - "(js...@ac...) and/or try to work around the problem, if you can."); + "%s and/or try to work around the problem, if you can.", VG_BUGS_TO); VG_(message)(Vg_UserMsg, ""); --- valgrind/coregrind/vg_mylibc.c #1.57:1.58 @@ -1107,5 +1107,5 @@ void VG_(skin_assert_fail) ( const Char* void VG_(core_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn ) { - assert_fail(expr, "valgrind", VG_EMAIL_ADDR, file, line, fn); + assert_fail(expr, "valgrind", VG_BUGS_TO, file, line, fn); } @@ -1120,5 +1120,5 @@ static void panic ( Char* name, Char* re void VG_(core_panic) ( Char* str ) { - panic("valgrind", VG_EMAIL_ADDR, str); + panic("valgrind", VG_BUGS_TO, str); } --- valgrind/coregrind/docs/coregrind_core.html #1.17:1.18 @@ -1161,5 +1161,5 @@ <a name="problems"></a> <h3>2.11 If you have problems</h3> -Mail me (<a href="mailto:js...@ac...">js...@ac...</a>). +Contact us at <a href="http://valgrind.kde.org">valgrind.kde.org</a>. <p>See <a href="#limits">this section</a> for the known limitations of --- valgrind/helgrind/hg_main.c #1.66:1.67 @@ -3239,5 +3239,5 @@ void SK_(pre_clo_init)(void) VG_(details_copyright_author)( "Copyright (C) 2002-2003, and GNU GPL'd, by Nicholas Nethercote."); - VG_(details_bug_reports_to) ("je...@go..."); + VG_(details_bug_reports_to) (VG_BUGS_TO); VG_(details_avg_translation_sizeB) ( 115 ); --- valgrind/include/vg_skin.h #1.100:1.101 @@ -39,4 +39,11 @@ +/* --------------------------------------------------------------------- + Where to send bug reports to. + ------------------------------------------------------------------ */ + +#define VG_BUGS_TO "valgrind.kde.org" + + /*====================================================================*/ /*=== Build options and table sizes. ===*/ --- valgrind/lackey/lk_main.c #1.20:1.21 @@ -82,5 +82,5 @@ void SK_(pre_clo_init)(void) VG_(details_copyright_author)( "Copyright (C) 2002-2003, and GNU GPL'd, by Nicholas Nethercote."); - VG_(details_bug_reports_to) ("nj...@ca..."); + VG_(details_bug_reports_to) (VG_BUGS_TO); VG_(details_avg_translation_sizeB) ( 175 ); --- valgrind/memcheck/mc_main.c #1.41:1.42 @@ -1660,5 +1660,5 @@ void SK_(pre_clo_init)(void) VG_(details_copyright_author)( "Copyright (C) 2002-2003, and GNU GPL'd, by Julian Seward."); - VG_(details_bug_reports_to) ("js...@ac..."); + VG_(details_bug_reports_to) (VG_BUGS_TO); VG_(details_avg_translation_sizeB) ( 228 ); --- valgrind/memcheck/docs/mc_techdocs.html #1.6:1.7 @@ -34,5 +34,5 @@ <p> <a href="mailto:js...@ac...">js...@ac...</a><br> -<a href="http://developer.kde.org/~sewardj">http://developer.kde.org/~sewardj</a><br> +<a href="http://valgrind.kde.org">http://valgrind.kde.org</a><br> Copyright © 2000-2003 Julian Seward <p> --- valgrind/none/nl_main.c #1.15:1.16 @@ -40,5 +40,5 @@ void SK_(pre_clo_init)(void) VG_(details_copyright_author)( "Copyright (C) 2002-2003, and GNU GPL'd, by Nicholas Nethercote."); - VG_(details_bug_reports_to) ("nj...@ca..."); + VG_(details_bug_reports_to) (VG_BUGS_TO); /* No needs, no core events to track */ |
|
From: Nicholas N. <nj...@ca...> - 2003-12-02 14:57:43
|
CVS commit by nethercote:
Tools using shadow memory can't handle the first 64KB being mapped, because
they rely on this area being unmapped for their quick sanity check. This
commit make Valgrind refuse to mmap() this area. Added a regtest for it.
A memcheck/tests/zeropage.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright]
A memcheck/tests/zeropage.stderr.exp 1.1
A memcheck/tests/zeropage.vgtest 1.1
M +12 -0 coregrind/vg_syscalls.c 1.62
M +4 -2 memcheck/tests/Makefile.am 1.30
--- valgrind/coregrind/vg_syscalls.c #1.61:1.62
@@ -3205,4 +3205,12 @@ PRE(mkdir)
}
+void check_mmap_start(ThreadState* tst, Addr start, Int flags)
+{
+ /* Refuse to mmap the first 64KB of memory, so that the cheap sanity test
+ for tools using shadow memory works. */
+ if (start < 65536 && (flags & VKI_MAP_FIXED))
+ tst->m_eax = -VKI_EINVAL;
+}
+
PRE(mmap2)
{
@@ -3215,4 +3223,6 @@ PRE(mmap2)
MAYBE_PRINTF("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
arg1, arg2, arg3, arg4, arg5, arg6 );
+
+ check_mmap_start(tst, arg1, arg4);
}
@@ -3241,4 +3251,6 @@ PRE(mmap)
MAYBE_PRINTF("mmap ( %p, %d, %d, %d, %d, %d )\n",
a1, a2, a3, a4, a5, a6 );
+
+ check_mmap_start(tst, a1, a4);
}
--- valgrind/memcheck/tests/Makefile.am #1.29:1.30
@@ -63,5 +63,6 @@
threadederrno.stderr.exp threadederrno.stdout.exp \
threadederrno.vgtest \
- writev.stderr.exp writev.vgtest
+ writev.stderr.exp writev.vgtest \
+ zeropage.stderr.exp zeropage.vgtest
check_PROGRAMS = \
@@ -74,5 +75,5 @@
realloc1 realloc2 realloc3 sigaltstack signal2 supp1 supp2 suppfree \
trivialleak tronical weirdioctl \
- mismatches new_override metadata threadederrno writev
+ mismatches new_override metadata threadederrno writev zeropage
AM_CPPFLAGS = -I$(top_srcdir)/include
@@ -126,4 +127,5 @@
threadederrno_LDADD = -lpthread
writev_SOURCES = writev.c
+zeropage_SOURCES = zeropage.c
# C++ ones
|
|
From: Jeremy F. <je...@go...> - 2003-12-16 02:05:54
|
CVS commit by fitzhardinge: This jumbo-checkin is the Full Virtualization checkin. This eliminates Valgrind's dependency on the dynamic linker for getting started, and instead takes things into its own hands. This checkin doesn't add much in the way of new functionality, but it is the basis for all future work on Valgrind. It allows us much more flexibility in implementation, and well as increasing the reliability of Valgrind by protecting it more from its clients. This patch requires some changes to tools to update them to the changes in the tool API, but they are straightforward. See the posting "Heads up: Full Virtualization" on valgrind-developers for a more complete description of this change and its effects on you. M +7 -3 Makefile.am 1.60 M +2 -2 autogen.sh 1.2 M +1 -1 configure.in 1.102 M +2 -0 valgrind.spec.in 1.11 M +12 -3 addrcheck/Makefile.am 1.47 M +33 -31 addrcheck/ac_main.c 1.56 M +6 -0 cachegrind/Makefile.am 1.41 M +2 -2 cachegrind/cg_main.c 1.58 M +6 -0 corecheck/Makefile.am 1.41 M +2 -2 corecheck/cc_main.c 1.18 M +8 -3 corecheck/tests/Makefile.am 1.18 M +92 -48 coregrind/Makefile.am 1.61 M +2 -1 coregrind/valgrind.vs 1.3 M +26 -0 coregrind/vg_constants.h 1.13 M +2 -87 coregrind/vg_default.c 1.19 M +18 -1 coregrind/vg_dispatch.S 1.12 M +92 -25 coregrind/vg_from_ucode.c 1.67 M +9 -10 coregrind/vg_helpers.S 1.25 M +203 -135 coregrind/vg_include.h 1.158 M +54 -122 coregrind/vg_intercept.c 1.26 M +53 -43 coregrind/vg_libpthread.c 1.141 M +194 -18 coregrind/vg_libpthread.vs 1.7 M +235 -479 coregrind/vg_main.c 1.128 M +84 -15 coregrind/vg_malloc2.c 1.16 M +685 -146 coregrind/vg_memory.c 1.45 M +143 -13 coregrind/vg_mylibc.c 1.60 M +29 -134 coregrind/vg_needs.c 1.13 M +41 -5 coregrind/vg_procselfmaps.c 1.10 M +3 -4 coregrind/vg_proxylwp.c 1.9 M +176 -170 coregrind/vg_replace_malloc.c 1.16 M +88 -15 coregrind/vg_scheduler.c 1.133 M +124 -9 coregrind/vg_signals.c 1.53 M +1 -1 coregrind/vg_stabs.c 1.2 M +0 -130 coregrind/vg_startup.S 1.20 M +369 -150 coregrind/vg_symtab2.c 1.65 M +7 -1 coregrind/vg_symtab2.h 1.4 M +326 -87 coregrind/vg_syscalls.c 1.67 M +2 -1 coregrind/vg_to_ucode.c 1.115 M +41 -30 coregrind/vg_translate.c 1.63 M +14 -0 coregrind/vg_transtab.c 1.26 M +4 -3 example/ex_main.c 1.14 M +12 -1 helgrind/Makefile.am 1.44 M +25 -23 helgrind/hg_main.c 1.69 M +12 -1 include/Makefile.am 1.5 M +7 -0 include/vg_constants_skin.h 1.6 M +5 -0 include/vg_kerneliface.h 1.9 M +667 -243 include/vg_skin.h 1.102 M +6 -0 lackey/Makefile.am 1.42 M +3 -2 lackey/lk_main.c 1.22 M +13 -4 memcheck/Makefile.am 1.47 M +1 -4 memcheck/mac_leakcheck.c 1.12 M +22 -2 memcheck/mac_replace_strmem.c 1.8 M +4 -0 memcheck/mc_clientreqs.c 1.17 M +3 -3 memcheck/mc_from_ucode.c 1.13 M +39 -39 memcheck/mc_main.c 1.43 M +4 -1 memcheck/memcheck.h 1.16 M +1 -1 memcheck/tests/badjump.stderr.exp 1.7 M +1 -1 memcheck/tests/fprw.vgtest 1.4 M +0 -1 memcheck/tests/nanoleak.supp 1.2 M +1 -0 memcheck/tests/sigaltstack.c 1.6 M +0 -3 memcheck/tests/sigaltstack.stderr.exp 1.8 M +4 -7 memcheck/tests/threadederrno.c 1.2 [POSSIBLY UNSAFE: printf] M +0 -3 memcheck/tests/threadederrno.stderr.exp 1.2 M +3 -3 memcheck/tests/threadederrno.stdout.exp 1.2 M +3 -0 memcheck/tests/zeropage.stderr.exp 1.2 M +6 -1 none/Makefile.am 1.42 M +20 -13 none/nl_main.c 1.17 M +1 -1 none/tests/Makefile.am 1.16 M +5 -1 none/tests/smc1.c 1.3 M +5 -5 none/tests/smc1.stdout.exp 1.3 M +4 -0 tests/filter_stderr_basic 1.12 M +1 -3 tests/vg_regtest.in 1.17 |
|
From: Jeremy F. <je...@go...> - 2003-12-16 02:15:11
|
CVS commit by fitzhardinge: Add and delete all the files which need adding and deleting. A corecheck/tests/as_mmap.c 1.1 [no copyright] A corecheck/tests/as_mmap.stderr.exp 1.1 A corecheck/tests/as_mmap.vgtest 1.1 A corecheck/tests/as_shm.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright] A corecheck/tests/as_shm.stderr.exp 1.1 A corecheck/tests/as_shm.stdout.exp 1.1 A corecheck/tests/as_shm.vgtest 1.1 A coregrind/gen_toolint.pl 1.1 A coregrind/stage1.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright] A coregrind/stage2.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright] A coregrind/toolfuncs.def 1.1 A coregrind/ume.c 1.1 [POSSIBLY UNSAFE: printf,scanf] [no copyright] A coregrind/ume.h 1.1 [no copyright] A coregrind/ume_arch.h 1.1 [no copyright] A coregrind/vg_skiplist.c 1.1 [no copyright] A coregrind/x86/Makefile.am 1.1 A coregrind/x86/stage2.lds 1.1 A coregrind/x86/ume_archdefs.c 1.1 [no copyright] A coregrind/x86/ume_archdefs.h 1.1 [no copyright] A coregrind/x86/ume_entry.S 1.1 A coregrind/x86/ume_go.c 1.1 [no copyright] A include/vg_skin.h.base 1.1 R coregrind/valgrind.in 1.41 R include/vg_skin.h 1.102 |
|
From: Dirk M. <mu...@kd...> - 2003-12-16 13:11:18
|
On Tuesday 16 December 2003 03:14, Jeremy Fitzhardinge wrote: > A corecheck/tests/as_mmap.c 1.1 [no copyright] > A corecheck/tests/as_mmap.stderr.exp 1.1 > A corecheck/tests/as_mmap.vgtest 1.1 > A corecheck/tests/as_shm.c 1.1 [POSSIBLY UNSAFE: printf] [no > copyright] A corecheck/tests/as_shm.stderr.exp 1.1 > A corecheck/tests/as_shm.stdout.exp 1.1 > A corecheck/tests/as_shm.vgtest 1.1 > A coregrind/gen_toolint.pl 1.1 > A coregrind/stage1.c 1.1 [POSSIBLY UNSAFE: printf] [no > copyright] A coregrind/stage2.c 1.1 [POSSIBLY UNSAFE: printf] > [no copyright] A coregrind/toolfuncs.def 1.1 > A coregrind/ume.c 1.1 [POSSIBLY UNSAFE: printf,scanf] [no > copyright] A coregrind/ume.h 1.1 [no copyright] > A coregrind/ume_arch.h 1.1 [no copyright] > A coregrind/vg_skiplist.c 1.1 [no copyright] > A coregrind/x86/Makefile.am 1.1 > A coregrind/x86/stage2.lds 1.1 > A coregrind/x86/ume_archdefs.c 1.1 [no copyright] > A coregrind/x86/ume_archdefs.h 1.1 [no copyright] > A coregrind/x86/ume_entry.S 1.1 > A coregrind/x86/ume_go.c 1.1 [no copyright] > A include/vg_skin.h.base 1.1 > R coregrind/valgrind.in 1.41 > R include/vg_skin.h 1.102 can you please add copyright and license statements to the files which are listed as "no copyright" ? Thanks. |
|
From: Dirk M. <dm...@gm...> - 2003-12-16 13:44:20
|
On Tuesday 16 December 2003 03:14, Jeremy Fitzhardinge wrote: > A coregrind/x86/stage2.lds 1.1 does anyone know what these "ONLY_IF_RO" and "ONLY_IF_RW" literals in this file are supposed to do? I can't find them defined or replaced anywhere else, and it doesn't look like any binutils version available from ftp.gnu.org supports them. removing them works fine for me btw. |
|
From: Josef W. <Jos...@gm...> - 2003-12-16 15:39:24
|
On Tuesday 16 December 2003 14:44, Dirk Mueller wrote: > On Tuesday 16 December 2003 03:14, Jeremy Fitzhardinge wrote: > > A coregrind/x86/stage2.lds 1.1 > > does anyone know what these "ONLY_IF_RO" and "ONLY_IF_RW" literals in this > file are supposed to do? No idea, seems to be Redhat specific. I had the same problem trying to compile this with Suse 9.0. But it works when using the output of "ld --verbose", and changing the lines with ENTRY(...) and first line of SECTIONS with "kickstart_base" instead. I suppose these are the "slight modifications" (Jeremy?). Perhaps it's the best to make some "ld --verbose | sed ... " from the Makefile, doing the needed modifications instead of supplying a full ld script. I managed my "calltree" to compile with the FV changes, but I get a segfault on running: =============================================== > valgrind --tool=calltree ls ... ==2826== Estimated CPU clock rate is 600 MHz ==2826== For more details, rerun with: -v ==2826== ==2826== Process terminating with default action of signal 11 (SIGSEGV): dumping core ==2826== at 0x81000C12: (within /lib/ld-2.3.2.so) ==2826== ... ================================================== As there are only minor changes in Cachegrind (which is working quite fine), I thought the same kind of modifications should be enough. Any idea? I have to look at the changes. One question: Where is code for helpers supposed to be located? Does a helper call now involve a context switch?! Cheers, Josef |
|
From: Jeremy F. <je...@go...> - 2003-12-16 17:59:38
|
On Tue, 2003-12-16 at 07:39, Josef Weidendorfer wrote: > No idea, seems to be Redhat specific. I had the same problem trying to compile > this with Suse 9.0. But it works when using the output of "ld --verbose", and > changing the lines with ENTRY(...) and first line of SECTIONS with > "kickstart_base" instead. I suppose these are the "slight > modifications" (Jeremy?). Yep, pretty much. I hadn't realized that the ONLY_IF_* stuff was a RedHatism. > Perhaps it's the best to make some "ld --verbose | sed ... " from the > Makefile, doing the needed modifications instead of supplying a full ld > script. Yes, that's probably a good idea. I'll fix it up today. > I managed my "calltree" to compile with the FV changes, but I get a segfault > on running: > =============================================== > > valgrind --tool=calltree ls > ... > ==2826== Estimated CPU clock rate is 600 MHz > ==2826== For more details, rerun with: -v > ==2826== > ==2826== Process terminating with default action of signal 11 (SIGSEGV): > dumping core > ==2826== at 0x81000C12: (within /lib/ld-2.3.2.so) > ==2826== > ... > ================================================== That looks like something is trying to escape the client address space. Try with --pointercheck=no to see if that works. Does your tool generate LOADs or STOREs as part of it's instrumentation? At the moment, the codegen assumes all LOADs and STOREs are from the client code, not the instrumentation. > As there are only minor changes in Cachegrind (which is working quite fine), I > thought the same kind of modifications should be enough. Any idea? > I have to look at the changes. One question: Where is code for helpers > supposed to be located? Does a helper call now involve a context switch?! No, calling a helper from generated code runs on the real CPU, and so has no restrictions. If you want to call out from code running on the VCPU back into Valgrind, you need to use a client request. J |
|
From: Josef W. <Jos...@gm...> - 2003-12-16 19:10:31
|
On Tuesday 16 December 2003 18:59, Jeremy Fitzhardinge wrote: > > I managed my "calltree" to compile with the FV changes, but I get a > > segfault on running: > > ... > That looks like something is trying to escape the client address space. > Try with --pointercheck=no to see if that works. Does your tool > generate LOADs or STOREs as part of it's instrumentation? At the No. It does the same as cachegrind, plus calls a handler at start of every basic block, and traps run_thread,pre/post_signal. ==11994== Process terminating with default action of signal 11 (SIGSEGV): dumping core ==11994== at 0x81000C12: (within /lib/ld-2.3.2.so) Looking at /lib/ld-2.3.2.so (mapped at 4000000) with objdump: 41000c10 <_start>: 41000c10: 89 e0 mov %esp,%eax 41000c12: e8 f9 00 00 00 call 41000d10 <_dl_start> So the segfault happens at the very start... BTW, does FV enable running valgrind itself under control of a debugger? > > idea? I have to look at the changes. One question: Where is code for > > helpers supposed to be located? Does a helper call now involve a context > > switch?! > > No, calling a helper from generated code runs on the real CPU, and so > has no restrictions. If you want to call out from code running on the > VCPU back into Valgrind, you need to use a client request. Oh, I misunderstood. I thought Valgrind and the client run somehow in different processes and different address spaces with FV... ? Josef |
|
From: Jeremy F. <je...@go...> - 2003-12-16 22:54:30
|
On Tue, 2003-12-16 at 11:10, Josef Weidendorfer wrote:
> No. It does the same as cachegrind, plus calls a handler at start of every
> basic block, and traps run_thread,pre/post_signal.
Hm, maybe there's something wrong with the signal track calls...
> ==11994== Process terminating with default action of signal 11 (SIGSEGV):
> dumping core
> ==11994== at 0x81000C12: (within /lib/ld-2.3.2.so)
>
> Looking at /lib/ld-2.3.2.so (mapped at 4000000) with objdump:
>
> 41000c10 <_start>:
> 41000c10: 89 e0 mov %esp,%eax
> 41000c12: e8 f9 00 00 00 call 41000d10 <_dl_start>
You mean it's the call _dl_start? Does '--pointercheck=no' make a
difference?
This fault is a bit unusual, because it isn't printing any reason for
the SEGV - which generally means that it was a General Protection Fault,
which are generally caused by an out-of-segment pointer dereference
(which is unfortunately why it can't even print what the faulting
address was).
I can't see how that call on its own could generate any bad memory
accesses - it's even on the same page as the first instruction, which
presumably did work.
I'm guessing it's something strange about your instrumentation - can you
post the output of '--trace-codegen=10001'? It shouldn't be very
long...
> So the segfault happens at the very start...
>
> BTW, does FV enable running valgrind itself under control of a debugger?
You can use "--wait-for-gdb=yes" to get it to pause early so you can
attach to it. There's three different views of the process depending on
which set of symbol tables you tell gdb to use: the valgrind launcher
(aka, stage1), valgrind proper (aka stage2) or the client program.
To debug Valgrind itself, do something like this:
$ VALGRINDLIB=.in_place/ valgrind '--wait-for-gdb=yes' '--tool=memcheck' memcheck/tests/badrw &
6706
$ ==6706== Memcheck, a memory error detector for x86-linux.
==6706== Copyright (C) 2002-2003, and GNU GPL'd, by Julian Seward.
==6706== Using valgrind-2.1.0, a program supervision framework for x86-linux.
==6706== Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.
pid=6706
$ gdb .in_place/stage2 6706
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
Attaching to program: /home/jeremy/cvs/kde/valgrind/.in_place/stage2, process 6706
Reading symbols from /lib/libdl.so.2...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from .in_place//vgskin_memcheck.so...done.
Loaded symbols for .in_place//vgskin_memcheck.so
0xb803dede in vgPlain_do_syscall ()
>>> OK, at this point Valgrind is blocked in a pause() syscall, hence
the vgPlain_do_syscall. You can set breakpoints and so on:
(gdb) break vgSkin_update_extra
Breakpoint 1 at 0xb015b3f4: file mac_needs.c, line 511.
>>> use this to get to fall out of the pause() and keep going with the
startup
(gdb) jump *$eip
Continuing at 0xb803dede.
==6706== Estimated CPU clock rate is 602 MHz
==6706== For more details, rerun with: -v
==6706==
>>> SIGSEGVs are expected and normal - they're used for expanding the
client's stack and shadow memory updates (if your tool uses them) -
these should be invisible to the client (and the tool, since they're not
client events). Of course, some SIGSEGVs are outright errors in the
client or Valgrind. Valgrind will try to print messages in the bad
cases. Using --trace-signals=yes will show more details about these
SEGVs (normal or otherwise).
Program received signal SIGSEGV, Segmentation fault.
0xb8742674 in ?? ()
(gdb) c
Continuing.
Breakpoint 1, vgSkin_update_extra (err=0x0) at mac_needs.c:511
511 {
(gdb) bt
#0 vgSkin_update_extra (err=0x0) at mac_needs.c:511
#1 0xb804abc3 in vgSkinInternal_update_extra (err=0x1) at vg_toolint.c:77
#2 0xb80135a2 in vgPlain_maybe_record_error (tid=1, ekind=0, a=0, s=0x0,
extra=0xbfffe930) at vg_errcontext.c:408
(gdb) n
512 switch (VG_(get_error_kind)(err)) {
(gdb)
529 case OverlapErr: return sizeof(OverlapExtra);
> Oh, I misunderstood. I thought Valgrind and the client run somehow in
> different processes and different address spaces with FV... ?
No. I use the terms "client address space" and "Valgrind address
space", but they're both just sub-ranges within the one process address
space as far as the kernel is concerned.
J
|
|
From: Josef W. <Jos...@gm...> - 2003-12-17 09:53:39
|
On Tuesday 16 December 2003 23:52, Jeremy Fitzhardinge wrote: > On Tue, 2003-12-16 at 11:10, Josef Weidendorfer wrote: > > 41000c10 <_start>: > > 41000c10: 89 e0 mov %esp,%eax > > 41000c12: e8 f9 00 00 00 call 41000d10 <_dl_start> > > You mean it's the call _dl_start? Does '--pointercheck=no' make a > difference? Yes, I think it's the call - somehow. And you are right, --pointercheck=no does change things! Now I get: =================================================== ==4743== For more details, rerun with: -v ==4743== valgrind: vg_scheduler.c:1171 (vgPlain_scheduler): Assertion `done_this_time >= 0' failed. ==4743== at 0xB8029505: vgPlain_skin_assert_fail (vg_mylibc.c:1161) ==4743== by 0xB8029504: assert_fail (vg_mylibc.c:1157) ==4743== by 0xB8029542: vgPlain_core_assert_fail (vg_mylibc.c:1168) ==4743== by 0xB800EDB4: vgPlain_scheduler (vg_scheduler.c:1206) sched status: Thread 1: status = Runnable, associated_mx = 0x0, associated_cv = 0x0 ==4743== at 0x81000C10: (within /lib/ld-2.3.2.so) ======================================== > I'm guessing it's something strange about your instrumentation - can you > post the output of '--trace-codegen=10001'? It shouldn't be very > long... That's another thing. --tracegen gives me nothing. If I do e.g. "valgrind -- tool=none --trace-codegen ls &>log", code generation printout in log starts at 0x81000D10. But I know for sure that my instrumentation is already called for BB 0x81000C10, as the "mov" at 0x81000C10 calls the cache simulator (seen when raising verbosity of my tool with --ct-verbose). > [Usefull info for debugging valgrind] Thanks. I will check this out later. > > Oh, I misunderstood. I thought Valgrind and the client run somehow in > > different processes and different address spaces with FV... ? > > No. I use the terms "client address space" and "Valgrind address > space", but they're both just sub-ranges within the one process address > space as far as the kernel is concerned. OK. My understanding of things should be correct now again ;-) BTW: The auto-generated stage2.lds is working fine here on Suse 9.0. Josef |
|
From: Jeremy F. <je...@go...> - 2003-12-18 01:07:34
|
On Wed, 2003-12-17 at 01:52, Josef Weidendorfer wrote: > That's another thing. --tracegen gives me nothing. If I do e.g. "valgrind -- > tool=none --trace-codegen ls &>log", code generation printout in log starts > at 0x81000D10. But I know for sure that my instrumentation is already called > for BB 0x81000C10, as the "mov" at 0x81000C10 calls the cache simulator (seen > when raising verbosity of my tool with --ct-verbose). Eh, are you saying that the --trace-codegen=10001 output only starts after 0x81000D10? I can't see any way in which can not print for early EIPs. BTW, could you also enable the VG_(printf) at the start of VG_(main) just to confirm the initial eip/esp values. > BTW: The auto-generated stage2.lds is working fine here on Suse 9.0. Great. J |
|
From: Josef W. <Jos...@gm...> - 2003-12-18 18:17:30
Attachments:
log
|
On Thursday 18 December 2003 02:06, Jeremy Fitzhardinge wrote:
> Eh, are you saying that the --trace-codegen=10001 output only starts
> after 0x81000D10? I can't see any way in which can not print for early
I found the culprit. Tracegen output started at BB 1, not at BB 0. Patch:
==================================================
--- vg_translate.c 18 Dec 2003 09:06:08 -0000 1.64
+++ vg_translate.c 18 Dec 2003 17:29:59 -0000
@@ -2386,7 +2386,7 @@ void VG_(translate) ( /*IN*/ ThreadId t
notrace_until_limit to be the number of translations to be made
before --trace-codegen= style printing takes effect. */
notrace_until_done
- = VG_(overall_in_count) > notrace_until_limit;
+ = VG_(overall_in_count) >= notrace_until_limit;
seg = VG_(find_segment)(orig_addr);
====================================================
I attached the output of "valgrind --skin=calltree --trace-codegen=10101 ls".
Using the debugger, I found out the place of the SEGFAULT at 0xb874d054,
in the translation of the first basic block. Disassembled with GDB:
...
Dump of assembler code from 0xb874d040 to 0xb874d060:
0xb874d040: mov $0x81000c17,%esi
0xb874d045: mov %edx,%edi
0xb874d047: mov %esi,%fs:(%edx)
0xb874d04a: mov $0xb018eb0c,%eax
0xb874d04f: mov $0x1,%ebx
0xb874d054: mov %ebx,%fs:(%eax)
0xb874d057: mov $0x68,%eax
0xb874d05c: mov %edi,%edx
0xb874d05e: call *0x30(%ebp)
...
Address 0xb874d054 corresponds to Offset 72 in the translated version (from
the attachment):
14: MOVL $0x1, %ebx [ab---D]
67: BB 01 00 00 00
movl $0x1, %ebx
15: STL %ebx, (%eax) [-----D]
72: 64 89 18
movl %ebx, (%eax)
Here, value 1 is a flag I write into a global variable of my skin/tool.
Obviously, this goes wrong as the client has no right to write into valgrind's
space (?). The flag is to be used in a helper called by the translation of the
next basic block.
Where should I allocate space for this flag?
Or better: How to get rid of the permission check, i.e. the "%fs:" segment?
Josef
|
|
From: Josef W. <Jos...@gm...> - 2003-12-18 20:12:22
|
On Thursday 18 December 2003 19:17, Josef Weidendorfer wrote:
> Where should I allocate space for this flag?
> Or better: How to get rid of the permission check, i.e. the "%fs:" segment?
Followup:
Of course, with --pointercheck=no, I can avoid the %fs prefix. But in this
case, this should be avoided even with --pointercheck=yes, as this is a
STORE instruction generated by the tool.
As LOAD/STORE always does a bound check, there are 3 possibilities:
* I add an extended UCode for this,
* We add LOAD/STORE variants that explicitly do no bound checks, which
can be used by tools.
* Add a flag to LOAD/STORE if a boundcheck should explicitly avoided.
I got a crash when I use valgrind with --pointercheck=no. This has nothing to
do with my tool.
E.g. a valgrind --tool=none --pointercheck=no gives me:
================================================
==12818== For more details, rerun with: -v
==12818==
valgrind: vg_scheduler.c:1172 (vgPlain_scheduler): Assertion `done_this_time
>= 0' failed.
==12818== at 0xB8029A61: vgPlain_skin_assert_fail (vg_mylibc.c:1161)
==12818== by 0xB8029A60: assert_fail (vg_mylibc.c:1157)
==12818== by 0xB8029A9E: vgPlain_core_assert_fail (vg_mylibc.c:1168)
==12818== by 0xB800EECC: vgPlain_scheduler (vg_scheduler.c:1216)
sched status:
Thread 1: status = Runnable, associated_mx = 0x0, associated_cv = 0x0
==12818== at 0x81000C10: (within /lib/ld-2.3.2.so)
==================================================
That's before the first BB is executed. Looking at vg_scheduler.c:
1171 done_this_time = (Int)dispatch_ctr_SAVED - (Int)VG_(dispatch_ctr) -1;
1172 vg_assert(done_this_time >= 0);
done_this_time should be the number of BB executed in the inner loop, isn't
it? But why the "-1" ? Somehow with "--pointercheck=no", done_this_time can
be -1 the first time, and thus the assertion failed.
So I simply removed the "-1".
Now I get another SEGFAULT crash. Using gdb, I found out that in vg_dispatch.S
there is a check for clo_checkpointer,assuming a integer type, but Bool is a
"unsigned char". Change the 2 checks, e.g. the first check to
movb VG_(clo_pointercheck), %al
testb %al,%al
, and valgrind runs fine with --pointercheck=no.
Even my skin runs fine now.
Cheers,
Josef
|
|
From: Jeremy F. <je...@go...> - 2003-12-19 00:26:07
|
On Thu, 2003-12-18 at 12:12, Josef Weidendorfer wrote: > On Thursday 18 December 2003 19:17, Josef Weidendorfer wrote: > > Where should I allocate space for this flag? > > Or better: How to get rid of the permission check, i.e. the "%fs:" segment? > > Followup: > Of course, with --pointercheck=no, I can avoid the %fs prefix. But in this > case, this should be avoided even with --pointercheck=yes, as this is a > STORE instruction generated by the tool. > As LOAD/STORE always does a bound check, there are 3 possibilities: > * I add an extended UCode for this, > * We add LOAD/STORE variants that explicitly do no bound checks, which > can be used by tools. I was thinking of adding CSTORE and CLOAD Uops (meaning either Checked or Client), so that LOAD and STORE can be used on any address. > * Add a flag to LOAD/STORE if a boundcheck should explicitly avoided. This is an option too, but it seems to be a significant enough difference to allocate a Uop for it. I wonder if tools will ever want to generate FP/SSE instructions? At the moment, they're always checked too. > 1171 done_this_time = (Int)dispatch_ctr_SAVED - (Int)VG_(dispatch_ctr) -1; > 1172 vg_assert(done_this_time >= 0); > > done_this_time should be the number of BB executed in the inner loop, isn't > it? But why the "-1" ? Somehow with "--pointercheck=no", done_this_time can > be -1 the first time, and thus the assertion failed. > So I simply removed the "-1". I think that assert fails if it didn't run even one basic block. That could be seen as a problem because you're not making any progress on your program. But I don't really know what the rationale for the assert is. However, it looks to me like that's a secondary symptom of some other problem. I assume this only happens with your tool, and not the rest. Can you see why it would be exiting the basic block early? Does --trace-signals=yes show any signals being delivered? > Now I get another SEGFAULT crash. Using gdb, I found out that in vg_dispatch.S > there is a check for clo_checkpointer,assuming a integer type, but Bool is a > "unsigned char". Change the 2 checks, e.g. the first check to > > movb VG_(clo_pointercheck), %al > testb %al,%al > > , and valgrind runs fine with --pointercheck=no. > Even my skin runs fine now. That's a bit embarrassing. |
|
From: Josef W. <Jos...@gm...> - 2003-12-19 10:34:12
|
On Friday 19 December 2003 01:26, Jeremy Fitzhardinge wrote:
> On Thu, 2003-12-18 at 12:12, Josef Weidendorfer wrote:
> > On Thursday 18 December 2003 19:17, Josef Weidendorfer wrote:
> > > Where should I allocate space for this flag?
> > > Or better: How to get rid of the permission check, i.e. the "%fs:"
> > > segment?
> > * We add LOAD/STORE variants that explicitly do no bound checks, which
> > can be used by tools.
>
> I was thinking of adding CSTORE and CLOAD Uops (meaning either Checked
> or Client), so that LOAD and STORE can be used on any address.
Seems to be a good idea.
> I wonder if tools will ever want to generate FP/SSE instructions? At
> the moment, they're always checked too.
Isn't there a way in the future to translate FP/SSE instructions which access
memory to also use CLOAD/CSTORE?
> > 1171 done_this_time = (Int)dispatch_ctr_SAVED - (Int)VG(dispatch_ctr)-1;
> > 1172 vg_assert(done_this_time >= 0);
> ...
Strange. I can't reproduce the failed assertion at the moment ;-(
Josef
PS: Can you supply the following patch to let --tracegen start at BB #0 ?
--- vg_translate.c 18 Dec 2003 09:06:08 -0000 1.64
+++ vg_translate.c 19 Dec 2003 10:32:58 -0000
@@ -2386,7 +2386,7 @@
notrace_until_limit to be the number of translations to be made
before --trace-codegen= style printing takes effect. */
notrace_until_done
- = VG_(overall_in_count) > notrace_until_limit;
+ = VG_(overall_in_count) >= notrace_until_limit;
seg = VG_(find_segment)(orig_addr);
|
|
From: Jeremy F. <je...@go...> - 2003-12-19 17:21:15
|
On Fri, 2003-12-19 at 02:34, Josef Weidendorfer wrote: > Isn't there a way in the future to translate FP/SSE instructions which access > memory to also use CLOAD/CSTORE? At the moment, FP memory operations are done with FPU_R/FPU_W; MMX and SSE have equivalent Uops. I think it's unlikely we'll start pulling those instructions apart to the extent that we'll end up generating LOAD/STORE for them. But it only matters if a tool actually wants to use FP/MMX/SSE as part of its instrumentation. > PS: Can you supply the following patch to let --tracegen start at BB #0 ? Done. J |
|
From: Jeremy F. <je...@go...> - 2003-12-22 08:49:40
|
CVS commit by fitzhardinge:
Re-add proper support for mremap(). Also, fix a bug in munmap().
A none/tests/mremap.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright]
A none/tests/mremap.stderr.exp 1.1
A none/tests/mremap.stdout.exp 1.1
A none/tests/mremap.vgtest 1.1
M +1 -0 coregrind/vg_include.h 1.162
M +20 -13 coregrind/vg_memory.c 1.46
M +180 -82 coregrind/vg_syscalls.c 1.72
M +4 -0 include/vg_kerneliface.h 1.10
M +3 -1 none/tests/Makefile.am 1.19
--- valgrind/coregrind/vg_include.h #1.161:1.162
@@ -1581,4 +1581,5 @@ extern Addr VG_(find_map_space)(Addr bas
extern Segment *VG_(find_segment)(Addr a);
extern Segment *VG_(next_segment)(Segment *);
+extern Segment *VG_(split_segment)(Addr a);
extern Bool VG_(seg_contains)(const Segment *s, Addr ptr, UInt size);
--- valgrind/coregrind/vg_memory.c #1.45:1.46
@@ -115,6 +115,6 @@ static void freeseg(Segment *s)
}
-/* Split a segment at address a */
-static Segment *split_segment(Addr a)
+/* Split a segment at address a, returning the new segment */
+Segment *VG_(split_segment)(Addr a)
{
Segment *s = VG_(SkipList_Find)(&sk_segments, &a);
@@ -158,4 +158,5 @@ void VG_(unmap_range)(Addr addr, UInt le
Segment *next;
static const Bool debug = False || mem_debug;
+ Addr end = addr+len;
if (len == 0)
@@ -175,4 +176,5 @@ void VG_(unmap_range)(Addr addr, UInt le
s != NULL && s->addr < (addr+len);
s = next) {
+ Addr seg_end = s->addr + s->len;
/* fetch next now in case we end up deleting this segment */
@@ -180,12 +182,17 @@ void VG_(unmap_range)(Addr addr, UInt le
if (debug)
- VG_(printf)("unmap: addr=%p s=%p ->addr=%p len=%d end=%p\n",
- addr, s, s->addr, s->len, s->addr+s->len);
+ VG_(printf)("unmap: addr=%p-%p s=%p ->addr=%p-%p len=%d\n",
+ addr, addr+len, s, s->addr, s->addr+s->len, s->len);
- if (!VG_(seg_overlaps)(s, addr, len))
+ if (!VG_(seg_overlaps)(s, addr, len)) {
+ if (debug)
+ VG_(printf)(" (no overlap)\n");
continue;
+ }
/* 4 cases: */
- if (addr > s->addr && addr < (s->addr + s->len)) {
+ if (addr > s->addr &&
+ addr < seg_end &&
+ end >= seg_end) {
/* this segment's tail is truncated by [addr, addr+len)
-> truncate tail
@@ -195,5 +202,5 @@ void VG_(unmap_range)(Addr addr, UInt le
if (debug)
VG_(printf)(" case 1: s->len=%d\n", s->len);
- } else if (addr <= s->addr && (addr+len) >= (s->addr + s->len)) {
+ } else if (addr <= s->addr && end >= seg_end) {
/* this segment is completely contained within [addr, addr+len)
-> delete segment
@@ -205,5 +212,5 @@ void VG_(unmap_range)(Addr addr, UInt le
if (debug)
VG_(printf)(" case 2: s==%p deleted\n", s);
- } else if ((addr+len) > s->addr && (addr+len) < (s->addr+s->len)) {
+ } else if (addr <= s->addr && end > s->addr && end < seg_end) {
/* this segment's head is truncated by [addr, addr+len)
-> truncate head
@@ -217,5 +224,5 @@ void VG_(unmap_range)(Addr addr, UInt le
if (debug)
VG_(printf)(" case 3: s->addr=%p s->len=%d delta=%d\n", s->addr, s->len, delta);
- } else if (addr > s->addr && (addr+len) < (s->addr + s->len)) {
+ } else if (addr > s->addr && end < seg_end) {
/* [addr, addr+len) is contained within a single segment
-> split segment into 3, delete middle portion
@@ -223,6 +230,6 @@ void VG_(unmap_range)(Addr addr, UInt le
Segment *middle, *rs;
- middle = split_segment(addr);
- split_segment(addr+len);
+ middle = VG_(split_segment)(addr);
+ VG_(split_segment)(addr+len);
vg_assert(middle->addr == addr);
@@ -456,6 +463,6 @@ void VG_(mprotect_range)(Addr a, UInt le
vg_assert((len & (VKI_BYTES_PER_PAGE-1)) == 0);
- split_segment(a);
- split_segment(a+len);
+ VG_(split_segment)(a);
+ VG_(split_segment)(a+len);
for(s = VG_(SkipList_Find)(&sk_segments, &a);
--- valgrind/coregrind/vg_syscalls.c #1.71:1.72
@@ -118,4 +118,40 @@ static void do_atfork_child(ThreadId tid
}
+/* return true if address range entirely contained within client
+ address space */
+static Bool valid_client_addr(Addr start, UInt size, ThreadId tid, const Char *syscall)
+{
+ Addr end = start+size;
+ Addr cl_base = VG_(client_base);
+ Bool ret;
+
+ if (size == 0)
+ return True;
+
+ if (cl_base < 0x10000)
+ cl_base = 0x10000;
+
+ ret =
+ (end >= start) &&
+ start >= cl_base && start < VG_(client_end) &&
+ (end <= VG_(client_end));
+
+ if (0)
+ VG_(printf)("%s: test=%p-%p client=%p-%p ret=%d\n",
+ syscall, start, end, cl_base, VG_(client_end), ret);
+
+ if (!ret && syscall != NULL) {
+ VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried to modify addresses %p-%p",
+ syscall, start, end);
+
+ if (VG_(clo_verbosity) > 1) {
+ ExeContext *ec = VG_(get_ExeContext)(tid);
+ VG_(pp_ExeContext)(ec);
+ }
+ }
+
+ return ret;
+}
+
/* ---------------------------------------------------------------------
Doing mmap, munmap, mremap, mprotect
@@ -163,7 +199,7 @@ void mmap_segment ( Addr a, UInt len, UI
VG_(map_fd_segment)(a, len, prot, flags, fd, offset, NULL);
- rr = prot & PROT_READ;
- ww = prot & PROT_WRITE;
- xx = prot & PROT_EXEC;
+ rr = prot & VKI_PROT_READ;
+ ww = prot & VKI_PROT_WRITE;
+ xx = prot & VKI_PROT_EXEC;
VG_TRACK( new_mem_mmap, a, len, rr, ww, xx );
@@ -196,7 +232,7 @@ void mprotect_segment ( Addr a, UInt len
VG_(mprotect_range)(a, len, prot);
- rr = prot & PROT_READ;
- ww = prot & PROT_WRITE;
- xx = prot & PROT_EXEC;
+ rr = prot & VKI_PROT_READ;
+ ww = prot & VKI_PROT_WRITE;
+ xx = prot & VKI_PROT_EXEC;
// if removing exe permission, should check and remove from exe_seg list
@@ -208,32 +244,137 @@ void mprotect_segment ( Addr a, UInt len
static
-void mremap_segment ( Addr old_addr, UInt old_size, Addr new_addr,
- UInt new_size )
+Addr mremap_segment ( Addr old_addr, UInt old_size,
+ Addr new_addr, UInt new_size,
+ UInt flags, ThreadId tid)
{
- /* If the block moves, assume new and old blocks can't overlap; seems to
- * be valid judging from Linux kernel code in mm/mremap.c */
- vg_assert(old_addr == new_addr ||
- old_addr+old_size < new_addr ||
- new_addr+new_size < old_addr);
+ Addr ret;
+ Segment *seg, *next;
- if (new_size < old_size) {
- // if exe_seg
- // unmap old symbols from old_addr+new_size..old_addr+new_size
- // update exe_seg size = new_size
- // update exe_seg addr = new_addr...
- VG_TRACK( copy_mem_remap, old_addr, new_addr, new_size );
- VG_TRACK( die_mem_munmap, old_addr+new_size, old_size-new_size );
+ old_size = PGROUNDUP(old_size);
+ new_size = PGROUNDUP(new_size);
+
+ if (PGROUNDDN(old_addr) != old_addr)
+ return -VKI_EINVAL;
+
+ if (!valid_client_addr(old_addr, old_size, tid, "mremap(old_addr)"))
+ return -VKI_EFAULT;
+
+ /* fixed at the current address means we don't move it */
+ if ((flags & VKI_MREMAP_FIXED) && (old_addr == new_addr))
+ flags &= ~(VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE);
+
+ if (flags & VKI_MREMAP_FIXED) {
+ if (PGROUNDDN(new_addr) != new_addr)
+ return -VKI_EINVAL;
+
+ if (!valid_client_addr(new_addr, new_size, tid, "mremap(new_addr)"))
+ return -VKI_ENOMEM;
+
+ /* check for overlaps */
+ if ((old_addr < (new_addr+new_size) &&
+ (old_addr+old_size) > new_addr) ||
+ (new_addr < (old_addr+new_size) &&
+ (new_addr+new_size) > old_addr))
+ return -VKI_EINVAL;
+ }
+
+ /* Do nothing */
+ if (!(flags & VKI_MREMAP_FIXED) && new_size == old_size)
+ return old_addr;
+
+ seg = VG_(find_segment)(old_addr);
+
+ /* range must be contained within segment */
+ if (seg == NULL || !VG_(seg_contains)(seg, old_addr, old_size))
+ return -VKI_EINVAL;
+
+ next = VG_(next_segment)(seg);
+
+ if (0)
+ VG_(printf)("mremap: old_addr+new_size=%p next->addr=%p flags=%d\n",
+ old_addr+new_size, next->addr, flags);
+
+ if ((flags & VKI_MREMAP_FIXED) ||
+ (next != NULL && (old_addr+new_size) > next->addr)) {
+ /* we're moving the block */
+ Addr a;
+
+ if ((flags & (VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE)) == 0)
+ return -VKI_ENOMEM; /* not allowed to move */
+
+ if ((flags & VKI_MREMAP_FIXED) == 0)
+ new_addr = 0;
+
+ a = VG_(find_map_space)(new_addr, new_size, True);
+
+ if ((flags & VKI_MREMAP_FIXED) && a != new_addr)
+ return -VKI_ENOMEM; /* didn't find the place we wanted */
+
+ new_addr = a;
+ ret = a;
+ /* we've nailed down the location */
+ flags |= VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE;
+
+ ret = VG_(do_syscall)(__NR_mremap, old_addr, old_size, new_size,
+ flags, new_addr);
+
+ if (ret != new_addr) {
+ vg_assert(VG_(is_kerror)(ret));
+ return ret;
+ }
+
+ VG_TRACK(copy_mem_remap, old_addr, new_addr,
+ (old_size < new_size) ? old_size : new_size);
+
+ if (new_size > old_size)
+ VG_TRACK(new_mem_mmap, new_addr+old_size, new_size-old_size,
+ seg->prot & VKI_PROT_READ,
+ seg->prot & VKI_PROT_WRITE,
+ seg->prot & VKI_PROT_EXEC);
+ VG_TRACK(die_mem_munmap, old_addr, old_size);
+
+ VG_(map_file_segment)(new_addr, new_size,
+ seg->prot,
+ seg->flags,
+ seg->dev, seg->ino,
+ seg->offset, seg->filename);
+
+ VG_(munmap)((void *)old_addr, old_size);
} else {
- // if exe_seg
- // map new symbols from new_addr+old_size..new_addr+new_size
- // update exe_seg size = new_size
- // update exe_seg addr = new_addr...
- VG_TRACK( copy_mem_remap, old_addr, new_addr, old_size );
- // what should the permissions on the new extended part be??
- // using 'rwx'
- VG_TRACK( new_mem_mmap, new_addr+old_size, new_size-old_size,
- True, True, True );
+ /* staying in place */
+ ret = old_addr;
+
+ if (new_size < old_size) {
+ VG_TRACK(die_mem_munmap, old_addr+new_size, old_size-new_size);
+ VG_(munmap)((void *)(old_addr+new_size), old_size-new_size);
+ } else {
+ /* we've nailed down the location */
+ flags &= ~VKI_MREMAP_MAYMOVE;
+
+ if (0)
+ VG_(printf)("mremap: old_addr=%p old_size=%d new_size=%d flags=%d\n",
+ old_addr, old_size, new_size, flags);
+
+ ret = VG_(do_syscall)(__NR_mremap, old_addr, old_size, new_size,
+ flags, 0);
+
+ if (ret != old_addr)
+ return ret;
+
+ VG_TRACK(new_mem_mmap, old_addr+old_size, new_size-old_size,
+ seg->prot & VKI_PROT_READ,
+ seg->prot & VKI_PROT_WRITE,
+ seg->prot & VKI_PROT_EXEC);
+
+ VG_(map_file_segment)(old_addr+old_size, new_size-old_size,
+ seg->prot,
+ seg->flags,
+ seg->dev, seg->ino,
+ seg->offset, seg->filename);
}
+ }
+
+ return ret;
}
@@ -847,40 +988,4 @@ static Addr do_brk(Addr newbrk)
-/* return true if address range entirely contained within client
- address space */
-static Bool valid_client_addr(Addr start, UInt size, ThreadId tid, const Char *syscall)
-{
- Addr end = start+size;
- Addr cl_base = VG_(client_base);
- Bool ret;
-
- if (size == 0)
- return True;
-
- if (cl_base < 0x10000)
- cl_base = 0x10000;
-
- ret =
- (end >= start) &&
- start >= cl_base && start < VG_(client_end) &&
- (end <= VG_(client_end));
-
- if (0)
- VG_(printf)("%s: test=%p-%p client=%p-%p ret=%d\n",
- syscall, start, end, cl_base, VG_(client_end), ret);
-
- if (!ret && syscall != NULL) {
- VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried to modify addresses %p-%p",
- syscall, start, end);
-
- if (VG_(clo_verbosity) > 1) {
- ExeContext *ec = VG_(get_ExeContext)(tid);
- VG_(pp_ExeContext)(ec);
- }
- }
-
- return ret;
-}
-
/* ---------------------------------------------------------------------
Vet file descriptors for sanity
@@ -1365,13 +1470,9 @@ PRE(mremap)
{
/* void* mremap(void * old_address, size_t old_size,
- size_t new_size, unsigned long flags); */
- MAYBE_PRINTF("mremap ( %p, %d, %d, 0x%x )\n",
- arg1, arg2, arg3, arg4);
- SYSCALL_TRACK( pre_mem_write, tid, "mremap(old_address)", arg1, arg2 );
-}
+ size_t new_size, unsigned long flags, void * new_address); */
+ MAYBE_PRINTF("mremap ( %p, %d, %d, 0x%x, %p )\n",
+ arg1, arg2, arg3, arg4, arg5);
-POST(mremap)
-{
- mremap_segment( arg1, arg2, (Addr)res, arg3 );
+ res = mremap_segment((Addr)arg1, arg2, (Addr)arg5, arg3, arg4, tid);
}
@@ -2381,4 +2482,6 @@ PRE(ipc)
}
case 22: /* IPCOP_shmdt */
+ if (!valid_client_addr(arg1, 1, tid, "shmdt"))
+ res = -VKI_EINVAL;
break;
case 23: /* IPCOP_shmget */
@@ -2518,12 +2621,7 @@ POST(ipc)
case 22: /* IPCOP_shmdt */
{
- /* ### FIXME: this should call make_noaccess on the
- * area passed to shmdt. But there's no way to
- * figure out the size of the shared memory segment
- * just from the address... Maybe we want to keep a
- * copy of the exiting mappings inside valgrind? */
Segment *s = VG_(find_segment)(arg1);
- if (s->addr == arg1 && (s->flags & SF_SHM)) {
+ if (s != NULL && (s->flags & SF_SHM) && VG_(seg_contains)(s, arg1, 1)) {
VG_TRACK( die_mem_munmap, s->addr, s->len );
VG_(unmap_range)(s->addr, s->len);
@@ -4782,4 +4880,5 @@ static const struct sys_info special_sys
SYSB_(brk, False),
SYSB_(mmap, False),
+ SYSB_(mremap, False),
#if SIGNAL_SIMULATION
@@ -4829,5 +4928,4 @@ static const struct sys_info sys_info[]
SYSB_(chroot, False),
SYSB_(madvise, True),
- SYSBA(mremap, False),
SYSB_(nice, False),
SYSB_(setresgid32, False),
--- valgrind/include/vg_kerneliface.h #1.9:1.10
@@ -317,4 +317,8 @@ struct vki_ucontext {
#define VKI_MAP_CLIENT 0x80000000 /* internal pseudo-flag to distinguish client mappings */
+/* linux/mman.h */
+#define VKI_MREMAP_MAYMOVE 1
+#define VKI_MREMAP_FIXED 2
+
/* Copied from linux-2.4.19/include/asm-i386/fcntl.h */
--- valgrind/none/tests/Makefile.am #1.18:1.19
@@ -24,4 +24,5 @@
gxx304.stderr.exp gxx304.vgtest \
map_unmap.stdout.exp map_unmap.vgtest \
+ mremap.stdout.exp mremap.vgtest \
munmap_exe.stderr.exp munmap_exe.vgtest \
pth_blockedsig.stderr.exp \
@@ -43,5 +44,5 @@
args bitfield1 bt_everything bt_literal coolo_strlen \
cpuid dastest discard floored fork fpu_lazy_eflags \
- fucomip munmap_exe map_unmap rcl_assert \
+ fucomip munmap_exe map_unmap mremap rcl_assert \
rcrl readline1 resolv seg_override sha1_test shortpush shorts smc1 \
pth_blockedsig \
@@ -66,4 +67,5 @@
fucomip_SOURCES = fucomip.c
map_unmap_SOURCES = map_unmap.c
+mremap_SOURCES = mremap.c
munmap_exe_SOURCES = munmap_exe.c
rcl_assert_SOURCES = rcl_assert.S
|
|
From: Jeremy F. <je...@go...> - 2003-12-22 10:58:38
|
CVS commit by fitzhardinge:
Fixed munmap bug - split_segment wasn't updating the lengths properly.
Turn off debug printing.
M +15 -14 coregrind/vg_memory.c 1.48
M +17 -5 none/tests/map_unmap.c 1.2 [POSSIBLY UNSAFE: printf,system]
--- valgrind/coregrind/vg_memory.c #1.47:1.48
@@ -142,4 +142,5 @@ Segment *VG_(split_segment)(Addr a)
ns->offset += delta;
ns->len -= delta;
+ s->len = delta;
if (s->filename != NULL)
@@ -160,5 +161,5 @@ void VG_(unmap_range)(Addr addr, UInt le
Segment *s;
Segment *next;
- static const Bool debug = True || mem_debug;
+ static const Bool debug = False || mem_debug;
Addr end;
@@ -207,22 +208,12 @@ void VG_(unmap_range)(Addr addr, UInt le
if (debug)
VG_(printf)(" case 1: s->len=%d\n", s->len);
- } else if (addr <= s->addr && end >= seg_end) {
- /* this segment is completely contained within [addr, addr+len)
- -> delete segment
- */
- Segment *rs = VG_(SkipList_Remove)(&sk_segments, &s->addr);
- vg_assert(rs == s);
- freeseg(s);
-
- if (debug)
- VG_(printf)(" case 2: s==%p deleted\n", s);
} else if (addr <= s->addr && end > s->addr && end < seg_end) {
/* this segment's head is truncated by [addr, addr+len)
-> truncate head
*/
- Int delta = (addr+len) - s->addr;
+ Int delta = end - s->addr;
if (debug)
- VG_(printf)(" case 3: s->addr=%p s->len=%d delta=%d\n", s->addr, s->len, delta);
+ VG_(printf)(" case 2: s->addr=%p s->len=%d delta=%d\n", s->addr, s->len, delta);
s->addr += delta;
@@ -231,4 +222,14 @@ void VG_(unmap_range)(Addr addr, UInt le
vg_assert(s->len != 0);
+ } else if (addr <= s->addr && end >= seg_end) {
+ /* this segment is completely contained within [addr, addr+len)
+ -> delete segment
+ */
+ Segment *rs = VG_(SkipList_Remove)(&sk_segments, &s->addr);
+ vg_assert(rs == s);
+ freeseg(s);
+
+ if (debug)
+ VG_(printf)(" case 3: s==%p deleted\n", s);
} else if (addr > s->addr && end < seg_end) {
/* [addr, addr+len) is contained within a single segment
@@ -489,7 +490,7 @@ void VG_(mprotect_range)(Addr a, UInt le
Addr VG_(find_map_space)(Addr addr, UInt len, Bool for_client)
{
+ static const Bool debug = False || mem_debug;
Segment *s;
Addr ret;
- static const Bool debug = False || mem_debug;
Addr limit = (for_client ? VG_(client_end) : VG_(valgrind_mmap_end));
--- valgrind/none/tests/map_unmap.c #1.1:1.2
@@ -27,7 +27,8 @@ static void nibblemap(void *p)
int i;
- off = (random() & ~0x1fff) % LEN;
+ off = (random() % LEN) & ~(pagesize-1);
for(i = 0; i < PAGES; i++) {
+ /* printf("unmapping off=%d\n", off/pagesize); */
munmap((char *)p + off, pagesize);
off += 619*pagesize;
@@ -36,4 +37,12 @@ static void nibblemap(void *p)
}
+static void prmaps()
+{
+ char buf[100];
+ sprintf(buf, "/bin/cat /proc/%d/maps", getpid());
+ system(buf);
+ exit(1);
+}
+
int main()
{
@@ -52,12 +62,14 @@ int main()
m1 = domap();
if (m1 != expect1) {
- printf("FAIL: m=%p expect=%p\n",
- m1, expect1);
+ printf("FAIL i=%d: m1=%p expect1=%p\n",
+ i, m1, expect1);
+ prmaps();
return 1;
}
m2 = domap();
if (m2 != expect2) {
- printf("FAIL: m=%p expect=%p\n",
- m2, expect2);
+ printf("FAIL i=%d: m2=%p expect2=%p\n",
+ i, m2, expect2);
+ prmaps();
return 1;
}
|
|
From: Jeremy F. <je...@go...> - 2004-01-16 02:16:19
|
CVS commit by fitzhardinge:
Fix bug 72650. Only restart syscalls on signal if the client asked for it.
A none/tests/syscall-restart1.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright]
A none/tests/syscall-restart1.stderr.exp 1.1
A none/tests/syscall-restart1.stdout.exp 1.1
A none/tests/syscall-restart1.vgtest 1.1
A none/tests/syscall-restart2.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright]
A none/tests/syscall-restart2.stderr.exp 1.1
A none/tests/syscall-restart2.stdout.exp 1.1
A none/tests/syscall-restart2.vgtest 1.1
M +2 -2 coregrind/vg_include.h 1.168
M +13 -13 coregrind/vg_proxylwp.c 1.12
M +1 -1 coregrind/vg_scheduler.c 1.136
M +5 -15 coregrind/vg_signals.c 1.57
M +37 -18 coregrind/vg_syscalls.c 1.77
M +5 -0 none/tests/Makefile.am 1.20
--- valgrind/none/tests/Makefile.am #1.19:1.20
@@ -39,4 +39,6 @@
shorts.stderr.exp shorts.vgtest \
smc1.stderr.exp smc1.stdout.exp smc1.vgtest \
+ syscall-restart1.vgtest syscall-restart1.stdout.exp syscall-restart1.stderr.exp \
+ syscall-restart2.vgtest syscall-restart2.stdout.exp syscall-restart2.stderr.exp \
yield.stdout.exp yield.vgtest
@@ -47,4 +49,5 @@
rcrl readline1 resolv seg_override sha1_test shortpush shorts smc1 \
pth_blockedsig \
+ syscall-restart1 syscall-restart2 \
coolo_sigaction gxx304 yield
@@ -78,4 +81,6 @@
shortpush_SOURCES = shortpush.c
shorts_SOURCES = shorts.c
+syscall_restart1_SOURCES = syscall-restart1.c
+syscall_restart2_SOURCES = syscall-restart2.c
yield_SOURCES = yield.c
yield_LDADD = -lpthread
--- valgrind/coregrind/vg_proxylwp.c #1.11:1.12
@@ -181,5 +181,5 @@ struct ProxyLWP {
};
-static void sys_wait_results(Bool block, ThreadId tid, enum RequestType reqtype);
+static void sys_wait_results(Bool block, ThreadId tid, enum RequestType reqtype, Bool restart);
struct PX_Request {
@@ -842,7 +842,7 @@ void VG_(proxy_sendsig)(ThreadId tid, In
syscall to dinish. */
if (tst->status == VgTs_WaitSys && tst->syscallno == __NR_rt_sigtimedwait)
- sys_wait_results(True, tid, PX_RunSyscall);
+ sys_wait_results(True, tid, PX_RunSyscall, True);
else
- sys_wait_results(True, tid, PX_Signal);
+ sys_wait_results(True, tid, PX_Signal, True);
}
}
@@ -867,5 +867,5 @@ void VG_(proxy_abort_syscall)(ThreadId t
VG_(ktkill)(lwp, VKI_SIGVGINT);
- sys_wait_results(True, tid, PX_RunSyscall);
+ sys_wait_results(True, tid, PX_RunSyscall, False);
vg_assert(tst->status == VgTs_Runnable);
@@ -1064,5 +1064,5 @@ void VG_(proxy_delete)(ThreadId tid, Boo
may be blocked writing to it, causing a deadlock with us as we
wait for it to exit. */
- sys_wait_results(True, tid, PX_Exiting);
+ sys_wait_results(True, tid, PX_Exiting, True);
res = proxy_wait(proxy, True, &status);
@@ -1092,5 +1092,5 @@ void VG_(proxy_delete)(ThreadId tid, Boo
wait for a reply for that particular tid.
*/
-static void sys_wait_results(Bool block, ThreadId tid, enum RequestType reqtype)
+static void sys_wait_results(Bool block, ThreadId tid, enum RequestType reqtype, Bool restart)
{
Bool found_reply = (reqtype == PX_BAD);
@@ -1154,5 +1154,5 @@ static void sys_wait_results(Bool block,
vg_assert(tst->status == VgTs_WaitSys);
- VG_(post_syscall)(res.tid);
+ VG_(post_syscall)(res.tid, restart);
break;
@@ -1188,8 +1188,8 @@ static void sys_wait_results(Bool block,
void VG_(proxy_results)(void)
{
- sys_wait_results(False, 0, PX_BAD);
+ sys_wait_results(False, 0, PX_BAD, True);
}
-void VG_(proxy_wait_sys)(ThreadId tid)
+void VG_(proxy_wait_sys)(ThreadId tid, Bool restart)
{
ThreadState *tst = VG_(get_ThreadState)(tid);
@@ -1197,5 +1197,5 @@ void VG_(proxy_wait_sys)(ThreadId tid)
vg_assert(tst->status == VgTs_WaitSys);
- sys_wait_results(True, tid, PX_RunSyscall);
+ sys_wait_results(True, tid, PX_RunSyscall, restart);
}
@@ -1227,5 +1227,5 @@ void VG_(proxy_setsigmask)(ThreadId tid)
updates their signal masks, A's update must be done before B's
is). */
- sys_wait_results(True, tid, PX_SetSigmask);
+ sys_wait_results(True, tid, PX_SetSigmask, True);
}
@@ -1272,5 +1272,5 @@ void VG_(proxy_waitsig)(void)
VG_(route_signals)();
else
- sys_wait_results(True, VG_INVALID_THREADID /* any */, PX_Signal);
+ sys_wait_results(True, VG_INVALID_THREADID /* any */, PX_Signal, True);
}
@@ -1365,5 +1365,5 @@ void VG_(proxy_sanity)(void)
sane = False;
}
- sys_wait_results(True, tid, PX_Ping);
+ sys_wait_results(True, tid, PX_Ping, True);
/* Can't make an assertion here, fortunately; this will
either come back or it won't. */
--- valgrind/coregrind/vg_signals.c #1.56:1.57
@@ -1448,20 +1448,10 @@ void VG_(deliver_signal) ( ThreadId tid,
results right now, so wait for them to appear. This makes
the thread runnable again, so we're in the right state to run
- the handler, and resume the syscall when we're done. */
- VG_(proxy_wait_sys)(tid);
-
+ the handler. We ask post_syscall to restart based on the
+ client's sigaction flags. */
if (0)
- VG_(printf)("signal %d interrupting syscall %d\n",
- sigNo, tst->syscallno);
-
- if (tst->m_eax == -VKI_ERESTARTSYS) {
- if (handler->scss_flags & VKI_SA_RESTART) {
- VG_(restart_syscall)(tid);
- } else
- tst->m_eax = -VKI_EINTR;
- } else {
- /* return value is already in eax - either EINTR or the
- normal return value */
- }
+ VG_(printf)("signal %d interrupted syscall %d; restart=%d\n",
+ sigNo, tst->syscallno, !!(handler->scss_flags & VKI_SA_RESTART));
+ VG_(proxy_wait_sys)(tid, !!(handler->scss_flags & VKI_SA_RESTART));
}
--- valgrind/coregrind/vg_include.h #1.167:1.168
@@ -1608,5 +1608,5 @@ extern void VG_(proxy_sigack) ( Thread
extern void VG_(proxy_abort_syscall) ( ThreadId tid );
extern void VG_(proxy_waitsig) ( void );
-extern void VG_(proxy_wait_sys) (ThreadId tid);
+extern void VG_(proxy_wait_sys) (ThreadId tid, Bool restart);
extern void VG_(proxy_shutdown) ( void ); /* shut down the syscall workers */
@@ -1631,5 +1631,5 @@ extern Char *VG_(resolve_filename)(Int f
extern Bool VG_(pre_syscall) ( ThreadId tid );
-extern void VG_(post_syscall)( ThreadId tid );
+extern void VG_(post_syscall)( ThreadId tid, Bool restart );
extern void VG_(restart_syscall) ( ThreadId tid );
--- valgrind/coregrind/vg_scheduler.c #1.135:1.136
@@ -700,5 +700,5 @@ void sched_do_syscall ( ThreadId tid )
/* If pre_syscall returns true, then we're done immediately */
if (VG_(pre_syscall)(tid)) {
- VG_(post_syscall(tid));
+ VG_(post_syscall(tid, True));
vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
} else {
--- valgrind/coregrind/vg_syscalls.c #1.76:1.77
@@ -5243,5 +5243,5 @@ Bool VG_(pre_syscall) ( ThreadId tid )
-void VG_(post_syscall) ( ThreadId tid )
+void VG_(post_syscall) ( ThreadId tid, Bool restart )
{
ThreadState* tst;
@@ -5249,4 +5249,5 @@ void VG_(post_syscall) ( ThreadId tid )
const struct sys_info *sys;
Bool special = False;
+ Bool restarted = False;
void *pre_res;
@@ -5273,8 +5274,34 @@ void VG_(post_syscall) ( ThreadId tid )
}
+ if (tst->m_eax == -VKI_ERESTARTSYS) {
+ /* Applications never expect to see this, so we should either
+ restart the syscall or fail it with EINTR, depending on what
+ our caller wants. Generally they'll want to restart, but if
+ client set the signal state to not restart, then we fail with
+ EINTR. Either way, ERESTARTSYS means the syscall made no
+ progress, and so can be failed or restarted without
+ consequence. */
+ if (0)
+ VG_(printf)("syscall %d returned ERESTARTSYS; restart=%d\n",
+ syscallno, restart);
+
+ if (restart) {
+ restarted = True;
+ VG_(restart_syscall)(tid);
+ } else
+ tst->m_eax = -VKI_EINTR;
+ }
+
+ if (!restarted) {
if (!VG_(is_kerror)(tst->m_eax) && sys->after != NULL)
(sys->after)(tst->tid, tst);
- /* Do any post-syscall actions */
+ /* Do any post-syscall actions
+
+ NOTE: this is only called if the syscall completed. If the
+ syscall was restarted, then it will call the Tool's
+ pre_syscall again, without calling post_syscall (ie, more
+ pre's than post's)
+ */
if (VG_(needs).syscall_wrapper) {
VGP_PUSHCC(VgpSkinSysWrap);
@@ -5282,16 +5309,8 @@ void VG_(post_syscall) ( ThreadId tid )
VGP_POPCC(VgpSkinSysWrap);
}
-
- if (tst->m_eax == -VKI_ERESTARTSYS) {
- /* Applications never expect to see this, so we should actually
- restart the syscall (it means the signal happened before the
- syscall made any progress, so we can safely restart it and
- pretend the signal happened before the syscall even
- started) */
- VG_(restart_syscall)(tid);
}
tst->status = VgTs_Runnable; /* runnable again */
- tst->syscallno = -1;
+ tst->syscallno = -1; /* no current syscall */
VGP_POPCC(VgpCoreSysWrap);
|
|
From: Nicholas N. <nj...@ca...> - 2004-01-20 09:27:24
|
CVS commit by nethercote: Adding files from Tom Hughes' SSE-completion patch, which I forgot yesterday. A none/tests/gen_insn_test.pl 1.1 A none/tests/insn_mmx.def 1.1 A none/tests/insn_mmx.stderr.exp 1.1 A none/tests/insn_mmx.stdout.exp 1.1 A none/tests/insn_mmx.vgtest 1.1 A none/tests/insn_sse.def 1.1 A none/tests/insn_sse.stderr.exp 1.1 A none/tests/insn_sse.stdout.exp 1.1 A none/tests/insn_sse.vgtest 1.1 A none/tests/insn_sse2.def 1.1 A none/tests/insn_sse2.stderr.exp 1.1 A none/tests/insn_sse2.stdout.exp 1.1 A none/tests/insn_sse2.vgtest 1.1 A tests/cputest.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright] |
|
From: Jeremy F. <je...@go...> - 2004-01-21 01:28:04
|
CVS commit by fitzhardinge:
This change implements the TLS extension to the x86 ABI. This allows
threads to have thread-private data which is quickly accessible via a
segment in the GDT, stored in %gs. The patch implements the relevent
syscalls (setthreadarea), and also manages switching the VCPU's segment
information at thread context-switch time. Mostly Tom Hughes' work.
A none/tests/tls.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright]
A none/tests/tls.stderr.exp 1.1
A none/tests/tls.stdout.exp 1.1
A none/tests/tls.vgtest 1.1
A none/tests/tls2.c 1.1 [no copyright]
A none/tests/tls2_so.c 1.1 [no copyright]
A none/tests/tls_so.c 1.1 [no copyright]
M +23 -0 glibc-2.3.supp 1.10
M +1 -1 coregrind/Makefile.am 1.63
M +0 -10 coregrind/stage2.c 1.7
M +15 -0 coregrind/vg_execontext.c 1.15
M +18 -0 coregrind/vg_include.h 1.170
M +120 -24 coregrind/vg_ldt.c 1.12
M +190 -36 coregrind/vg_libpthread.c 1.144
M +6 -1 coregrind/vg_main.c 1.138
M +9 -0 coregrind/vg_proxylwp.c 1.13
M +30 -2 coregrind/vg_scheduler.c 1.137
M +69 -9 coregrind/vg_syscalls.c 1.80
M +13 -0 include/vg_kerneliface.h 1.12
M +14 -1 none/tests/Makefile.am 1.23
M +2 -2 none/tests/seg_override.c 1.2
--- valgrind/glibc-2.3.supp #1.9:1.10
@@ -130,4 +130,9 @@
fun:_dl_runtime_resolve
}
+{
+ _dl_fini
+ Helgrind:Eraser
+ fun:_dl_fini
+}
#-------- Threading bugs?
@@ -192,2 +197,20 @@
obj:/lib/ld-2.3.2.so
}
+
+##----------------------------------------------------------------------##
+## SuSE 9 after FV changes (post 2.1.0)
+
+{
+ strlen/_dl_init_paths/dl_main/_dl_sysdep_start(Cond)
+ Memcheck:Cond
+ fun:strlen
+ fun:_dl_init_paths
+ fun:dl_main
+ fun:_dl_sysdep_start
+}
+
+{
+ Ugly strchr error in /lib/ld-2.3.2.so
+ Memcheck:Cond
+ obj:/lib/ld-2.3.2.so
+}
--- valgrind/coregrind/Makefile.am #1.62:1.63
@@ -109,5 +109,5 @@
libpthread_so_DEPENDENCIES = $(srcdir)/vg_libpthread.vs
libpthread_so_LDFLAGS = -Werror -fno-omit-frame-pointer -UVG_LIBDIR \
- -shared -fpic \
+ -shared -fpic -ldl \
-Wl,-version-script $(srcdir)/vg_libpthread.vs \
-Wl,-z,nodelete \
--- valgrind/coregrind/stage2.c #1.6:1.7
@@ -473,5 +473,4 @@ static void list_tools(void)
1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
- 3. LD_ASSUME_KERNEL=2.4.1
If any of these is missing, then it is added.
@@ -489,11 +488,8 @@ static char **fix_environment(char **ori
static const char ld_preload[] = "LD_PRELOAD=";
static const int ld_preload_len = sizeof(ld_preload)-1;
- static const char ld_assume_kernel[] = "LD_ASSUME_KERNEL=";
- static const int ld_assume_kernel_len = sizeof(ld_assume_kernel)-1;
static const char valgrind_clo[] = VALGRINDCLO "=";
static const char valgrind_clo_len = sizeof(valgrind_clo)-1;
int ld_preload_done = 0;
int ld_library_path_done = 0;
- int ld_assume_kernel_done = 0;
char *inject_path;
int inject_path_len;
@@ -571,7 +567,4 @@ static char **fix_environment(char **ori
ld_preload_done = 1;
- } else if (memcmp(*cpp, ld_assume_kernel, ld_assume_kernel_len) == 0) {
- *cpp = "LD_ASSUME_KERNEL=2.4.1";
- ld_assume_kernel_done = 1;
} else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
*cpp = "";
@@ -601,7 +594,4 @@ static char **fix_environment(char **ori
}
- if (!ld_assume_kernel_done)
- ret[envc++] = "LD_ASSUME_KERNEL=2.4.1";
-
ret[envc] = NULL;
--- valgrind/coregrind/vg_execontext.c #1.14:1.15
@@ -320,4 +320,19 @@ void get_needed_regs(ThreadId tid, Addr*
*stack_highest_word = tst->stack_highest_word;
}
+
+ /* Nasty little hack to deal with sysinfo syscalls - if libc is
+ using the sysinfo page for syscalls (the TLS version does), then
+ eip will always appear to be in that page when doing a syscall,
+ not the actual libc function doing the syscall. This check sees
+ if EIP is within the syscall code, and pops the return address
+ off the stack so that eip is placed within the library function
+ calling the syscall. This makes stack backtraces much more
+ useful. */
+ if (*eip >= VG_(client_trampoline_code)+VG_(tramp_syscall_offset) &&
+ *eip < VG_(client_trampoline_code)+VG_(trampoline_code_length) &&
+ VG_(is_addressable)(*esp, sizeof(Addr))) {
+ *eip = *(Addr *)*esp;
+ *esp += sizeof(Addr);
+ }
}
--- valgrind/coregrind/vg_include.h #1.169:1.170
@@ -625,4 +625,6 @@ extern VgLdtEntry*
extern void
VG_(deallocate_LDT_for_thread) ( VgLdtEntry* ldt );
+extern void
+ VG_(clear_TLS_for_thread) ( VgLdtEntry* tls );
/* Simulate the modify_ldt syscall. */
@@ -630,4 +632,10 @@ extern Int VG_(sys_modify_ldt) ( ThreadI
Int func, void* ptr, UInt bytecount );
+/* Simulate the {get,set}_thread_area syscalls. */
+extern Int VG_(sys_set_thread_area) ( ThreadId tid,
+ struct vki_modify_ldt_ldt_s* info );
+extern Int VG_(sys_get_thread_area) ( ThreadId tid,
+ struct vki_modify_ldt_ldt_s* info );
+
/* Called from generated code. Given a segment selector and a virtual
address, return a linear address, and do limit checks too. */
@@ -804,4 +812,8 @@ typedef
VgLdtEntry* ldt;
+ /* TLS table. This consists of a small number (currently 3) of
+ entries from the Global Descriptor Table. */
+ VgLdtEntry tls[VKI_GDT_TLS_ENTRIES];
+
/* Saved machine context. Note the FPU state, %EIP and segment
registers are not shadowed.
@@ -1623,4 +1635,7 @@ extern void VG_(proxy_handlesig)( const
const struct vki_sigcontext *sigcontext );
+/* Get the PID/TID of the ProxyLWP. */
+extern Int VG_(proxy_id)(ThreadId tid);
+
/* ---------------------------------------------------------------------
@@ -1831,4 +1846,7 @@ extern Int VGOFF_(sh_eflags);
extern Int VGOFF_(ldt);
+/* This thread's TLS pointer. */
+extern Int VGOFF_(tls);
+
/* Nb: Most helper offsets are in include/vg_skin.h, for use by skins */
--- valgrind/coregrind/vg_ldt.c #1.11:1.12
@@ -122,4 +122,22 @@ void VG_(deallocate_LDT_for_thread) ( Vg
+/* Clear a TLS array. */
+void VG_(clear_TLS_for_thread) ( VgLdtEntry* tls )
+{
+ VgLdtEntry* tlsp;
+
+ if (0)
+ VG_(printf)("clear_TLS_for_thread\n" );
+
+ for (tlsp = tls; tlsp < tls + VKI_GDT_TLS_ENTRIES; tlsp++) {
+ tlsp->LdtEnt.Words.word1 = 0;
+ tlsp->LdtEnt.Words.word2 = 0;
+ }
+
+ return;
+}
+
+
+
/* Fish the base field out of an VgLdtEntry. This is the only part we
are particularly interested in. */
@@ -152,7 +170,7 @@ unsigned int wine_ldt_get_limit( const V
Addr VG_(do_useseg) ( UInt seg_selector, Addr virtual_addr )
{
+ UInt table;
Addr base;
UInt limit;
- VgLdtEntry* the_ldt;
if (0)
@@ -162,11 +180,27 @@ Addr VG_(do_useseg) ( UInt seg_selector,
seg_selector &= 0x0000FFFF;
- /* Sanity check the segment selector. Ensure that TI=1 (LDT) and
- that RPL=11b (least privilege). These form the bottom 3 bits
- of the selector. */
- vg_assert((seg_selector & 7) == 7);
+ /* Sanity check the segment selector. Ensure that RPL=11b (least
+ privilege). This forms the bottom 2 bits of the selector. */
+ vg_assert((seg_selector & 3) == 3);
- /* convert it onto a table index */
+ /* Extract the table number */
+ table = (seg_selector & 4) >> 2;
+
+ /* Convert the segment selector onto a table index */
seg_selector >>= 3;
+
+ if (table == 0) {
+ VgLdtEntry* the_tls;
+
+ vg_assert(seg_selector >= VKI_GDT_TLS_MIN && seg_selector < VKI_GDT_TLS_MAX);
+
+ /* Come up with a suitable GDT entry. We look at the thread's TLS
+ array, which is pointed to by a VG_(baseBlock) entry. */
+ the_tls = (VgLdtEntry*)VG_(baseBlock)[VGOFF_(tls)];
+ base = (Addr)wine_ldt_get_base ( &the_tls[seg_selector-VKI_GDT_TLS_MIN] );
+ limit = (UInt)wine_ldt_get_limit ( &the_tls[seg_selector-VKI_GDT_TLS_MIN] );
+ } else {
+ VgLdtEntry* the_ldt;
+
vg_assert(seg_selector >= 0 && seg_selector < 8192);
@@ -188,4 +222,5 @@ Addr VG_(do_useseg) ( UInt seg_selector,
limit = (UInt)wine_ldt_get_limit ( &the_ldt[seg_selector] );
}
+ }
/* Note, this check is just slightly too slack. Really it should
@@ -200,4 +235,8 @@ Addr VG_(do_useseg) ( UInt seg_selector,
}
+ if (0)
+ VG_(printf)("do_useseg: base = %p, addr = %p\n",
+ base, base + virtual_addr);
+
return base + virtual_addr;
}
@@ -368,4 +407,61 @@ Int VG_(sys_modify_ldt) ( ThreadId tid,
+Int VG_(sys_set_thread_area) ( ThreadId tid,
+ struct vki_modify_ldt_ldt_s* info )
+{
+ Int idx = info->entry_number;
+
+ if (idx == -1) {
+ for (idx = 0; idx < VKI_GDT_TLS_ENTRIES; idx++) {
+ VgLdtEntry* tls = VG_(threads)[tid].tls + idx;
+
+ if (tls->LdtEnt.Words.word1 == 0 && tls->LdtEnt.Words.word2 == 0)
+ break;
+ }
+
+ if (idx == VKI_GDT_TLS_ENTRIES)
+ return -VKI_ESRCH;
+ } else if (idx < VKI_GDT_TLS_MIN || idx > VKI_GDT_TLS_MAX) {
+ return -VKI_EINVAL;
+ } else {
+ idx = info->entry_number - VKI_GDT_TLS_MIN;
+ }
+
+ translate_to_hw_format(info, VG_(threads)[tid].tls + idx, 0);
+
+ info->entry_number = idx + VKI_GDT_TLS_MIN;
+
+ return 0;
+}
+
+
+Int VG_(sys_get_thread_area) ( ThreadId tid,
+ struct vki_modify_ldt_ldt_s* info )
+{
+ Int idx = info->entry_number;
+ VgLdtEntry* tls;
+
+ if (idx < VKI_GDT_TLS_MIN || idx > VKI_GDT_TLS_MAX)
+ return -VKI_EINVAL;
+
+ tls = VG_(threads)[tid].tls + idx - VKI_GDT_TLS_MIN;
+
+ info->base_addr = ( tls->LdtEnt.Bits.BaseHi << 24 ) |
+ ( tls->LdtEnt.Bits.BaseMid << 16 ) |
+ tls->LdtEnt.Bits.BaseLow;
+ info->limit = ( tls->LdtEnt.Bits.LimitHi << 16 ) |
+ tls->LdtEnt.Bits.LimitLow;
+ info->seg_32bit = tls->LdtEnt.Bits.Default_Big;
+ info->contents = ( tls->LdtEnt.Bits.Type >> 2 ) & 0x3;
+ info->read_exec_only = ( tls->LdtEnt.Bits.Type & 0x1 ) ^ 0x1;
+ info->limit_in_pages = tls->LdtEnt.Bits.Granularity;
+ info->seg_not_present = tls->LdtEnt.Bits.Pres ^ 0x1;
+ info->useable = tls->LdtEnt.Bits.Sys;
+ info->reserved = 0;
+
+ return 0;
+}
+
+
/*--------------------------------------------------------------------*/
/*--- end vg_ldt.c ---*/
--- valgrind/coregrind/vg_libpthread.c #1.143:1.144
@@ -61,4 +61,8 @@
#undef __USE_UNIX98
+#define __USE_GNU
+#include <dlfcn.h>
+#undef __USE_GNU
+
#include <unistd.h>
#include <string.h>
@@ -108,4 +112,7 @@ int is_kerror ( int res )
static
+void init_thread_specific_state ( void );
+
+static
void init_libc_tsd_keys ( void );
@@ -524,4 +531,36 @@ int pthread_getconcurrency(void)
------------------------------------------------ */
+typedef void *(*__attribute__ ((regparm (3), stdcall)) allocate_tls_t) (void *result);
+typedef void (*__attribute__ ((regparm (3), stdcall)) deallocate_tls_t) (void *tcb, int dealloc_tcb);
+
+static allocate_tls_t allocate_tls = NULL;
+static deallocate_tls_t deallocate_tls = NULL;
+
+static
+int get_gs()
+{
+ int gs;
+
+ asm volatile ("movw %%gs, %w0" : "=q" (gs));
+
+ return gs & 0xffff;
+}
+
+static
+void set_gs( int gs )
+{
+ asm volatile ("movw %w0, %%gs" :: "q" (gs));
+}
+
+static
+void *get_tcb()
+{
+ void *tcb;
+
+ asm volatile ("movl %%gs:0, %0" : "=r" (tcb));
+
+ return tcb;
+}
+
/* All exiting threads eventually pass through here, bearing the
return value, or PTHREAD_CANCELED, in ret_val. */
@@ -571,4 +610,10 @@ void thread_exit_wrapper ( void* ret_val
my_free(specifics_ptr);
+ /* Free up any TLS data */
+ if ((get_gs() & 7) == 3 && pthread_self() > 1) {
+ my_assert(deallocate_tls != NULL);
+ deallocate_tls(get_tcb(), 1);
+ }
+
/* Decide on my final disposition. */
VALGRIND_MAGIC_SEQUENCE(detached, (-1) /* default */,
@@ -602,4 +647,7 @@ typedef
struct {
int attr__detachstate;
+ void* tls_data;
+ int tls_segment;
+ unsigned long sysinfo;
void* (*root_fn) ( void* );
void* arg;
@@ -607,4 +655,14 @@ typedef
NewThreadInfo;
+/* Struct used to describe a TDB header, copied from glibc. */
+typedef
+ struct {
+ void *tcb;
+ void *dtv;
+ void *self;
+ int multiple_threads;
+ unsigned long sysinfo;
+ }
+ tcbhead_t;
/* This is passed to the VG_USERREQ__APPLY_IN_NEW_THREAD and so must
@@ -616,4 +674,7 @@ void thread_wrapper ( NewThreadInfo* inf
{
int attr__detachstate;
+ void* tls_data;
+ int tls_segment;
+ unsigned long sysinfo;
void* (*root_fn) ( void* );
void* arg;
@@ -621,7 +682,39 @@ void thread_wrapper ( NewThreadInfo* inf
attr__detachstate = info->attr__detachstate;
+ tls_data = info->tls_data;
+ tls_segment = info->tls_segment;
+ sysinfo = info->sysinfo;
root_fn = info->root_fn;
arg = info->arg;
+ if (tls_data) {
+ tcbhead_t *tcb = tls_data;
+ struct vki_modify_ldt_ldt_s ldt_info;
+
+ /* Fill in the TCB header */
+ tcb->tcb = tcb;
+ tcb->self = tcb;
+ tcb->multiple_threads = 1;
+ tcb->sysinfo = sysinfo;
+
+ /* Fill in an LDT descriptor */
+ ldt_info.entry_number = tls_segment;
+ ldt_info.base_addr = (unsigned long)tls_data;
+ ldt_info.limit = 0xfffff;
+ ldt_info.seg_32bit = 1;
+ ldt_info.contents = 0;
+ ldt_info.read_exec_only = 0;
+ ldt_info.limit_in_pages = 1;
+ ldt_info.seg_not_present = 0;
+ ldt_info.useable = 1;
+ ldt_info.reserved = 0;
+
+ /* Install the thread area */
+ VG_(do_syscall)(__NR_set_thread_area, &ldt_info);
+
+ /* Setup the GS segment register */
+ set_gs(ldt_info.entry_number * 8 + 3);
+ }
+
/* Free up the arg block that pthread_create malloced. */
my_free(info);
@@ -634,4 +727,7 @@ void thread_wrapper ( NewThreadInfo* inf
pthread_detach(pthread_self());
+ /* Initialise thread specific state */
+ init_thread_specific_state();
+
# ifdef GLIBC_2_3
/* Set this thread's locale to the global (default) locale. A hack
@@ -689,4 +785,5 @@ pthread_create (pthread_t *__restrict __
int tid_child;
NewThreadInfo* info;
+ int gs;
ensure_valgrind("pthread_create");
@@ -706,4 +803,27 @@ pthread_create (pthread_t *__restrict __
info->attr__detachstate = PTHREAD_CREATE_JOINABLE;
+ gs = get_gs();
+
+ if ((gs & 7) == 3) {
+ tcbhead_t *tcb = get_tcb();
+
+ if (allocate_tls == NULL || deallocate_tls == NULL) {
+ allocate_tls = (allocate_tls_t)dlsym(RTLD_DEFAULT, "_dl_allocate_tls");
+ deallocate_tls = (deallocate_tls_t)dlsym(RTLD_DEFAULT, "_dl_deallocate_tls");
+ }
+
+ my_assert(allocate_tls != NULL);
+
+ info->tls_data = allocate_tls(NULL);
+ info->tls_segment = gs >> 3;
+ info->sysinfo = tcb->sysinfo;
+
+ tcb->multiple_threads = 1;
+ } else {
+ info->tls_data = NULL;
+ info->tls_segment = -1;
+ info->sysinfo = 0;
+ }
+
info->root_fn = __start_routine;
info->arg = __arg;
@@ -1620,15 +1740,31 @@ void __pthread_initialize ( void )
#include <resolv.h>
-static int thread_specific_errno[VG_N_THREADS];
-static int thread_specific_h_errno[VG_N_THREADS];
-static struct __res_state
- thread_specific_res_state[VG_N_THREADS];
-#undef errno
-extern int errno;
+typedef
+ struct {
+ int *errno_ptr;
+ int *h_errno_ptr;
+ struct __res_state *res_state_ptr;
+ int errno_data;
+ int h_errno_data;
+ struct __res_state res_state_data;
+ }
+ ThreadSpecificState;
+
+static ThreadSpecificState thread_specific_state[VG_N_THREADS];
+
+static
+void init_thread_specific_state ( void )
+{
+ int tid = pthread_self();
+
+ thread_specific_state[tid].errno_ptr = NULL;
+ thread_specific_state[tid].h_errno_ptr = NULL;
+ thread_specific_state[tid].res_state_ptr = NULL;
+}
+
int* __errno_location ( void )
{
int tid;
- int *ret;
ensure_valgrind("__errno_location");
@@ -1639,14 +1775,15 @@ int* __errno_location ( void )
if (tid < 1 || tid >= VG_N_THREADS)
barf("__errno_location: invalid ThreadId");
- if (tid == 1)
- ret = &errno;
+ if (thread_specific_state[tid].errno_ptr == NULL) {
+ if ((get_gs() & 7) == 3)
+ thread_specific_state[tid].errno_ptr = dlsym(RTLD_DEFAULT, "errno");
+ else if (tid == 1)
+ thread_specific_state[tid].errno_ptr = dlvsym(RTLD_DEFAULT, "errno", "GLIBC_2.0");
else
- ret = &thread_specific_errno[tid];
-
- return ret;
+ thread_specific_state[tid].errno_ptr = &thread_specific_state[tid].errno_data;
+ }
+ return thread_specific_state[tid].errno_ptr;
}
-#undef h_errno
-extern int h_errno;
int* __h_errno_location ( void )
{
@@ -1659,12 +1796,15 @@ int* __h_errno_location ( void )
if (tid < 1 || tid >= VG_N_THREADS)
barf("__h_errno_location: invalid ThreadId");
- if (tid == 1)
- return &h_errno;
- return & thread_specific_h_errno[tid];
+ if (thread_specific_state[tid].h_errno_ptr == NULL) {
+ if ((get_gs() & 7) == 3)
+ thread_specific_state[tid].h_errno_ptr = dlsym(RTLD_DEFAULT, "h_errno");
+ else if (tid == 1)
+ thread_specific_state[tid].h_errno_ptr = dlvsym(RTLD_DEFAULT, "h_errno", "GLIBC_2.0");
+ else
+ thread_specific_state[tid].h_errno_ptr = &thread_specific_state[tid].h_errno_data;
+ }
+ return thread_specific_state[tid].h_errno_ptr;
}
-
-#undef _res
-extern struct __res_state _res;
struct __res_state* __res_state ( void )
{
@@ -1677,7 +1817,16 @@ struct __res_state* __res_state ( void )
if (tid < 1 || tid >= VG_N_THREADS)
barf("__res_state: invalid ThreadId");
- if (tid == 1)
- return & _res;
- return & thread_specific_res_state[tid];
+ if (thread_specific_state[tid].res_state_ptr == NULL) {
+ if ((get_gs() & 7) == 3) {
+ struct __res_state **resp = dlsym(RTLD_DEFAULT, "__resp");
+
+ thread_specific_state[tid].res_state_ptr = *resp;
+ } else if (tid == 1) {
+ thread_specific_state[tid].res_state_ptr = dlvsym(RTLD_DEFAULT, "_res", "GLIBC_2.0");
+ } else {
+ thread_specific_state[tid].res_state_ptr = &thread_specific_state[tid].res_state_data;
+ }
+ }
+ return thread_specific_state[tid].res_state_ptr;
}
@@ -2919,8 +3067,12 @@ weak_alias(pthread_rwlock_trywrlock, __p
-/* I've no idea what these are, but they get called quite a lot.
- Anybody know? */
-
#ifndef __UCLIBC__
+/* These are called as part of stdio to lock the FILE structure for MT
+ programs. Unfortunately, the lock is not always a pthreads lock -
+ the NPTL version uses a lighter-weight lock which uses futex
+ directly (and uses a structure which is smaller than
+ pthread_mutex). So basically, this is completely broken on recent
+ glibcs. */
+
#undef _IO_flockfile
void _IO_flockfile ( _IO_FILE * file )
@@ -2928,4 +3080,5 @@ void _IO_flockfile ( _IO_FILE * file )
pthread_mutex_lock(file->_lock);
}
+strong_alias(_IO_flockfile, __flockfile);
weak_alias(_IO_flockfile, flockfile);
@@ -2935,4 +3088,5 @@ void _IO_funlockfile ( _IO_FILE * file )
pthread_mutex_unlock(file->_lock);
}
+strong_alias(_IO_funlockfile, __funlockfile);
weak_alias(_IO_funlockfile, funlockfile);
#endif
--- valgrind/coregrind/vg_main.c #1.137:1.138
@@ -59,4 +59,5 @@ Int VGOFF_(m_dflag) = INVALID_OFFSET;
Int VGOFF_(m_ssestate) = INVALID_OFFSET;
Int VGOFF_(ldt) = INVALID_OFFSET;
+Int VGOFF_(tls) = INVALID_OFFSET;
Int VGOFF_(m_cs) = INVALID_OFFSET;
Int VGOFF_(m_ss) = INVALID_OFFSET;
@@ -328,6 +329,7 @@ static void vg_init_baseBlock ( void )
);
- /* This thread's LDT pointer, and segment registers. */
+ /* This thread's LDT and TLS pointers, and segment registers. */
VGOFF_(ldt) = alloc_BaB(1);
+ VGOFF_(tls) = alloc_BaB(1);
VGOFF_(m_cs) = alloc_BaB(1);
VGOFF_(m_ss) = alloc_BaB(1);
@@ -449,4 +451,7 @@ static void vg_init_baseBlock ( void )
VG_(baseBlock)[VGOFF_(ldt)] = (UInt)NULL;
+ /* Pretend the root thread has no TLS array for now. */
+ VG_(baseBlock)[VGOFF_(tls)] = (UInt)NULL;
+
/* Initialise shadow regs */
if (VG_(needs).shadow_regs) {
--- valgrind/coregrind/vg_proxylwp.c #1.12:1.13
@@ -1374,4 +1374,13 @@ void VG_(proxy_sanity)(void)
}
+/* Get the PID/TID of the ProxyLWP. */
+Int VG_(proxy_id)(ThreadId tid)
+{
+ ThreadState *tst = VG_(get_ThreadState)(tid);
+ ProxyLWP *proxy = tst->proxy;
+
+ return proxy->lwp;
+}
+
/*--------------------------------------------------------------------*/
/*--- Proxy LWP machinery. vg_proxylwp.c ---*/
--- valgrind/coregrind/vg_scheduler.c #1.136:1.137
@@ -340,4 +340,5 @@ void VG_(load_thread_state) ( ThreadId t
VG_(baseBlock)[VGOFF_(ldt)] = (UInt)VG_(threads)[tid].ldt;
+ VG_(baseBlock)[VGOFF_(tls)] = (UInt)VG_(threads)[tid].tls;
VG_(baseBlock)[VGOFF_(m_cs)] = VG_(threads)[tid].m_cs;
VG_(baseBlock)[VGOFF_(m_ss)] = VG_(threads)[tid].m_ss;
@@ -421,4 +422,17 @@ void VG_(save_thread_state) ( ThreadId t
== (void*)VG_(baseBlock)[VGOFF_(ldt)]);
+ /* We don't copy out the TLS entry, because it can never be changed
+ by the normal actions of the thread, only by the set_thread_area
+ syscall, in which case we will correctly be updating
+ VG_(threads)[tid].tls. This printf happens iff the following
+ assertion fails. */
+ if ((void*)VG_(threads)[tid].tls != (void*)VG_(baseBlock)[VGOFF_(tls)])
+ VG_(printf)("VG_(threads)[%d].tls=%p VG_(baseBlock)[VGOFF_(tls)]=%p\n",
+ tid, (void*)VG_(threads)[tid].tls,
+ (void*)VG_(baseBlock)[VGOFF_(tls)]);
+
+ vg_assert((void*)VG_(threads)[tid].tls
+ == (void*)VG_(baseBlock)[VGOFF_(tls)]);
+
VG_(threads)[tid].m_cs = VG_(baseBlock)[VGOFF_(m_cs)];
VG_(threads)[tid].m_ss = VG_(baseBlock)[VGOFF_(m_ss)];
@@ -470,4 +484,5 @@ void VG_(save_thread_state) ( ThreadId t
/* Fill it up with junk. */
VG_(baseBlock)[VGOFF_(ldt)] = junk;
+ VG_(baseBlock)[VGOFF_(tls)] = junk;
VG_(baseBlock)[VGOFF_(m_cs)] = junk;
VG_(baseBlock)[VGOFF_(m_ss)] = junk;
@@ -539,4 +554,5 @@ void mostly_clear_thread_record ( Thread
vg_assert(tid >= 0 && tid < VG_N_THREADS);
VG_(threads)[tid].ldt = NULL;
+ VG_(clear_TLS_for_thread)(VG_(threads)[tid].tls);
VG_(threads)[tid].tid = tid;
VG_(threads)[tid].status = VgTs_Empty;
@@ -597,4 +613,5 @@ void VG_(scheduler_init) ( void )
vg_tid_currently_in_baseBlock = tid_main;
vg_tid_last_in_baseBlock = tid_main;
+ VG_(baseBlock)[VGOFF_(tls)] = (UInt)VG_(threads)[tid_main].tls;
VG_(save_thread_state) ( tid_main );
@@ -1373,4 +1390,7 @@ void cleanup_after_thread_exited ( Threa
VG_(threads)[tid].ldt = NULL;
+ /* Clear its TLS array. */
+ VG_(clear_TLS_for_thread)( VG_(threads)[tid].tls );
+
/* Not interested in the timeout anymore */
VG_(threads)[tid].awaken_at = 0xFFFFFFFF;
@@ -1859,4 +1879,8 @@ void do__apply_in_new_thread ( ThreadId
}
+ /* Initialise the thread's TLS array */
+ VG_(clear_TLS_for_thread)( VG_(threads)[tid].tls );
+ VG_(baseBlock)[VGOFF_(tls)] = (UInt)VG_(threads)[tid].tls;
+
VG_(save_thread_state)(tid);
vg_tid_last_in_baseBlock = tid;
@@ -2076,6 +2100,10 @@ void do_pthread_mutex_lock( ThreadId tid
if (mutex->__m_count > 0) {
-
- vg_assert(VG_(is_valid_tid)((ThreadId)mutex->__m_owner));
+ if (!VG_(is_valid_tid)((ThreadId)mutex->__m_owner)) {
+ VG_(record_pthread_error)( tid,
+ "pthread_mutex_lock/trylock: mutex has invalid owner");
+ SET_PTHREQ_RETVAL(tid, VKI_EINVAL);
+ return;
+ }
/* Someone has it already. */
--- valgrind/coregrind/vg_syscalls.c #1.79:1.80
@@ -1047,13 +1047,4 @@ PRE(exit)
}
-PRE(clone)
-{
- VG_(unimplemented)
- ("clone(): not supported by Valgrind.\n "
- "We do now support programs linked against\n "
- "libpthread.so, though. Re-run with -v and ensure that\n "
- "you are picking up Valgrind's implementation of libpthread.so.");
-}
-
PRE(ptrace)
{
@@ -1185,4 +1176,31 @@ PRE(modify_ldt)
}
+PRE(set_thread_area)
+{
+ MAYBE_PRINTF("set_thread_area ( %p )\n", arg1);
+
+ SYSCALL_TRACK( pre_mem_read, tid,
+ "set_thread_area(ptr)", arg1,
+ sizeof(struct vki_modify_ldt_ldt_s) );
+
+ /* "do" the syscall ourselves; the kernel never sees it */
+ res = VG_(sys_set_thread_area)( tid, (void *)arg1 );
+}
+
+PRE(get_thread_area)
+{
+ MAYBE_PRINTF("get_thread_area ( %p )\n", arg1);
+ SYSCALL_TRACK( pre_mem_write, tid,
+ "get_thread_area(ptr)", arg1,
+ sizeof(struct vki_modify_ldt_ldt_s) );
+
+ /* "do" the syscall ourselves; the kernel never sees it */
+ res = VG_(sys_get_thread_area)( tid, (void *)arg1 );
+
+ if (!VG_(is_kerror)(res)) {
+ VG_TRACK( post_mem_write, arg1, sizeof(struct vki_modify_ldt_ldt_s) );
+ }
+}
+
PRE(setresgid)
{
@@ -2142,4 +2160,22 @@ POST(fork)
}
+PRE(clone)
+{
+ MAYBE_PRINTF("clone ( %d, %p, %p, %p, %p )\n",arg1,arg2,arg3,arg4,arg5);
+
+ if (arg2 == 0 &&
+ arg1 == (VKI_CLONE_CHILD_CLEARTID|VKI_CLONE_CHILD_SETTID|VKI_SIGCHLD)) {
+ before_fork(tid, tst);
+ res = VG_(do_syscall)(SYSNO, arg1, arg2, arg3, arg4, arg5);
+ after_fork(tid, tst);
+ } else {
+ VG_(unimplemented)
+ ("clone(): not supported by Valgrind.\n "
+ "We do now support programs linked against\n "
+ "libpthread.so, though. Re-run with -v and ensure that\n "
+ "you are picking up Valgrind's implementation of libpthread.so.");
+ }
+}
+
PRE(fsync)
{
@@ -4728,4 +4764,25 @@ PRE(utimes)
}
+PRE(futex)
+{
+ /* int futex(void *futex, int op, int val, const struct timespec *timeout); */
+ MAYBE_PRINTF("futex ( %p, %d, %d, %p, %p )\n", arg1,arg2,arg3,arg4,arg5);
+ SYSCALL_TRACK( pre_mem_read, tid, "futex(futex)", arg1, sizeof(int) );
+ if (arg2 == VKI_FUTEX_WAIT && arg4 != (UInt)NULL)
+ SYSCALL_TRACK( pre_mem_read, tid, "futex(timeout)", arg4,
+ sizeof(struct timespec) );
+ if (arg2 == VKI_FUTEX_REQUEUE)
+ SYSCALL_TRACK( pre_mem_read, tid, "futex(futex2)", arg4, sizeof(int) );
+}
+
+POST(futex)
+{
+ if (!VG_(is_kerror)(res)) {
+ VG_TRACK( post_mem_write, arg1, sizeof(int) );
+ if (arg2 == VKI_FUTEX_FD && VG_(clo_track_fds))
+ record_fd_open(tid, res, NULL);
+ }
+}
+
#define SIGNAL_SIMULATION 1
@@ -4928,4 +4985,6 @@ static const struct sys_info special_sys
SYSB_(modify_ldt, False),
+ SYSB_(set_thread_area, False),
+ SYSB_(get_thread_area, False),
SYSB_(execve, False),
@@ -5127,4 +5186,5 @@ static const struct sys_info sys_info[]
SYSBA(mmap2, False),
SYSBA(clock_gettime, False),
+ SYSBA(futex, True),
/* new signal handling makes these normal blocking syscalls */
--- valgrind/include/vg_kerneliface.h #1.11:1.12
@@ -632,4 +632,5 @@ typedef struct vki_modify_ldt_ldt_s {
unsigned int seg_not_present:1;
unsigned int useable:1;
+ unsigned int reserved:25;
} vki_modify_ldt_t;
@@ -638,4 +639,7 @@ typedef struct vki_modify_ldt_ldt_s {
#define VKI_MODIFY_LDT_CONTENTS_CODE 2
+#define VKI_GDT_TLS_ENTRIES 3
+#define VKI_GDT_TLS_MIN 6
+#define VKI_GDT_TLS_MAX (VKI_GDT_TLS_MIN + VKI_GDT_TLS_ENTRIES)
/* Flags for clone() */
@@ -727,4 +731,13 @@ struct statfs64 {
};
+/*
+ * linux/futex.h
+ */
+
+#define VKI_FUTEX_WAIT 0
+#define VKI_FUTEX_WAKE 1
+#define VKI_FUTEX_FD 2
+#define VKI_FUTEX_REQUEUE 3
+
#endif /* __VG_KERNELIFACE_H */
--- valgrind/none/tests/Makefile.am #1.22:1.23
@@ -43,4 +43,5 @@
shortpush.stderr.exp shortpush.vgtest \
shorts.stderr.exp shorts.vgtest \
+ tls.stderr.exp tls.stdout.exp tls.vgtest \
smc1.stderr.exp smc1.stdout.exp smc1.vgtest \
syscall-restart1.vgtest syscall-restart1.stdout.exp syscall-restart1.stderr.exp \
@@ -54,5 +55,5 @@
munmap_exe map_unmap mremap rcl_assert \
rcrl readline1 resolv seg_override sha1_test shortpush shorts smc1 \
- pth_blockedsig \
+ tls.so tls2.so tls pth_blockedsig \
syscall-restart1 syscall-restart2 \
coolo_sigaction gxx304 yield
@@ -96,7 +97,19 @@
syscall_restart1_SOURCES = syscall-restart1.c
syscall_restart2_SOURCES = syscall-restart2.c
+tls_SOURCES = tls.c tls2.c
+tls_DEPENDENCIES = tls.so
+tls_LDFLAGS = -Wl,-rpath,$(srcdir)
+tls_LDADD = tls.so -lpthread
+tls_so_SOURCES = tls_so.c
+tls_so_LDADD = tls2.so
+tls_so_DEPENDENCIES = tls2.so
+tls_so_LDFLAGS = -Wl,-rpath,$(srcdir) -shared
+tls2_so_SOURCES = tls2_so.c
+tls2_so_LDFLAGS = -shared
yield_SOURCES = yield.c
yield_LDADD = -lpthread
+tls_so.o tls2_so.o: CFLAGS += -fpic
+
# pthread C ones
pth_blockedsig_SOURCES = pth_blockedsig.c
--- valgrind/none/tests/seg_override.c #1.1:1.2
@@ -111,6 +111,6 @@ void ldt_seg_write ( int ldt_entno, unsi
asm volatile("movl %2, %%eax\n\t"
"movl %1, %%edx\n\t"
- "movl %0, %%gs\n\t"
- "movl %%eax, %%gs:(%%edx)\t"
+ "movl %0, %%fs\n\t"
+ "movl %%eax, %%fs:(%%edx)\t"
:
: "r" (7 /* LDT(TI), least privilege */ + (ldt_entno << 3)),
|
|
From: Nicholas N. <nj...@ca...> - 2004-01-24 18:19:26
|
CVS commit by nethercote: Moved stage2.c into vg_main.c. Merged main() and VG_(main)(); VG_(main)() no longer exists. One advantage of this is that global variables/structures needed for communicating between the two can be made local. Also, the order in which things happen has been simplified. This is mostly just a big refactoring. Startup is now a fair bit easier to understand. Dependencies between the various startup stages are fairly well documented in comments. Also, --help and --version now work properly -- eg. --help gives tool-specific help if --tool was specified. There is still some parts where things could be reordered and/or simplified, and where the dependencies aren't clear. These are marked with 'XXX'. One new feature was added: ability to read options from ~/.valgrindrc and ./.valgrindrc. Part of this is support for specifying tool-specific options in the form --toolname:tool-specific-option. M +0 -1 coregrind/Makefile.am 1.64 M +1 -1 coregrind/stage1.c 1.6 M +4 -1 coregrind/ume.c 1.8 M +3 -3 coregrind/ume.h 1.4 M +2 -2 coregrind/vg_dispatch.S 1.16 M +9 -59 coregrind/vg_include.h 1.172 M +2336 -1163 coregrind/vg_main.c 1.140 [POSSIBLY UNSAFE: printf] M +9 -122 coregrind/vg_memory.c 1.51 M +1 -2 coregrind/vg_scheduler.c 1.139 M +64 -3 coregrind/vg_syscalls.c 1.81 M +29 -10 coregrind/docs/coregrind_core.html 1.23 M +1 -7 include/vg_skin.h.base 1.11 |