KernelNewbies:

Roel Kluin

Email: MailTo(12o3l AT SPAMFREE tiscali DOT nl) ...


CategoryHomepage

all code is (c) Roel kluin, 2007 GNU GPL V.2.

==Examples==

These may require the variables in the script 'vars' below, and should be called in a git tree. I simply paste them into my console (bash).

some of

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 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 n; do
sed -n "/struct${s}sk_buff${s}\*${s}${n}/,/^[{}].*$/{ /kfree(${s}${n}${s})/= }" $f | while read 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

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 n; do
echo "$n"; 
done | 
sort | uniq -c | sort -rn | while read 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 useful functions for kernel hacking. usage: "source path/to/vars" N.B. do not source this in the shell where you will compile the kernel ($Q is used in Makefiles as well, which will give problems)

# (c) Roel kluin, 2008 GNU GPL V.2

# 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"

alias gg="git-grep -n"

# Usage: v /path/to/sourcefile.c:1
# (as pasted from git-grep -n)
v()
{
  [ -n "$1" ] && vi ${1%[:-]*} +${1##*[:-]}
}

# works similar to git-grep -n "$query" | tr ":" " "
# except that :'s in the line are preserved
ggrep2fnl()
{
  git-grep -n "$1" | while read 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"
getfuncat()
{
  head -n$2 "$1" | tac | sed -n "p; /^\(${V}[*&[:space:]]\+\)*$V$s(${ccode}[^;]$cendl/q" | tac
  #sed -n "/^\(${V}[*&[:space:]]\+\)*$V$s(${ccode}[^;]$cendl/,$(($2 - 1))p" "$1" | sed "{$2,/^[\}]$cendl/p}"
}

#print function declaration(s)
getfunc()
{
  q="^\(${V}[*&[:space:]]\+\)*$1$s(${ccode}[^;]$cendl";
  ggrep2fnl "$q" | while read 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 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"
}

#print function declaration(s) / definition(s) / macro(s)
getfod()
{
  getfunc $1;
  getdef $1;
}

#print macro(s) or function declaration(s)
getfom()
{
  getfunc $1;
  getmac $1;
}

# 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 name; do
        sed -n "/^P:[ \t]*.*$name/,/^$/{
                s/^L:[ \t]*\(.*\)$/\1/p
        }" ./MAINTAINERS
done | sort | uniq -c | sort -n -r | while read 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 nr tot list; do
        echo -e "$nr/$tot Acks were commited by maintainers of list $list"
done

KernelNewbies: RoelKluin (last edited 2008-03-18 21:02:30 by 82-171-187-43)