#!/usr/bin/env bash # you shouldn't normally be calling this script directly, it should be called # by build.sh, but only when build.sh is invoked from libfuzzer-build.sh. set -ex -o pipefail # logging functions export green="\e[92m" export red="\e[95m" export normal="\e[0m" export color=$normal function log { while read line do (echo ; echo -e "${color}${line}${normal}") >> "$LOGFILE" ; done } # command-line parsing export FINAL_LINK=0 # by default we using -fsanitize=fuzzer-no-link for arg do shift if [ "$arg" = "-fPIE" ] # no more pie then set -- "$@" "-fPIC" "-fno-pie" continue fi if [ "$arg" = "-pie" ] then set -- "$@" "-no-pie" continue fi if [ "$arg" = "-o" ] # here an output file is being specified then if [ "$1" = "zcashd" ] # here zcashd is the output file then export FINAL_LINK=1 # we should use -fsanitize=fuzzer because that links libfuzzer fi # note no continue, we fall through to default set fi set -- "$@" "$arg" done # which source dirs to instrument if [ "$dirs_to_instrument" = "" ] then export dirs_to_instrument=("^.*\/src$") fi # Store the command line we were given to a file echo "`hostname`:`pwd` \$" | log echo -- "original command: $0 $@" | log # decide on a sanitizer option beyond just fuzzing: # to link nor not to link libfuzzer we only link on # the final call, to the linker. if [ "$LLVM_SANITIZE" = "" ] then export LLVM_SANITIZE="address" # you can override this behavior by setting this environment variable first fi if [ "$FINAL_LINK" = "1" ] then export LLVM_SANITIZE="-fsanitize=fuzzer,$LLVM_SANITIZE" else export LLVM_SANITIZE="-fsanitize=fuzzer-no-link,$LLVM_SANITIZE" fi # Work out which compiler we were called as case $0 in *zcash-wrapper-clang) COMPILER="clang" export DEFINES_FLAGS="${CFLAGS} -DZCASH_FUZZ=1 -DFUZZ_WITH_LIBFUZZER=1 -fPIC" export INSTRUMENT_FLAGS="${DEFINES_FLAGS} ${LLVM_SANITIZE}" ;; *zcash-wrapper-clang++) COMPILER="clang++" export DEFINES_FLAGS="${CXXFLAGS} -DZCASH_FUZZ=1 -DFUZZ_WITH_LIBFUZZER=1 -fPIC" export INSTRUMENT_FLAGS="${DEFINES_FLAGS} ${LLVM_SANITIZE}" ;; *zcash-wrapper) echo -n "Call this script instead of your regular compiler, and if the absolute " echo -n "path of the CWD the wrapper was called from matches a regex in the " echo -n "array 'dirs_to_instrument', it will instrument the resulting object. " echo -n "Otherwise it will exec directly to the original compiler without " echo "changing arguments." echo -n "You can also set LLVM_SANITIZE to whatever sanitizers you'd like to use." echo -n "the default is 'address'. You don't need the -fsanitize=fuzzer part, " echo "this script handles that" exit ;; esac # Check if we should instrument for i in "${dirs_to_instrument[@]}" do if echo -- "`pwd`" | grep "$i"; then # We found a match, let's instrument this one. echo "pwd (`pwd`) matches dirs_to_instrument array element ($i). Adding instrumentation flags..." | log echo "command with defines and instrumentation added:" | color=$green log echo -- "$COMPILER" $INSTRUMENT_FLAGS "$@" | log exec -- "$COMPILER" $INSTRUMENT_FLAGS "$@" fi done # No match, just pass-through. echo -e -- "${red}command with defines added:${normal}" | color=$red log echo -- "$COMPILER" $DEFINES_FLAGS "$@" | log exec -- "$COMPILER" $DEFINES_FLAGS "$@"