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