diff --git a/Makefile.am b/Makefile.am index ccdf027..c4142a4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,8 @@ TOOLS = memcheck \ massif \ lackey \ none \ - helgrind + helgrind \ + mmt EXP_TOOLS = exp-omega \ exp-drd diff --git a/configure b/configure index 1f13ea0..be8d6ec 100755 --- a/configure +++ b/configure @@ -721,13 +721,13 @@ echo X"$0" | /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then + if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi -if test ! -r $srcdir/$ac_unique_file; then +if test ! -r "$srcdir/$ac_unique_file"; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } @@ -736,7 +736,7 @@ if test ! -r $srcdir/$ac_unique_file; then { (exit 1); exit 1; }; } fi fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || +(cd $srcdir && test -r "./$ac_unique_file") 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` @@ -7518,7 +7518,7 @@ fi # -------------------- ok. We're done. -------------------- - ac_config_files="$ac_config_files Makefile valgrind.spec valgrind.pc docs/Makefile docs/lib/Makefile docs/images/Makefile docs/internals/Makefile docs/xml/Makefile tests/Makefile tests/vg_regtest perf/Makefile perf/vg_perf include/Makefile include/vki/Makefile auxprogs/Makefile coregrind/Makefile memcheck/Makefile memcheck/tests/Makefile memcheck/tests/amd64/Makefile memcheck/tests/ppc32/Makefile memcheck/tests/ppc64/Makefile memcheck/tests/x86/Makefile memcheck/docs/Makefile cachegrind/Makefile cachegrind/tests/Makefile cachegrind/tests/amd64/Makefile cachegrind/tests/ppc32/Makefile cachegrind/tests/ppc64/Makefile cachegrind/tests/x86/Makefile cachegrind/docs/Makefile cachegrind/cg_annotate callgrind/Makefile callgrind/callgrind_annotate callgrind/callgrind_control callgrind/tests/Makefile callgrind/docs/Makefile helgrind/Makefile helgrind/tests/Makefile helgrind/docs/Makefile massif/Makefile massif/tests/Makefile massif/perf/Makefile massif/docs/Makefile massif/ms_print lackey/Makefile lackey/tests/Makefile lackey/docs/Makefile none/Makefile none/tests/Makefile none/tests/amd64/Makefile none/tests/ppc32/Makefile none/tests/ppc64/Makefile none/tests/x86/Makefile none/docs/Makefile exp-omega/Makefile exp-omega/tests/Makefile exp-omega/docs/Makefile exp-drd/Makefile exp-drd/docs/Makefile exp-drd/tests/Makefile" + ac_config_files="$ac_config_files Makefile valgrind.spec valgrind.pc docs/Makefile docs/lib/Makefile docs/images/Makefile docs/internals/Makefile docs/xml/Makefile tests/Makefile tests/vg_regtest perf/Makefile perf/vg_perf include/Makefile include/vki/Makefile auxprogs/Makefile coregrind/Makefile memcheck/Makefile memcheck/tests/Makefile memcheck/tests/amd64/Makefile memcheck/tests/ppc32/Makefile memcheck/tests/ppc64/Makefile memcheck/tests/x86/Makefile memcheck/docs/Makefile cachegrind/Makefile cachegrind/tests/Makefile cachegrind/tests/amd64/Makefile cachegrind/tests/ppc32/Makefile cachegrind/tests/ppc64/Makefile cachegrind/tests/x86/Makefile cachegrind/docs/Makefile cachegrind/cg_annotate callgrind/Makefile callgrind/callgrind_annotate callgrind/callgrind_control callgrind/tests/Makefile callgrind/docs/Makefile helgrind/Makefile helgrind/tests/Makefile helgrind/docs/Makefile massif/Makefile massif/tests/Makefile massif/perf/Makefile massif/docs/Makefile massif/ms_print lackey/Makefile lackey/tests/Makefile lackey/docs/Makefile mmt/Makefile mmt/tests/Makefile mmt/docs/Makefile none/Makefile none/tests/Makefile none/tests/amd64/Makefile none/tests/ppc32/Makefile none/tests/ppc64/Makefile none/tests/x86/Makefile none/docs/Makefile exp-omega/Makefile exp-omega/tests/Makefile exp-omega/docs/Makefile exp-drd/Makefile exp-drd/docs/Makefile exp-drd/tests/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -8213,6 +8213,9 @@ do "lackey/Makefile" ) CONFIG_FILES="$CONFIG_FILES lackey/Makefile" ;; "lackey/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES lackey/tests/Makefile" ;; "lackey/docs/Makefile" ) CONFIG_FILES="$CONFIG_FILES lackey/docs/Makefile" ;; + "mmt/Makefile" ) CONFIG_FILES="$CONFIG_FILES mmt/Makefile" ;; + "mmt/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES mmt/tests/Makefile" ;; + "mmt/docs/Makefile" ) CONFIG_FILES="$CONFIG_FILES mmt/docs/Makefile" ;; "none/Makefile" ) CONFIG_FILES="$CONFIG_FILES none/Makefile" ;; "none/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES none/tests/Makefile" ;; "none/tests/amd64/Makefile" ) CONFIG_FILES="$CONFIG_FILES none/tests/amd64/Makefile" ;; diff --git a/configure.in b/configure.in index 75cc768..2ebec75 100644 --- a/configure.in +++ b/configure.in @@ -1024,6 +1024,9 @@ AC_OUTPUT( lackey/Makefile lackey/tests/Makefile lackey/docs/Makefile + mmt/Makefile + mmt/tests/Makefile + mmt/docs/Makefile none/Makefile none/tests/Makefile none/tests/amd64/Makefile diff --git a/coregrind/m_libcbase.c b/coregrind/m_libcbase.c index d895bd3..673a7f1 100644 --- a/coregrind/m_libcbase.c +++ b/coregrind/m_libcbase.c @@ -217,6 +217,26 @@ Long VG_(atoll16) ( Char* str ) return VG_(strtoll16)(str, NULL); } +Long VG_(strtoll) ( Char* str, Char **endptr, Int base ) +{ + Bool neg = False; + Long n = 0; + if (*str == '-') { str++; neg = True; }; + if (base == 16 && *str == '0' && *(str + 1) == 'x') { str += 2; } + while ((*str >= '0' && *str <= '9') || (*str >= 'a' && *str <= 'f')) { + n = base * n; + if (*str <= '9') + n += (*str - '0'); + else + n += (*str - 'a' + 10); + str++; + } + if (neg) n = -n; + if (endptr) + *endptr = str; + return n; +} + Long VG_(atoll36) ( Char* str ) { return VG_(strtoll36)(str, NULL); diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index 95a6d3f..9d8f1aa 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -160,7 +160,7 @@ ML_(notify_aspacem_and_tool_of_mmap) ( Addr a, SizeT len, UInt prot, ww = toBool(prot & VKI_PROT_WRITE); xx = toBool(prot & VKI_PROT_EXEC); - VG_TRACK( new_mem_mmap, a, len, rr, ww, xx ); + VG_TRACK( new_mem_mmap, a, len, offset, rr, ww, xx ); if (d) VG_(discard_translations)( (Addr64)a, (ULong)len, @@ -303,7 +303,7 @@ SysRes do_mremap( Addr old_addr, SizeT old_len, VG_TRACK( copy_mem_remap, old_addr, new_addr, MIN_SIZET(old_len,new_len) ); if (new_len > old_len) - VG_TRACK( new_mem_mmap, new_addr+old_len, new_len-old_len, + VG_TRACK( new_mem_mmap, new_addr+old_len, new_len-old_len, 0, old_seg->hasR, old_seg->hasW, old_seg->hasX ); VG_TRACK(die_mem_munmap, old_addr, old_len); if (d) { @@ -345,7 +345,7 @@ SysRes do_mremap( Addr old_addr, SizeT old_len, if (ok && advised == needA) { ok = VG_(am_extend_map_client)( &d, (NSegment*)old_seg, needL ); if (ok) { - VG_TRACK( new_mem_mmap, needA, needL, + VG_TRACK( new_mem_mmap, needA, needL, 0, old_seg->hasR, old_seg->hasW, old_seg->hasX ); if (d) @@ -366,7 +366,7 @@ SysRes do_mremap( Addr old_addr, SizeT old_len, VG_TRACK( copy_mem_remap, old_addr, advised, MIN_SIZET(old_len,new_len) ); if (new_len > old_len) - VG_TRACK( new_mem_mmap, advised+old_len, new_len-old_len, + VG_TRACK( new_mem_mmap, advised+old_len, new_len-old_len, 0, old_seg->hasR, old_seg->hasW, old_seg->hasX ); VG_TRACK(die_mem_munmap, old_addr, old_len); if (d) { @@ -405,7 +405,7 @@ SysRes do_mremap( Addr old_addr, SizeT old_len, ok = VG_(am_extend_map_client)( &d, (NSegment*)old_seg, needL ); if (!ok) goto eNOMEM; - VG_TRACK( new_mem_mmap, needA, needL, + VG_TRACK( new_mem_mmap, needA, needL, 0, old_seg->hasR, old_seg->hasW, old_seg->hasX ); if (d) VG_(discard_translations)( needA, needL, "do_remap(6)" ); @@ -1694,7 +1694,7 @@ ML_(generic_POST_sys_shmat) ( ThreadId tid, /* we don't distinguish whether it's read-only or * read-write -- it doesn't matter really. */ - VG_TRACK( new_mem_mmap, res, segmentSize, True, True, False ); + VG_TRACK( new_mem_mmap, res, segmentSize, 0, True, True, False ); if (d) VG_(discard_translations)( (Addr64)res, (ULong)VG_PGROUNDUP(segmentSize), diff --git a/coregrind/m_tooliface.c b/coregrind/m_tooliface.c index 2aa74e9..ee2ca24 100644 --- a/coregrind/m_tooliface.c +++ b/coregrind/m_tooliface.c @@ -289,7 +289,7 @@ void VG_(fn)(VG_REGPARM(1) void(*f)(args)) \ DEF(track_new_mem_startup, Addr, SizeT, Bool, Bool, Bool) DEF(track_new_mem_stack_signal, Addr, SizeT) DEF(track_new_mem_brk, Addr, SizeT) -DEF(track_new_mem_mmap, Addr, SizeT, Bool, Bool, Bool) +DEF(track_new_mem_mmap, Addr, SizeT, Off64T, Bool, Bool, Bool) DEF(track_copy_mem_remap, Addr, Addr, SizeT) DEF(track_change_mem_mprotect, Addr, SizeT, Bool, Bool, Bool) diff --git a/coregrind/pub_core_tooliface.h b/coregrind/pub_core_tooliface.h index 7f77fed..13cb96b 100644 --- a/coregrind/pub_core_tooliface.h +++ b/coregrind/pub_core_tooliface.h @@ -164,7 +164,7 @@ typedef struct { void (*track_new_mem_startup) (Addr, SizeT, Bool, Bool, Bool); void (*track_new_mem_stack_signal)(Addr, SizeT); void (*track_new_mem_brk) (Addr, SizeT); - void (*track_new_mem_mmap) (Addr, SizeT, Bool, Bool, Bool); + void (*track_new_mem_mmap) (Addr, SizeT, Off64T, Bool, Bool, Bool); void (*track_copy_mem_remap) (Addr src, Addr dst, SizeT); void (*track_change_mem_mprotect) (Addr, SizeT, Bool, Bool, Bool); diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c index f246e66..884e0ce 100644 --- a/helgrind/hg_main.c +++ b/helgrind/hg_main.c @@ -5432,7 +5432,7 @@ void evh__new_mem ( Addr a, SizeT len ) { static void evh__new_mem_w_perms ( Addr a, SizeT len, - Bool rr, Bool ww, Bool xx ) { + Bool rr, Bool ww, Bool xx ) { if (SHOW_EVENTS >= 1) VG_(printf)("evh__new_mem_w_perms(%p, %lu, %d,%d,%d)\n", (void*)a, len, (Int)rr, (Int)ww, (Int)xx ); @@ -5443,6 +5443,18 @@ void evh__new_mem_w_perms ( Addr a, SizeT len, } static +void evh__new_mem_w_perms_mmap ( Addr a, SizeT len, + Off64T offset, Bool rr, Bool ww, Bool xx ) { + if (SHOW_EVENTS >= 1) + VG_(printf)("evh__new_mem_w_perms_mmap(%p, %lu, %d,%d,%d)\n", + (void*)a, len, (Int)rr, (Int)ww, (Int)xx ); + if (rr || ww || xx) + shadow_mem_make_New( get_current_Thread(), a, len ); + if (len >= SCE_BIGRANGE_T && (clo_sanity_flags & SCE_BIGRANGE)) + all__sanity_check("evh__new_mem_w_perms_mmap-post"); +} + +static void evh__set_perms ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx ) { if (SHOW_EVENTS >= 1) @@ -8807,7 +8819,7 @@ static void hg_pre_clo_init ( void ) VG_(track_new_mem_startup) ( evh__new_mem_w_perms ); VG_(track_new_mem_stack_signal)( evh__die_mem ); VG_(track_new_mem_brk) ( evh__new_mem ); - VG_(track_new_mem_mmap) ( evh__new_mem_w_perms ); + VG_(track_new_mem_mmap) ( evh__new_mem_w_perms_mmap ); VG_(track_new_mem_stack) ( evh__new_mem ); // FIXME: surely this isn't thread-aware diff --git a/include/pub_tool_libcbase.h b/include/pub_tool_libcbase.h index f262377..dcfa011 100644 --- a/include/pub_tool_libcbase.h +++ b/include/pub_tool_libcbase.h @@ -65,6 +65,7 @@ extern double VG_(strtod) ( Char* str, Char** endptr ); extern Long VG_(atoll) ( Char* str ); // base 10 extern Long VG_(atoll16) ( Char* str ); // base 16; leading 0x accepted +extern Long VG_(strtoll) ( Char* str, Char** endptr, Int base ); extern Long VG_(atoll36) ( Char* str ); // base 36 /* --------------------------------------------------------------------- diff --git a/include/pub_tool_options.h b/include/pub_tool_options.h index ed5c37e..338d97d 100644 --- a/include/pub_tool_options.h +++ b/include/pub_tool_options.h @@ -60,6 +60,11 @@ if ('\0' != s[0] || (qq_var) != n) VG_(err_bad_option)(qq_arg); \ } +#define VG_HEX_CLO(qq_arg, qq_option, qq_var) \ + if (VG_CLO_STREQN(VG_(strlen)(qq_option)+1, qq_arg, qq_option"=")) { \ + (qq_var) = (Int)VG_(strtoll)( &qq_arg[ VG_(strlen)(qq_option)+1 ], NULL, 16 ); \ + } + /* Bounded integer arg */ #define VG_BNUM_CLO(qq_arg, qq_option, qq_var, qq_lo, qq_hi) \ if (VG_CLO_STREQN(VG_(strlen)(qq_option)+1, qq_arg, qq_option"=")) { \ @@ -94,6 +99,14 @@ if ('\0' != s[0]) VG_(err_bad_option)(qq_arg); \ } +/* Bounded integer arg, given in hex */ +#define VG_BHEX_CLO(qq_arg, qq_option, qq_var, qq_lo, qq_hi) \ + if (VG_CLO_STREQN(VG_(strlen)(qq_option)+1, qq_arg, qq_option"=")) { \ + (qq_var) = (Int)VG_(strtoll)( &qq_arg[ VG_(strlen)(qq_option)+1 ], NULL, 16 ); \ + if ((qq_var) < (qq_lo)) (qq_var) = (qq_lo); \ + if ((qq_var) > (qq_hi)) (qq_var) = (qq_hi); \ + } + /* Bool arg whose value is denoted by the exact presence of the given string. */ #define VG_XACT_CLO(qq_arg, qq_option, qq_var) \ if (VG_CLO_STREQ(qq_arg, qq_option)) { \ diff --git a/include/pub_tool_tooliface.h b/include/pub_tool_tooliface.h index cfc57d7..7564025 100644 --- a/include/pub_tool_tooliface.h +++ b/include/pub_tool_tooliface.h @@ -475,7 +475,7 @@ void VG_(track_new_mem_startup) (void(*f)(Addr a, SizeT len, Bool rr, Bool ww, Bool xx)); void VG_(track_new_mem_stack_signal)(void(*f)(Addr a, SizeT len)); void VG_(track_new_mem_brk) (void(*f)(Addr a, SizeT len)); -void VG_(track_new_mem_mmap) (void(*f)(Addr a, SizeT len, +void VG_(track_new_mem_mmap) (void(*f)(Addr a, SizeT len, Off64T offset, Bool rr, Bool ww, Bool xx)); void VG_(track_copy_mem_remap) (void(*f)(Addr from, Addr to, SizeT len)); diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c index b7e7006..78daaed 100644 --- a/memcheck/mc_main.c +++ b/memcheck/mc_main.c @@ -2539,7 +2539,7 @@ void mc_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx ) } static -void mc_new_mem_mmap ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx ) +void mc_new_mem_mmap ( Addr a, SizeT len, Off64T o, Bool rr, Bool ww, Bool xx ) { MC_(make_mem_defined)(a, len); } diff --git a/mmt/Makefile.am b/mmt/Makefile.am new file mode 100644 index 0000000..e8f7101 --- /dev/null +++ b/mmt/Makefile.am @@ -0,0 +1,47 @@ +include $(top_srcdir)/Makefile.tool.am + +noinst_PROGRAMS = +if VGP_X86_LINUX +noinst_PROGRAMS += mmt-x86-linux +endif +if VGP_AMD64_LINUX +noinst_PROGRAMS += mmt-amd64-linux +endif +if VGP_PPC32_LINUX +noinst_PROGRAMS += mmt-ppc32-linux +endif +if VGP_PPC64_LINUX +noinst_PROGRAMS += mmt-ppc64-linux +endif + +MMT_SOURCES_COMMON = mmt_main.c + +mmt_x86_linux_SOURCES = $(MMT_SOURCES_COMMON) +mmt_x86_linux_CPPFLAGS = $(AM_CPPFLAGS_X86_LINUX) +mmt_x86_linux_CFLAGS = $(AM_CFLAGS_X86_LINUX) +mmt_x86_linux_DEPENDENCIES = $(COREGRIND_LIBS_X86_LINUX) +mmt_x86_linux_LDADD = $(TOOL_LDADD_X86_LINUX) +mmt_x86_linux_LDFLAGS = $(TOOL_LDFLAGS_X86_LINUX) + +mmt_amd64_linux_SOURCES = $(MMT_SOURCES_COMMON) +mmt_amd64_linux_CPPFLAGS = $(AM_CPPFLAGS_AMD64_LINUX) +mmt_amd64_linux_CFLAGS = $(AM_CFLAGS_AMD64_LINUX) +mmt_amd64_linux_DEPENDENCIES = $(COREGRIND_LIBS_AMD64_LINUX) +mmt_amd64_linux_LDADD = $(TOOL_LDADD_AMD64_LINUX) +mmt_amd64_linux_LDFLAGS = $(TOOL_LDFLAGS_AMD64_LINUX) + +mmt_ppc32_linux_SOURCES = $(MMT_SOURCES_COMMON) +mmt_ppc32_linux_CPPFLAGS = $(AM_CPPFLAGS_PPC32_LINUX) +mmt_ppc32_linux_CFLAGS = $(AM_CFLAGS_PPC32_LINUX) +mmt_ppc32_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC32_LINUX) +mmt_ppc32_linux_LDADD = $(TOOL_LDADD_PPC32_LINUX) +mmt_ppc32_linux_LDFLAGS = $(TOOL_LDFLAGS_PPC32_LINUX) + +mmt_ppc64_linux_SOURCES = $(MMT_SOURCES_COMMON) +mmt_ppc64_linux_CPPFLAGS = $(AM_CPPFLAGS_PPC64_LINUX) +mmt_ppc64_linux_CFLAGS = $(AM_CFLAGS_PPC64_LINUX) +mmt_ppc64_linux_DEPENDENCIES = $(COREGRIND_LIBS_PPC64_LINUX) +mmt_ppc64_linux_LDADD = $(TOOL_LDADD_PPC64_LINUX) +mmt_ppc64_linux_LDFLAGS = $(TOOL_LDFLAGS_PPC64_LINUX) + +mmtincludedir = $(includedir)/valgrind diff --git a/mmt/mmt_main.c b/mmt/mmt_main.c new file mode 100644 index 0000000..32bfb7a --- /dev/null +++ b/mmt/mmt_main.c @@ -0,0 +1,385 @@ +/* + * vim:sw=3 ts=3 sts=3 noexpandtab + */ + +/*--------------------------------------------------------------------*/ +/*--- mmaptrace: The mmaptracer tool. mmt_main.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + Copyright (C) 2006 Dave Airlie + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#include "pub_tool_basics.h" +#include "pub_tool_libcprint.h" +#include "pub_tool_libcassert.h" +#include "pub_tool_tooliface.h" +#include "pub_tool_debuginfo.h" +#include "pub_tool_libcbase.h" +#include "pub_tool_options.h" +#include "pub_tool_machine.h" // VG_(fnptr_to_fnentry) + +#define MAX_ITEMS 100 + +static struct mmt_memmap { + Bool initialized; + Addr offset; + Addr addr; + SizeT len; +} mmt_gpu_reg[MAX_ITEMS]; + +static UInt current_item; + +static struct mmt_op { + Addr offset; + SizeT size; + UInt value; + ULong reps; + UInt store; +} last_op; + + +/* Command line options */ +UInt mmt_clo_offset = (UInt) -1; + +static struct mmt_memmap *find_mmap(Addr addr) +{ + struct mmt_memmap *ptr = NULL; + UInt i; + + for (i = 0; i < MAX_ITEMS; i++) { + ptr = &mmt_gpu_reg[i]; + + if (!ptr->initialized) { + /* since we cannot un-init entries in the array, + * we can return once we hit the first uninitialized + * item -- there can't be initialized items following it. + */ + return NULL; + } + + if ((addr > ptr->addr) && (addr < ptr->addr + ptr->len)) + return ptr; + } + + return NULL; +} + +static void +print_op(void) +{ + int i; + + if (last_op.reps > 5) { + VG_(printf)(" ... repeated %lu times total\n", last_op.reps); + } + else { + for (i = 0; i < last_op.reps; i++) { + VG_(printf)("%s: %p, %d, %p\n", last_op.store ? "store" : "load", + last_op.offset, last_op.size, last_op.value); + } + } +} + +static VG_REGPARM(2) void +trace_store(Addr addr, SizeT size, UInt value) +{ + struct mmt_memmap *ptr; + + ptr = find_mmap(addr); + if (!ptr) + return; + + if (last_op.offset != (addr - ptr->addr) || last_op.size != size || + last_op.value != value || !last_op.store) { + print_op(); + + last_op.offset = addr - ptr->addr; + last_op.size = size; + last_op.value = value; + last_op.store = 1; + last_op.reps = 1; + } + else { + last_op.reps++; + + if (last_op.reps % 1000 == 0) + VG_(printf)(" ... repeating: %d times\n", last_op.reps); + if (last_op.reps == ~0UL) + VG_(printf)(" ... overflow!\n"); + } +} + +static VG_REGPARM(2) void +trace_load(Addr addr, SizeT size) +{ + struct mmt_memmap *ptr; + UInt value; + + ptr = find_mmap(addr); + if (!ptr) + return; + + switch (size) { + case 1: + value = *(UChar*) addr; + break; + case 2: + value = *(UShort*) addr; + break; + case 4: + value = *(UInt*) addr; + break; + case 8: + value = *(ULong*) addr; + default: + return; + } + + if (last_op.offset != (addr - ptr->addr) || last_op.size != size || + last_op.value != value || last_op.store) { + print_op(); + + last_op.offset = addr - ptr->addr; + last_op.size = size; + last_op.value = value; + last_op.store = 0; + last_op.reps = 1; + } + else { + last_op.reps++; + + if (last_op.reps % 1000 == 0) + VG_(printf)(" ... repeating: %d times\n", last_op.reps); + if (last_op.reps == ~0UL) + VG_(printf)(" ... overflow!\n"); + } +} + +static void +handle_load(IRSB* bb, IRExpr* addr, Int size) +{ + IRExpr** argv = mkIRExprVec_2(addr, mkIRExpr_HWord(size)); + IRDirty* di = unsafeIRDirty_0_N(2, + "trace_load", + VG_(fnptr_to_fnentry)(trace_load), + argv); + addStmtToIRSB(bb, IRStmt_Dirty(di)); +} + +static void +handle_store(IRSB*bb, IRExpr* addr, Int size, IRExpr* data) +{ + IRExpr** argv = mkIRExprVec_3(addr, mkIRExpr_HWord(size), data); + IRDirty* di = unsafeIRDirty_0_N(2, + "trace_store", + VG_(fnptr_to_fnentry)(trace_store), + argv); + addStmtToIRSB(bb, IRStmt_Dirty(di)); +} + +static IRSB* +mmt_instrument(VgCallbackClosure* closure, + IRSB* bbIn, + VexGuestLayout* layout, + VexGuestExtents* vge, + IRType gWordTy, IRType hWordTy) +{ + IRSB* bbOut; + int i = 0; + + if (gWordTy != hWordTy) { + /* We don't currently support this case. */ + VG_(tool_panic)("host/guest word size mismatch"); + } + if (gWordTy != Ity_I32 && gWordTy != Ity_I64) { + VG_(tool_panic)("word size must be 32 or 64 bits"); + } + + /* Set up BB */ + bbOut = deepCopyIRSBExceptStmts(bbIn); + + /* Copy verbatim any IR preamble preceding the first IMark */ + while (i < bbIn->stmts_used && bbIn->stmts[i]->tag != Ist_IMark) { + addStmtToIRSB(bbOut, bbIn->stmts[i]); + i++; + } + + for (; i < bbIn->stmts_used; i++) { + IRStmt* st = bbIn->stmts[i]; + IRExpr* data_expr; + IRType arg_ty; + IRTemp t = IRTemp_INVALID; + IRStmt* cast = NULL; + + if (!st) + continue; + + if (st->tag == Ist_Store) { + arg_ty = typeOfIRExpr(bbIn->tyenv, st->Ist.Store.data); + + data_expr = st->Ist.Store.data; + + /* convert data_expr into a 64 bit value */ + switch (arg_ty) { + case Ity_I8: + if (gWordTy == Ity_I32) { + t = newIRTemp(bbOut->tyenv, Ity_I32); + cast = IRStmt_WrTmp(t, IRExpr_Unop(Iop_8Uto32, data_expr)); + } + else { + t = newIRTemp(bbOut->tyenv, Ity_I64); + cast = IRStmt_WrTmp(t, IRExpr_Unop(Iop_8Uto64, data_expr)); + } + break; + case Ity_I16: + if (gWordTy == Ity_I32) { + t = newIRTemp(bbOut->tyenv, Ity_I32); + cast = IRStmt_WrTmp(t, IRExpr_Unop(Iop_16Uto32, data_expr)); + } + else { + t = newIRTemp(bbOut->tyenv, Ity_I64); + cast = IRStmt_WrTmp(t, IRExpr_Unop(Iop_16Uto64, data_expr)); + } + break; + case Ity_I32: + if (gWordTy == Ity_I64) { + t = newIRTemp(bbOut->tyenv, Ity_I64); + cast = IRStmt_WrTmp(t, IRExpr_Unop(Iop_32Uto64, data_expr)); + } + break; + case Ity_I64: + if (gWordTy == Ity_I64) { + break; + } + default: + /* since we only support stores up to the guest word size, we + * will never have to evaluate the data_expr that this case + * generates. + */ + if (gWordTy == Ity_I32) { + t = newIRTemp(bbOut->tyenv, Ity_I32); + cast = IRStmt_WrTmp(t, IRExpr_Const (IRConst_U32 (0))); + } + else { + t = newIRTemp(bbOut->tyenv, Ity_I64); + cast = IRStmt_WrTmp(t, IRExpr_Const (IRConst_U64 (0))); + } + break; + } + + if (cast) { + addStmtToIRSB(bbOut, cast); + data_expr = IRExpr_RdTmp(t); + } + + handle_store(bbOut, st->Ist.Store.addr, + sizeofIRType(arg_ty), data_expr); + } else if (st->tag == Ist_WrTmp) { + data_expr = st->Ist.WrTmp.data; + + if (data_expr->tag == Iex_Load) { + handle_load(bbOut, data_expr->Iex.Load.addr, + sizeofIRType (data_expr->Iex.Load.ty)); + } + } + + addStmtToIRSB(bbOut, st); + } + + return bbOut; +} + +static Bool +mmt_process_cmd_line_option(Char* arg) +{ + /* FIXME: make this argument mandatory */ + VG_BHEX_CLO(arg, "--offset", mmt_clo_offset, 0, 0xffffffff) + else + return False; + + VG_(message)(Vg_UserMsg, "set offset to %lx\n", mmt_clo_offset); + + return True; +} + +static void +mmt_print_usage(void) +{ + VG_(printf)(" --offset= (number must be in decimal!)\n"); +} + +static void +mmt_print_debug_usage(void) +{ +} + +static void +mmt_new_mem_mmap(Addr a, SizeT len, Off64T offset, Bool rr, Bool ww, Bool xx) +{ + if (offset != mmt_clo_offset) + return; + + mmt_gpu_reg[current_item].offset = offset; + mmt_gpu_reg[current_item].addr = a; + mmt_gpu_reg[current_item].len = len; + mmt_gpu_reg[current_item].initialized = True; + current_item++; + + VG_(message)(Vg_UserMsg, "got new mmap for %p, len %d, offset %p\n", a, len, offset); +} + +static void +mmt_fini(Int exitcode) +{ +} + +static void mmt_post_clo_init(void) +{ +} + +static void +mmt_pre_clo_init(void) +{ + VG_(details_name) ("mmaptrace"); + VG_(details_version) (NULL); + VG_(details_description) ("an MMAP tracer"); + VG_(details_copyright_author)( + "Copyright (C) 2006, and GNU GPL'd, by Dave Airlie."); + VG_(details_bug_reports_to) (VG_BUGS_TO); + + VG_(basic_tool_funcs) (mmt_post_clo_init, + mmt_instrument, + mmt_fini); + + VG_(needs_command_line_options)(mmt_process_cmd_line_option, + mmt_print_usage, + mmt_print_debug_usage); + + VG_(track_new_mem_mmap) (mmt_new_mem_mmap); + + last_op.offset = 0; + last_op.size = 0; + last_op.value = 0; + last_op.store = 0; + last_op.reps = 0; +} + +VG_DETERMINE_INTERFACE_VERSION(mmt_pre_clo_init) diff --git a/valgrind.sh b/valgrind.sh new file mode 100755 index 0000000..fcd0b72 --- /dev/null +++ b/valgrind.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +valgrind --tool=mmt --offset=$1 /usr/bin/Xorg :0 -ac