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