##############################################################
#
# 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 :=

# This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS.
TEST_ROOTS :=

# 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 :=

# This defines the tools which will be run during the the tests, and were not already defined in
# TEST_TOOL_ROOTS.
TOOL_ROOTS :=

# 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 :=

# 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 OS-specific definitions here ######

# Android
ifeq ($(TARGET_OS),android)
    TEST_ROOTS += fork_vm_lock badexec fork_jit sigchld bind_now follow_execv_with_config1 follow_execv_with_config2 \
                  follow_execv_with_config3 apparmor unique_logfile injectchild injectparent selfexec selfexeclog \
                  unix_launcher null_argument
    TOOL_ROOTS += fork_vm_lock_tool fork_jit_tool fork_probed_tool follow_child unix_parent_tool null_arg_check_tool \
                  bind_now_tool simple_tool
    APP_ROOTS += fork_vm_lock_app fork_app vfork_app fork_app_static vfork_app_static parent_process child_process \
                 injection_test_app sigchld_app null_check_app1 null_check_app2 bind_now_app badexec selfexec_app
    ifeq ($(PROBE),1)
        TEST_ROOTS += fork_probed vfork_probed fork_probed_static vfork_probed_static follow_execv_with_config1_probe \
                      follow_execv_with_config2_probe follow_execv_with_config3_probe null_argument_probed execve_errno \
                      sigchld2
    endif 
endif

# Linux
ifeq ($(TARGET_OS),linux)
    TEST_ROOTS += fork_vm_lock badexec fork_jit sigchld bind_now follow_execv_with_config1 follow_execv_with_config2 \
                  follow_execv_with_config3 apparmor unique_logfile injectchild injectparent selfexec selfexeclog \
                  unix_launcher null_argument
    TOOL_ROOTS += fork_vm_lock_tool fork_jit_tool fork_probed_tool follow_child unix_parent_tool null_arg_check_tool \
                  bind_now_tool simple_tool
    APP_ROOTS += fork_vm_lock_app fork_app vfork_app fork_app_static vfork_app_static parent_process child_process \
                 injection_test_app sigchld_app null_check_app1 null_check_app2 bind_now_app badexec selfexec_app
    ifeq ($(PROBE),1)
        TEST_ROOTS += fork_probed vfork_probed fork_probed_static vfork_probed_static follow_execv_with_config1_probe \
                      follow_execv_with_config2_probe follow_execv_with_config3_probe null_argument_probed execve_errno \
                      sigchld2
    endif 
endif

# Mac
ifeq ($(TARGET_OS),mac)
    TEST_ROOTS += fork_jit badexec unique_logfile_mac null_argument follow_execv_with_config1 follow_execv_with_config2 \
                  follow_execv_with_config3
    TOOL_ROOTS += fork_jit_tool follow_child unix_parent_tool null_arg_check_tool
    APP_ROOTS += fork_app vfork_app parent_process child_process injection_test_app null_check_app1 null_check_app2 \
                 badexec
    ifeq ($(TARGET),intel64)
        # OS X* doesn't support follow-execv for mixed arch and /bin/sh is 64 bits
        # therefore, since can't run script cross-platform unix_launcher can be 
        # tested only in 64 bits target.
        TEST_ROOTS += unix_launcher
    endif
endif

# Windows
ifeq ($(TARGET_OS),windows)
    TEST_ROOTS += win_parent_process1 win_parent_process1_probed win_parent_process1_unicode_probed \
                  win_parent_process2_jjj win_parent_process2_jjp win_parent_process2_jpj win_parent_process2_jpp \
                  win_parent_process2_pjj win_parent_process2_pjp win_parent_process2_ppj win_parent_process2_ppp \
                  win_parent_process2_unicode_ppp win_parent_process2_mt_ppp win_parent_process1_unicode_probed_withsym \
                  win_early_termination win_early_termination_debugged win_early_termination_probed \
                  win_early_termination_probed_debugged
    TOOL_ROOTS += follow_child_3gen_tool follow_child_3gen_tool_initsym grand_parent_tool parent_tool follow_child_tool
    APP_ROOTS += win_parent_process win_child_process win_launcher_process win_launcher_debugged_process \
                 win_early_termination win_parent_process_unicode win_parent_process_mt
    DLL_ROOTS += win_terminate_process_dll
endif

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

# TODO: These tests fail - fix and remove the following:

#See Mantis 3188
ifeq ($(TARGET_OS),mac)
    TEST_ROOTS := $(filter-out badexec follow_execv_with_config1 follow_execv_with_config2 follow_execv_with_config3 \
                               fork_jit null_argument unique_logfile_mac unix_launcher, $(TEST_ROOTS))
endif

# See Mantis 3189
ifeq ($(TARGET_OS),linux)
    ifeq ($(HOST_ARCH),intel64)
        ifeq ($(TARGET),ia32)
            TEST_ROOTS := $(filter-out sigchld2 execve_errno null_argument null_argument_probed unix_launcher, \
                                       $(TEST_ROOTS))
        endif
    endif
endif

#See Mantis 3109 for the following tests (Runtime errors): selfexec, selfexeclog,injectchild, injectparent,
# vfork_probed_static
ifeq ($(TARGET_OS),android)
    TEST_ROOTS := $(filter-out sigchld2 execve_errno null_argument null_argument_probed unix_launcher injectchild selfexec \
                               selfexeclog injectparent vfork_probed_static, $(TEST_ROOTS))
endif

# See Mantis 2603
ifeq ($(TARGET_OS),windows)
    TEST_ROOTS := $(filter-out win_early_termination_debugged win_early_termination_probed_debugged, $(TEST_ROOTS))
endif


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

###### Finalize sanity here ######

SANITY_SUBSET := $(TEST_TOOL_ROOTS) $(TEST_ROOTS)

# 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

injectchild.test: $(OBJDIR)injection_test_app$(EXE_SUFFIX)
	$(PIN) -injection child -- $(OBJDIR)injection_test_app$(EXE_SUFFIX) ch_file

injectparent.test: $(OBJDIR)injection_test_app$(EXE_SUFFIX)
	$(PIN) -injection parent -- $(OBJDIR)injection_test_app$(EXE_SUFFIX) pa_file

# This test is not run by default because it is expected to fail sometimes.  The "self"
# injection mode will fail if the kernel happens to load the Pin image in a range that
# conflicts with the application.  Since there is some randomness in the address ranges
# the kernel selects for Pin and it's shared libraries, this test will sometimes fail
# and sometimes succeed.  It appears to me (gmlueck) that it fails about 1 in 10 tries.
injectself.test:
	touch $(OBJDIR)injectself.makefile.copy; $(RM) $(OBJDIR)injectself.makefile.copy
	$(PIN) -injection self -- $(TESTAPP) makefile $(OBJDIR)injectself.makefile.copy
	$(DIFF) makefile $(OBJDIR)injectself.makefile.copy
	$(RM) $(OBJDIR)injectself.makefile.copy

fork_jit.test: $(OBJDIR)fork_jit_tool$(PINTOOL_SUFFIX) $(OBJDIR)fork_app$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)fork_jit_tool$(PINTOOL_SUFFIX) -o $(OBJDIR)fork_jit.out -- $(OBJDIR)fork_app$(EXE_SUFFIX)
	$(QGREP) "correct in child process" $(OBJDIR)fork_jit.out*
	$(QGREP) "correct in parent process" $(OBJDIR)fork_jit.out*
	$(RM) $(OBJDIR)fork_jit.out*

fork_probed.test: $(OBJDIR)fork_probed_tool$(PINTOOL_SUFFIX) $(OBJDIR)fork_app$(EXE_SUFFIX)
	$(PIN) -t $(OBJDIR)fork_probed_tool$(PINTOOL_SUFFIX) -o $(OBJDIR)fork_probed.out -- $(OBJDIR)fork_app$(EXE_SUFFIX)
	$(QGREP) "After fork in parent" $(OBJDIR)fork_probed.out*
	$(QGREP) "After fork in child" $(OBJDIR)fork_probed.out*
	$(RM) $(OBJDIR)fork_probed.out*

vfork_probed.test: $(OBJDIR)fork_probed_tool$(PINTOOL_SUFFIX) $(OBJDIR)vfork_app$(EXE_SUFFIX) $(OBJDIR)null_check_app2$(EXE_SUFFIX)
	$(PIN) -follow_execv -t $(OBJDIR)fork_probed_tool$(PINTOOL_SUFFIX) -o $(OBJDIR)vfork_probed.out \
	  --  $(OBJDIR)vfork_app$(EXE_SUFFIX) $(OBJDIR)null_check_app2$(EXE_SUFFIX)
	$(QGREP) Before $(OBJDIR)vfork_probed.out*
	$(QGREP) "After fork in parent" $(OBJDIR)vfork_probed.out*
	$(QGREP) "After fork in child" $(OBJDIR)vfork_probed.out*
	$(QGREP) "At follow child callback in child process" $(OBJDIR)vfork_probed.out*
	$(QGREP) "At follow child callback in parent process" $(OBJDIR)vfork_probed.out*
	$(RM) -f $(OBJDIR)vfork_probed.out*

fork_probed_static.test: $(OBJDIR)fork_probed_tool$(PINTOOL_SUFFIX) $(OBJDIR)fork_app_static$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)fork_probed_static.out*
	$(PIN) -t $(OBJDIR)fork_probed_tool$(PINTOOL_SUFFIX) -o $(OBJDIR)fork_probed_static.out \
	  -- $(OBJDIR)fork_app_static$(EXE_SUFFIX)
	$(QGREP) "After fork in parent" $(OBJDIR)fork_probed_static.out*
	$(QGREP) "After fork in child" $(OBJDIR)fork_probed_static.out*
	$(RM) $(OBJDIR)fork_probed_static.out*

vfork_probed_static.test: $(OBJDIR)fork_probed_tool$(PINTOOL_SUFFIX) $(OBJDIR)vfork_app_static$(EXE_SUFFIX) $(OBJDIR)null_check_app2$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)vfork_probed_static.out*
	$(PIN) -follow_execv -t $(OBJDIR)fork_probed_tool$(PINTOOL_SUFFIX) -o $(OBJDIR)vfork_probed_static.out \
	  --  $(OBJDIR)vfork_app_static$(EXE_SUFFIX) $(OBJDIR)null_check_app2$(EXE_SUFFIX)
	$(QGREP) Before $(OBJDIR)vfork_probed_static.out*
	$(QGREP) "After fork in parent" $(OBJDIR)vfork_probed_static.out*
	$(QGREP) "After fork in child" $(OBJDIR)vfork_probed_static.out*
	$(RM) -f  $(OBJDIR)vfork_probed_static.out*

sigchld.test: $(OBJDIR)sigchld_app$(EXE_SUFFIX)
	$(PIN) -follow_execv -injection parent -- $(OBJDIR)sigchld_app$(EXE_SUFFIX)
	$(DIFF) sigchld_app.out sigchld_app.reference
	$(PIN) -follow_execv -injection child -- $(OBJDIR)sigchld_app$(EXE_SUFFIX)
	$(RM) sigchld_app.out

sigchld2.test: $(OBJDIR)simple_tool$(PINTOOL_SUFFIX) uname_script.sh
	$(PIN) -follow_execv -injection parent -t $(OBJDIR)simple_tool$(PINTOOL_SUFFIX) -probe \
	  -- ./uname_script.sh $(OBJDIR)sigchld2.out 
	uname -s > $(OBJDIR)uname_expected.out
	$(CMP) $(OBJDIR)uname_expected.out $(OBJDIR)sigchld2.out
	$(PIN) -follow_execv -injection child -t $(OBJDIR)simple_tool$(PINTOOL_SUFFIX) -probe \
	  -- ./uname_script.sh $(OBJDIR)sigchld2_inj_child.out
	$(RM) -f $(OBJDIR)uname_expected.out $(OBJDIR)sigchld2.out $(OBJDIR)sigchld2_inj_child.out

fork_vm_lock.test: $(OBJDIR)fork_vm_lock_tool$(PINTOOL_SUFFIX) $(OBJDIR)fork_vm_lock_app$(EXE_SUFFIX)
	$(PIN) -follow_execv -t $(OBJDIR)fork_vm_lock_tool$(PINTOOL_SUFFIX) -- $(OBJDIR)fork_vm_lock_app$(EXE_SUFFIX) 

# (1) do not run child under the Pin
follow_execv_with_config1.test: $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX)
	$(PIN) -follow_execv 1 -t $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) \
	  -o $(OBJDIR)$(@:test=tool.out) -app ./child_process_xxx \
	    -- $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) "param1 param2" param3 \
	      > $(OBJDIR)$(@:test=app.out)
	## child_process_xxx is not equal to child_process, do not run child under Pin at all
	$(QGREP) "Do not run Pin under the child process" $(OBJDIR)$(@:test=tool.out)
	## unix_parent_tool should appear 1 time in the output since it was used in parent only
	$(BASHTEST) `$(CGREP) "In unix_parent_tool PinTool" $(OBJDIR)$(@:test=tool.out)` -eq "1"
	$(RM) $(OBJDIR)$(@:test=app.out) $(OBJDIR)$(@:test=tool.out)

# (1-probe) do not run child under the Pin
follow_execv_with_config1_probe.test: $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX)
	$(PIN) -follow_execv 1 -t $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) \
	  -o $(OBJDIR)follow_execv_with_config1_probe.tool.out -xyzzy -probe -app ./child_process_xxx \
	    -- $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) "param1 param2" param3 \
	      > $(OBJDIR)follow_execv_with_config1_probe.app.out
	## child_process_xxx is not equal to child_process, do not run child under Pin at all
	$(QGREP) "Do not run Pin under the child process" $(OBJDIR)follow_execv_with_config1_probe.tool.out
	## unix_parent_tool should appear 1 time in the output since it was used in parent only
	$(BASHTEST) `$(CGREP) "In unix_parent_tool PinTool" $(OBJDIR)follow_execv_with_config1_probe.tool.out` -eq "1"
	$(RM) -f $(OBJDIR)follow_execv_with_config1_probe.tool.out $(OBJDIR)follow_execv_with_config1_probe.app.out

# (2) run child under the Pin, but don't change Pin command line
follow_execv_with_config2.test: $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX)
	$(PIN) -follow_execv 1 -t $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) \
	  -o $(OBJDIR)follow_execv_with_config2.tool.out -xyzzy -app $(OBJDIR)child_process$(EXE_SUFFIX) \
	    -- $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) "param1 param2" param3 \
	      > $(OBJDIR)follow_execv_with_config2.app.out
	## -app argument is equal to application name, run the child process under the Pin
	$(QGREP) "Pin command line remains unchanged" $(OBJDIR)follow_execv_with_config2.tool.out
	## unix_parent_tool should appear 2 times in the output since it was used in the parent and in the child
	$(BASHTEST) `$(CGREP) "In unix_parent_tool PinTool" $(OBJDIR)follow_execv_with_config2.tool.out` -eq "2"
	$(RM) $(OBJDIR)follow_execv_with_config2.tool.out $(OBJDIR)follow_execv_with_config2.app.out

# (2-probe) run child under the Pin, but don't change Pin command line
follow_execv_with_config2_probe.test: $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX)
	$(PIN) -follow_execv 1 -t $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) \
	  -o $(OBJDIR)follow_execv_with_config2_probe.tool.out -xyzzy -probe -app $(OBJDIR)child_process$(EXE_SUFFIX) -- \
	    $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) "param1 param2" param3 \
	      > $(OBJDIR)follow_execv_with_config2_probe.app.out
	## -app argument is equal to application name, run the child process under the Pin
	$(QGREP) "Pin command line remains unchanged" $(OBJDIR)follow_execv_with_config2_probe.tool.out
	## unix_parent_tool should appear 2 times in the output since it was used in the parent and in the child
	$(BASHTEST) `$(CGREP) "In unix_parent_tool PinTool" $(OBJDIR)follow_execv_with_config2_probe.tool.out` -eq "2"
	$(RM) $(OBJDIR)follow_execv_with_config2_probe.app.out $(OBJDIR)follow_execv_with_config2_probe.tool.out

# (3) run child under the Pin, and change Pin command line
follow_execv_with_config3.test: $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) $(OBJDIR)follow_child$(PINTOOL_SUFFIX)
	$(PIN) -follow_execv 1 -t $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) \
	  -o $(OBJDIR)follow_execv_with_config3.tool.out -xyzzy -app $(OBJDIR)child_process$(EXE_SUFFIX) \
	    -pin "$(PIN) -t $(OBJDIR)follow_child$(PINTOOL_SUFFIX) -o $(OBJDIR)follow_execv_with_config3.childtool.out" \
	      -- $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) "param1 param2" param3 \
	        > $(OBJDIR)follow_execv_with_config3.app.out
	## change Pin command line
	$(QGREP) "Process to execute" $(OBJDIR)follow_execv_with_config3.tool.out
	## unix_parent_tool should appear 1 time in the output since it was used in the parent only
	$(BASHTEST) `$(CGREP) "In unix_parent_tool PinTool" $(OBJDIR)follow_execv_with_config3.tool.out` -eq "1"
	## follow_child tool should appear 1 time in the output since it was used in the child only
	$(BASHTEST) `$(CGREP) "In follow_child PinTool" $(OBJDIR)follow_execv_with_config3.childtool.out` -eq "1"
	$(RM) $(OBJDIR)follow_execv_with_config3.tool.out $(OBJDIR)follow_execv_with_config3.app.out \
	  $(OBJDIR)follow_execv_with_config3.childtool.out

# (3-probe) run child under the Pin, and change Pin command line
follow_execv_with_config3_probe.test: $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) $(OBJDIR)follow_child$(PINTOOL_SUFFIX)
	$(PIN) -follow_execv 1 -t $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) \
	  -o $(OBJDIR)$(@:test=tool.out) -xyzzy -probe -app $(OBJDIR)child_process$(EXE_SUFFIX) \
	    -pin "$(PIN) -t ./$(OBJDIR)follow_child$(PINTOOL_SUFFIX) -o $(OBJDIR)$(@:test=childtool.out)" \
	      -- $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) "param1 param2" param3 \
	        > $(OBJDIR)$(@:test=app.out)
	## change Pin command line
	$(QGREP) "Process to execute" $(OBJDIR)$(@:test=tool.out)
	## unix_parent_tool should appear 1 time in the output since it was used in the parent only
	$(BASHTEST) `$(CGREP) "In unix_parent_tool PinTool" $(OBJDIR)$(@:test=tool.out)` -eq "1"
	## follow_child tool should appear 1 time in the output since it was used in the child only
	$(BASHTEST) `$(CGREP) "In follow_child PinTool" $(OBJDIR)$(@:test=childtool.out) ` -eq "1"
	$(RM) $(OBJDIR)$(@:test=*.out)

# launcher runs parent_process twice; parent_process runs child_process
unix_launcher.test: $(OBJDIR)follow_child$(PINTOOL_SUFFIX) $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) parent_process_launcher.sh
	./parent_process_launcher.sh $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) \
	  > $(OBJDIR)unix_launcher.reference
	$(PIN) -follow_execv 1 -t $(OBJDIR)follow_child$(PINTOOL_SUFFIX) -o $(OBJDIR)$(@:test=tool.out) -- \
	  /bin/sh ./parent_process_launcher.sh $(OBJDIR)parent_process $(OBJDIR)child_process > $(OBJDIR)$(@:test=app.out)
	$(DIFF) $(OBJDIR)$(@:test=app.out) $(OBJDIR)unix_launcher.reference
	## PinTool should appear 5 times: 
	## parent_process_launcher.sh - 1, parent_process - 2 child_process - 2
	$(BASHTEST) `$(CGREP) PinTool $(OBJDIR)$(@:test=tool.out)` -eq "5"
	$(RM) $(OBJDIR)$(@:test=*.out) $(OBJDIR)unix_launcher.reference

selfexec.test: $(OBJDIR)selfexec_app$(EXE_SUFFIX)
	$(PIN) -follow_execv 1 -- $(OBJDIR)selfexec_app$(EXE_SUFFIX) > $(OBJDIR)selfexec.out
	$(QGREP) "Number of recursive calls" $(OBJDIR)selfexec.out
	$(RM) $(OBJDIR)selfexec.out

selfexeclog.test: $(OBJDIR)selfexec_app$(EXE_SUFFIX)
	$(PIN) -follow_execv 1 -xyzzy -mesgon log_syscall -logfile $(OBJDIR)selfexeclog.log \
	  -- $(OBJDIR)selfexec_app$(EXE_SUFFIX) > $(OBJDIR)selfexeclog.out
	$(QGREP) "Number of recursive calls" $(OBJDIR)selfexeclog.out
	$(RM) $(OBJDIR)selfexeclog.out $(OBJDIR)selfexeclog.log

# Execve with 0 in second argument execv(app, NULL)
null_argument.test: $(OBJDIR)null_arg_check_tool$(PINTOOL_SUFFIX) $(OBJDIR)null_check_app1$(EXE_SUFFIX) $(OBJDIR)null_check_app2$(EXE_SUFFIX)
	$(PIN) -follow_execv 1 -t $(OBJDIR)null_arg_check_tool$(PINTOOL_SUFFIX) \
	  -- $(OBJDIR)null_check_app1$(EXE_SUFFIX) $(OBJDIR)null_check_app2$(EXE_SUFFIX)

null_argument_probed.test: $(OBJDIR)null_arg_check_tool$(PINTOOL_SUFFIX) $(OBJDIR)null_check_app1$(EXE_SUFFIX) $(OBJDIR)null_check_app2$(EXE_SUFFIX)
	$(PIN) -follow_execv 1 -probe -t $(OBJDIR)null_arg_check_tool$(PINTOOL_SUFFIX) \
	  -- $(OBJDIR)null_check_app1$(EXE_SUFFIX) $(OBJDIR)null_check_app2$(EXE_SUFFIX)

# Execve fails and returns with error code
badexec.test: $(OBJDIR)badexec$(EXE_SUFFIX)
	$(OBJDIR)badexec$(EXE_SUFFIX) > $(OBJDIR)badexec.reference
	$(PIN) -xyzzy -follow_execv 1 -- $(OBJDIR)badexec > $(OBJDIR)badexec.out 2>&1
	$(DIFF) $(OBJDIR)badexec.out $(OBJDIR)badexec.reference
	$(RM) $(OBJDIR)badexec.out $(OBJDIR)badexec.reference 

# Execve fails and and sets errno
# Bash checks errno value after execve return
execve_errno.test: $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) 1.sh 2.sh
	$(PIN) -follow_execv -t $(OBJDIR)unix_parent_tool$(PINTOOL_SUFFIX) -o $(@:test=tool.out) -probe -app ./2.sh \
	  -- ./1.sh > $(@:test=app.out) 2>&1
	$(QGREP) SUCCESS $(@:test=app.out)
	$(RM) $(@:test=*.out)

# Test for getpid() inside Pin; -unique_logfile calls to getpid()
unique_logfile.test: $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)unique_logfile.log.*
	$(PIN) -follow_execv 1 -xyzzy -mesgon log_syscall -logfile $(OBJDIR)unique_logfile.log -unique_logfile \
	  -injection child \
	    -- $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) "param1 param2" param3 \
	      > $(OBJDIR)unique_logfile.out
	$(BASHTEST) `ls $(OBJDIR)unique_logfile.log.* | $(LINECOUNT)` -eq 2
	$(RM) $(OBJDIR)unique_logfile.log.* $(OBJDIR)unique_logfile.out
	$(PIN) -follow_execv 1 -xyzzy -mesgon log_syscall -logfile $(OBJDIR)unique_logfile.log -unique_logfile \
	  -injection parent \
	    -- $(OBJDIR)parent_process$(EXE_SUFFIX) $(OBJDIR)child_process$(EXE_SUFFIX) "param1 param2" param3 \
	      > $(OBJDIR)unique_logfile.out
	$(BASHTEST) `ls $(OBJDIR)unique_logfile.log.* | $(LINECOUNT)` -eq 2
	$(RM) $(OBJDIR)unique_logfile.log.* $(OBJDIR)unique_logfile.out

unique_logfile_mac.test: $(OBJDIR)parent_process $(OBJDIR)child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)unique_logfile_mac.log.*
	$(PIN) -follow_execv 1 -xyzzy -mesgon log_syscall -logfile $(OBJDIR)unique_logfile_mac.log -unique_logfile \
	  -- $(OBJDIR)parent_process $(OBJDIR)child_process "param1 param2" param3 > $(OBJDIR)unique_logfile_mac.out
	$(BASHTEST) `ls $(OBJDIR)unique_logfile_mac.log.* | $(LINECOUNT)` -eq 2
	$(RM) $(OBJDIR)unique_logfile_mac.log.* $(OBJDIR)unique_logfile_mac.out

# Test for LD_BIND_NOW
bind_now.test: $(OBJDIR)bind_now_tool$(PINTOOL_SUFFIX) $(OBJDIR)bind_now_app$(EXE_SUFFIX)
	$(RM) -f bind_now.out
	$(PIN) -follow_execv -t $(OBJDIR)bind_now_tool$(PINTOOL_SUFFIX) -- $(OBJDIR)bind_now_app$(EXE_SUFFIX) -child
	$(BASHTEST) `$(CGREP) "LD_BIND_NOW was found" bind_now.out` -eq 5
	$(RM) bind_now.out

# Test for Pin injection in application guarded by AppArmor
apparmor.test:
	if $(BASHTEST) -f /etc/apparmor.d/bin.netstat && $(BASHTEST) -f /bin/netstat ; then \
	  $(PIN) -- netstat -g > $(OBJDIR)apparmor.out 2>&1 || $(GREP) AppArmor $(OBJDIR)apparmor.out; \
	  $(RM) $(OBJDIR)apparmor.out; \
	fi
	if $(BASHTEST) -f /etc/apparmor.d/usr.sbin.nscd && $(BASHTEST) -f /usr/sbin/nscd ; then \
	  $(PIN) -- /usr/sbin/nscd -V > $(OBJDIR)apparmor.out 2>&1 || $(GREP) AppArmor $(OBJDIR)apparmor.out; \
	  $(RM) $(OBJDIR)apparmor.out; \
	fi

# (1) run child under the Pin, but don't change Pin command line
win_parent_process1.test: $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process1.out
	$(PINBIN) $(PIN_TESTFLAGS) $(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv \
	  -t $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) \
	    -- $(CMD) win_parent_process_launcher.bat $(OBJDIR) > $(OBJDIR)win_parent_process1.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process1.out win_parent_process1.reference
	$(RM) $(OBJDIR)win_parent_process1.out

win_parent_process1_probed.test: $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process1_probed.out
	$(PINBIN) $(PIN_TESTFLAGS) $(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -probe \
	  -t $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) \
	    -- $(CMD) win_parent_process_launcher.bat $(OBJDIR) > $(OBJDIR)win_parent_process1_probed.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process1_probed.out win_parent_process1_probed.reference
	$(RM) $(OBJDIR)win_parent_process1_probed.out

win_parent_process1_unicode_probed.test: $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process_unicode$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process1_unicode_probed.out
	$(PINBIN) $(PIN_TESTFLAGS) $(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -probe \
	  -t $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) \
	    -- $(CMD) win_parent_process_unicode_launcher.bat $(OBJDIR) > $(OBJDIR)win_parent_process1_unicode_probed.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process1_unicode_probed.out win_parent_process1_unicode_probed.reference
	$(RM) $(OBJDIR)win_parent_process1_unicode_probed.out

win_parent_process1_unicode_probed_withsym.test: $(OBJDIR)follow_child_3gen_tool_initsym$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process_unicode$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process1_unicode_probed_withsym.out
	$(PINBIN) $(PIN_TESTFLAGS) $(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -probe \
	  -t $(OBJDIR)follow_child_3gen_tool_initsym$(PINTOOL_SUFFIX) \
	    -- $(CMD) win_parent_process_unicode_launcher.bat $(OBJDIR) \
	      > $(OBJDIR)win_parent_process1_unicode_probed_withsym.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process1_unicode_probed_withsym.out win_parent_process1_unicode_probed_withsym.reference
	$(RM) $(OBJDIR)win_parent_process1_unicode_probed_withsym.out

win_early_termination.test: $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_launcher_process$(EXE_SUFFIX) $(OBJDIR)win_early_termination$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_early_termination.out
	$(PINBIN) $(PIN_TESTFLAGS) $(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv \
	  -t $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) \
	    -- $(OBJDIR)win_launcher_process$(EXE_SUFFIX) $(OBJDIR)win_early_termination$(EXE_SUFFIX) \
	      > $(OBJDIR)win_early_termination.out 2>&1
	$(BASHTEST) `$(CGREP) "At follow child callback" $(OBJDIR)win_early_termination.out` -eq "1"
	$(QGREP) "Terminating process in DllMain(PROCESS_ATTACH)" $(OBJDIR)win_early_termination.out
	$(RM) $(OBJDIR)win_early_termination.out

	$(PINBIN) $(PIN_TESTFLAGS) $(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv \
	  -t $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) -load_system_dlls 1 \
	    -- $(OBJDIR)win_launcher_process$(EXE_SUFFIX) $(OBJDIR)win_early_termination$(EXE_SUFFIX) \
	      > $(OBJDIR)win_early_termination.out 2>&1
	$(BASHTEST) `$(CGREP) "In tool's main, probed = 0" $(OBJDIR)win_early_termination.out` -eq "2"
	$(BASHTEST) `$(CGREP) "At follow child callback" $(OBJDIR)win_early_termination.out` -eq "1"
	$(QGREP) "Terminating process in DllMain(PROCESS_ATTACH)" $(OBJDIR)win_early_termination.out
	$(RM) $(OBJDIR)win_early_termination.out

win_early_termination_debugged.test: $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_launcher_debugged_process$(EXE_SUFFIX) $(OBJDIR)win_early_termination$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_early_termination_debugged.out
	$(PINBIN) $(PIN_TESTFLAGS) $(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv \
	  -t $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) \
	    -- $(OBJDIR)win_launcher_debugged_process$(EXE_SUFFIX) $(OBJDIR)win_early_termination$(EXE_SUFFIX) \
	      > $(OBJDIR)win_early_termination_debugged.out 2>&1
	$(BASHTEST) `$(CGREP) "In tool's main, probed = 0" $(OBJDIR)win_early_termination_debugged.out` -eq "1"
	$(BASHTEST) `$(CGREP) "At follow child callback" $(OBJDIR)win_early_termination_debugged.out` -eq "1"
	$(QGREP) "Terminating process in DllMain(PROCESS_ATTACH)" $(OBJDIR)win_early_termination_debugged.out
	$(RM) $(OBJDIR)win_early_termination_debugged.out

	$(PINBIN) $(PIN_TESTFLAGS) $(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv \
	  -t $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) -load_system_dlls 1 \
	    -- $(OBJDIR)win_launcher_debugged_process$(EXE_SUFFIX) $(OBJDIR)win_early_termination$(EXE_SUFFIX) \
	      > $(OBJDIR)win_early_termination_debugged.out 2>&1
	$(BASHTEST) `$(CGREP) "In tool's main, probed = 0" $(OBJDIR)win_early_termination_debugged.out` -eq "1"
	$(BASHTEST) `$(CGREP) "At follow child callback" $(OBJDIR)win_early_termination_debugged.out` -eq "1"
	$(QGREP) "Terminating process in DllMain(PROCESS_ATTACH)" $(OBJDIR)win_early_termination_debugged.out
	$(RM) $(OBJDIR)win_early_termination_debugged.out

win_early_termination_probed.test: $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_launcher_process$(EXE_SUFFIX) $(OBJDIR)win_launcher_debugged_process$(EXE_SUFFIX) $(OBJDIR)win_early_termination$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_early_termination_probed.out
	$(PINBIN) $(PIN_TESTFLAGS) $(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -probe -follow_execv \
	  -t $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) \
	    -- $(OBJDIR)win_launcher_process$(EXE_SUFFIX) $(OBJDIR)win_early_termination$(EXE_SUFFIX) \
	      > $(OBJDIR)win_early_termination_probed.out 2>&1
	$(BASHTEST) `$(CGREP) "In tool's main, probed = 1" $(OBJDIR)win_early_termination_probed.out` -eq "2"
	$(BASHTEST) `$(CGREP) "At follow child callback" $(OBJDIR)win_early_termination_probed.out` -eq "1"
	$(QGREP) "Terminating process in DllMain(PROCESS_ATTACH)" $(OBJDIR)win_early_termination_probed.out
	$(RM) $(OBJDIR)win_early_termination_probed.out

	$(PINBIN) $(PIN_TEST_FLAGS) -p32 $(PIN32) -p64 $(PIN64) -probe -follow_execv \
	  -t $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) -load_system_dlls 1\
	    -- $(OBJDIR)win_launcher_process $(OBJDIR)win_early_termination$(EXE_SUFFIX) > $(OBJDIR)win_early_termination_probed.out 2>&1
	$(BASHTEST) `$(CGREP) "In tool's main, probed = 1" $(OBJDIR)win_early_termination_probed.out` -eq "2"
	$(BASHTEST) `$(CGREP) "At follow child callback" $(OBJDIR)win_early_termination_probed.out` -eq "1"
	$(QGREP) "Terminating process in DllMain(PROCESS_ATTACH)" $(OBJDIR)win_early_termination_probed.out
	$(RM) $(OBJDIR)win_early_termination_probed.out

win_early_termination_probed_debugged.test: $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_launcher_debugged_process$(EXE_SUFFIX) $(OBJDIR)win_early_termination$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_early_termination_probed_debugged.out
	$(PINBIN) $(PIN_TESTFLAGS) $(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -probe -follow_execv \
	  -t $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) \
	    -- $(OBJDIR)win_launcher_debugged_process$(EXE_SUFFIX) $(OBJDIR)win_early_termination$(EXE_SUFFIX) \
	      > $(OBJDIR)win_early_termination_probed_debugged.out 2>&1
	$(BASHTEST) `$(CGREP) "In tool's main, probed = 1" $(OBJDIR)win_early_termination_probed_debugged.out` -eq "1"
	$(BASHTEST) `$(CGREP) "At follow child callback" $(OBJDIR)win_early_termination_probed_debugged.out` -eq "1"
	$(QGREP) "Terminating process in DllMain(PROCESS_ATTACH)" $(OBJDIR)win_early_termination_probed_debugged.out
	$(RM) $(OBJDIR)win_early_termination_probed_debugged.out

	$(PINBIN) $(PIN_TESTFLAGS) $(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -probe -follow_execv \
	  -t $(OBJDIR)follow_child_tool$(PINTOOL_SUFFIX) -load_system_dlls 1 \
	    -- $(OBJDIR)win_launcher_debugged_process$(EXE_SUFFIX) $(OBJDIR)win_early_termination$(EXE_SUFFIX) \
	      > $(OBJDIR)win_early_termination_probed_debugged.out 2>&1
	$(BASHTEST) `$(CGREP) "In tool's main, probed = 1" $(OBJDIR)win_early_termination_probed_debugged.out` -eq "1"
	$(BASHTEST) `$(CGREP) "At follow child callback" $(OBJDIR)win_early_termination_probed_debugged.out` -eq "1"
	$(QGREP) "Terminating process in DllMain(PROCESS_ATTACH)" $(OBJDIR)win_early_termination_probed_debugged.out
	$(RM) $(OBJDIR)win_early_termination_probed_debugged.out

# (2) run child processes under Pin for some processes (filter by name), and change Pin command line for them.
# j means jitted, p means probed - so win_parent_process2_jjp.test means:
# grandparent jitted, parent jitted, child probed

#jjj
win_parent_process2_jjj.test: $(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process2_jjj.out
	$(CMD) win_parent_process_test_launcher.bat $(PINBIN) "$(PIN_TESTFLAGS)" \
	  "$(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -t" "$(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX)" \
	    "-- $(CMD) win_parent_process_launcher.bat $(OBJDIR)" >  $(OBJDIR)win_parent_process2_jjj.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process2_jjj.out win_parent_process2_jjj.reference
	$(RM) $(OBJDIR)win_parent_process2_jjj.out

#jjp
win_parent_process2_jjp.test: $(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process2_jjp.out
	$(CMD) win_parent_process_test_launcher_w_pintool_args.bat $(PINBIN) "$(PIN_TESTFLAGS)" \
	  "$(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -t" "$(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX)" \
	  "-probe_grand_child 1" "-- $(CMD) win_parent_process_launcher.bat $(OBJDIR)" \
	    > $(OBJDIR)win_parent_process2_jjp.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process2_jjp.out win_parent_process2_jjp.reference
	$(RM) $(OBJDIR)win_parent_process2_jjp.out

#jpj
win_parent_process2_jpj.test: $(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process2_jpj.out
	$(CMD) win_parent_process_test_launcher_w_pintool_args.bat $(PINBIN) "$(PIN_TESTFLAGS)" \
	  "$(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -t" "$(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX)" \
	  "-probe_child 1" "-- $(CMD) win_parent_process_launcher.bat $(OBJDIR)" > $(OBJDIR)win_parent_process2_jpj.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process2_jpj.out win_parent_process2_jpj.reference
	$(RM) $(OBJDIR)win_parent_process2_jpj.out

#jpp
win_parent_process2_jpp.test: $(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process2_jpp.out
	$(CMD) win_parent_process_test_launcher_w_pintool_args.bat $(PINBIN) "$(PIN_TESTFLAGS)" \
	  "$(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -t" "$(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX)" \
	  "-probe_child 1 -probe_grand_child 1" "-- $(CMD) win_parent_process_launcher.bat $(OBJDIR)" \
	    > $(OBJDIR)win_parent_process2_jpp.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process2_jpp.out win_parent_process2_jpp.reference
	$(RM) $(OBJDIR)win_parent_process2_jpp.out

#pjj
win_parent_process2_pjj.test: $(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process2_pjj.out
	$(CMD) win_parent_process_test_launcher.bat $(PINBIN) "$(PIN_TESTFLAGS)" \
	  "$(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -probe -t" "$(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX)" \
	  "-- $(CMD) win_parent_process_launcher.bat $(OBJDIR)" > $(OBJDIR)win_parent_process2_pjj.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process2_pjj.out win_parent_process2_pjj.reference
	$(RM) $(OBJDIR)win_parent_process2_pjj.out

#pjp
win_parent_process2_pjp.test: $(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process2_pjp.out
	$(CMD) win_parent_process_test_launcher_w_pintool_args.bat $(PINBIN) "$(PIN_TESTFLAGS)" \
	  "$(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -probe -t" "$(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX)" \
	  "-probe_grand_child 1" "-- $(CMD) win_parent_process_launcher.bat $(OBJDIR)" \
	    > $(OBJDIR)win_parent_process2_pjp.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process2_pjp.out win_parent_process2_pjp.reference
	$(RM) $(OBJDIR)win_parent_process2_pjp.out

#ppj
win_parent_process2_ppj.test: $(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process2_ppj.out
	$(CMD) win_parent_process_test_launcher_w_pintool_args.bat $(PINBIN) "$(PIN_TESTFLAGS)" \
	  "$(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -probe -t" "$(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX)" \
	  "-probe_child 1" "-- $(CMD) win_parent_process_launcher.bat $(OBJDIR)" > $(OBJDIR)win_parent_process2_ppj.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process2_ppj.out win_parent_process2_ppj.reference
	$(RM) $(OBJDIR)win_parent_process2_ppj.out

#ppp
win_parent_process2_ppp.test: $(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	touch win_parent_process2_ppp.out; $(RM) win_parent_process2_ppp.out
	$(CMD) win_parent_process_test_launcher_w_pintool_args.bat $(PINBIN) "$(PIN_TESTFLAGS)" \
	  "$(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -probe -t" "$(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX)" \
	  "-probe_child 1 -probe_grand_child 1" "-- $(CMD) win_parent_process_launcher.bat $(OBJDIR)" \
	    > $(OBJDIR)win_parent_process2_ppp.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process2_ppp.out win_parent_process2_ppp.reference
	$(RM) $(OBJDIR)win_parent_process2_ppp.out

win_parent_process2_unicode_ppp.test: $(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process_unicode$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process2_unicode_ppp.out
	$(CMD) win_parent_process_test_launcher_w_pintool_args.bat $(PINBIN) "$(PIN_TESTFLAGS)" \
	  "$(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -probe -t" "$(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX)" \
	  "-probe_child 1 -probe_grand_child 1" "-- $(CMD) win_parent_process_unicode_launcher.bat $(OBJDIR)" \
	    > $(OBJDIR)win_parent_process2_unicode_ppp.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process2_unicode_ppp.out win_parent_process2_unicode_ppp.reference
	$(RM) $(OBJDIR)win_parent_process2_unicode_ppp.out

#multi-threaded processes

#ppp
win_parent_process2_mt_ppp.test: $(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)parent_tool$(PINTOOL_SUFFIX) $(OBJDIR)follow_child_3gen_tool$(PINTOOL_SUFFIX) $(OBJDIR)win_parent_process_mt$(EXE_SUFFIX) $(OBJDIR)win_child_process$(EXE_SUFFIX)
	$(RM) -f $(OBJDIR)win_parent_process2_mt_ppp.out
	$(CMD) win_parent_process_mt_test_launcher_w_pintool_args.bat $(PINBIN) "$(PIN_TESTFLAGS)" \
	  "$(PINFLAGS) -p32 $(PIN32) -p64 $(PIN64) -follow_execv -probe -t" "$(OBJDIR)grand_parent_tool$(PINTOOL_SUFFIX)" \
	  "-probe_child 1 -probe_grand_child 1" "-- $(CMD) win_parent_process_mt_launcher.bat $(OBJDIR)" \
	    > $(OBJDIR)win_parent_process2_mt_ppp.out 2>&1
	$(DIFF) $(OBJDIR)win_parent_process2_mt_ppp.out win_parent_process2_mt_ppp.reference
	$(RM) $(OBJDIR)win_parent_process2_mt_ppp.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)unix_parent_tool$(PINTOOL_SUFFIX): $(OBJDIR)unix_parent_tool$(OBJ_SUFFIX) $(OBJDIR)arglist$(OBJ_SUFFIX)
	$(LINKER) $(TOOL_LDFLAGS) $(LINK_EXE)$@ $^ $(TOOL_LPATHS) $(TOOL_LIBS)

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

$(OBJDIR)fork_app_static$(EXE_SUFFIX): fork_app.c
	$(APP_CC) $(APP_CXXFLAGS) $(DBG_INFO_CXX_ALWAYS) $(COMP_EXE)$@ $< $(APP_LDFLAGS) $(STATIC) $(APP_LIBS) $(DBG_INFO_LD_ALWAYS) 

$(OBJDIR)vfork_app_static$(EXE_SUFFIX): vfork_app.c
	$(APP_CC) $(APP_CXXFLAGS) $(DBG_INFO_CXX_ALWAYS) $(COMP_EXE)$@ $< $(APP_LDFLAGS) $(STATIC) $(APP_LIBS) $(DBG_INFO_LD_ALWAYS) 

$(OBJDIR)win_parent_process$(EXE_SUFFIX): win_parent_process.cpp
	$(APP_CXX) $(APP_CXXFLAGS) $(COMP_EXE)$@ $< $(APP_LDFLAGS) $(APP_LIBS) Advapi32.lib

$(OBJDIR)win_parent_process_mt$(EXE_SUFFIX): win_parent_process_mt.cpp 
	$(APP_CXX) $(APP_CXXFLAGS) $(COMP_EXE)$@ $< $(APP_LDFLAGS) $(APP_LIBS) Advapi32.lib

$(OBJDIR)win_parent_process_unicode$(EXE_SUFFIX): win_parent_process_unicode.cpp
	$(APP_CXX) $(APP_CXXFLAGS) $(COMP_EXE)$@ $< $(APP_LDFLAGS) $(APP_LIBS) Advapi32.lib

$(OBJDIR)win_early_termination$(EXE_SUFFIX): win_early_termination.cpp $(OBJDIR)$(DLL_PREFIX)win_terminate_process_dll$(DLL_SUFFIX)
	$(APP_CXX) $(APP_CXXFLAGS) $(COMP_EXE)$@ $< $(APP_LDFLAGS) $(APP_LIBS) Advapi32.lib Dbghelp.lib $(OBJDIR)$(DLL_PREFIX)win_terminate_process_dll$(LIB_SUFFIX)

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

$(OBJDIR)unix_parent_tool$(OBJ_SUFFIX): unix_parent_tool.cpp arglist.h
	$(CXX) $(TOOL_CXXFLAGS) $(COMP_OBJ)$@ $<

$(OBJDIR)arglist$(OBJ_SUFFIX): arglist.cpp arglist.h
	$(CXX) $(TOOL_CXXFLAGS) $(COMP_OBJ)$@ $<

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

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