1*8a28caf0SHeinrich Schuchardt#!/bin/bash 2*8a28caf0SHeinrich Schuchardt# SPDX-License-Identifier: GPL-2.0 3*8a28caf0SHeinrich Schuchardt# Linux kernel coccicheck 4*8a28caf0SHeinrich Schuchardt# 5*8a28caf0SHeinrich Schuchardt# Read doc/README.coccinelle 6*8a28caf0SHeinrich Schuchardt# 7*8a28caf0SHeinrich Schuchardt# This script requires at least spatch 8*8a28caf0SHeinrich Schuchardt# version 1.0.0-rc11. 9*8a28caf0SHeinrich Schuchardt 10*8a28caf0SHeinrich SchuchardtDIR="$(dirname $(readlink -f $0))/.." 11*8a28caf0SHeinrich SchuchardtSPATCH="`which ${SPATCH:=spatch}`" 12*8a28caf0SHeinrich Schuchardt 13*8a28caf0SHeinrich Schuchardtif [ ! -x "$SPATCH" ]; then 14*8a28caf0SHeinrich Schuchardt echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/' 15*8a28caf0SHeinrich Schuchardt exit 1 16*8a28caf0SHeinrich Schuchardtfi 17*8a28caf0SHeinrich Schuchardt 18*8a28caf0SHeinrich SchuchardtSPATCH_VERSION=$($SPATCH --version | head -1 | awk '{print $3}') 19*8a28caf0SHeinrich SchuchardtSPATCH_VERSION_NUM=$(echo $SPATCH_VERSION | ${DIR}/scripts/ld-version.sh) 20*8a28caf0SHeinrich Schuchardt 21*8a28caf0SHeinrich SchuchardtUSE_JOBS="no" 22*8a28caf0SHeinrich Schuchardt$SPATCH --help | grep "\-\-jobs" > /dev/null && USE_JOBS="yes" 23*8a28caf0SHeinrich Schuchardt 24*8a28caf0SHeinrich Schuchardt# The verbosity may be set by the environmental parameter V= 25*8a28caf0SHeinrich Schuchardt# as for example with 'make V=1 coccicheck' 26*8a28caf0SHeinrich Schuchardt 27*8a28caf0SHeinrich Schuchardtif [ -n "$V" -a "$V" != "0" ]; then 28*8a28caf0SHeinrich Schuchardt VERBOSE="$V" 29*8a28caf0SHeinrich Schuchardtelse 30*8a28caf0SHeinrich Schuchardt VERBOSE=0 31*8a28caf0SHeinrich Schuchardtfi 32*8a28caf0SHeinrich Schuchardt 33*8a28caf0SHeinrich Schuchardtif [ -z "$J" ]; then 34*8a28caf0SHeinrich Schuchardt NPROC=$(getconf _NPROCESSORS_ONLN) 35*8a28caf0SHeinrich Schuchardtelse 36*8a28caf0SHeinrich Schuchardt NPROC="$J" 37*8a28caf0SHeinrich Schuchardtfi 38*8a28caf0SHeinrich Schuchardt 39*8a28caf0SHeinrich SchuchardtFLAGS="--very-quiet" 40*8a28caf0SHeinrich Schuchardt 41*8a28caf0SHeinrich Schuchardt# You can use SPFLAGS to append extra arguments to coccicheck or override any 42*8a28caf0SHeinrich Schuchardt# heuristics done in this file as Coccinelle accepts the last options when 43*8a28caf0SHeinrich Schuchardt# options conflict. 44*8a28caf0SHeinrich Schuchardt# 45*8a28caf0SHeinrich Schuchardt# A good example for use of SPFLAGS is if you want to debug your cocci script, 46*8a28caf0SHeinrich Schuchardt# you can for instance use the following: 47*8a28caf0SHeinrich Schuchardt# 48*8a28caf0SHeinrich Schuchardt# $ export COCCI=scripts/coccinelle/misc/irqf_oneshot.cocci 49*8a28caf0SHeinrich Schuchardt# $ make coccicheck MODE=report DEBUG_FILE="all.err" SPFLAGS="--profile --show-trying" M=./drivers/mfd/arizona-irq.c 50*8a28caf0SHeinrich Schuchardt# 51*8a28caf0SHeinrich Schuchardt# "--show-trying" should show you what rule is being processed as it goes to 52*8a28caf0SHeinrich Schuchardt# stdout, you do not need a debug file for that. The profile output will be 53*8a28caf0SHeinrich Schuchardt# be sent to stdout, if you provide a DEBUG_FILE the profiling data can be 54*8a28caf0SHeinrich Schuchardt# inspected there. 55*8a28caf0SHeinrich Schuchardt# 56*8a28caf0SHeinrich Schuchardt# --profile will not output if --very-quiet is used, so avoid it. 57*8a28caf0SHeinrich Schuchardtecho $SPFLAGS | egrep -e "--profile|--show-trying" 2>&1 > /dev/null 58*8a28caf0SHeinrich Schuchardtif [ $? -eq 0 ]; then 59*8a28caf0SHeinrich Schuchardt FLAGS="--quiet" 60*8a28caf0SHeinrich Schuchardtfi 61*8a28caf0SHeinrich Schuchardt 62*8a28caf0SHeinrich Schuchardt# spatch only allows include directories with the syntax "-I include" 63*8a28caf0SHeinrich Schuchardt# while gcc also allows "-Iinclude" and "-include include" 64*8a28caf0SHeinrich SchuchardtCOCCIINCLUDE=${LINUXINCLUDE//-I/-I } 65*8a28caf0SHeinrich SchuchardtCOCCIINCLUDE=${COCCIINCLUDE// -include/ --include} 66*8a28caf0SHeinrich Schuchardt 67*8a28caf0SHeinrich Schuchardtif [ "$C" = "1" -o "$C" = "2" ]; then 68*8a28caf0SHeinrich Schuchardt ONLINE=1 69*8a28caf0SHeinrich Schuchardt 70*8a28caf0SHeinrich Schuchardt # Take only the last argument, which is the C file to test 71*8a28caf0SHeinrich Schuchardt shift $(( $# - 1 )) 72*8a28caf0SHeinrich Schuchardt OPTIONS="$COCCIINCLUDE $1" 73*8a28caf0SHeinrich Schuchardtelse 74*8a28caf0SHeinrich Schuchardt ONLINE=0 75*8a28caf0SHeinrich Schuchardt if [ "$KBUILD_EXTMOD" = "" ] ; then 76*8a28caf0SHeinrich Schuchardt OPTIONS="--dir $srctree $COCCIINCLUDE" 77*8a28caf0SHeinrich Schuchardt else 78*8a28caf0SHeinrich Schuchardt OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE" 79*8a28caf0SHeinrich Schuchardt fi 80*8a28caf0SHeinrich Schuchardtfi 81*8a28caf0SHeinrich Schuchardt 82*8a28caf0SHeinrich Schuchardtif [ "$KBUILD_EXTMOD" != "" ] ; then 83*8a28caf0SHeinrich Schuchardt OPTIONS="--patch $srctree $OPTIONS" 84*8a28caf0SHeinrich Schuchardtfi 85*8a28caf0SHeinrich Schuchardt 86*8a28caf0SHeinrich Schuchardt# You can override by using SPFLAGS 87*8a28caf0SHeinrich Schuchardtif [ "$USE_JOBS" = "no" ]; then 88*8a28caf0SHeinrich Schuchardt trap kill_running SIGTERM SIGINT 89*8a28caf0SHeinrich Schuchardt declare -a SPATCH_PID 90*8a28caf0SHeinrich Schuchardtelif [ "$NPROC" != "1" ]; then 91*8a28caf0SHeinrich Schuchardt # Using 0 should work as well, refer to _SC_NPROCESSORS_ONLN use on 92*8a28caf0SHeinrich Schuchardt # https://github.com/rdicosmo/parmap/blob/master/setcore_stubs.c 93*8a28caf0SHeinrich Schuchardt OPTIONS="$OPTIONS --jobs $NPROC --chunksize 1" 94*8a28caf0SHeinrich Schuchardtfi 95*8a28caf0SHeinrich Schuchardt 96*8a28caf0SHeinrich Schuchardtif [ "$MODE" = "" ] ; then 97*8a28caf0SHeinrich Schuchardt if [ "$ONLINE" = "0" ] ; then 98*8a28caf0SHeinrich Schuchardt echo 'You have not explicitly specified the mode to use. Using default "report" mode.' 99*8a28caf0SHeinrich Schuchardt echo 'Available modes are the following: patch, report, context, org' 100*8a28caf0SHeinrich Schuchardt echo 'You can specify the mode with "make coccicheck MODE=<mode>"' 101*8a28caf0SHeinrich Schuchardt echo 'Note however that some modes are not implemented by some semantic patches.' 102*8a28caf0SHeinrich Schuchardt fi 103*8a28caf0SHeinrich Schuchardt MODE="report" 104*8a28caf0SHeinrich Schuchardtfi 105*8a28caf0SHeinrich Schuchardt 106*8a28caf0SHeinrich Schuchardtif [ "$MODE" = "chain" ] ; then 107*8a28caf0SHeinrich Schuchardt if [ "$ONLINE" = "0" ] ; then 108*8a28caf0SHeinrich Schuchardt echo 'You have selected the "chain" mode.' 109*8a28caf0SHeinrich Schuchardt echo 'All available modes will be tried (in that order): patch, report, context, org' 110*8a28caf0SHeinrich Schuchardt fi 111*8a28caf0SHeinrich Schuchardtelif [ "$MODE" = "report" -o "$MODE" = "org" ] ; then 112*8a28caf0SHeinrich Schuchardt FLAGS="--no-show-diff $FLAGS" 113*8a28caf0SHeinrich Schuchardtfi 114*8a28caf0SHeinrich Schuchardt 115*8a28caf0SHeinrich Schuchardtif [ "$ONLINE" = "0" ] ; then 116*8a28caf0SHeinrich Schuchardt echo '' 117*8a28caf0SHeinrich Schuchardt echo 'Please check for false positives in the output before submitting a patch.' 118*8a28caf0SHeinrich Schuchardt echo 'When using "patch" mode, carefully review the patch before submitting it.' 119*8a28caf0SHeinrich Schuchardt echo '' 120*8a28caf0SHeinrich Schuchardtfi 121*8a28caf0SHeinrich Schuchardt 122*8a28caf0SHeinrich Schuchardtrun_cmd_parmap() { 123*8a28caf0SHeinrich Schuchardt if [ $VERBOSE -ne 0 ] ; then 124*8a28caf0SHeinrich Schuchardt echo "Running ($NPROC in parallel): $@" 125*8a28caf0SHeinrich Schuchardt fi 126*8a28caf0SHeinrich Schuchardt if [ "$DEBUG_FILE" != "/dev/null" -a "$DEBUG_FILE" != "" ]; then 127*8a28caf0SHeinrich Schuchardt if [ -f $DEBUG_FILE ]; then 128*8a28caf0SHeinrich Schuchardt echo "Debug file $DEBUG_FILE exists, bailing" 129*8a28caf0SHeinrich Schuchardt exit 130*8a28caf0SHeinrich Schuchardt fi 131*8a28caf0SHeinrich Schuchardt else 132*8a28caf0SHeinrich Schuchardt DEBUG_FILE="/dev/null" 133*8a28caf0SHeinrich Schuchardt fi 134*8a28caf0SHeinrich Schuchardt $@ 2>$DEBUG_FILE 135*8a28caf0SHeinrich Schuchardt if [[ $? -ne 0 ]]; then 136*8a28caf0SHeinrich Schuchardt echo "coccicheck failed" 137*8a28caf0SHeinrich Schuchardt exit $? 138*8a28caf0SHeinrich Schuchardt fi 139*8a28caf0SHeinrich Schuchardt} 140*8a28caf0SHeinrich Schuchardt 141*8a28caf0SHeinrich Schuchardtrun_cmd_old() { 142*8a28caf0SHeinrich Schuchardt local i 143*8a28caf0SHeinrich Schuchardt if [ $VERBOSE -ne 0 ] ; then 144*8a28caf0SHeinrich Schuchardt echo "Running ($NPROC in parallel): $@" 145*8a28caf0SHeinrich Schuchardt fi 146*8a28caf0SHeinrich Schuchardt for i in $(seq 0 $(( NPROC - 1)) ); do 147*8a28caf0SHeinrich Schuchardt eval "$@ --max $NPROC --index $i &" 148*8a28caf0SHeinrich Schuchardt SPATCH_PID[$i]=$! 149*8a28caf0SHeinrich Schuchardt if [ $VERBOSE -eq 2 ] ; then 150*8a28caf0SHeinrich Schuchardt echo "${SPATCH_PID[$i]} running" 151*8a28caf0SHeinrich Schuchardt fi 152*8a28caf0SHeinrich Schuchardt done 153*8a28caf0SHeinrich Schuchardt wait 154*8a28caf0SHeinrich Schuchardt} 155*8a28caf0SHeinrich Schuchardt 156*8a28caf0SHeinrich Schuchardtrun_cmd() { 157*8a28caf0SHeinrich Schuchardt if [ "$USE_JOBS" = "yes" ]; then 158*8a28caf0SHeinrich Schuchardt run_cmd_parmap $@ 159*8a28caf0SHeinrich Schuchardt else 160*8a28caf0SHeinrich Schuchardt run_cmd_old $@ 161*8a28caf0SHeinrich Schuchardt fi 162*8a28caf0SHeinrich Schuchardt} 163*8a28caf0SHeinrich Schuchardt 164*8a28caf0SHeinrich Schuchardtkill_running() { 165*8a28caf0SHeinrich Schuchardt for i in $(seq 0 $(( NPROC - 1 )) ); do 166*8a28caf0SHeinrich Schuchardt if [ $VERBOSE -eq 2 ] ; then 167*8a28caf0SHeinrich Schuchardt echo "Killing ${SPATCH_PID[$i]}" 168*8a28caf0SHeinrich Schuchardt fi 169*8a28caf0SHeinrich Schuchardt kill ${SPATCH_PID[$i]} 2>/dev/null 170*8a28caf0SHeinrich Schuchardt done 171*8a28caf0SHeinrich Schuchardt} 172*8a28caf0SHeinrich Schuchardt 173*8a28caf0SHeinrich Schuchardt# You can override heuristics with SPFLAGS, these must always go last 174*8a28caf0SHeinrich SchuchardtOPTIONS="$OPTIONS $SPFLAGS" 175*8a28caf0SHeinrich Schuchardt 176*8a28caf0SHeinrich Schuchardtcoccinelle () { 177*8a28caf0SHeinrich Schuchardt COCCI="$1" 178*8a28caf0SHeinrich Schuchardt 179*8a28caf0SHeinrich Schuchardt OPT=`grep "Option" $COCCI | cut -d':' -f2` 180*8a28caf0SHeinrich Schuchardt REQ=`grep "Requires" $COCCI | cut -d':' -f2 | sed "s| ||"` 181*8a28caf0SHeinrich Schuchardt REQ_NUM=$(echo $REQ | ${DIR}/scripts/ld-version.sh) 182*8a28caf0SHeinrich Schuchardt if [ "$REQ_NUM" != "0" ] ; then 183*8a28caf0SHeinrich Schuchardt if [ "$SPATCH_VERSION_NUM" -lt "$REQ_NUM" ] ; then 184*8a28caf0SHeinrich Schuchardt echo "Skipping coccinele SmPL patch: $COCCI" 185*8a28caf0SHeinrich Schuchardt echo "You have coccinelle: $SPATCH_VERSION" 186*8a28caf0SHeinrich Schuchardt echo "This SmPL patch requires: $REQ" 187*8a28caf0SHeinrich Schuchardt return 188*8a28caf0SHeinrich Schuchardt fi 189*8a28caf0SHeinrich Schuchardt fi 190*8a28caf0SHeinrich Schuchardt 191*8a28caf0SHeinrich Schuchardt# The option '--parse-cocci' can be used to syntactically check the SmPL files. 192*8a28caf0SHeinrich Schuchardt# 193*8a28caf0SHeinrich Schuchardt# $SPATCH -D $MODE $FLAGS -parse_cocci $COCCI $OPT > /dev/null 194*8a28caf0SHeinrich Schuchardt 195*8a28caf0SHeinrich Schuchardt if [ $VERBOSE -ne 0 -a $ONLINE -eq 0 ] ; then 196*8a28caf0SHeinrich Schuchardt 197*8a28caf0SHeinrich Schuchardt FILE=`echo $COCCI | sed "s|$srctree/||"` 198*8a28caf0SHeinrich Schuchardt 199*8a28caf0SHeinrich Schuchardt echo "Processing `basename $COCCI`" 200*8a28caf0SHeinrich Schuchardt echo "with option(s) \"$OPT\"" 201*8a28caf0SHeinrich Schuchardt echo '' 202*8a28caf0SHeinrich Schuchardt echo 'Message example to submit a patch:' 203*8a28caf0SHeinrich Schuchardt 204*8a28caf0SHeinrich Schuchardt sed -ne 's|^///||p' $COCCI 205*8a28caf0SHeinrich Schuchardt 206*8a28caf0SHeinrich Schuchardt if [ "$MODE" = "patch" ] ; then 207*8a28caf0SHeinrich Schuchardt echo ' The semantic patch that makes this change is available' 208*8a28caf0SHeinrich Schuchardt elif [ "$MODE" = "report" ] ; then 209*8a28caf0SHeinrich Schuchardt echo ' The semantic patch that makes this report is available' 210*8a28caf0SHeinrich Schuchardt elif [ "$MODE" = "context" ] ; then 211*8a28caf0SHeinrich Schuchardt echo ' The semantic patch that spots this code is available' 212*8a28caf0SHeinrich Schuchardt elif [ "$MODE" = "org" ] ; then 213*8a28caf0SHeinrich Schuchardt echo ' The semantic patch that makes this Org report is available' 214*8a28caf0SHeinrich Schuchardt else 215*8a28caf0SHeinrich Schuchardt echo ' The semantic patch that makes this output is available' 216*8a28caf0SHeinrich Schuchardt fi 217*8a28caf0SHeinrich Schuchardt echo " in $FILE." 218*8a28caf0SHeinrich Schuchardt echo '' 219*8a28caf0SHeinrich Schuchardt echo ' More information about semantic patching is available at' 220*8a28caf0SHeinrich Schuchardt echo ' http://coccinelle.lip6.fr/' 221*8a28caf0SHeinrich Schuchardt echo '' 222*8a28caf0SHeinrich Schuchardt 223*8a28caf0SHeinrich Schuchardt if [ "`sed -ne 's|^//#||p' $COCCI`" ] ; then 224*8a28caf0SHeinrich Schuchardt echo 'Semantic patch information:' 225*8a28caf0SHeinrich Schuchardt sed -ne 's|^//#||p' $COCCI 226*8a28caf0SHeinrich Schuchardt echo '' 227*8a28caf0SHeinrich Schuchardt fi 228*8a28caf0SHeinrich Schuchardt fi 229*8a28caf0SHeinrich Schuchardt 230*8a28caf0SHeinrich Schuchardt if [ "$MODE" = "chain" ] ; then 231*8a28caf0SHeinrich Schuchardt run_cmd $SPATCH -D patch \ 232*8a28caf0SHeinrich Schuchardt $FLAGS --cocci-file $COCCI $OPT $OPTIONS || \ 233*8a28caf0SHeinrich Schuchardt run_cmd $SPATCH -D report \ 234*8a28caf0SHeinrich Schuchardt $FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff || \ 235*8a28caf0SHeinrich Schuchardt run_cmd $SPATCH -D context \ 236*8a28caf0SHeinrich Schuchardt $FLAGS --cocci-file $COCCI $OPT $OPTIONS || \ 237*8a28caf0SHeinrich Schuchardt run_cmd $SPATCH -D org \ 238*8a28caf0SHeinrich Schuchardt $FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff || exit 1 239*8a28caf0SHeinrich Schuchardt elif [ "$MODE" = "rep+ctxt" ] ; then 240*8a28caf0SHeinrich Schuchardt run_cmd $SPATCH -D report \ 241*8a28caf0SHeinrich Schuchardt $FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff && \ 242*8a28caf0SHeinrich Schuchardt run_cmd $SPATCH -D context \ 243*8a28caf0SHeinrich Schuchardt $FLAGS --cocci-file $COCCI $OPT $OPTIONS || exit 1 244*8a28caf0SHeinrich Schuchardt else 245*8a28caf0SHeinrich Schuchardt run_cmd $SPATCH -D $MODE $FLAGS --cocci-file $COCCI $OPT $OPTIONS || exit 1 246*8a28caf0SHeinrich Schuchardt fi 247*8a28caf0SHeinrich Schuchardt 248*8a28caf0SHeinrich Schuchardt} 249*8a28caf0SHeinrich Schuchardt 250*8a28caf0SHeinrich Schuchardtif [ "$COCCI" = "" ] ; then 251*8a28caf0SHeinrich Schuchardt for f in `find $srctree/scripts/coccinelle/ -name '*.cocci' -type f | sort`; do 252*8a28caf0SHeinrich Schuchardt coccinelle $f 253*8a28caf0SHeinrich Schuchardt done 254*8a28caf0SHeinrich Schuchardtelse 255*8a28caf0SHeinrich Schuchardt coccinelle $COCCI 256*8a28caf0SHeinrich Schuchardtfi 257