Size: 3957
Comment:
|
Size: 8237
Comment: cleanup
|
Deletions are marked like this. | Additions are marked like this. |
Line 3: | Line 3: |
== Your Name == Roel Kluin |
== Roel Kluin == |
Line 12: | Line 11: |
some scripts for configuring a kernel: To translate a module name (as listed in modprobe -l or modinfo -n ''module'') into a kernel .config option: {{{ #!/bin/bash mod="${1%.ko}"; dir="${1%/*}"; sed -e :a -e '/\\$/N; s/\\\n//; ta' "${dir#*/kernel/}/Makefile" | \ sed -n "s/^obj-\$(CONFIG_\([A-Z0-9_]*\))\W*+=\W*"${mod##*/}"\.o$/\1/p"; }}} a sed script to check ioremap/iounmap balancing (can be adapted for others) {{{ git-grep -l '[^[:alnum:]]ioremap' | while read g; do |
all code is (c) Roel kluin, 2007 GNU GPL V.2. == Examples == These may require the script 'vars' below sourced, and should be called in a git tree. I simply paste them into my console (bash). Match Unlikely(x) ?= y {{{ git-grep -n "\(un\)\?likely$s([^()]*\(([^()]*)[^()]*\)*)$s.=" }}} These can be replaced with strchr: {{{ E="\([^\"\\]\|\\[\\tnr\?'\"0bafv]\|\\[0-7]\{1,3\}\|\\[a-f0-9]\{1,2\}\|\\[A-F0-9]\{1,2\}\)" git-grep -n "strstr$s($s$W$s,$s\"$E\"$s)" }}} Show module initializing functions, not using {{{__init}}} or similarly exit: {{{ git-grep -n "\(void\|int\)$s[[:alnum:]_]*module_[ei][xn]it(void)" | grep -v "__[ie][xn]it" }}} Matches if(function) BUG(): {{{ q="${s}if$s(\($ccode$Q\)\?$L$s($ccode)$s$ccode$s)" git-grep -n -B1 "^\($q\)\?${s}BUG($s)$s;$cendl" | grep "$q$cendl" | grep -v "\(sizeof\|unlikely\|likely\)($ccode)" | less }}} A sed script to audit ioremap/iounmap balancing (can be adapted for others): {{{ git-grep -l '[^[:alnum:]]ioremap' | while read -r g; do |
Line 45: | Line 60: |
scripts below may use these variables: {{{ # a number D="[0-9]\+" # we could also use this, to match something like 1ul, floats or hexes as well: # but the parentheses will cost one backreference for (git-)grep d="\([0-9]\+[uUlLfF]\?\|[0-9]\+[uU]\?[lL][lL]\?\|0x[a-f0-9]\+\|0x[A-F0-9]\+\|[0-9]\+[lL][lL][uU]\|[0-9]*\.[0-9]\+[fF]\?\)" # can be used for a variable/function name: V="[A-Za-z_]\+[A-Za-z0-9_]*" # capital: a config option/definition K="[A-Z]\+[A-Z0-9_]*"; # works the same as above, but also for members and arrays: one backreference W="$V\(\[$s$V$s\]\|\[$s$D$s\]\|\.$V\|->$V\)*" # seperators: s="[[:space:]]*"; S="[[:space:]]\+" # useful to delimit a variable name: Q="[^[:alnum:]_]" # match the end of the line, including comments: one backreference (but at eol) cendl="$s\(\/[\*\/].*\)\?$" # match something that is not comment, string or character: 2 backreferences ccode="\([^\/\"']*\|\/[^\*\/]\|\/\*\([^\*]*\|\**[^\/\*]\)*\*\/\|'[^']*'\|\"[^\"]*\"\)*" # resp function open and end (only works when indentation is correct. fo="^[\{]$cendl" fe="^[\}]$cendl" }}} Make sure no-one is freeing skbs with kfree instead of kfree_skb |
Make sure no-one is freeing skbs with kfree instead of kfree_skb: |
Line 85: | Line 63: |
sed -n "s/^.*struct${S}sk_buff${s}\*${s}\(${V}\)$Q.*$/\1/p" $f | sort | uniq | while read n; do sed -n "/struct${s}sk_buff${s}\*${s}${n}/,/^[{}].*$/{ /kfree(${s}${n}${s})/= }" $f | while read q; do |
sed -n "s/^.*struct${S}sk_buff${s}\*${s}\(${V}\)$Q.*$/\1/p" $f | sort | uniq | while read -r n; do sed -n "/struct${s}sk_buff${s}\*${s}${n}/,/^[{}].*$/{ /kfree(${s}${n}${s})/= }" $f | while read -r q; do |
Line 94: | Line 72: |
show module initializing functions, not using {{{__init}}} or similarly exit {{{ git-grep -n "\(void\|int\)$s[[:alnum:]_]*module_[ei][xn]it(void)" | grep -v "__[ie][xn]it" }}} these can be replaced with strchr {{{ E="\([^\"\\]\|\\[\\tnr\?'\"0bafv]\|\\[0-7]\{1,3\}\|\\[a-f0-9]\{1,2\}\)" git-grep -n "strstr$s($s$W$s,$s\"$E\"$s)" }}} matches if(function) BUG() {{{ cendl="$s\(\/[\*\/].*\)\?$" ccode="\([^\/\"']*\|\/[^\*\/]\|\/\*\([^\*]*\|\**[^\/\*]\)*\*\/\|'[^']*'\|\"[^\"]*\"\)*" q="${s}if$s(\($ccode$Q\)\?$L$s($ccode)$s$ccode$s)" git-grep -n -B1 "^\($q\)\?${s}BUG($s)$s;$cendl" | grep "$q$cendl" | grep -v "\(sizeof\|unlikely\|likely\)($ccode)" | less |
matches a comparison as the last argument of a function. This may be correct but it is sometimes a misplaced check (and should be placed after the parenthesis instead). Use getcalls and/or getfunc to determine whether a boolean as the last argument is correct: {{{ h="\(([^()]*)\)\+"; git-grep -n -A9 ",[^);,]*=" | sed -n "s/^\([^\.]*\.[chsS]-[0-9]*-\|\([^\.]*\.[chsS]:[0-9]*:\)$s\)\(.*\)$/\2\3/p" | tr "\n" "@" | grep -o "@[^@]*$W$s(\(\([^,()]*\|$h\)*,\)\+\([^,()]*\|$h\)*[^\"]=${s}[^\",()]*)${s}[)&|]" | tr "@\t" " " | tr -s " " | less }}} Find values used as a boolean instead of the more common bitwise usage: {{{ f1="\($W${s}[&|]\|[0-9]\+${s}[&|]\|)${s}[&|]\)" # adds 2 h="\(([^()]*\(([^()]*\(([^()]*)[^()]*\)*[^()]*)[^()]*\)*)\)\?" git-grep "\($f1$s$V$s$h$s\(&&\|||\|)\|?\)\|\(&&\|||\|(\)$s$V$s$h${s}[&|]$s\([0-9]*\($W\|[^0]\)[0-9]*\)\)" | sed -n "s/^.*\($f1$s\($V\)$s\(([^()]*)\)\?$s\(&&\|||\|)\)\|\(&&\|||\|(\)$s\($V\)$s\(([^()]*)\)\?${s}[&|]$s\([0-9]*\($W\|[^0]\)[0-9]*\)\).*$/\4\8/p" | while read -r n; do echo "$n"; done | sort | uniq -c | sort -rn | while read -r n a; do b=$(git-grep -n "\(\(\(if\|while\)$s(\|&&\|||\|\!\)$s$a$s\(&&\|||\|\|)?\|(\)\|\(&&\|||\|(\)$s$a$s\(&&\|||\|(\|?\)\)" | grep -v "Kconfig") [ -z "$b" ] && continue; c=`echo "$b" | wc -l` let d=$(($n/$c)) echo "----[ a=\"$a\" # used $n times as bitwise, $c times as boolean, div $d ]----" [ $c -gt 20 ] && continue; [ $d -lt 5 ] && continue; echo "$b" done | less }}} == Scripts == I called it vars, it contains some functions for kernel hacking. usage: "source path/to/vars" N.B. do not source this in a shell that you plan to use to compile a kernel ($Q is used in Makefiles as well, which will give some problems) {{{ #!/bin/bash # (c) Roel kluin, 2008 GNU GPL V.2 alias gg="git-grep -n" # Usage: v /path/to/sourcefile.c:1 # (as pasted from git-grep -n) v() { [ -n "$1" ] && vi ${1%[:-]*} +${1##*[:-]} } # a number export D="[0-9]\+" # we could also use this, to match something like 1ul, floats or hexes as well: # but the parentheses will cost one backreference for (git-)grep export d="\([0-9]\+[uUlLfF]\?\|[0-9]\+[uU]\?[lL][lL]\?\|0x[a-f0-9]\+\|0x[A-F0-9]\+\|[0-9]\+[lL][lL][uU]\|[0-9]*\.[0-9]\+[fF]\?\)" # can be used for a variable/function name: export V="[A-Za-z_]\+[A-Za-z0-9_]*" # capital: a config option/definition export K="[A-Z]\+[A-Z0-9_]*"; # works the same as above, but also for members and arrays: one backreference export W="$V\(\[$s$V$s\]\|\[$s$D$s\]\|\.$V\|->$V\)*" # seperators: export s="[[:space:]]*"; export S="[[:space:]]\+" # useful to delimit a variable name: export Q="[^[:alnum:]_]" # match the end of the line, including comments: one backreference (but at eol) export cendl="$s\(\/[\*\/].*\)\?$" # match something that is not comment, string or character: 2 backreferences export ccode="\([^\/\"']*\|\/[^\*\/]\|\/\*\([^\*]*\|\**[^\/\*]\)*\*\+\/\|'[^']*'\|\"[^\"]*\"\)*" # resp function open and end (only works when indentation is correct. export fo="^[\{]$cendl" export fe="^[\}]$cendl" # works similar to git-grep -n "$query" | tr ":" " " # except that :'s in the line are preserved ggrep2fnl() { git-grep -n "$1" | while read -r fnl; do f="$(echo "$fnl"| cut -d":" -f1)"; e="$(echo "$f" | rev | cut --complement -c3- | rev)"; [ "$e" != ".h" -a "$e" != ".c" ] && continue; echo "$f $(echo "$fnl"| cut -d":" -f2) $(echo "$fnl"| cut -d":" -f3-)"; done } #print function declaration at file "$1", line "$2" # also works for /path/to/filename.c:nr getfuncat() { [ $# -ne 1 ] && return 1; f="${1%[:-]*}" [ ! -f "$f" ] && return 2; l="${1##*[:-]}" Z="@[:space:]" a="[^()]*" nested_parentheses="\(($a\(($a\(($a\(($a\(($a)$a\)*)$a\)*)$a\)*)$a\)*)$a\)*" func="\(${V}[$Z]\+\)*${V}[*$Z]\+$V$s($a$nested_parentheses)" eol="[$Z]*\([$Z]\|\/\/[^@]*@\|\/\*\([^\*]*\|\**[^\/\*]\)*\*\+\/\)*@{" head -n$l "$f" | tr "\n" "@" | sed -n "s/.*@\($func\)$eol.*/\1@/p" | tail -n1 | tr "@" "\n" } #print function declaration(s) getfunc() { q="^\(${V}[*&[:space:]]\+\)*$1$s(${ccode}[^;]$cendl"; ggrep2fnl "$q" | while read -r f n l; do [ -z "`echo $l | grep "{$cendl"`" -a \ -n "`sed -n "$n,/{$cendl/{/;/p}" "$f"`" ] && continue echo "//---[ vi $f +$n ]---" [ -n "`echo $l | grep "^$s$1"`" ] && let "n--" sed -n "$n,/$fe/p" "$f" done } # helper to print definition(s) / macro(s) _getdef() { ggrep2fnl "$2" | while read -r f n l; do echo "---[ vi $f +$n ]---" 1>&2 if [ -z "`echo $l | grep "\\$cendl"`" ]; then echo $l else sed -n "/$2/,/[^\\]$cendl/p" "$f" fi done } #print definition(s) / macro(s) getdef() { _getdef "$1" "^$s#${s}define$S$1\(([^()]*)\)\?$S" } #print only macro(s) getmac() { _getdef "$1" "^$s#${s}define$S$1([^()]*)$S" } # echoes "function name" at file "$1" line "$2" det_func() { q="^\(${V}[*&[:space:]]\+\)*\($V\)$s(${ccode}[^;]$cendl" head "$1" -n"$2" | tac | sed -n "/$q/{s/$q/\2/p;q}" } getcalls() { git-grep -n "\(^\|^$ccode$Q\)$1$s(\($ccode\()$s;\|[^)]\|)$ccode)$ccode\)\)\?$cendl" } }}} To translate a module name (as listed in modprobe -l or modinfo -n ''module'') into a kernel .config option: {{{ #!/bin/bash mod="${1%.ko}"; dir="${1%/*}"; sed -e :a -e '/\\$/N; s/\\\n//; ta' "${dir#*/kernel/}/Makefile" | \ sed -n "s/^obj-\$(CONFIG_\([A-Z0-9_]*\))\W*+=\W*"${mod##*/}"\.o$/\1/p"; |
Line 119: | Line 253: |
sort | uniq | sort -n -r | while read name; do | sort | uniq | sort -n -r | while read -r name; do |
Line 123: | Line 257: |
done | sort | uniq -c | sort -n -r | while read nr list; do | done | sort | uniq -c | sort -n -r | while read -r nr list; do |
Line 126: | Line 260: |
done | sort -r | cut -d " " -f2- | while read nr tot list; do | done | sort -r | cut -d " " -f2- | while read -r nr tot list; do |
Roel Kluin
Email: MailTo(12o3l AT SPAMFREE tiscali DOT nl) ...
all code is (c) Roel kluin, 2007 GNU GPL V.2.
Examples
These may require the script 'vars' below sourced, and should be called in a git tree. I simply paste them into my console (bash).
Match Unlikely(x) ?= y
git-grep -n "\(un\)\?likely$s([^()]*\(([^()]*)[^()]*\)*)$s.="
These can be replaced with strchr:
E="\([^\"\\]\|\\[\\tnr\?'\"0bafv]\|\\[0-7]\{1,3\}\|\\[a-f0-9]\{1,2\}\|\\[A-F0-9]\{1,2\}\)" git-grep -n "strstr$s($s$W$s,$s\"$E\"$s)"
Show module initializing functions, not using __init or similarly exit:
git-grep -n "\(void\|int\)$s[[:alnum:]_]*module_[ei][xn]it(void)" | grep -v "__[ie][xn]it"
Matches if(function) BUG():
q="${s}if$s(\($ccode$Q\)\?$L$s($ccode)$s$ccode$s)" git-grep -n -B1 "^\($q\)\?${s}BUG($s)$s;$cendl" | grep "$q$cendl" | grep -v "\(sizeof\|unlikely\|likely\)($ccode)" | less
A sed script to audit ioremap/iounmap balancing (can be adapted for others):
git-grep -l '[^[:alnum:]]ioremap' | while read -r g; do echo "--------------------------[ $g ]--------------------------" sed -n "/[^[:alnum:]]ioremap.*(\(.*\))/,/^[}{]$/{ s/\(.*return.*\)/\1\t\t-------return/ tp s/\(.*goto.*\)/\1\t\t------goto/ tp s/\(.*iounmap.*\)/\1\t\t<----/ tp s/\(.*ioremap.*\)/\1\t\t---->/ Tp = :p p }" $g done | less
Make sure no-one is freeing skbs with kfree instead of kfree_skb:
for f in $(git-grep -l "struct${s}sk_buff"); do sed -n "s/^.*struct${S}sk_buff${s}\*${s}\(${V}\)$Q.*$/\1/p" $f | sort | uniq | while read -r n; do sed -n "/struct${s}sk_buff${s}\*${s}${n}/,/^[{}].*$/{ /kfree(${s}${n}${s})/= }" $f | while read -r q; do echo -e "kfreeing sk_buff $n at line $q in $f\n$q"; sed -n "/struct${s}sk_buff${s}\*${s}${n}/,/^[{}].*$/p" $f; done done done 2>&1 | less
matches a comparison as the last argument of a function. This may be correct but it is sometimes a misplaced check (and should be placed after the parenthesis instead). Use getcalls and/or getfunc to determine whether a boolean as the last argument is correct:
h="\(([^()]*)\)\+"; git-grep -n -A9 ",[^);,]*=" | sed -n "s/^\([^\.]*\.[chsS]-[0-9]*-\|\([^\.]*\.[chsS]:[0-9]*:\)$s\)\(.*\)$/\2\3/p" | tr "\n" "@" | grep -o "@[^@]*$W$s(\(\([^,()]*\|$h\)*,\)\+\([^,()]*\|$h\)*[^\"]=${s}[^\",()]*)${s}[)&|]" | tr "@\t" " " | tr -s " " | less
Find values used as a boolean instead of the more common bitwise usage:
f1="\($W${s}[&|]\|[0-9]\+${s}[&|]\|)${s}[&|]\)" # adds 2 h="\(([^()]*\(([^()]*\(([^()]*)[^()]*\)*[^()]*)[^()]*\)*)\)\?" git-grep "\($f1$s$V$s$h$s\(&&\|||\|)\|?\)\|\(&&\|||\|(\)$s$V$s$h${s}[&|]$s\([0-9]*\($W\|[^0]\)[0-9]*\)\)" | sed -n "s/^.*\($f1$s\($V\)$s\(([^()]*)\)\?$s\(&&\|||\|)\)\|\(&&\|||\|(\)$s\($V\)$s\(([^()]*)\)\?${s}[&|]$s\([0-9]*\($W\|[^0]\)[0-9]*\)\).*$/\4\8/p" | while read -r n; do echo "$n"; done | sort | uniq -c | sort -rn | while read -r n a; do b=$(git-grep -n "\(\(\(if\|while\)$s(\|&&\|||\|\!\)$s$a$s\(&&\|||\|\|)?\|(\)\|\(&&\|||\|(\)$s$a$s\(&&\|||\|(\|?\)\)" | grep -v "Kconfig") [ -z "$b" ] && continue; c=`echo "$b" | wc -l` let d=$(($n/$c)) echo "----[ a=\"$a\" # used $n times as bitwise, $c times as boolean, div $d ]----" [ $c -gt 20 ] && continue; [ $d -lt 5 ] && continue; echo "$b" done | less
Scripts
I called it vars, it contains some functions for kernel hacking. usage: "source path/to/vars" N.B. do not source this in a shell that you plan to use to compile a kernel ($Q is used in Makefiles as well, which will give some problems)
# (c) Roel kluin, 2008 GNU GPL V.2 alias gg="git-grep -n" # Usage: v /path/to/sourcefile.c:1 # (as pasted from git-grep -n) v() { [ -n "$1" ] && vi ${1%[:-]*} +${1##*[:-]} } # a number export D="[0-9]\+" # we could also use this, to match something like 1ul, floats or hexes as well: # but the parentheses will cost one backreference for (git-)grep export d="\([0-9]\+[uUlLfF]\?\|[0-9]\+[uU]\?[lL][lL]\?\|0x[a-f0-9]\+\|0x[A-F0-9]\+\|[0-9]\+[lL][lL][uU]\|[0-9]*\.[0-9]\+[fF]\?\)" # can be used for a variable/function name: export V="[A-Za-z_]\+[A-Za-z0-9_]*" # capital: a config option/definition export K="[A-Z]\+[A-Z0-9_]*"; # works the same as above, but also for members and arrays: one backreference export W="$V\(\[$s$V$s\]\|\[$s$D$s\]\|\.$V\|->$V\)*" # seperators: export s="[[:space:]]*"; export S="[[:space:]]\+" # useful to delimit a variable name: export Q="[^[:alnum:]_]" # match the end of the line, including comments: one backreference (but at eol) export cendl="$s\(\/[\*\/].*\)\?$" # match something that is not comment, string or character: 2 backreferences export ccode="\([^\/\"']*\|\/[^\*\/]\|\/\*\([^\*]*\|\**[^\/\*]\)*\*\+\/\|'[^']*'\|\"[^\"]*\"\)*" # resp function open and end (only works when indentation is correct. export fo="^[\{]$cendl" export fe="^[\}]$cendl" # works similar to git-grep -n "$query" | tr ":" " " # except that :'s in the line are preserved ggrep2fnl() { git-grep -n "$1" | while read -r fnl; do f="$(echo "$fnl"| cut -d":" -f1)"; e="$(echo "$f" | rev | cut --complement -c3- | rev)"; [ "$e" != ".h" -a "$e" != ".c" ] && continue; echo "$f $(echo "$fnl"| cut -d":" -f2) $(echo "$fnl"| cut -d":" -f3-)"; done } #print function declaration at file "$1", line "$2" # also works for /path/to/filename.c:nr getfuncat() { [ $# -ne 1 ] && return 1; f="${1%[:-]*}" [ ! -f "$f" ] && return 2; l="${1##*[:-]}" Z="@[:space:]" a="[^()]*" nested_parentheses="\(($a\(($a\(($a\(($a\(($a)$a\)*)$a\)*)$a\)*)$a\)*)$a\)*" func="\(${V}[$Z]\+\)*${V}[*$Z]\+$V$s($a$nested_parentheses)" eol="[$Z]*\([$Z]\|\/\/[^@]*@\|\/\*\([^\*]*\|\**[^\/\*]\)*\*\+\/\)*@{" head -n$l "$f" | tr "\n" "@" | sed -n "s/.*@\($func\)$eol.*/\1@/p" | tail -n1 | tr "@" "\n" } #print function declaration(s) getfunc() { q="^\(${V}[*&[:space:]]\+\)*$1$s(${ccode}[^;]$cendl"; ggrep2fnl "$q" | while read -r f n l; do [ -z "`echo $l | grep "{$cendl"`" -a \ -n "`sed -n "$n,/{$cendl/{/;/p}" "$f"`" ] && continue echo "//---[ vi $f +$n ]---" [ -n "`echo $l | grep "^$s$1"`" ] && let "n--" sed -n "$n,/$fe/p" "$f" done } # helper to print definition(s) / macro(s) _getdef() { ggrep2fnl "$2" | while read -r f n l; do echo "---[ vi $f +$n ]---" 1>&2 if [ -z "`echo $l | grep "\\$cendl"`" ]; then echo $l else sed -n "/$2/,/[^\\]$cendl/p" "$f" fi done } #print definition(s) / macro(s) getdef() { _getdef "$1" "^$s#${s}define$S$1\(([^()]*)\)\?$S" } #print only macro(s) getmac() { _getdef "$1" "^$s#${s}define$S$1([^()]*)$S" } # echoes "function name" at file "$1" line "$2" det_func() { q="^\(${V}[*&[:space:]]\+\)*\($V\)$s(${ccode}[^;]$cendl" head "$1" -n"$2" | tac | sed -n "/$q/{s/$q/\2/p;q}" } getcalls() { git-grep -n "\(^\|^$ccode$Q\)$1$s(\($ccode\()$s;\|[^)]\|)$ccode)$ccode\)\)\?$cendl" }
To translate a module name (as listed in modprobe -l or modinfo -n module) into a kernel .config option:
mod="${1%.ko}"; dir="${1%/*}"; sed -e :a -e '/\\$/N; s/\\\n//; ta' "${dir#*/kernel/}/Makefile" | \ sed -n "s/^obj-\$(CONFIG_\([A-Z0-9_]*\))\W*+=\W*"${mod##*/}"\.o$/\1/p";
Based on Linus' script to get the email address of a maintainer, I wrote this script to get the address of a list rather than a maintainers address for mailing.
git log --since="1 year ago" "$@" | sed -n "s/^ .[-a-z]*by: \(.*\) <.*$/\1/p" | sort | uniq | sort -n -r | while read -r name; do sed -n "/^P:[ \t]*.*$name/,/^$/{ s/^L:[ \t]*\(.*\)$/\1/p }" ./MAINTAINERS done | sort | uniq -c | sort -n -r | while read -r nr list; do tot=`grep -c "^L:\W*.*$list.*" ./MAINTAINERS` echo "`expr $nr / \( $tot + 1 \)` $nr $tot $list" done | sort -r | cut -d " " -f2- | while read -r nr tot list; do echo -e "$nr/$tot Acks were commited by maintainers of list $list" done