##############################################################
#
# This file includes all the test targets as well as all the
# non-default build rules and test recipes.
#
##############################################################


##############################################################
#
# Test targets
#
##############################################################

###### Place all generic definitions here ######

# This defines tests which run tools of the same name.  This is simply for convenience to avoid
# defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS).
# Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS.
TEST_TOOL_ROOTS := memory_addr_callback memory_callback_error after hello icount1 icount2 icount3 icount4 icount5 \
                   context-pc icountcheck sequence sequencecheck reg brtaken verify bblnull sec callargs malloc new \
                   removeinstrumentation rtnNumIns rtn_create_at_dup IARGList inscount_per_image imageLoadBackward \
                   bblCache traceOriginal finiRemove bblFallThrough detach imageLoad parse_executed_rtns

# This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS.
TEST_ROOTS := icount1_jit_recursion verify-nocmov check_env

# This defines a list of tests that should run in the "short" sanity. Tests in this list must also
# appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list.
# If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the
# SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl).
SANITY_SUBSET := icount2 verify after brtaken callargs

# This defines the tools which will be run during the the tests, and were not already defined in
# TEST_TOOL_ROOTS.
TOOL_ROOTS := segv probe traceusage rtn_insert_call_probed tracecount smc_check \
              multipleinstrumentation inscount2_mt_debuginfo cflowcheck

# This defines the static analysis tools which will be run during the the tests. They should not
# be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in
# TEST_ROOTS.
# Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library.
# This library provides a subset of the Pin APIs which allows the tool to perform static analysis
# of an application or dll. Pin itself is not used when this tool runs.
SA_TOOL_ROOTS :=

# This defines all the applications that will be run during the tests.
APP_ROOTS := foobar

# This defines any additional object files that need to be compiled.
OBJECT_ROOTS :=

# This defines any additional dlls (shared objects), other than the pintools, that need to be compiled.
DLL_ROOTS :=

# This defines any static libraries (archives), that need to be built.
LIB_ROOTS :=

###### Place architecture-specific definitions here ######

# Place ia32-specific definitions here if they apply to all supported operating systems.
ifeq ($(TARGET),ia32)
    TEST_TOOL_ROOTS += alah emu checkaddress operand syntax
    TEST_ROOTS += test_ebx_in_exceptions emu-bridge
    APP_ROOTS += test_ebx_in_exceptions
    OBJECT_ROOTS += test_ebx_in_exceptions_asm test_ebx_in_exceptions
endif

# Place intel64-specific definitions here if they apply to all supported operating systems.
ifeq ($(TARGET),intel64)
    TEST_TOOL_ROOTS += snprintf
    TEST_ROOTS += snprintf_non_inlined_bridge
endif

###### Place OS-specific definitions here ######

# Linux
ifeq ($(TARGET_OS),linux)
    TEST_TOOL_ROOTS += reg_ref_inlined ifunc_tst exitProcess context_stack_and_spill ifuncmemcpy
    TEST_ROOTS += launcher_linux context_stack_and_spill_noinline_bridge toolwithoutso toolpathwithoutso imageLoader \
                  illegal_envp sourceLocation statdyn
    TOOL_ROOTS += launcher_tool ea_verifier sourceLocation_tool statdyn_tool
    APP_ROOTS += launcher_app illegalEnvp_app sourceLocation_app statdyn_app exitProcessApp memcpy_app strcmp_app
    DLL_ROOTS += sourceLocation_img1 sourceLocation_img2
    ifeq ($(TARGET),ia32)
        TEST_TOOL_ROOTS += limitedTraces thread symOutOfBound util prefix  \
                           insMix xedReg
        TEST_ROOTS += verify-ia32 verify-ia32-nocmov
        APP_ROOTS += loop threadApp prefixApp insMixApp
    endif
    ifeq ($(TARGET),intel64)
        TEST_TOOL_ROOTS += syntax_tst
        TEST_ROOTS += checkaddress64 injectionStack child_sig_while_execv
        TOOL_ROOTS += checkaddress
        APP_ROOTS += mysetenv checkaddressapp child_sig_while_execv_app child_sig_while_execv_simple_app sampleApp
    endif
    ifeq ($(PROBE),1)
        TEST_ROOTS += callargs_probe illegal_envp_probed ifunc_tst_probe
        TEST_TOOL_ROOTS += callargs_probe_tool
        APP_ROOTS += strcmp_app
    endif
endif

# Windows
ifeq ($(TARGET_OS),windows)
    TEST_TOOL_ROOTS += callargs_probe_tool reg_ref_inlined context_stack_and_spill
    TEST_ROOTS += callargs_probe context_stack_and_spill_noinline_bridge winapp_runs_pin ifunc_win_tst
    TOOL_ROOTS += ea_verifier ifunc_tst
    APP_ROOTS += foobar winapp_runs_pin correct_winapp_runs_pin_cmdline strcmp_win_app
    ifeq ($(TARGET),ia32)
        TEST_ROOTS += win-emu-bridge
        TOOL_ROOTS += set_df_flag_tool clear_df_flag_tool set_status_flags_tool
        APP_ROOTS += lasterror
    endif
endif

# Mac
ifeq ($(TARGET_OS),mac)
    TEST_ROOTS += launcher_mac 
    TOOL_ROOTS += launcher_tool
    APP_ROOTS += launcher_app
endif

###### Handle exceptions here ######

# The launcher is only relevant when running from the kit structure.
ifneq ($(KIT),1)
    TEST_ROOTS := $(filter-out launcher_linux launcher_mac, $(TEST_ROOTS))
    TOOL_ROOTS := $(filter-out launcher_tool, $(TOOL_ROOTS))
    APP_ROOTS := $(filter-out launcher_app, $(APP_ROOTS))
endif

# Disable the reg_ref_inlined test in the Windows icc.kit.test. See Mantis 3048
ifeq ($(ICC),1)
    ifeq ($(TARGET_OS),windows)
        TEST_TOOL_ROOTS := $(filter-out reg_ref_inlined, $(TEST_TOOL_ROOTS))
    endif
endif

# TODO: These tests fail - fix and remove the following:
# For sourceLocation see Mantis 2960.
# For context_stack_and_spill and context_stack_and_spill_noinline_bridge see Mantis 3073.
# For ifunc_tst see Mantis 3080.
# For launcher_linux see Matis 3081.
# For all the rest see Mantis 2963
ifeq ($(TARGET),mic)
    TEST_TOOL_ROOTS := $(filter-out ifunc_tst context_stack_and_spill memory_addr_callback memory_callback_error \
                                    imageLoad imageLoadBackward, $(TEST_TOOL_ROOTS))
    TEST_ROOTS := $(filter-out launcher_linux context_stack_and_spill_noinline_bridge imageLoader sourceLocation, \
                               $(TEST_ROOTS))
    TOOL_ROOTS := $(filter-out launcher_tool sourceLocation_tool, $(TOOL_ROOTS))
    APP_ROOTS := $(filter-out launcher_app sourceLocation_app, $(APP_ROOTS))
endif

# See Mantis #3181
ifeq ($(TARGET_OS),android)
    TEST_TOOL_ROOTS := $(filter-out util symOutOfBound ifunc_tst, $(TEST_TOOL_ROOTS))
    TEST_ROOTS := $(filter-out check_env launcher_android imageLoader, $(TEST_ROOTS))
    APP_ROOTS := $(filter-out strcmp_app, $(APP_ROOTS))
endif

# Disable the check_env test under certain conditions:
# 1. On 64-bit Unix platforms, the shell is a 64-bit application, so it can't be instrumented with a 32-bit tool.
#    Therefore disable the test when cross-testing.
# 2. On Windows, under cygwin, the shell is a 32-bit application, so it can't be instrumented with a 64-bit tool.
#    Therefore disable the test on 64-bit systems.
# 3. On 32-bit Windows, see Mantis 3077.
ifeq ($(TARGET_OS),windows)
    ifeq ($(TARGET),ia32)
        TEST_ROOTS := $(filter-out check_env, $(TEST_ROOTS))
    endif
    ifeq ($(TARGET),intel64)
        TEST_ROOTS := $(filter-out check_env, $(TEST_ROOTS))
    endif
else
    ifeq ($(HOST_ARCH)-$(TARGET),intel64-ia32)
        TEST_ROOTS := $(filter-out check_env, $(TEST_ROOTS))
    endif
endif


##############################################################
#
# Test recipes
#
##############################################################

# This section contains recipes for tests other than the default.
# See makefile.default.rules for the default test rules.
# All tests in this section should adhere to the naming convention: <testname>.test

winapp_runs_pin.test: $(OBJDIR)winapp_runs_pin$(EXE_SUFFIX) $(OBJDIR)correct_winapp_runs_pin_cmdline$(EXE_SUFFIX) $(TESTAPP)
	echo $(PIN) > pin_invoke.txt
	$(OBJDIR)correct_winapp_runs_pin_cmdline$(EXE_SUFFIX) \
	  -- $(TESTAPP) makefile $(OBJDIR)makefile.winapp_runs_pin.copy > $(OBJDIR)correct_winapp_runs_pin_cmdline.txt 
	$(OBJDIR)winapp_runs_pin$(EXE_SUFFIX) `cat $(OBJDIR)correct_winapp_runs_pin_cmdline.txt`
	$(CMP) makefile $(OBJDIR)makefile.winapp_runs_pin.copy
	$(RM) $(OBJDIR)makefile.winapp_runs_pin.copy $(OBJDIR)correct_winapp_runs_pin_cmdline.txt pin_invoke.txt

child_sig_while_execv.test: $(OBJDIR)child_sig_while_execv_app$(EXE_SUFFIX) $(OBJDIR)child_sig_while_execv_simple_app$(EXE_SUFFIX)
	$(PIN) -follow_execv -- $(OBJDIR)child_sig_while_execv_app$(EXE_SUFFIX)

ifuncmemcpy.test: $(OBJDIR)ifuncmemcpy$(PINTOOL_SUFFIX) $(OBJDIR)memcpy_app$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)ifuncmemcpy$(PINTOOL_SUFFIX) -o $(OBJDIR)ifuncmemcpy.out\
	  -- $(OBJDIR)memcpy_app$(EXE_SUFFIX) $(OBJDIR)ifuncmemcpy.out 2>&1
	if $(QGREP) "Ifunc memcpy" $(OBJDIR)ifuncmemcpy.out ; then \
	    $(QGREP) "memcpy (ifunc)" $(OBJDIR)ifuncmemcpy.out ; \
	else \
	$(QGREP) "memcpy (normal)" $(OBJDIR)ifuncmemcpy.out ; \
	  fi
	$(RM) $(OBJDIR)ifuncmemcpy.out
	
launcher_linux.test: $(OBJDIR)launcher_tool$(PINTOOL_SUFFIX) $(OBJDIR)launcher_app$(EXE_SUFFIX)
	env LD_LIBRARY_PATH="/usr/lib" LD_ASSUME_KERNEL=`uname -r` LD_BIND_NOW=1 LD_PRELOAD=libm.so \
	  $(PIN) -t $(OBJDIR)launcher_tool$(PINTOOL_SUFFIX) -- $(OBJDIR)launcher_app$(EXE_SUFFIX)

launcher_mac.test: $(OBJDIR)launcher_tool$(PINTOOL_SUFFIX) $(OBJDIR)launcher_app$(EXE_SUFFIX)
	env DYLD_LIBRARY_PATH="/usr/lib" $(PIN) -t $(OBJDIR)launcher_tool$(PINTOOL_SUFFIX) -- $(OBJDIR)launcher_app$(EXE_SUFFIX)
          
statdyn.test: $(OBJDIR)statdyn_tool$(PINTOOL_SUFFIX) $(OBJDIR)statdyn_app$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)statdyn_tool$(PINTOOL_SUFFIX) -- $(OBJDIR)statdyn_app$(EXE_SUFFIX)

sourceLocation.test: $(OBJDIR)sourceLocation_tool$(PINTOOL_SUFFIX) $(OBJDIR)sourceLocation_app$(EXE_SUFFIX) $(OBJDIR)$(DLL_PREFIX)sourceLocation_img1$(DLL_SUFFIX) $(OBJDIR)$(DLL_PREFIX)sourceLocation_img2$(DLL_SUFFIX)
	$(PIN) -t $(OBJDIR)sourceLocation_tool$(PINTOOL_SUFFIX) -- $(OBJDIR)sourceLocation_app$(EXE_SUFFIX) \
	  $(OBJDIR)$(DLL_PREFIX)sourceLocation_img1$(DLL_SUFFIX) $(OBJDIR)$(DLL_PREFIX)sourceLocation_img2$(DLL_SUFFIX)

icount1_jit_recursion.test: $(OBJDIR)icount1$(PINTOOL_SUFFIX) $(TESTAPP)
	$(PIN) -xyzzy -max_jit_recursion_level 5 -jit_all_exits 1 -t $(OBJDIR)icount1$(PINTOOL_SUFFIX) \
	  -- $(TESTAPP) makefile $(OBJDIR)icount1_jit_recursion.makefile.copy
	$(DIFF) makefile $(OBJDIR)icount1_jit_recursion.makefile.copy
	$(RM) $(OBJDIR)icount1_jit_recursion.makefile.copy

illegal_envp.test: $(OBJDIR)illegalEnvp_app$(EXE_SUFFIX) $(TESTAPP)
	$(PIN) -follow_execv -- $(OBJDIR)illegalEnvp_app$(EXE_SUFFIX) $(TESTAPP) makefile $(OBJDIR)illegal_envp.makefile.copy
	$(CMP) makefile $(OBJDIR)illegal_envp.makefile.copy
	$(RM) $(OBJDIR)illegal_envp.makefile.copy

illegal_envp_probed.test: $(OBJDIR)illegalEnvp_app$(EXE_SUFFIX) $(TESTAPP)
	$(PIN) -probe -follow_execv -- $(OBJDIR)illegalEnvp_app$(EXE_SUFFIX) $(TESTAPP) \
	  makefile $(OBJDIR)illegal_envp_probed.makefile.copy
	$(CMP) makefile $(OBJDIR)illegal_envp_probed.makefile.copy
	$(RM) $(OBJDIR)illegal_envp_probed.makefile.copy

ifunc_tst_probe.test: $(OBJDIR)ifunc_tst$(PINTOOL_SUFFIX) $(OBJDIR)strcmp_app$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)ifunc_tst$(PINTOOL_SUFFIX)  -probe_mode 1 -- $(OBJDIR)strcmp_app$(EXE_SUFFIX)\
	 > $(OBJDIR)ifunc_tst_probe.out
	# Use ldd to get the libc.so location
	ldd $(OBJDIR)strcmp_app$(EXE_SUFFIX) | $(GREP) " /[a-z,/,\.,0-9,_,-]*/libc\.so[\.,0-9]*" -o > \
	$(OBJDIR)ifunc_tst_probe_libc.out
	# Use nm -D to get the list of libc.so dynamic symbols
	nm -D `cat $(OBJDIR)ifunc_tst_probe_libc.out` > $(OBJDIR)ifunc_tst_probe_nm.out
	# if strcmp is IFUNC symbol make sure ifunc_tst_probe tool recognize it and make sure the function
	# is called only once
	if $(QGREP) "i strcmp" $(OBJDIR)ifunc_tst_probe_nm.out ; then \
	  $(GREP) "ifunc strcmp called" $(OBJDIR)ifunc_tst_probe.out -c > $(OBJDIR)ifunc_tst_probe_num_calls.out; \
	  echo "2" > $(OBJDIR)ifunc_tst_probe_num_calls_ref_2.out; \
	  echo "4" > $(OBJDIR)ifunc_tst_probe_num_calls_ref_4.out; \
	  if $(CMP) $(OBJDIR)ifunc_tst_probe_num_calls.out $(OBJDIR)ifunc_tst_probe_num_calls_ref_2.out ; then\
	    $(CMP) $(OBJDIR)ifunc_tst_probe_num_calls.out $(OBJDIR)ifunc_tst_probe_num_calls_ref_2.out; \
	  else \
	    $(CMP) $(OBJDIR)ifunc_tst_probe_num_calls.out $(OBJDIR)ifunc_tst_probe_num_calls_ref_4.out; \
	  fi \
	else \
	  $(QGREP) "Found non IFUNC strcmp" $(OBJDIR)ifunc_tst_probe.out; \
	fi
	$(RM) $(OBJDIR)ifunc_tst_probe*.out

ifunc_tst.test: $(OBJDIR)ifunc_tst$(PINTOOL_SUFFIX) $(OBJDIR)strcmp_app$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)ifunc_tst$(PINTOOL_SUFFIX) -- $(OBJDIR)strcmp_app$(EXE_SUFFIX) > $(OBJDIR)ifunc_tst.out
	# Use ldd to get the libc.so location
	ldd $(OBJDIR)strcmp_app$(EXE_SUFFIX) | $(GREP) " /[a-z,/,\.,0-9,_,-]*/libc\.so[\.,0-9]*" -o > \
	$(OBJDIR)ifunc_tst_libc.out
	# Use nm -D to get the list of libc.so dynamic symbols
	nm -D `cat $(OBJDIR)ifunc_tst_libc.out` > $(OBJDIR)ifunc_tst_nm.out
	# if strcmp is IFUNC symbol make sure ifunc_tst tool recognize it and make sure the function is called only once
	if $(QGREP) "i strcmp" $(OBJDIR)ifunc_tst_nm.out ; then \
	  $(QGREP) "Found IFUNC strcmp" $(OBJDIR)ifunc_tst.out; \
	  $(GREP) "ifunc strcmp called" $(OBJDIR)ifunc_tst.out -c > $(OBJDIR)ifunc_tst_num_calls.out; \
	  echo "2" > $(OBJDIR)ifunc_tst_num_calls_ref_2.out; \
	  echo "4" > $(OBJDIR)ifunc_tst_num_calls_ref_4.out; \
	  if $(CMP) $(OBJDIR)ifunc_tst_num_calls.out $(OBJDIR)ifunc_tst_num_calls_ref_2.out ; then\
	    $(CMP) $(OBJDIR)ifunc_tst_num_calls.out $(OBJDIR)ifunc_tst_num_calls_ref_2.out; \
	  else \
	    $(CMP) $(OBJDIR)ifunc_tst_num_calls.out $(OBJDIR)ifunc_tst_num_calls_ref_4.out; \
	  fi \
	else \
	  $(QGREP) "Found non IFUNC strcmp" $(OBJDIR)ifunc_tst.out; \
	fi
	$(RM) $(OBJDIR)ifunc_tst*.out

ifunc_win_tst.test: $(OBJDIR)ifunc_tst$(PINTOOL_SUFFIX) $(OBJDIR)strcmp_win_app$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)ifunc_tst$(PINTOOL_SUFFIX) -- $(OBJDIR)strcmp_win_app$(EXE_SUFFIX) > $(OBJDIR)ifunc_win_tst.out
	$(QGREP) "Found non IFUNC strcmp" $(OBJDIR)ifunc_win_tst.out
	$(RM) $(OBJDIR)ifunc_win_tst*.out
    
syntax_tst.test: $(OBJDIR)syntax_tst$(PINTOOL_SUFFIX) $(OBJDIR)sampleApp$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)syntax_tst$(PINTOOL_SUFFIX) -setsyntax 0 -- $(OBJDIR)sampleApp$(EXE_SUFFIX) > $(OBJDIR)setsyntax_0.out
	$(QGREP) "call " $(OBJDIR)setsyntax_0.out
	$(PIN) -t $(OBJDIR)syntax_tst$(PINTOOL_SUFFIX) -setsyntax 1 -- $(OBJDIR)sampleApp$(EXE_SUFFIX) > $(OBJDIR)setsyntax_1.out
	$(QGREP) "callq" $(OBJDIR)setsyntax_1.out
	$(PIN) -t $(OBJDIR)syntax_tst$(PINTOOL_SUFFIX) -setsyntax 2 -- $(OBJDIR)sampleApp$(EXE_SUFFIX) > $(OBJDIR)setsyntax_2.out
	$(QGREP) "CALL_NEAR" $(OBJDIR)setsyntax_2.out
	$(RM) $(OBJDIR)setsyntax_0.out $(OBJDIR)setsyntax_1.out $(OBJDIR)setsyntax_2.out

callargs.test: $(OBJDIR)callargs$(PINTOOL_SUFFIX) $(OBJDIR)foobar$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)callargs$(PINTOOL_SUFFIX) -- $(OBJDIR)foobar$(EXE_SUFFIX)

callargs_probe.test: $(OBJDIR)callargs_probe_tool$(PINTOOL_SUFFIX) $(OBJDIR)foobar$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)callargs_probe_tool$(PINTOOL_SUFFIX) -- $(OBJDIR)foobar$(EXE_SUFFIX)

context_stack_and_spill.test: $(OBJDIR)context_stack_and_spill$(PINTOOL_SUFFIX) $(TESTAPP)
	$(PIN) -t $(OBJDIR)context_stack_and_spill$(PINTOOL_SUFFIX) -context_at_trace 1 -compare_contexts 1 \
	  -reverse_compare_contexts 1 -- $(TESTAPP) makefile $(OBJDIR)context_stack_and_spill.makefile.copy
	$(CMP) makefile $(OBJDIR)context_stack_and_spill.makefile.copy
	$(RM) $(OBJDIR)context_stack_and_spill.makefile.copy

context_stack_and_spill_noinline_bridge.test: $(OBJDIR)context_stack_and_spill$(PINTOOL_SUFFIX) $(TESTAPP)
	$(PIN) -xyzzy -inline_bridge 0 -t $(OBJDIR)context_stack_and_spill$(PINTOOL_SUFFIX) -context_at_trace 1 \
	  -compare_contexts 1 -reverse_compare_contexts 1 \
	    -- $(TESTAPP) makefile $(OBJDIR)context_stack_and_spill_noinline_bridge.makefile.copy
	$(CMP) makefile $(OBJDIR)context_stack_and_spill_noinline_bridge.makefile.copy
	$(RM) $(OBJDIR)context_stack_and_spill_noinline_bridge.makefile.copy

context-pc.test: $(OBJDIR)context-pc$(PINTOOL_SUFFIX) $(TESTAPP)
	$(PIN) -t $(OBJDIR)context-pc$(PINTOOL_SUFFIX) -o $(OBJDIR)context-pc.out \
	  -- $(TESTAPP) makefile $(OBJDIR)context-pc.makefile.copy
	$(CMP) makefile $(OBJDIR)context-pc.makefile.copy
	$(RM) $(OBJDIR)context-pc.makefile.copy $(OBJDIR)context-pc.out

memory_addr_callback.test: $(OBJDIR)memory_addr_callback$(PINTOOL_SUFFIX)
	$(PIN) -t $(OBJDIR)memory_addr_callback$(PINTOOL_SUFFIX) \
	  -- $(TESTAPP) makefile $(OBJDIR)memory_addr_callback.makefile.copy
	$(CMP) makefile $(OBJDIR)memory_addr_callback.makefile.copy
	$(RM) $(OBJDIR)memory_addr_callback.makefile.copy

memory_callback_error.test: $(OBJDIR)memory_callback_error$(PINTOOL_SUFFIX)
	-$(PIN) -t $(OBJDIR)memory_callback_error$(PINTOOL_SUFFIX) \
	  -- $(TESTAPP) makefile $(OBJDIR)memory_callback_error.makefile.copy > $(OBJDIR)memory_callback_error.out 2>&1
	$(QGREP) "Illegal use of memory address callback and register parameters" $(OBJDIR)memory_callback_error.out
	$(RM) $(OBJDIR)memory_callback_error.out
	$(RM) -f $(OBJDIR)memory_callback_error.makefile.copy # this file might not be generated so we use the -f flag

toolwithoutso.test: $(OBJDIR)callargs$(PINTOOL_SUFFIX) $(OBJDIR)foobar$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)callargs -- $(OBJDIR)foobar$(EXE_SUFFIX)

toolpathwithoutso.test: $(OBJDIR)callargs$(PINTOOL_SUFFIX) $(OBJDIR)foobar$(EXE_SUFFIX)
	$(PIN) -t $(TOOLS_ROOT)/Tests/$(OBJDIR)callargs -- $(OBJDIR)foobar$(EXE_SUFFIX)

verify-ia32.test: $(OBJDIR)verify$(PINTOOL_SUFFIX) $(OBJDIR)loop$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)verify$(PINTOOL_SUFFIX) -- $(OBJDIR)loop$(EXE_SUFFIX)

snprintf_non_inlined_bridge.test: $(OBJDIR)snprintf$(PINTOOL_SUFFIX)
	$(PIN) -xyzzy -inline_bridge 0 -t $(OBJDIR)snprintf$(PINTOOL_SUFFIX) \
	  -- $(TESTAPP) makefile $(OBJDIR)snprintf_non_inlined_bridge.makefile.copy
	$(CMP) makefile $(OBJDIR)snprintf_non_inlined_bridge.makefile.copy
	$(RM) $(OBJDIR)snprintf_non_inlined_bridge.makefile.copy

reg.test: $(OBJDIR)reg$(PINTOOL_SUFFIX)
	$(PIN) -t $(OBJDIR)reg$(PINTOOL_SUFFIX) -- $(TESTAPP) makefile $(OBJDIR)reg.makefile.copy
	$(CMP) makefile $(OBJDIR)reg.makefile.copy
	$(RM) $(OBJDIR)reg.makefile.copy 

reg_ref_inlined.test: $(OBJDIR)reg_ref_inlined$(PINTOOL_SUFFIX)
	$(PIN) -log_inline -xyzzy -logfile $(OBJDIR)reg_ref_inlined.log -t $(OBJDIR)reg_ref_inlined$(PINTOOL_SUFFIX) \
	  -- $(TESTAPP) makefile $(OBJDIR)reg_ref_inlined.makefile.copy
	$(CMP) makefile $(OBJDIR)reg_ref_inlined.makefile.copy
	$(BASHTEST) `$(CGREP) "NOT INLINED" $(OBJDIR)reg_ref_inlined.log` -le "4" 
	$(QGREP) "INLINED" $(OBJDIR)reg_ref_inlined.log
	$(RM) $(OBJDIR)reg_ref_inlined.makefile.copy $(OBJDIR)reg_ref_inlined.log

verify-ia32-nocmov.test: $(OBJDIR)verify$(PINTOOL_SUFFIX) $(OBJDIR)loop$(EXE_SUFFIX)
	$(PIN) -xyzzy -nocmov 1 -t $(OBJDIR)verify$(PINTOOL_SUFFIX) -- $(OBJDIR)loop$(EXE_SUFFIX)

verify-nocmov.test: $(OBJDIR)verify$(PINTOOL_SUFFIX) $(TESTAPP)
	$(PIN) -xyzzy -nocmov 1 -t $(OBJDIR)verify$(PINTOOL_SUFFIX) -- $(TESTAPP) makefile $(OBJDIR)verify-nocmov.makefile.copy
	$(CMP) makefile $(OBJDIR)verify-nocmov.makefile.copy
	$(RM) $(OBJDIR)verify-nocmov.makefile.copy

check_env.test: $(OBJDIR)hello$(PINTOOL_SUFFIX)
	$(SH) ./check_env.sh $(EGREP) > $(OBJDIR)check_env.before
	$(PIN) -t $(OBJDIR)hello$(PINTOOL_SUFFIX) -- $(SH) ./check_env.sh $(EGREP) > $(OBJDIR)check_env.tool.after
	$(PIN) -- $(SH) ./check_env.sh $(EGREP) > $(OBJDIR)check_env.notool.after
	$(CMP) $(OBJDIR)check_env.before $(OBJDIR)check_env.tool.after
	$(CMP) $(OBJDIR)check_env.before $(OBJDIR)check_env.notool.after
	$(RM) $(OBJDIR)check_env.before $(OBJDIR)check_env.tool.after $(OBJDIR)check_env.notool.after 

emu-bridge.test: $(OBJDIR)emu$(PINTOOL_SUFFIX)
	$(PIN) -xyzzy -inline 0 -t $(OBJDIR)emu$(PINTOOL_SUFFIX) -- $(TESTAPP) makefile $(OBJDIR)emu-bridge.makefile.copy
	$(CMP) makefile $(OBJDIR)emu-bridge.makefile.copy
	$(RM) $(OBJDIR)emu-bridge.makefile.copy

win-emu-bridge.test: $(OBJDIR)emu$(PINTOOL_SUFFIX) $(OBJDIR)lasterror$(EXE_SUFFIX)
	$(PIN) -xyzzy -inline 0 -t $(OBJDIR)emu$(PINTOOL_SUFFIX) -- $(OBJDIR)lasterror$(EXE_SUFFIX)

checkaddress64.test: $(OBJDIR)checkaddress$(PINTOOL_SUFFIX) $(OBJDIR)checkaddressapp$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)checkaddress$(PINTOOL_SUFFIX) -- $(OBJDIR)checkaddressapp$(EXE_SUFFIX)

thread.test: $(OBJDIR)thread$(PINTOOL_SUFFIX) $(OBJDIR)threadApp$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)thread$(PINTOOL_SUFFIX) -- $(OBJDIR)threadApp$(EXE_SUFFIX)

util.test: $(OBJDIR)util$(PINTOOL_SUFFIX) $(TESTAPP)
	$(PIN) -t $(OBJDIR)util$(PINTOOL_SUFFIX) -- $(TESTAPP) makefile $(OBJDIR)util.makefile.copy
	$(CMP) makefile $(OBJDIR)util.makefile.copy
	$(RM) $(OBJDIR)util.makefile.copy

injectionStack.test: $(OBJDIR)mysetenv$(EXE_SUFFIX) $(TESTAPP)
	$(OBJDIR)mysetenv$(EXE_SUFFIX) $(PIN) -- $(TESTAPP) makefile $(OBJDIR)injectionStack.makefile.copy
	$(CMP) makefile $(OBJDIR)injectionStack.makefile.copy
	$(RM) $(OBJDIR)injectionStack.makefile.copy

prefix.test: $(OBJDIR)prefix$(PINTOOL_SUFFIX) $(OBJDIR)prefixApp$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)prefix$(PINTOOL_SUFFIX) -- $(OBJDIR)prefixApp$(EXE_SUFFIX)

insMix.test: $(OBJDIR)insMix$(PINTOOL_SUFFIX) $(OBJDIR)insMixApp$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)insMix$(PINTOOL_SUFFIX) -- $(OBJDIR)insMixApp$(EXE_SUFFIX)

exitProcess.test: $(OBJDIR)exitProcess$(PINTOOL_SUFFIX) $(OBJDIR)exitProcessApp$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)exitProcess$(PINTOOL_SUFFIX) -- $(OBJDIR)exitProcessApp$(EXE_SUFFIX)

test_ebx_in_exceptions.test: $(OBJDIR)test_ebx_in_exceptions$(EXE_SUFFIX)
	$(PIN) -- $(OBJDIR)test_ebx_in_exceptions$(EXE_SUFFIX)

removeinstrumentation.test: $(OBJDIR)removeinstrumentation$(PINTOOL_SUFFIX) $(TESTAPP)
	$(RM) -f $(OBJDIR)removeinstrumentation.makefile.copy
	$(PIN) -t $(OBJDIR)removeinstrumentation$(PINTOOL_SUFFIX) -o $(OBJDIR)removeinstrumentation1.out \
	  -- $(TESTAPP) makefile $(OBJDIR)removeinstrumentation.makefile.copy
	$(CMP) makefile $(OBJDIR)removeinstrumentation.makefile.copy
	$(RM) $(OBJDIR)removeinstrumentation.makefile.copy $(OBJDIR)removeinstrumentation1.out

imageLoader.test: $(OBJDIR)imageLoad$(PINTOOL_SUFFIX) $(TESTAPP)
ifeq ($(TARGET),intel64)
	$(PIN) -t $(OBJDIR)imageLoad$(PINTOOL_SUFFIX) -l -o $(OBJDIR)imageLoader.out \
	  -- /lib64/ld-linux-x86-64.so.2 $(TESTAPP) makefile $(OBJDIR)imageLoader.makefile.copy
else
	$(PIN) -t $(OBJDIR)imageLoad$(PINTOOL_SUFFIX) -l -o $(OBJDIR)imageLoader.out \
	  -- /lib/ld-linux.so.2 $(TESTAPP) makefile $(OBJDIR)imageLoader.makefile.copy
endif
	$(QGREP) cp $(OBJDIR)imageLoader.out
	$(QGREP) libc.so.6 $(OBJDIR)imageLoader.out 
	$(RM) $(OBJDIR)imageLoader.makefile.copy $(OBJDIR)imageLoader.out 

inscount_per_image.test: $(OBJDIR)inscount_per_image$(PINTOOL_SUFFIX) $(TESTAPP)
	$(PIN) -t $< -o $(OBJDIR)inscount_per_image.out -- $(TESTAPP) makefile $(OBJDIR)inscount_per_image.makefile.copy
	$(CMP) makefile $(OBJDIR)inscount_per_image.makefile.copy
	$(RM) $(OBJDIR)inscount_per_image.makefile.copy $(OBJDIR)inscount_per_image.out


##############################################################
#
# Build rules
#
##############################################################

# This section contains the build rules for all binaries that have special build rules.
# See makefile.default.rules for the default build rules.

###### Special tools' build rules ######

$(OBJDIR)context_stack_and_spill$(PINTOOL_SUFFIX): $(OBJDIR)context_stack_and_spill$(OBJ_SUFFIX) $(SUPPORTS_AVX_OBJ)
	$(LINKER) $(TOOL_LDFLAGS) $(LINK_EXE)$@ $^ $(TOOL_LPATHS) $(TOOL_LIBS)

###### Special applications' build rules ######

# This executable is currently checked in to source control. No need to rebuild it, only
# copy it to the relevant directory.
# The originl build rule is left here as a reference.
#
# $(OBJDIR)winapp_runs_pin$(EXE_SUFFIX): winapp_runs_pin.cpp
# ifeq ($(TARGET),intel64)
#	devenv winapp_runs_pin.sln /Rebuild "Release|x64"
#	cp x64/Release/winapp_runs_pin$(EXE_SUFFIX) $(OBJDIR)winapp_runs_pin$(EXE_SUFFIX)
# else
#	devenv winapp_runs_pin.sln /Rebuild "Release|ia32"
#	cp ia32/Release/winapp_runs_pin$(EXE_SUFFIX) $(OBJDIR)winapp_runs_pin$(EXE_SUFFIX)
# endif
$(OBJDIR)winapp_runs_pin$(EXE_SUFFIX): winapp_runs_pin_$(TARGET).xex
	cp winapp_runs_pin_$(TARGET).xex $(OBJDIR)winapp_runs_pin$(EXE_SUFFIX)

$(OBJDIR)child_sig_while_execv_app$(EXE_SUFFIX): child_sig_while_execv_app.c
	$(APP_CC) $(APP_CXXFLAGS_NOOPT) $(COMP_EXE)$@ $< $(APP_LDFLAGS_NOOPT) $(APP_LIBS)

$(OBJDIR)child_sig_while_execv_simple_app$(EXE_SUFFIX): child_sig_while_execv_simple_app.c
	$(APP_CC) $(APP_CXXFLAGS_NOOPT) $(COMP_EXE)$@ $< $(APP_LDFLAGS_NOOPT) $(APP_LIBS)

$(OBJDIR)mysetenv$(EXE_SUFFIX): mysetenv.c
	$(APP_CC) $(APP_CXXFLAGS_NOOPT) $(COMP_EXE)$@ $< $(APP_LDFLAGS_NOOPT) $(APP_LIBS)

$(OBJDIR)foobar$(EXE_SUFFIX): foobar.c
	$(APP_CC) $(APP_CXXFLAGS_NOOPT) $(COMP_EXE)$@ $< $(APP_LDFLAGS_NOOPT) $(APP_LIBS)

$(OBJDIR)strcmp_win_app$(EXE_SUFFIX): strcmp_app.c
	$(APP_CC) $(APP_CXXFLAGS_NOOPT) $(COMP_EXE)$@ $< $(APP_LDFLAGS_NOOPT) $(APP_LIBS)

$(OBJDIR)memcpy_app$(EXE_SUFFIX): memcpy_app.c
	$(APP_CC) $(APP_CXXFLAGS_NOOPT) $(DEBUG_INFO_CXX_ALWAYS) $(COMP_EXE)$@ $< $(APP_LDFLAGS_NOOPT) $(APP_LIBS) \
	  $(DEBUG_INFO_LD_ALWAYS)
	
$(OBJDIR)strcmp_app$(EXE_SUFFIX): strcmp_app.c
	$(APP_CC) $(APP_CXXFLAGS_NOOPT) $(DEBUG_INFO_CXX_ALWAYS)$(COMP_EXE)$@ $< $(APP_LDFLAGS_NOOPT) $(APP_LIBS) \
	  $(DEBUG_INFO_LD_ALWAYS) 

# This application should be linked with Xed, so we add APP_LIB_XED.
$(OBJDIR)test_ebx_in_exceptions$(EXE_SUFFIX): $(OBJDIR)test_ebx_in_exceptions$(OBJ_SUFFIX) $(OBJDIR)test_ebx_in_exceptions_xed_interface$(OBJ_SUFFIX) $(OBJDIR)test_ebx_in_exceptions_asm$(OBJ_SUFFIX)
	$(APP_CXX) $(COMP_EXE)$@ $^ $(APP_LDFLAGS_NOOPT) $(APP_LPATHS) $(APP_LIBS) $(APP_LIB_XED) $(CXX_LPATHS) $(CXX_LIBS)

$(OBJDIR)illegalEnvp_app$(EXE_SUFFIX): illegalEnvp_app.c
	$(APP_CC) $(APP_CXXFLAGS_NOOPT) $(COMP_EXE)$@ $< $(APP_LDFLAGS_NOOPT) $(APP_LIBS)

$(OBJDIR)loop$(EXE_SUFFIX): loop$(ASM_SUFFIX)
	$(ASMBLR) $(ASM_FLAGS) $(COMP_EXE)$@ $< $(STATIC)

$(OBJDIR)sampleApp$(EXE_SUFFIX): sampleApp$(ASM_SUFFIX)
	$(ASMBLR) $(ASM_FLAGS) $(COMP_EXE)$@ $< $(STATIC)

$(OBJDIR)prefixApp$(EXE_SUFFIX): prefixApp$(ASM_SUFFIX)
	$(ASMBLR) $(ASM_FLAGS) $(COMP_EXE)$@ $< $(APP_LDFLAGS)

$(OBJDIR)insMixApp$(EXE_SUFFIX): insMixApp$(ASM_SUFFIX)
	$(ASMBLR) $(ASM_FLAGS) $(COMP_EXE)$@ $< $(APP_LDFLAGS)

$(OBJDIR)checkaddressapp$(EXE_SUFFIX): checkaddressapp$(ASM_SUFFIX)
	$(ASMBLR) $(ASM_FLAGS) $(COMP_EXE)$@ $<

$(OBJDIR)statdyn_app$(EXE_SUFFIX): statdyn_app.cpp
	$(APP_CXX) $(APP_CXXFLAGS_NOOPT) -Wl,--export-dynamic $(COMP_EXE)$@ $< $(APP_LDFLAGS_NOOPT) $(APP_LIBS)

###### Special objects' build rules ######

# This object is part of an application, however it needs to be be built with the static MT library so we
# use TOOL_CXXFLAGS_NOOPT instead of APP_CXXFLAGS_NOOPT.
$(OBJDIR)test_ebx_in_exceptions$(OBJ_SUFFIX): test_ebx_in_exceptions_$(OS_TYPE).cpp
	$(APP_CXX) $(TOOL_CXXFLAGS_NOOPT) $(COMP_OBJ)$@ $<

# This object is part of an application. However, it uses some Xed and Pin interfaces, so it should be
# compiled with all the flags of a tool.
$(OBJDIR)test_ebx_in_exceptions_xed_interface$(OBJ_SUFFIX): test_ebx_in_exceptions_xed_interface.cpp
	$(CXX) $(TOOL_CXXFLAGS) $(COMP_OBJ)$@ $<

###### Special dlls' build rules ######

$(OBJDIR)$(DLL_PREFIX)sourceLocation_img1$(DLL_SUFFIX): sourceLocation_img1.cpp
	$(APP_CXX) $(APP_CXXFLAGS) $(DLL_CXXFLAGS) $(COMP_EXE)$@ $< $(APP_LDFLAGS) $(DLL_LDFLAGS) $(APP_LIBS)

$(OBJDIR)$(DLL_PREFIX)sourceLocation_img2$(DLL_SUFFIX): sourceLocation_img2.cpp
	$(APP_CXX) $(APP_CXXFLAGS) $(DLL_CXXFLAGS) $(COMP_EXE)$@ $< $(APP_LDFLAGS) $(DLL_LDFLAGS) $(APP_LIBS)
