18c2ecf20Sopenharmony_ci#!/bin/bash
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
38c2ecf20Sopenharmony_ci# Linux kernel coccicheck
48c2ecf20Sopenharmony_ci#
58c2ecf20Sopenharmony_ci# Read Documentation/dev-tools/coccinelle.rst
68c2ecf20Sopenharmony_ci#
78c2ecf20Sopenharmony_ci# This script requires at least spatch
88c2ecf20Sopenharmony_ci# version 1.0.0-rc11.
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ciDIR="$(dirname $(readlink -f $0))/.."
118c2ecf20Sopenharmony_ciSPATCH="`which ${SPATCH:=spatch}`"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ciif [ ! -x "$SPATCH" ]; then
148c2ecf20Sopenharmony_ci    echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/'
158c2ecf20Sopenharmony_ci    exit 1
168c2ecf20Sopenharmony_cifi
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ciSPATCH_VERSION=$($SPATCH --version | head -1 | awk '{print $3}')
198c2ecf20Sopenharmony_ciSPATCH_VERSION_NUM=$(echo $SPATCH_VERSION | ${DIR}/scripts/ld-version.sh)
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ciUSE_JOBS="no"
228c2ecf20Sopenharmony_ci$SPATCH --help | grep "\-\-jobs" > /dev/null && USE_JOBS="yes"
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci# The verbosity may be set by the environmental parameter V=
258c2ecf20Sopenharmony_ci# as for example with 'make V=1 coccicheck'
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ciif [ -n "$V" -a "$V" != "0" ]; then
288c2ecf20Sopenharmony_ci	VERBOSE="$V"
298c2ecf20Sopenharmony_cielse
308c2ecf20Sopenharmony_ci	VERBOSE=0
318c2ecf20Sopenharmony_cifi
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ciFLAGS="--very-quiet"
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci# You can use SPFLAGS to append extra arguments to coccicheck or override any
368c2ecf20Sopenharmony_ci# heuristics done in this file as Coccinelle accepts the last options when
378c2ecf20Sopenharmony_ci# options conflict.
388c2ecf20Sopenharmony_ci#
398c2ecf20Sopenharmony_ci# A good example for use of SPFLAGS is if you want to debug your cocci script,
408c2ecf20Sopenharmony_ci# you can for instance use the following:
418c2ecf20Sopenharmony_ci#
428c2ecf20Sopenharmony_ci# $ export COCCI=scripts/coccinelle/misc/irqf_oneshot.cocci
438c2ecf20Sopenharmony_ci# $ make coccicheck MODE=report DEBUG_FILE="all.err" SPFLAGS="--profile --show-trying" M=./drivers/mfd/arizona-irq.c
448c2ecf20Sopenharmony_ci#
458c2ecf20Sopenharmony_ci# "--show-trying" should show you what rule is being processed as it goes to
468c2ecf20Sopenharmony_ci# stdout, you do not need a debug file for that. The profile output will be
478c2ecf20Sopenharmony_ci# be sent to stdout, if you provide a DEBUG_FILE the profiling data can be
488c2ecf20Sopenharmony_ci# inspected there.
498c2ecf20Sopenharmony_ci#
508c2ecf20Sopenharmony_ci# --profile will not output if --very-quiet is used, so avoid it.
518c2ecf20Sopenharmony_ciecho $SPFLAGS | egrep -e "--profile|--show-trying" 2>&1 > /dev/null
528c2ecf20Sopenharmony_ciif [ $? -eq 0 ]; then
538c2ecf20Sopenharmony_ci	FLAGS="--quiet"
548c2ecf20Sopenharmony_cifi
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci# spatch only allows include directories with the syntax "-I include"
578c2ecf20Sopenharmony_ci# while gcc also allows "-Iinclude" and "-include include"
588c2ecf20Sopenharmony_ciCOCCIINCLUDE=${LINUXINCLUDE//-I/-I }
598c2ecf20Sopenharmony_ciCOCCIINCLUDE=${COCCIINCLUDE// -include/ --include}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ciif [ "$C" = "1" -o "$C" = "2" ]; then
628c2ecf20Sopenharmony_ci    ONLINE=1
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci    # Take only the last argument, which is the C file to test
658c2ecf20Sopenharmony_ci    shift $(( $# - 1 ))
668c2ecf20Sopenharmony_ci    OPTIONS="$COCCIINCLUDE $1"
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci    # No need to parallelize Coccinelle since this mode takes one input file.
698c2ecf20Sopenharmony_ci    NPROC=1
708c2ecf20Sopenharmony_cielse
718c2ecf20Sopenharmony_ci    ONLINE=0
728c2ecf20Sopenharmony_ci    if [ "$KBUILD_EXTMOD" = "" ] ; then
738c2ecf20Sopenharmony_ci        OPTIONS="--dir $srctree $COCCIINCLUDE"
748c2ecf20Sopenharmony_ci    else
758c2ecf20Sopenharmony_ci        OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
768c2ecf20Sopenharmony_ci    fi
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci    # Use only one thread per core by default if hyperthreading is enabled
798c2ecf20Sopenharmony_ci    THREADS_PER_CORE=$(lscpu | grep "Thread(s) per core: " | tr -cd "[:digit:]")
808c2ecf20Sopenharmony_ci    if [ -z "$J" ]; then
818c2ecf20Sopenharmony_ci        NPROC=$(getconf _NPROCESSORS_ONLN)
828c2ecf20Sopenharmony_ci	if [ $THREADS_PER_CORE -gt 1 -a $NPROC -gt 4 ] ; then
838c2ecf20Sopenharmony_ci		NPROC=$((NPROC/2))
848c2ecf20Sopenharmony_ci	fi
858c2ecf20Sopenharmony_ci    else
868c2ecf20Sopenharmony_ci        NPROC="$J"
878c2ecf20Sopenharmony_ci    fi
888c2ecf20Sopenharmony_cifi
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ciif [ "$KBUILD_EXTMOD" != "" ] ; then
918c2ecf20Sopenharmony_ci    OPTIONS="--patch $srctree $OPTIONS"
928c2ecf20Sopenharmony_cifi
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci# You can override by using SPFLAGS
958c2ecf20Sopenharmony_ciif [ "$USE_JOBS" = "no" ]; then
968c2ecf20Sopenharmony_ci	trap kill_running SIGTERM SIGINT
978c2ecf20Sopenharmony_ci	declare -a SPATCH_PID
988c2ecf20Sopenharmony_cielif [ "$NPROC" != "1" ]; then
998c2ecf20Sopenharmony_ci	# Using 0 should work as well, refer to _SC_NPROCESSORS_ONLN use on
1008c2ecf20Sopenharmony_ci	# https://github.com/rdicosmo/parmap/blob/master/setcore_stubs.c
1018c2ecf20Sopenharmony_ci	OPTIONS="$OPTIONS --jobs $NPROC --chunksize 1"
1028c2ecf20Sopenharmony_cifi
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ciif [ "$MODE" = "" ] ; then
1058c2ecf20Sopenharmony_ci    if [ "$ONLINE" = "0" ] ; then
1068c2ecf20Sopenharmony_ci	echo 'You have not explicitly specified the mode to use. Using default "report" mode.'
1078c2ecf20Sopenharmony_ci	echo 'Available modes are the following: patch, report, context, org, chain'
1088c2ecf20Sopenharmony_ci	echo 'You can specify the mode with "make coccicheck MODE=<mode>"'
1098c2ecf20Sopenharmony_ci	echo 'Note however that some modes are not implemented by some semantic patches.'
1108c2ecf20Sopenharmony_ci    fi
1118c2ecf20Sopenharmony_ci    MODE="report"
1128c2ecf20Sopenharmony_cifi
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ciif [ "$MODE" = "chain" ] ; then
1158c2ecf20Sopenharmony_ci    if [ "$ONLINE" = "0" ] ; then
1168c2ecf20Sopenharmony_ci	echo 'You have selected the "chain" mode.'
1178c2ecf20Sopenharmony_ci	echo 'All available modes will be tried (in that order): patch, report, context, org'
1188c2ecf20Sopenharmony_ci    fi
1198c2ecf20Sopenharmony_cielif [ "$MODE" = "report" -o "$MODE" = "org" ] ; then
1208c2ecf20Sopenharmony_ci    FLAGS="--no-show-diff $FLAGS"
1218c2ecf20Sopenharmony_cifi
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ciif [ "$ONLINE" = "0" ] ; then
1248c2ecf20Sopenharmony_ci    echo ''
1258c2ecf20Sopenharmony_ci    echo 'Please check for false positives in the output before submitting a patch.'
1268c2ecf20Sopenharmony_ci    echo 'When using "patch" mode, carefully review the patch before submitting it.'
1278c2ecf20Sopenharmony_ci    echo ''
1288c2ecf20Sopenharmony_cifi
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cirun_cmd_parmap() {
1318c2ecf20Sopenharmony_ci	if [ $VERBOSE -ne 0 ] ; then
1328c2ecf20Sopenharmony_ci		echo "Running ($NPROC in parallel): $@"
1338c2ecf20Sopenharmony_ci	fi
1348c2ecf20Sopenharmony_ci	if [ "$DEBUG_FILE" != "/dev/null" -a "$DEBUG_FILE" != "" ]; then
1358c2ecf20Sopenharmony_ci                echo $@>>$DEBUG_FILE
1368c2ecf20Sopenharmony_ci                $@ 2>>$DEBUG_FILE
1378c2ecf20Sopenharmony_ci        else
1388c2ecf20Sopenharmony_ci                echo $@
1398c2ecf20Sopenharmony_ci                $@ 2>&1
1408c2ecf20Sopenharmony_ci	fi
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	err=$?
1438c2ecf20Sopenharmony_ci	if [[ $err -ne 0 ]]; then
1448c2ecf20Sopenharmony_ci		echo "coccicheck failed"
1458c2ecf20Sopenharmony_ci		exit $err
1468c2ecf20Sopenharmony_ci	fi
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cirun_cmd_old() {
1508c2ecf20Sopenharmony_ci	local i
1518c2ecf20Sopenharmony_ci	if [ $VERBOSE -ne 0 ] ; then
1528c2ecf20Sopenharmony_ci		echo "Running ($NPROC in parallel): $@"
1538c2ecf20Sopenharmony_ci	fi
1548c2ecf20Sopenharmony_ci	for i in $(seq 0 $(( NPROC - 1)) ); do
1558c2ecf20Sopenharmony_ci		eval "$@ --max $NPROC --index $i &"
1568c2ecf20Sopenharmony_ci		SPATCH_PID[$i]=$!
1578c2ecf20Sopenharmony_ci		if [ $VERBOSE -eq 2 ] ; then
1588c2ecf20Sopenharmony_ci			echo "${SPATCH_PID[$i]} running"
1598c2ecf20Sopenharmony_ci		fi
1608c2ecf20Sopenharmony_ci	done
1618c2ecf20Sopenharmony_ci	wait
1628c2ecf20Sopenharmony_ci}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cirun_cmd() {
1658c2ecf20Sopenharmony_ci	if [ "$USE_JOBS" = "yes" ]; then
1668c2ecf20Sopenharmony_ci		run_cmd_parmap $@
1678c2ecf20Sopenharmony_ci	else
1688c2ecf20Sopenharmony_ci		run_cmd_old $@
1698c2ecf20Sopenharmony_ci	fi
1708c2ecf20Sopenharmony_ci}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cikill_running() {
1738c2ecf20Sopenharmony_ci	for i in $(seq 0 $(( NPROC - 1 )) ); do
1748c2ecf20Sopenharmony_ci		if [ $VERBOSE -eq 2 ] ; then
1758c2ecf20Sopenharmony_ci			echo "Killing ${SPATCH_PID[$i]}"
1768c2ecf20Sopenharmony_ci		fi
1778c2ecf20Sopenharmony_ci		kill ${SPATCH_PID[$i]} 2>/dev/null
1788c2ecf20Sopenharmony_ci	done
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci# You can override heuristics with SPFLAGS, these must always go last
1828c2ecf20Sopenharmony_ciOPTIONS="$OPTIONS $SPFLAGS"
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cicoccinelle () {
1858c2ecf20Sopenharmony_ci    COCCI="$1"
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci    OPT=`grep "Options:" $COCCI | cut -d':' -f2`
1888c2ecf20Sopenharmony_ci    REQ=`grep "Requires:" $COCCI | cut -d':' -f2 | sed "s| ||"`
1898c2ecf20Sopenharmony_ci    REQ_NUM=$(echo $REQ | ${DIR}/scripts/ld-version.sh)
1908c2ecf20Sopenharmony_ci    if [ "$REQ_NUM" != "0" ] ; then
1918c2ecf20Sopenharmony_ci	    if [ "$SPATCH_VERSION_NUM" -lt "$REQ_NUM" ] ; then
1928c2ecf20Sopenharmony_ci		    echo "Skipping coccinelle SmPL patch: $COCCI"
1938c2ecf20Sopenharmony_ci		    echo "You have coccinelle:           $SPATCH_VERSION"
1948c2ecf20Sopenharmony_ci		    echo "This SmPL patch requires:      $REQ"
1958c2ecf20Sopenharmony_ci		    return
1968c2ecf20Sopenharmony_ci	    fi
1978c2ecf20Sopenharmony_ci    fi
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci#   The option '--parse-cocci' can be used to syntactically check the SmPL files.
2008c2ecf20Sopenharmony_ci#
2018c2ecf20Sopenharmony_ci#    $SPATCH -D $MODE $FLAGS -parse_cocci $COCCI $OPT > /dev/null
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci    if [ $VERBOSE -ne 0 -a $ONLINE -eq 0 ] ; then
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	FILE=${COCCI#$srctree/}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	echo "Processing `basename $COCCI`"
2088c2ecf20Sopenharmony_ci	echo "with option(s) \"$OPT\""
2098c2ecf20Sopenharmony_ci	echo ''
2108c2ecf20Sopenharmony_ci	echo 'Message example to submit a patch:'
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	sed -ne 's|^///||p' $COCCI
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	if [ "$MODE" = "patch" ] ; then
2158c2ecf20Sopenharmony_ci	    echo ' The semantic patch that makes this change is available'
2168c2ecf20Sopenharmony_ci	elif [ "$MODE" = "report" ] ; then
2178c2ecf20Sopenharmony_ci	    echo ' The semantic patch that makes this report is available'
2188c2ecf20Sopenharmony_ci	elif [ "$MODE" = "context" ] ; then
2198c2ecf20Sopenharmony_ci	    echo ' The semantic patch that spots this code is available'
2208c2ecf20Sopenharmony_ci	elif [ "$MODE" = "org" ] ; then
2218c2ecf20Sopenharmony_ci	    echo ' The semantic patch that makes this Org report is available'
2228c2ecf20Sopenharmony_ci	else
2238c2ecf20Sopenharmony_ci	    echo ' The semantic patch that makes this output is available'
2248c2ecf20Sopenharmony_ci	fi
2258c2ecf20Sopenharmony_ci	echo " in $FILE."
2268c2ecf20Sopenharmony_ci	echo ''
2278c2ecf20Sopenharmony_ci	echo ' More information about semantic patching is available at'
2288c2ecf20Sopenharmony_ci	echo ' http://coccinelle.lip6.fr/'
2298c2ecf20Sopenharmony_ci	echo ''
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	if [ "`sed -ne 's|^//#||p' $COCCI`" ] ; then
2328c2ecf20Sopenharmony_ci	    echo 'Semantic patch information:'
2338c2ecf20Sopenharmony_ci	    sed -ne 's|^//#||p' $COCCI
2348c2ecf20Sopenharmony_ci	    echo ''
2358c2ecf20Sopenharmony_ci	fi
2368c2ecf20Sopenharmony_ci    fi
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci    if [ "$MODE" = "chain" ] ; then
2398c2ecf20Sopenharmony_ci	run_cmd $SPATCH -D patch   \
2408c2ecf20Sopenharmony_ci		$FLAGS --cocci-file $COCCI $OPT $OPTIONS               || \
2418c2ecf20Sopenharmony_ci	run_cmd $SPATCH -D report  \
2428c2ecf20Sopenharmony_ci		$FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff || \
2438c2ecf20Sopenharmony_ci	run_cmd $SPATCH -D context \
2448c2ecf20Sopenharmony_ci		$FLAGS --cocci-file $COCCI $OPT $OPTIONS               || \
2458c2ecf20Sopenharmony_ci	run_cmd $SPATCH -D org     \
2468c2ecf20Sopenharmony_ci		$FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff || exit 1
2478c2ecf20Sopenharmony_ci    elif [ "$MODE" = "rep+ctxt" ] ; then
2488c2ecf20Sopenharmony_ci	run_cmd $SPATCH -D report  \
2498c2ecf20Sopenharmony_ci		$FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff && \
2508c2ecf20Sopenharmony_ci	run_cmd $SPATCH -D context \
2518c2ecf20Sopenharmony_ci		$FLAGS --cocci-file $COCCI $OPT $OPTIONS || exit 1
2528c2ecf20Sopenharmony_ci    else
2538c2ecf20Sopenharmony_ci	run_cmd $SPATCH -D $MODE   $FLAGS --cocci-file $COCCI $OPT $OPTIONS || exit 1
2548c2ecf20Sopenharmony_ci    fi
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci}
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ciif [ "$DEBUG_FILE" != "/dev/null" -a "$DEBUG_FILE" != "" ]; then
2598c2ecf20Sopenharmony_ci	if [ -f $DEBUG_FILE ]; then
2608c2ecf20Sopenharmony_ci		echo "Debug file $DEBUG_FILE exists, bailing"
2618c2ecf20Sopenharmony_ci		exit
2628c2ecf20Sopenharmony_ci	fi
2638c2ecf20Sopenharmony_cielse
2648c2ecf20Sopenharmony_ci	DEBUG_FILE="/dev/null"
2658c2ecf20Sopenharmony_cifi
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ciif [ "$COCCI" = "" ] ; then
2688c2ecf20Sopenharmony_ci    for f in `find $srctree/scripts/coccinelle/ -name '*.cocci' -type f | sort`; do
2698c2ecf20Sopenharmony_ci	coccinelle $f
2708c2ecf20Sopenharmony_ci    done
2718c2ecf20Sopenharmony_cielse
2728c2ecf20Sopenharmony_ci    coccinelle $COCCI
2738c2ecf20Sopenharmony_cifi
274