1#! /bin/sh 2# SPDX-License-Identifier: GPL-2.0 3# 4# (c) 2019, Google 5progname="${0##*/}" 6 7# Add instrumentation to module_init and probe functions. 8 9USAGE="USAGE: ${progname} [dir|file] 10 11Add debug instrumentation to module_init and probe functions." 12 13if [ X"--help" = X"${1}" -o X"{-h}" = X"${1}" ]; then 14 echo "${USAGE}" >&2 15 exit 16fi 17DIR=. 18if [ 1 = ${#} ]; then 19 DIR=${1} 20 shift 21fi 22if [ 0 != ${#} ]; then 23 echo "Unexpected Argument: ${*}" >&2 24 echo >&2 25 echo "${USAGE}" >&2 26 exit 1 27fi 28 29# A _real_ embedded tab character 30TAB="`echo | tr '\n' '\t'`" 31# A _real_ embedded escape character 32ESCAPE="`echo | tr '\n' '\033'`" 33# Colours 34RED="${ESCAPE}[38;5;196m" 35ORANGE="${ESCAPE}[38;5;255:165:0m" 36BLUE="${ESCAPE}[35m" 37NORMAL="${ESCAPE}[0m" 38 39TMP=`mktemp -d` 40 41# ${file} ${call} and ${symbol} input 42SYMBOLS=" " 43add_debug_printk() 44{ 45 message="printk(KERN_WARNING \"${file##*/}:" 46 if [ -z "${call#select}" ]; then 47 # We need uniqueness for discovery, so instead of truth of __func__ to 48 # cover any of our mistakes(!), we select the expectation. 49 message+="${symbol}: ENTER\\\\n\");" 50 else 51 message+="%s:${call}: ENTER\\\\n\", __func__);" 52 fi 53 if grep "${TAB}${message%%\\*}" ${file} >/dev/null; then 54 if [ "${SYMBOLS}" == "${SYMBOLS#* ${symbol}:${call#select}}" ]; then 55 echo INFO: already ${file} instrumented ${call#select} ${symbol} >&2 56 SYMBOLS="${SYMBOLS}${symbol}:${call} " 57 fi 58 return 59 fi 60 if [ "device_initcall" = "${call}" -o "module_init" = "${call}" -o "module_exit" = "${call}" ] && 61 grep "${TAB}printk(KERN_WARNING \"${file##*/}:%s:\(builtin\|module\)_[a-z]*_driver: ENTER" ${file} >/dev/null; then 62 if [ "${SYMBOLS}" == "${SYMBOLS#* ${symbol}:${call#select}}" ]; then 63 echo INFO: maybe already ${file} instrumented ${call#select} ${symbol} >&2 64 fi 65 return 66 fi 67 sed "/^\(static \)\{0,1\}.* ${symbol}(/ { 68 N 69 s/^\(static \)\{0,1\}\(.* ${symbol}(\)\(void\)\{0,1\}) {[ ${TAB}]*}\(\n\)/\1\2\3)\4{\4${TAB}${message}\4}\4/ 70 t exit 71 N 72 /\/[*][^*]*\$/ { 73 : comment_loop 74 N 75 /\/[*].*[*]\// b comment_done 76 b comment_loop 77 : comment_done 78 /\/[*].*[*]\/\$/ N 79 } 80 /printk(KERN_WARNING \"${file##*/}:/ b exit 81 s/\(\n${TAB}\)\(kfree(\|DBG(\|return[ ${TAB}]\|if (\|platform_driver_\|class_destroy(\|pr_info(\|[a-z_0-9]*_register\(_drivers\|_simple\)\{0,1\}(\|[a-z_0-9]*_\(un\|de\)register\(_drivers\|_simple\)\{0,1\}(\|[a-z+_0-9]*_driver(\)/\1${message}&/ 82 t exit 83 N 84 /printk(KERN_WARNING \"${file##*/}:/ b exit 85 s/\(\n${TAB}\)\(DBG(\|return[ ${TAB}]\|if (\|platform_driver_\|pr_info(\|[a-z_0-9]*_register\(_drivers\|_simple\)\{0,1\}(\|[a-z_0-9]*_\(un\|de\)register\(_drivers\|_simple\)\{0,1\}(\)/\1${message}&/ 86 t exit 87 s/\(static void .*\)\(\n${TAB}\)\([a-z].*\)\2}\$/\1\2${message}\2\3\2}/ 88 t exit 89 N 90 /printk(KERN_WARNING \"${file##*/}:/ b exit 91 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 92 t exit 93 N 94 /printk(KERN_WARNING \"${file##*/}:/ b exit 95 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 96 t exit 97 N 98 /printk(KERN_WARNING \"${file##*/}:/ b exit 99 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 100 t exit 101 N 102 /printk(KERN_WARNING \"${file##*/}:/ b exit 103 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 104 t exit 105 N 106 /printk(KERN_WARNING \"${file##*/}:/ b exit 107 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 108 t exit 109 N 110 /printk(KERN_WARNING \"${file##*/}:/ b exit 111 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 112 t exit 113 N 114 /printk(KERN_WARNING \"${file##*/}:/ b exit 115 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 116 t exit 117 N 118 /printk(KERN_WARNING \"${file##*/}:/ b exit 119 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 120 t exit 121 N 122 /printk(KERN_WARNING \"${file##*/}:/ b exit 123 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 124 t exit 125 N 126 /printk(KERN_WARNING \"${file##*/}:/ b exit 127 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 128 t exit 129 N 130 /printk(KERN_WARNING \"${file##*/}:/ b exit 131 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 132 t exit 133 N 134 /printk(KERN_WARNING \"${file##*/}:/ b exit 135 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 136 t exit 137 N 138 /printk(KERN_WARNING \"${file##*/}:/ b exit 139 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 140 t exit 141 N 142 /printk(KERN_WARNING \"${file##*/}:/ b exit 143 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 144 t exit 145 N 146 /printk(KERN_WARNING \"${file##*/}:/ b exit 147 s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/ 148 : exit 149 } 150 s/^builtin_\([a-z]*\)_driver(\(${symbol}\));\$/static int __init \2_init(void)\n{\n${TAB}${message}\n${TAB}return \1_driver_register(\&\2);\n}\ndevice_initcall(\2_init);/ 151 s/^module_\([a-z]*\)_driver(\(${symbol}\));\$/static int __init \2_init(void)\n{\n${TAB}${message}\n${TAB}return \1_driver_register(\&\2);\n}\nmodule_init(\2_init);\n\nstatic void __exit \2_exit(void)\n{\n${TAB}${message}\n${TAB}\1_driver_unregister(\&\2);\n}\nmodule_exit(\2_exit);/ 152 " ${file} > ${TMP}/${file##*/} && 153 ! cmp -s ${file} ${TMP}/${file##*/} && 154 cp ${TMP}/${file##*/} ${file} && 155 ( 156 echo INFO: modified ${file} to instrument ${call#select} ${symbol} >&2 157 echo ${symbol} 158 ) || 159 ( 160 files=`grep -lr "^\(static \)\{0,1\}[^ ${TAB}][ %{TAB}_a-zA-Z0-9]* ${symbol}(" ${DIR} | 161 sed -e '/[.]h$/d' -e 's@^[.]/@@'` 162 if [ X"${file}" != X"${files}" ]; then 163 echo "${ORANGE}WARNING${NORMAL}: ${symbol} is in ${files}" >&2 164 if [ 1 -eq `echo ${files} | wc -w` ]; then 165 file=${files} 166 add_debug_printk 167 exit 168 fi 169 fi 170 if [ "${SYMBOLS}" == "${SYMBOLS#* ${symbol}:${call#select}}" ]; then 171 echo "${RED}ERROR${NORMAL}: failed to modify ${file} to instrument" ${call#select} ${symbol} >&2 172 fi 173 false 174 ) 175 ret=${?} 176 rm -f ${TMP}/${file##*/} 177 if [ 0 -eq ${ret} ]; then 178 SYMBOLS="${SYMBOLS}${symbol}:${call} " 179 fi 180 return ${ret} 181} 182 183# module_init, module_exit, late_initcall ... 184( 185 grep -Hr '^\(builtin_[a-z]*_driver\|module_[a-z]*_driver\|module_\(init\|exit\)\|[a-z]*_initcall\)(' ${DIR} | 186 sed -n 's@^[.]/@@ 187 s/^\([^:]*\):\(builtin_[a-z]*_driver\|module_[a-z]*_driver\|module_init\|module_exit\|[a-z]*_initcall\)(\([^)]*\));$/\1 \2 \3/p' | 188 sort -u 189 find ${DIR} -name '*.c' | 190 while read file; do 191 sed -n "/.* [a-z_0-9]*(void)\$/ { 192 : loop 193 N 194 /^[^\n]* [a-z_0-9]*(void)\n.*\n}\$/ { 195 /.*platform_\(driver\|device\)_\(un\)\{0,1\}register([&][^)]*).*/ { 196 s@^[^\n]* \([a-z_0-9]*\)(void)\n.*@${file} select \1@p 197 b exit 198 } 199 /.*[ ${TAB}]_[a-z]_\(un\)\{0,1\}register_driver([&][^, ${TAB})]*).*/ { 200 s@^[^\n]* \([a-z_0-9]*\)(void)\n.*@${file} select \1@p 201 b exit 202 } 203 /.*i2c_\(add\|del\)_driver([&][^)]*).*/ { 204 s@^[^\n]* \([a-z_0-9]*\)(void)\n.*@${file} select \1@p 205 } 206 b exit 207 } 208 b loop 209 } 210 : exit" ${file} 211 done | 212 sort -u 213) | 214 while read file call symbol; do 215 if ! add_debug_printk && [ "${SYMBOLS}" == "${SYMBOLS#* ${symbol}:${call#select}}" ]; then 216 echo FAILED 217 fi 218 219 if [ "${call}" != "${call#builtin_*_driver}" -o "${call}" != "${call#module_*_driver}" ]; then 220 symbol=${symbol}_init 221 fi 222 call=probe 223 sed -n "/\(static \)\{0,1\}.* ${symbol}(/,/^}/ { 224 s/.*platform_\(driver\|device\)_register([&]\([^)]*\)).*/struct platform_\1 \2/p 225 s/.*[ ${TAB}]\(_[a-z]\)_register_driver([&]\([^, ${TAB})]*\)).*/struct \1_driver \2/p 226 s/.*i2c_add_driver([&]\([^)]*\)).*/struct i2c_driver \1/p 227 } 228 s/\(builtin\|module\)_\([a-z]*_driver\)(\([^)]*\));/struct \2 \3/p" ${file} | 229 sort -u | 230 while read struct; do 231 sed -n "/\(static \)\{0,1\}${struct} = {/,/^};/ { 232 s/^[ ${TAB}]*[.]probe[ ${TAB}]*=[ ${TAB}]*\([^ ${TAB}]*\),\$/\1/p 233 }" ${file} | 234 sort -u | 235 while read symbol; do 236 if ! add_debug_printk && [ "${SYMBOLS}" == "${SYMBOLS#* ${symbol}:${call} }" ]; then 237 echo FAILED 238 fi 239 done 240 done 241 done | 242 sort -u | 243 tee ${TMP}/list | 244 grep '^FAILED' >/dev/null 245ret=${?} 246SYMBOLS=`grep -v '^FAILED$' ${TMP}/list` 247 248rm -rf ${TMP} 249 250if [ 0 -ne ${ret} ]; then 251 echo "DONE" >&2 252 253 AUTHOR_NAME="`git config user.name`" 254 AUTHOR_EMAIL="`git config user.email`" 255 if [ -z "${AUTHOR_EMAIL}" ]; then 256 AUTHOR_EMAIL="`${USER}@google.com`" 257 fi 258 if [ -z "${AUTHOR_NAME}" ]; then 259 convert_ldap_to_name() { 260 echo "${1##*/}" | 261 sed "s@[-_]@ @g 262 s@ *@ @g" | 263 sed 's@\(^\| \)a@\1A@g 264 s@\(^\| \)b@\1B@g 265 s@\(^\| \)c@\1C@g 266 s@\(^\| \)d@\1D@g 267 s@\(^\| \)e@\1E@g 268 s@\(^\| \)f@\1F@g 269 s@\(^\| \)g@\1G@g 270 s@\(^\| \)h@\1H@g 271 s@\(^\| \)i@\1I@g 272 s@\(^\| \)j@\1J@g 273 s@\(^\| \)k@\1K@g 274 s@\(^\| \)l@\1L@g 275 s@\(^\| \)m@\1M@g 276 s@\(^\| \)n@\1N@g 277 s@\(^\| \)o@\1O@g 278 s@\(^\| \)p@\1P@g 279 s@\(^\| \)q@\1Q@g 280 s@\(^\| \)r@\1R@g 281 s@\(^\| \)s@\1S@g 282 s@\(^\| \)t@\1T@g 283 s@\(^\| \)u@\1U@g 284 s@\(^\| \|Mc\)v@\1V@g 285 s@\(^\| \)w@\1W@g 286 s@\(^\| \)x@\1X@g 287 s@\(^\| \)y@\1Y@g 288 s@\(^\| \)z@\1Z@g' 289 } 290 AUTHOR_NAME="`convert_ldap_to_name ${USER}`" 291 fi 292 293 git commit -a -m "GKI: DEBUG: add instrumentation to init and probe functions 294 295Automatically generated by ${0} 296 297The following symbols are instrumented: 298`echo \"${SYMBOLS}\" | 299 sed 's/^/ - /'` 300 301Signed-off-by: ${AUTHOR_NAME} <${AUTHOR_EMAIL}> 302Test: compile" || 303 echo "${RED}ERROR${NORMAL}: failed to commit changes to git" >&2 304 exit 305fi 306echo "${RED}FAILED${NORMAL}: could not complete task" >&2 307exit 1 308