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