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