summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-02-12 22:22:55 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-02-12 22:22:55 +0000
commitb2106dcb0b3186405174c107e6e8bbf783693be0 (patch)
tree4e000be0865a5c9c573ed62be838002ad6aec6cb
parenta5006dc4f1dac9fb23e16275db8b9cb08a76da1f (diff)
parent7c43ab3ab06fe9c9490193062d1241c03a5fcb30 (diff)
downloadbuild-b2106dcb0b3186405174c107e6e8bbf783693be0.tar.gz
Merge "GKI: helpful modularization scripts" am: 5ffa3b2a33 am: f381234993 am: 7c43ab3ab0
Change-Id: Ibc64ca34005681323078380fabacc222ef1cc6e6
-rw-r--r--gki/README.md132
-rwxr-xr-xgki/add_EXPORT_SYMBOL_GPL389
-rwxr-xr-xgki/add_MODULE_LICENSE112
-rwxr-xr-xgki/device_snapshot675
-rwxr-xr-xgki/find_circular170
-rwxr-xr-xgki/instrument_module_init307
6 files changed, 1785 insertions, 0 deletions
diff --git a/gki/README.md b/gki/README.md
new file mode 100644
index 00000000..e848894d
--- /dev/null
+++ b/gki/README.md
@@ -0,0 +1,132 @@
+GKI Tools for Android Kernels
+=============================
+
+Overview
+--------
+
+This directory contains helpful tools that may be used to aid in the
+development of modularized drivers.
+
+add_EXPORT_SYMBOLS_GPL
+----------------------
+
+ USAGE: add_EXPORT_SYMBOL_GPL [--no-skip-arch] < kernel_build_error_log
+ add_EXPORT_SYMBOL_GPL [--no-skip-arch] kernel_build_error_log
+ grep /<module>[.]ko build_error_log | add_EXPORT_SYMBOL_GPL [--no-skip-arch]
+ vi `add_EXPORT_SYMBOL_GPL [--no-skip-arch] < kernel_build_error_log`
+
+To acquire the kernel_build_error_log eg:
+
+ $ ./build_sm8250.sh -j50 2>&1 | tee kernel_build_error_log
+
+To only create commit related to symbols needed for cam_spec.ko module:
+
+ $ grep /cam_spec[.]ko kernel_build_error_log | add_EXPORT_SYMBOL_GPL
+
+The script will only affect the current directory level and downward,
+this allows one to segregate the adjusted content. Any symbols that
+are needed outside the range of that directory will result in errors
+and the git commit phase will not be performed.
+
+Add EXPORT_SYMBOL_GPL for any noted missing symbols, output the list of files
+modified to stdout (so it can be passed to an editor command line should you
+need to check or adjust the results). Automatically commit the list of files
+into git.
+
+Deals as simply as it can to handle \_\_trace\_\<symbols>, sorting the result.
+
+Keep in mind exports can change, be added or subtracted, and that preliminary
+work may expose or remove required symbols to resolve during later work. As
+such this script only adds, so you may need to revert the results and try
+again to get the most up to date set. By making this part automated it can
+deal with the tens or thousands of exports that need to be discovered or
+added. If you need to adjust a subsystem, run this script in the subsystem
+directory, and it will only adjust from that point downwards leaving other
+higher up trees alone.
+
+add_MODULE_LICENSE
+------------------
+
+ USAGE: add_MODULE_LICENSE < kernel_build_error_log
+ add_MODULE_LICENSE kernel_build_error_log
+
+Add MODULE_LICENSE to all the files.
+
+Must be performed in the root directory.
+
+find_circular
+-------------
+
+ USAGE: find_circular [dir]
+
+Call this when depmod breaks down, or when one needs a list of the symbols
+implicated in the circular dependency.
+
+Search current or dir directory for all kernel modules. Itemize what they
+export, and what they import. Discover links and report who fulfills them.
+Report any first order circular relationships and the symbols that got us
+into the situation.
+
+Standard output is of the form:
+
+module1.ko(symbols) -> module2.ko(symbols) -> module1.ko
+
+Leaves an annotated modules.dep file in the specified directory.
+
+device_snapshot
+---------------
+
+ USAGE: device_snapshot [-s <serialno>] [-D] [-f [<input>]] [-F [-o <output> [-d <input>]]]
+
+Collect filtered /dev and /sys details, along with dmesg and probe list.
+
+-o \<output> will drop the collection into a set of files, but will not
+overrite existing content. -F will overwrite.
+
+-D will wait for the display
+
+if \<output> is empty ('' or last option), will not collect dmesg or probe
+list. If no -o option is specified, then \<output> will be default of -
+(stdout) and all pieces will go to the standard output separated by a cut
+and snip header. If specified, \<output> will contain the filtered /dev/
+and /sys/ dumps, \<output>.probed the subset filter of just the probed drivers,
+\<output>.dmesg the kernel logs and \<output>.config the uncompressed
+/proc/config.gz.
+
+-d \<input> will take the dropped collection specified to -o \<output> and
+produce a diff -U1 output compared against the \<input>.
+
+-f \<input> allows one to utilize the filter to an existing find /dev /sys
+output from a device. No dmesg will be collected.
+
+-s \<serialno> will allow one to specify a device to connect to when multiples
+are available, otherwise will default to one available or ANDROID_SERIAL
+environment variable.
+
+In your local build/flash/boot script for tight development cycles, add
+
+ SEQ=`for i in out/${DEFAULT_BUILD}.snapshot.[0-9]*; do
+ echo ${i#out/${DEFAULT_BUILD}.snapshot.}
+ done |
+ sed 's/^0*//' |
+ grep -v 0-9 |
+ tr -d .[:alpha:] |
+ sort -nu |
+ tail -1` &&
+ NEWSEQ=$((${SEQ:-0}+1)) &&
+ NEWSEQ=`printf "%03u" ${NEWSEQ}`
+ if [ -z "${SEQ}" ]; then
+ private/msm-google/scripts/gki/device_snapshot \
+ -o out/${DEFAULT_BUILD}.snapshot.${NEWSEQ}
+ else
+ SEQ=`printf "%03u" ${SEQ}`
+ private/msm-google/scripts/gki/device_snapshot \
+ -o out/${DEFAULT_BUILD}.snapshot.${NEWSEQ} \
+ -d out/${DEFAULT_BUILD}.snapshot.${SEQ}
+ fi
+
+instrument_module_init
+----------------------
+ USAGE: instrument_module_init [dir|file]
+
+Add debug instrumentation to module_init and probe functions.
diff --git a/gki/add_EXPORT_SYMBOL_GPL b/gki/add_EXPORT_SYMBOL_GPL
new file mode 100755
index 00000000..f1d2b84e
--- /dev/null
+++ b/gki/add_EXPORT_SYMBOL_GPL
@@ -0,0 +1,389 @@
+#! /bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# (c) 2019, Google
+progname="${0##*/}"
+
+# Change to EXPORT_SYMBOL, EXPORT_SYMBOL_GPL or other namespace variant default
+EXPORT_SYMBOL=${EXPORT_SYMBOL_GPL:-${progname#add_}}
+
+USAGE="USAGE: ${progname} [--no-skip-arch] < kernel_build_error_log
+ ${progname} [--no-skip-arch] kernel_build_error_log
+ grep /<module>[.]ko build_error_log | ${progname} [--no-skip-arch]
+ ${EDITOR:-vi} \`${progname} [--no-skip-arch] < kernel_build_error_log\`
+
+To acquire the kernel_build_error_log eg:
+\$ ./build_sm8250.sh -j50 2>&1 | tee kernel_build_error_log
+
+To only create commit related to symbols needed for cam_spec.ko module:
+\$ grep /cam_spec[.]ko kernel_build_error_log | ${progname}
+
+The script will only affect the current directory level and downward,
+this allows one to segregate the adjusted content. Any symbols that
+are needed outside the range of that directory will result in errors
+and the git commit phase will not be performed.
+
+Add ${EXPORT_SYMBOL} for any noted missing symbols, output the list of files
+modified to stdout (so it can be passed to an editor command line should you
+need to check or adjust the results). Automatically commit the list of files
+into git.
+
+Deals as simply as it can to handle __trace_<symbols>, sorting the result.
+
+Keep in mind exports can change, be added or subtracted, and that preliminary
+work may expose or remove required symbols to resolve during later work. As
+such this script only adds, so you may need to revert the results and try
+again to get the most up to date set. By making this part automated it can
+deal with the tens or thousands of exports that need to be discovered or
+added. If you need to adjust a subsystem, run this script in the subsystem
+directory, and it will only adjust from that point downwards leaving other
+higher up trees alone."
+
+if [ X"--help" = X"${1}" -o X"{-h}" = X"${1}" ]; then
+ echo "${USAGE}" >&2
+ exit
+fi
+skip_arch=true
+if [ X"--no-skip-arch" = X"${1}" ]; then
+ skip_arch=false
+ shift
+fi
+INPUT=
+if [ 1 = ${#} ]; then
+ INPUT=${1}
+ shift
+fi
+if [ 0 != ${#} ]; then
+ echo "Unexpected Argument: ${*}" >&2
+ echo >&2
+ echo "${USAGE}" >&2
+ exit 1
+fi
+
+# A _real_ embedded tab character
+TAB="`echo | tr '\n' '\t'`"
+# A _real_ embedded escape character
+ESCAPE="`echo | tr '\n' '\033'`"
+# Colours
+RED="${ESCAPE}[38;5;196m"
+BLUE="${ESCAPE}[35m"
+NORMAL="${ESCAPE}[0m"
+
+# Common grep/sed regex expressions
+STRUCT_TYPE="struct[ ${TAB}][^ ${TAB}]\{1,\}"
+VAR_TYPE="\(${STRUCT_TYPE}\|bool\|char\|int\|long\|long long\|u\{0,1\}int[0-9]*t\)[ ${TAB}]\{1,\}[*]\{0,1\}"
+STRUCT_TYPE="${STRUCT_TYPE}[ ${TAB}]\{1,\}[*]\{0,1\}"
+
+# Files that exports should never exist, or need to be carefully considered
+skip_arch_files() {
+ if ${skip_arch}; then
+ grep -v '\(^\|^[^:]*/\)arch/[^a][^r][^m][^:]*:'
+ else
+ cat -
+ fi
+}
+
+# Following sucks in all the data from stdin or ${INPUT}
+# Check for depmod output (undefined!) or built-in kernel complaints (undefined
+# references). The later is not advised because it means the kernel may be
+# dependent on a module, we collect it to provide a signal for future work.
+echo "Reading symbols" >&2
+MODULES="`
+ sed -n \
+ -e 's/^ERROR: "\([^"]*\)" [[]\(.*[.]ko\)[]] undefined!$/\1 \2/p' \
+ -e 's/^[^:]*:[0-9]*: undefined reference to \`\([^'\'']*\)'\''$/\1/p' \
+ ${INPUT} |
+ sort -u`"
+SYMBOLS="`echo \"${MODULES}\" | sed 's/ .*$//' | sort -u`"
+if [ -z "${SYMBOLS}" ]; then
+ echo "${BLUE}WARNING${NORMAL}: no symbols found" >&2
+ exit
+fi
+
+SYMBOLS_PLUS_TRACE="${SYMBOLS}"
+TRACE_MODULES="`echo \"${MODULES}\" |
+ sed -n 's/__tracepoint_.* //p' |
+ sort -u`"
+TRACE_MODULES_2=
+c=`echo "${TRACE_MODULES}" | wc -l`
+if [ 1 -eq ${c} ];then
+ TRACE_MODULES="${TRACE_MODULES%/*.ko}"
+ if [ -z "${INPUT}" ]; then
+ TRACE_MODULES_2=*
+ else
+ TRACE_MODULES_2=${INPUT}
+ fi
+elif [ -z "${INPUT}" ]; then
+ TRACE_MODULES=*
+else
+ TRACE_MODULES=${INPUT}
+fi
+TRACE_FILE="`grep -rl '^#define CREATE_TRACE_POINTS' ${TRACE_MODULES}`"
+if [ -z "${TRACE_FILE}" -a -n "${TRACE_MODULES_2}" ]; then
+ TRACE_FILE="`grep -rl '^#define CREATE_TRACE_POINTS' ${TRACE_MODULES_2}`"
+fi
+c=0
+if [ -n "${TRACE_FILE}" ]; then
+ c=`echo "${TRACE_FILE}" | wc -l`
+fi
+if [ 1 -eq ${c} ]; then
+ SYMBOLS_PLUS_TRACE="${SYMBOLS}
+`echo \"${SYMBOLS}\" |
+ sed -n 's/^__tracepoint_\(.*\)/EXPORT_TRACEPOINT_SYMBOL_GPL(\1);/p'`"
+else
+ TRACE_FILE=
+fi
+
+echo "Finding symbols in the current tree" >&2
+DATA="`grep -Fr \"${SYMBOLS_PLUS_TRACE}\" * |
+ grep \"^[^:]*[.][cS]:[^ ${TAB}]\" |
+ skip_arch_files`"
+echo "Editing the files that contain the symbols" >&2
+TMP=`mktemp -d`
+
+[ 'USAGE: report_strip_of_tag tag
+
+Report if a problematic function segment tag is stripped from the file
+
+expects ${F}, ${TMP}, ${TAB}, ${RED} and ${NORMAL} to be defined' ]
+report_strip_of_tag() {
+ if diff --side-by-side --suppress-common-lines ${F} ${TMP}/${F##*/} |
+ sed -n "s/\(.*[ ${TAB}]\)\(__${1}\)\([^a-zA-Z0-9_].*[^ ${TAB}]\)[ ${TAB}]\{1,\}|[ ${TAB}]\{1,\}/\1${BLUE}\2${NORMAL}\3 -> /p" |
+ grep __${1} >&2; then
+ echo "${RED}ERROR${NORMAL}: scrubbing __${1} from function in ${F}" >&2
+ echo " Compile check, possibly edit ${F} and friends." >&2
+ echo " Then re-run ${progname} to complete." >&2
+ echo FAILED
+ fi
+}
+
+for s in ${SYMBOLS}; do
+ # Already there?
+ if echo "${DATA}" |
+ grep "EXPORT_\(TRACEPOINT_SYMBOL_GPL*(${s#__tracepoint_}\|SYMBOL\(_GPL\)*(${s}\))" >/dev/null; then
+ echo INFO: ${s} found and already exported >&2
+ continue
+ fi
+ m="`echo \"${DATA}\" | grep \"^[^:]*:\([^ ${TAB}].*[ *]\|\)${s}(\"`"
+ c=0
+ if [ -n "${m}" ]; then
+ c=`echo "${m}" | wc -l`
+ fi
+ if [ 0 -eq ${c} ]; then
+ m="`echo \"${DATA}\" | grep \"^[^:]*:\(const[ ${TAB}]\{1,\}\|\)${STRUCT_TYPE}${s}\([[][]]\|\) = {\"`"
+ c=0
+ if [ -n "${m}" ]; then
+ c=`echo "${m}" | wc -l`
+ fi
+ if [ 0 -eq ${c} ]; then
+ m="`echo \"${DATA}\" | grep \"^[^:]*:\(const[ ${TAB}]\{1,\}\|\)${VAR_TYPE}${s}[\[ ${TAB};=]\"`"
+ c=0
+ if [ -n "${m}" ]; then
+ c=`echo "${m}" | wc -l`
+ fi
+ if [ 0 -eq ${c} ]; then
+ if [ -z "${TRACE_FILE}" -o "${s}" = "${s#__tracepoint_}" ]; then
+ echo "${RED}ERROR${NORMAL}: ${s} not found" >&2
+ if [ "${s}" != "${s#__tracepoint_}" -o "${s}" = "${s#__}" ]; then
+ echo FAILED
+ else
+ echo "${RED}WARNING${NORMAL}: ${s} might be a linker variable? skipping marking as failure" >&2
+ fi
+ else
+ echo ${TRACE_FILE} ${s}
+ fi
+ elif [ 1 -eq ${c} ]; then
+ echo "${DATA}" |
+ sed -n "s/^\([^:]*\):\(const[ $TAB]\{1,\}\|\)${VAR_TYPE}${s}.*/\1 ${s}/p"
+ else
+ echo "${RED}ERROR${NORMAL}: ${c} matches: `echo \"${m}\" |
+ tr '\n' '&' |
+ sed -e 's/&$//' \
+ -e 's/&/ & /g'`" >&2
+ echo FAILED
+ fi
+ elif [ 1 -eq ${c} ]; then
+ echo "${DATA}" |
+ sed -n "s/^\([^:]*\):\(const[ $TAB]\{1,\}\|\)${STRUCT_TYPE}\(${s}\)\([[][]]\|\) = {.*/\1 \3/p"
+ else
+ echo "${RED}ERROR${NORMAL}: ${c} matches: `echo \"${m}\" |
+ tr '\n' '&' |
+ sed -e 's/&$//' \
+ -e 's/&/ & /g'`" >&2
+ echo FAILED
+ fi
+ elif [ 1 -eq ${c} ]; then
+ echo "${DATA}" |
+ sed -n "s/^\([^:]*\):\([^ ${TAB}].*[ *]\|\)\(${s}\)(.*/\1 \3/p"
+ else
+ echo "${RED}ERROR${NORMAL}: ${c} matches: `echo \"${m}\" |
+ tr '\n' '&' |
+ sed -e 's/&$//' \
+ -e 's/&/ & /g'`" >&2
+ echo FAILED
+ fi
+done |
+ sort -u |
+ while read F s; do
+ if [ "FAILED" = "${F}" ]; then
+ echo FAILED
+ continue
+ fi
+ if [ "${s}" != "${s#__tracepoint_}" ]; then
+ sed "\$ {
+ /^[^E]/ {
+ a \
+
+ }
+ a \
+ newEXPORT_TRACEPOINT_SYMBOL_GPL(${s#__tracepoint_});
+ }" ${F}
+ else
+ cat ${F}
+ fi |
+ sed "/^\([^ ${TAB}].*[ *]\|\)${s}(/ {
+ : loop1
+ N
+ /\(\n}\);*$/ {
+ s//\1/
+ s/^\([^\n]*[^\n ${TAB}]\|\)[ ${TAB}]\{1,\}__\(init\|exit\)[ ${TAB}]\{1,\}\([^\n]*(\)/\1 \3/
+ s/^\([^\n]*[^\n ${TAB}]\|\)[ ${TAB}]\{1,\}__\(init\|exit\)\([^ ${TAB}a-zA-Z0-9_][^\n]*(\)/\1 \3/
+ s/^__\(init\|exit\)[ ${TAB}]\{1,\}\([^\n]*(\)/\2/
+ s/^__\(init\|exit\)\([^ ${TAB}a-zA-Z0-9_][^\n]*(\)/\2/
+ a \
+ new${EXPORT_SYMBOL}(${s});
+ b next1
+ }
+ b loop1
+ : next1
+ }
+ /^\(const[ ${TAB}]\{1,\}\|\)${STRUCT_TYPE}${s}\([[][]]\|\)[ ${TAB}]*=[ ${TAB}]*{/ {
+ : loop2
+ N
+ /\n};$/ {
+ a \
+ new${EXPORT_SYMBOL}(${s});
+ b next2
+ }
+ b loop2
+ : next2
+ }
+ /^\(const[ ${TAB}]\{1,\}\|\)${VAR_TYPE}${s}\(\([[][]]\|\)[ ${TAB}]*=.*\|\);/ {
+ a \
+ new${EXPORT_SYMBOL}(${s});
+ }
+ /^\(const[ ${TAB}]\{1,\}\|\)${VAR_TYPE}${s}\([[][]]\|\)[ ${TAB}]*=[ ${TAB}]*{\{0,1\}\$/ {
+ : loop3
+ N
+ /;$/ {
+ a \
+ new${EXPORT_SYMBOL}(${s});
+ b next3
+ }
+ b loop3
+ : next3
+ }" |
+ sed '/^newEXPORT/ {
+ s//EXPORT/
+ N
+ : loop
+ N
+ s/\(\n\)\n$/\1/
+ t loop
+ }' >${TMP}/${F##*/} &&
+ ! cmp -s ${F} ${TMP}/${F##*/} &&
+ [ -s ${TMP}/${F##*/} ] &&
+ report_strip_of_tag init &&
+ report_strip_of_tag exit &&
+ cp ${TMP}/${F##*/} ${F} &&
+ echo INFO: export ${s} in ${F} >&2 ||
+ (
+ echo "${RED}ERROR${NORMAL}: export ${s} in ${F}" >&2
+ echo FAILED
+ )
+ echo ${F}
+ rm ${TMP}/${F##*/}
+ done >${TMP}/${progname}.out
+FILES="`grep -v '^FAILED$' ${TMP}/${progname}.out | sort -u`"
+echo "${FILES}"
+grep '^FAILED$' ${TMP}/${progname}.out >/dev/null
+ret=${?}
+rm -rf ${TMP}
+if [ 0 -ne ${ret} ]; then
+ echo "DONE" >&2
+ GIT_FILES="`git diff |
+ sed -n 's@^diff --git a/\(.*\) b/\1$@\1@p' |
+ sort -u`"
+ if [ -z "${GIT_FILES}" ]; then
+ echo "${BLUE}WARNING${NORMAL}: no changes to commit" >&2
+ if [ -n "${FILES}" ]; then
+ echo " but we altered files!" >&2
+ fi
+ exit
+ fi
+ SEMI=""
+ if [ X"${GIT_FILES}" != X"`echo ${FILES} | tr ' ' '\n' | sort -u`" ]; then
+ SEMI="Semi-"
+ FILES=`echo ${FILES} ${GIT_FILES} |
+ tr ' ' '\n' |
+ sort -u`
+ echo "${BLUE}WARNING${NORMAL}: list of files in git different from files we expected to edit, continuation?" >&2
+ fi
+
+ AUTHOR_NAME="`git config user.name`"
+ AUTHOR_EMAIL="`git config user.email`"
+ if [ -z "${AUTHOR_EMAIL}" ]; then
+ AUTHOR_EMAIL="`${USER}@google.com`"
+ fi
+ if [ -z "${AUTHOR_NAME}" ]; then
+ convert_ldap_to_name() {
+ echo "${1##*/}" |
+ sed "s@[-_]@ @g
+ s@ *@ @g" |
+ sed 's@\(^\| \)a@\1A@g
+ s@\(^\| \)b@\1B@g
+ s@\(^\| \)c@\1C@g
+ s@\(^\| \)d@\1D@g
+ s@\(^\| \)e@\1E@g
+ s@\(^\| \)f@\1F@g
+ s@\(^\| \)g@\1G@g
+ s@\(^\| \)h@\1H@g
+ s@\(^\| \)i@\1I@g
+ s@\(^\| \)j@\1J@g
+ s@\(^\| \)k@\1K@g
+ s@\(^\| \)l@\1L@g
+ s@\(^\| \)m@\1M@g
+ s@\(^\| \)n@\1N@g
+ s@\(^\| \)o@\1O@g
+ s@\(^\| \)p@\1P@g
+ s@\(^\| \)q@\1Q@g
+ s@\(^\| \)r@\1R@g
+ s@\(^\| \)s@\1S@g
+ s@\(^\| \)t@\1T@g
+ s@\(^\| \)u@\1U@g
+ s@\(^\| \|Mc\)v@\1V@g
+ s@\(^\| \)w@\1W@g
+ s@\(^\| \)x@\1X@g
+ s@\(^\| \)y@\1Y@g
+ s@\(^\| \)z@\1Z@g'
+ }
+ AUTHOR_NAME="`convert_ldap_to_name ${USER}`"
+ fi
+
+ git commit ${FILES} -m "GKI: add missing exports for <config>=m for <compatible>
+
+<edit>
+
+${SEMI}Automatically generated by ${0##*/}
+
+The following symbols are exported:
+`echo \"${SYMBOLS}\" |
+ sed 's/^/ - /'`
+
+Signed-off-by: ${AUTHOR_NAME} <${AUTHOR_EMAIL}>
+Test: compile" ||
+ echo "${RED}ERROR${NORMAL}: failed to commit changes to git" >&2
+ exit
+fi
+echo "${RED}FAILED${NORMAL}: could not complete task" >&2
+exit 1
diff --git a/gki/add_MODULE_LICENSE b/gki/add_MODULE_LICENSE
new file mode 100755
index 00000000..d76fa85a
--- /dev/null
+++ b/gki/add_MODULE_LICENSE
@@ -0,0 +1,112 @@
+#! /bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# (c) 2019, Google
+progname="${0##*/}"
+
+USAGE="USAGE: ${progname} < kernel_build_error_log
+ ${progname} kernel_build_error_log
+
+Add MODULE_LICENSE to all the files.
+
+Must be performed in the root directory."
+
+if [ X"--help" = X"${1}" -o X"{-h}" = X"${1}" ]; then
+ echo "${USAGE}" >&2
+ exit
+fi
+INPUT=
+if [ 1 = ${#} ]; then
+ INPUT=${1}
+ shift
+fi
+if [ 0 != ${#} ]; then
+ echo "Unexpected Argument: ${*}" >&2
+ echo >&2
+ echo "${USAGE}" >&2
+ exit 1
+fi
+
+convert_to_module_name() {
+ echo "${1##*/}" |
+ sed 's@[-_]@ @g
+ s@ *@ @g
+ s@^btfm @BTFM @
+ s@^msm @MSM @
+ s@ dma\( \|$\)@ DMA\1@g
+ s@ irq\( \|$\)@ IRQ\1@g
+ s@ io\( \|$\)@ I/O\1@g
+ s@ mem\( \|$\)@ memory\1@g
+ s@ hw\( \|$\)@ hardware\1@g
+ s@ jpeg\( \|$\)@ JPEG\1@g
+ s@ mgr$@ manager@
+ s@ util$@ utilities@
+ s@\(^\| \)a@\1A@g
+ s@\(^\| \)b@\1B@g
+ s@\(^\| \)c@\1C@g
+ s@\(^\| \)d@\1D@g
+ s@\(^\| \)e@\1E@g
+ s@\(^\| \)f@\1F@g
+ s@\(^\| \)g@\1G@g
+ s@\(^\| \)h@\1H@g
+ s@\(^\| \)i@\1I@g
+ s@\(^\| \)j@\1J@g
+ s@\(^\| \)k@\1K@g
+ s@\(^\| \)l@\1L@g
+ s@\(^\| \)m@\1M@g
+ s@\(^\| \)n@\1N@g
+ s@\(^\| \)o@\1O@g
+ s@\(^\| \)p@\1P@g
+ s@\(^\| \)q@\1Q@g
+ s@\(^\| \)r@\1R@g
+ s@\(^\| \)s@\1S@g
+ s@\(^\| \)t@\1T@g
+ s@\(^\| \)u@\1U@g
+ s@\(^\| \)v@\1V@g
+ s@\(^\| \)w@\1W@g
+ s@\(^\| \)x@\1X@g
+ s@\(^\| \)y@\1Y@g
+ s@\(^\| \)z@\1Z@g'
+}
+
+sed -n \
+ 's/WARNING: modpost: missing MODULE_LICENSE() in \(.*\)[.]o$/\1/p' \
+ ${INPUT} |
+ sort -u |
+ while read f; do
+ F=${f}.c
+ if [ ! -f "${F}" ]; then
+ F=${f%${f##*/}}`echo ${f##*/} | tr -- - _`.c
+ if [ ! -f "${F}" ]; then
+ F=${F%.c}_core.c
+ if [ ! -f "${F}" ]; then
+ F=${f%${f##*/}}`echo ${f##*/} | tr _ -`.c
+ if [ ! -f "${F}" ]; then
+ F=${F%.c}_core.c
+ if [ ! -f "${F}" ]; then
+ echo WARNING: ${f}.c not found, needs a MODULE_LICENSE >&2
+ continue
+ fi
+ fi
+ fi
+ fi
+ fi
+ if grep MODULE_LICENSE ${F} >/dev/null 2>/dev/null; then
+ echo INFO: MODULE_LICENSE already present in ${F} >&2
+ continue
+ fi
+ module="`convert_to_module_name ${f}`"
+ if [ -z "${module}" ]; then
+ echo ERROR: ${f} can not be converted into a module name >&2
+ continue
+ fi
+ sed -i "\${
+ a \\
+\\
+MODULE_LICENSE(\"GPL v2\");\\
+MODULE_DESCRIPTION(\"${module}\");
+ }" ${F} &&
+ echo INFO: Added MODULE_LICENSE to ${F} >&2 ||
+ echo ERROR: Failed to add MODULE_LICENSE to ${F} >&2
+ done
+
diff --git a/gki/device_snapshot b/gki/device_snapshot
new file mode 100755
index 00000000..089e5d9d
--- /dev/null
+++ b/gki/device_snapshot
@@ -0,0 +1,675 @@
+#! /bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# (c) 2019, Google
+
+progname=${0##*/}
+NUM=XX
+USAGE="USAGE: ${progname} [-s <serialno>] [-D] [-f [<input>]] [-F [-o <output> [-d <input>]]]
+
+Collect filtered /dev and /sys details, along with dmesg and probe list.
+
+-o <output> will drop the collection into a set of files, but will not
+overwrite existing content. -F will overwrite.
+
+-D will wait for the display.
+
+if <output> is empty ('' or last option), will not collect dmesg or probe
+list. If no -o option is specified, then <output> will be default of -
+(stdout) and all pieces will go to the standard output separated by a cut
+and snip header. If specified, <output> will contain the filtered /dev/
+and /sys/ dumps, <output>.probed the subset filter of just the probed drivers,
+<output>.dmesg the kernel logs and <output>.config the uncompressed
+/proc/config.gz.
+
+-d <input> will take the dropped collection specified to -o <output> and
+produce a diff -U1 output compared against the <input>.
+
+-f <input> allows one to utilize the filter to an existing find /dev /sys
+output from a device. No dmesg will be collected.
+
+-s <serialno> will allow one to specify a device to connect to when multiples
+are available, otherwise will default to one available or ANDROID_SERIAL
+environment variable.
+
+NB: The /dev/ and /sys/ dumps can be compared with something like a diff -U1
+ and report a generally noiseless result so it is easy to spot the side
+ effects from one build to the next. Basically nothing else should be
+ added or removed from the differences other than the expectations, save
+ for normal noise from the dynamic nature of the kernel, thus making it
+ beneficial to run this script collection at the same point in the boot
+ process to keep noise down.
+
+NB: for default standard output, the probed list will be post-filter so
+ some details may be altered to make it easier to discover differences.
+ So if bus enumerations change, some of the enumerators will be replaced
+ with an '${NUM}' so that they continue to match when moved. For a
+ specified output, the <output>.probed file will retain the details."
+
+EMPTY=""
+SPACE=" "
+# A _real_ embedded tab character
+TAB="`echo | tr '\n' '\t'`"
+# A _real_ embedded carriage return character
+CR="`echo | tr '\n' '\r'`"
+# A _real_ embedded escape character
+ESCAPE="`echo | tr '\n' '\033'`"
+# Colours
+RED="${ESCAPE}[38;5;196m"
+ORANGE="${ESCAPE}[38;5;255:165:0m"
+BLUE="${ESCAPE}[35m"
+NORMAL="${ESCAPE}[0m"
+
+##
+## Helper Functions
+##
+
+[ "USAGE: inFastboot
+
+Returns: true if device is in fastboot mode" ]
+inFastboot() {
+ fastboot devices |
+ if [ -n "${ANDROID_SERIAL}" ]; then
+ grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
+ else
+ wc -l | grep '^1$' >/dev/null
+ fi
+}
+
+[ "USAGE: inAdb
+
+Returns: true if device is in adb mode" ]
+inAdb() {
+ adb devices </dev/null |
+ grep -v -e 'List of devices attached' -e '^$' -e "[${SPACE}${TAB}]recovery\$" |
+ if [ -n "${ANDROID_SERIAL}" ]; then
+ grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
+ else
+ wc -l | grep '^1$' >/dev/null
+ fi
+}
+
+[ "USAGE: inRecovery
+
+Returns: true if device is in recovery mode" ]
+inRecovery() {
+ local list="`adb devices |
+ grep -v -e 'List of devices attached' -e '^$'`"
+ if [ -n "${ANDROID_SERIAL}" ]; then
+ echo "${list}" |
+ grep "^${ANDROID_SERIAL}[${SPACE}${TAB}][${SPACE}${TAB}]*recovery\$" >/dev/null
+ return ${?}
+ fi
+ if echo "${list}" | wc -l | grep '^1$' >/dev/null; then
+ echo "${list}" |
+ grep "[${SPACE}${TAB}]recovery\$" >/dev/null
+ return ${?}
+ fi
+ false
+}
+
+[ "USAGE: USB_DEVICE=\`usb_devnum [--next]\`
+
+USB_DEVICE contains cache. Update if system changes.
+
+Returns: the devnum for the USB_SERIAL device" ]
+usb_devnum() {
+ if [ -n "${USB_SERIAL}" ]; then
+ local usb_device=`cat ${USB_SERIAL%/serial}/devnum 2>/dev/null | tr -d ' \t\r\n'`
+ if [ -n "${usb_device}" ]; then
+ USB_DEVICE=dev${usb_device}
+ elif [ -n "${USB_DEVICE}" -a "${1}" ]; then
+ USB_DEVICE=dev`expr ${USB_DEVICE#dev} + 1`
+ fi
+ echo "${USB_DEVICE}"
+ fi
+}
+
+[ "USAGE: adb_sh <commands> </dev/stdin >/dev/stdout 2>/dev/stderr
+
+Returns: true if the command succeeded" ]
+adb_sh() {
+ local args=
+ for i in "${@}"; do
+ [ -z "${args}" ] || args="${args} "
+ if [ X"${i}" != X"${i#\'}" ]; then
+ args="${args}${i}"
+ elif [ X"${i}" != X"${i#*\\}" ]; then
+ args="${args}`echo ${i} | sed 's/\\\\/\\\\\\\\/g'`"
+ elif [ X"${i}" != X"${i#* }" ]; then
+ args="${args}'${i}'"
+ elif [ X"${i}" != X"${i#*${TAB}}" ]; then
+ args="${args}'${i}'"
+ else
+ args="${args}${i}"
+ fi
+ done
+ adb shell "${args}"
+}
+
+[ "USAGE: adb_su <commands> </dev/stdin >/dev/stdout 2>/dev/stderr
+
+Returns: true if the command running as root succeeded" ]
+adb_su() {
+ adb_sh su root "${@}"
+}
+
+[ "USAGE: get_property <prop>
+
+Returns the property value" ]
+get_property() {
+ adb_sh getprop ${1} 2>/dev/null </dev/null
+}
+
+[ "USAGE: format_duration [<seconds>|<seconds>s|<minutes>m|<hours>h|<days>d]
+
+human readable output whole seconds, whole minutes or mm:ss" ]
+format_duration() {
+ if [ -z "${1}" ]; then
+ echo unknown
+ return
+ fi
+ local duration="${1}"
+ if [ X"${duration}" != X"${duration%s}" ]; then
+ duration=${duration%s}
+ elif [ X"${duration}" != X"${duration%m}" ]; then
+ duration=`expr ${duration%m} \* 60`
+ elif [ X"${duration}" != X"${duration%h}" ]; then
+ duration=`expr ${duration%h} \* 3600`
+ elif [ X"${duration}" != X"${duration%d}" ]; then
+ duration=`expr ${duration%d} \* 86400`
+ fi
+ local seconds=`expr ${duration} % 60`
+ local minutes=`expr \( ${duration} / 60 \) % 60`
+ local hours=`expr ${duration} / 3600`
+ if [ 0 -eq ${minutes} -a 0 -eq ${hours} ]; then
+ if [ 1 -eq ${duration} ]; then
+ echo 1 second
+ return
+ fi
+ echo ${duration} seconds
+ return
+ elif [ 60 -eq ${duration} ]; then
+ echo 1 minute
+ return
+ elif [ 0 -eq ${seconds} -a 0 -eq ${hours} ]; then
+ echo ${minutes} minutes
+ return
+ fi
+ if [ 0 -eq ${hours} ]; then
+ echo ${minutes}:`expr ${seconds} / 10``expr ${seconds} % 10`
+ return
+ fi
+ echo ${hours}:`expr ${minutes} / 10``expr ${minutes} % 10`:`expr ${seconds} / 10``expr ${seconds} % 10`
+}
+
+[ "USAGE: adb_wait [timeout]
+
+Returns: waits until the device has returned for adb or optional timeout" ]
+adb_wait() {
+ local start=`date +%s`
+ local duration=
+ local ret
+ if [ -n "${1}" ]; then
+ USB_DEVICE=`usb_devnum --next`
+ duration=`format_duration ${1}`
+ echo -n ". . . waiting ${duration}" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
+ timeout --preserve-status --signal=KILL ${1} adb wait-for-device 2>/dev/null
+ ret=${?}
+ echo -n " ${CR}"
+ else
+ adb wait-for-device
+ ret=${?}
+ fi
+ USB_DEVICE=`usb_devnum`
+ if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
+ local active_slot=`get_active_slot`
+ if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
+ fi
+ fi
+ local end=`date +%s`
+ local diff_time=`expr ${end} - ${start}`
+ local _print_time=${print_time}
+ if [ ${diff_time} -lt 15 ]; then
+ _print_time=false
+ fi
+ diff_time=`format_duration ${diff_time}`
+ if [ "${diff_time}" = "${duration}" ]; then
+ _print_time=false
+ fi
+
+ local reason=
+ if inAdb; then
+ reason=`get_property ro.boot.bootreason`
+ fi
+ case ${reason} in
+ reboot*)
+ reason=
+ ;;
+ ${EMPTY})
+ ;;
+ *)
+ reason=" for boot reason ${reason}"
+ ;;
+ esac
+ if ${_print_time} || [ -n "${reason}" ]; then
+ echo "${BLUE}[ INFO ]${NORMAL} adb wait duration ${diff_time}${reason}"
+ fi >&2
+
+ return ${ret}
+}
+
+[ "USAGE: fastboot_wait [timeout]
+
+Returns: waits until the device has returned for fastboot or optional timeout" ]
+fastboot_wait() {
+ local ret
+ # fastboot has no wait-for-device, but it does an automatic
+ # wait and requires (even a nonsensical) command to do so.
+ if [ -n "${1}" ]; then
+ USB_DEVICE=`usb_devnum --next`
+ echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
+ timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null
+ ret=${?}
+ echo -n " ${CR}"
+ ( exit ${ret} )
+ else
+ fastboot wait-for-device >/dev/null 2>/dev/null
+ fi ||
+ inFastboot
+ ret=${?}
+ USB_DEVICE=`usb_devnum`
+ if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
+ local active_slot=`get_active_slot`
+ if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
+ fi >&2
+ fi
+ return ${ret}
+}
+
+[ "USAGE: recovery_wait [timeout]
+
+Returns: waits until the device has returned for recovery or optional timeout" ]
+recovery_wait() {
+ local ret
+ if [ -n "${1}" ]; then
+ USB_DEVICE=`usb_devnum --next`
+ echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
+ timeout --preserve-status --signal=KILL ${1} adb wait-for-recovery 2>/dev/null
+ ret=${?}
+ echo -n " ${CR}"
+ else
+ adb wait-for-recovery
+ ret=${?}
+ fi
+ USB_DEVICE=`usb_devnum`
+ if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
+ local active_slot=`get_active_slot`
+ if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
+ fi >&2
+ fi
+ return ${ret}
+}
+
+[ "any_wait [timeout]
+
+Returns: waits until a device has returned or optional timeout" ]
+any_wait() {
+ (
+ adb_wait ${1} &
+ adb_pid=${!}
+ fastboot_wait ${1} &
+ fastboot_pid=${!}
+ recovery_wait ${1} &
+ recovery_pid=${!}
+ wait -n
+ kill "${adb_pid}" "${fastboot_pid}" "${recovery_pid}"
+ ) >/dev/null 2>/dev/null
+ inFastboot || inAdb || inRecovery
+}
+
+##
+## RUNTIME
+##
+
+filter=
+output=-
+input=
+display=false
+force=false
+while [ ${#} -gt 0 ]; do
+ case ${1} in
+ -f=* | --filter=*)
+ filter="${1#-f=}"
+ filter="${filter#--filter=}"
+ ;;
+ -f | --filter)
+ if [ ${#} = 1 -o -z "${2}" ]; then
+ filter=-
+ else
+ shift
+ filter="${1}"
+ fi
+ ;;
+ -F | --force)
+ force=true
+ ;;
+ -h | -\? | --help)
+ echo "${USAGE}"
+ exit 0
+ ;;
+ -o=* | --output=*)
+ output="${1#-o=}"
+ output="${output#--output=}"
+ ;;
+ -o | --output)
+ if [ ${#} = 1 -o -z "${2}" ]; then
+ # empty output results in no dmesg or probed collection
+ output=
+ else
+ shift
+ output="${1}"
+ fi
+ ;;
+ -d=* | --diff=*)
+ input="${1#-d=}"
+ input="${input#--diff=}"
+ ;;
+ -d | --diff)
+ shift
+ input="${1}"
+ ;;
+ -D | --wait-for-display)
+ display=true
+ ;;
+ -s=* | --serial=*)
+ ANDROID_SERIAL="${1#-s=}"
+ export ANDROID_SERIAL="${ANDROID_SERIAL#--serial=}"
+ ;;
+ -s | --serial)
+ shift
+ export ANDROID_SERIAL="${1}"
+ ;;
+ *)
+ echo "${RED}[ ERROR ]${NORMAL} unknown parm ${1}" >&2
+ echo "${USAGE}" >&2
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+if [ -n "${input}" -a -z "${output#-}" ]; then
+ echo "${RED}[ ERROR ]${NORMAL} must specify an -o <output> along with the -d ${input}" >&2
+ echo "${USAGE}" >&2
+ exit 1
+fi
+
+USB_SERIAL=
+[ -z "${ANDROID_SERIAL}" ] || USB_SERIAL=`find /sys/devices -name serial |
+ grep usb |
+ xargs grep -l ${ANDROID_SERIAL}`
+USB_ADDRESS=
+if [ -n "${USB_SERIAL}" ]; then
+ USB_ADDRESS=${USB_SERIAL%/serial}
+ USB_ADDRESS=usb${USB_ADDRESS##*/}
+fi
+
+[ "USAGE: input= BLUE= output= NORMAL= perform_diff < ${output}
+
+Reports the differences between stdin and \${input}" ]
+perform_diff() {
+ diff -U1 "${input}" - |
+ grep '[-+ ]' ||
+ echo "${BLUE}[ INFO ]${NORMAL} no differences in /dev/ and /sys/ since last device snapshot" >&2
+ if [ -s "${output}.probed" -a -s "${input}.probed" ]; then
+ diff -U1 "${input}.probed" "${output}.probed" |
+ grep '[-+ ]' ||
+ echo "${BLUE}[ INFO ]${NORMAL} no differences in probed devices and drivers" >&2
+ fi
+ if [ -s "${output}.dmesg" -a -s "${input}.dmesg" ]; then
+ TMP=`mktemp -d`
+ mknod ${TMP}/input p
+ sed -n 's@^.*init: Loaded kernel module /lib/modules/@@p' ${input}.dmesg > ${TMP}/input &
+ sed -n 's@^.*init: Loaded kernel module /lib/modules/@@p' ${output}.dmesg |
+ diff -U1 ${TMP}/input - |
+ grep '[-+ ]' ||
+ echo "${BLUE}[ INFO ]${NORMAL} no differences in module load order" >&2
+ wait
+ rm -rf ${TMP}
+ fi
+ if [ -s "${output}.config" -a -s "${input}.config" ]; then
+ diff -U1 "${input}.config" "${output}.config" |
+ grep '[-+ ]' ||
+ echo "${BLUE}[ INFO ]${NORMAL} no differences in config" >&2
+ fi
+ if [ -s "${output}.getprop" -a -s "${input}.getprop" ]; then
+ TMP=`mktemp -d`
+ sed -n 's/[[]ro[.]boottime[.]\([^]]*\)[]]: [[]\([0-9]*\)[]]$/\1 \2/p' "${input}.getprop" >${TMP}/old.getprop
+ sed -n 's/[[]ro[.]boottime[.]\([^]]*\)[]]: [[]\([0-9]*\)[]]$/\2 \1/p' "${output}.getprop" |
+ sort -un |
+ while read monotonic action; do
+ [ -n "${action}" ] || continue
+ [ -n "${monotonic}" ] || continue
+ old=`sed -n "s/^${action} //p" ${TMP}/old.getprop`
+ [ -n "${old}" ] || continue
+ old="$((${monotonic} - ${old}))"
+ [ -n "${old}" -a 0 != "${old}" ] || continue
+ sign=+
+ if [ -z "${old##-*}" ]; then
+ sign=-
+ old=${old#-}
+ fi
+ printf "${action}\t${sign}%u.%09us\n" $((${old} / 1000000000)) $((${old} % 1000000000))
+ done |
+ grep '[0-9][.][0-9]' ||
+ echo "${BLUE}[ INFO ]${NORMAL} no differences in boottime" >&2
+ rm -rf ${TMP}
+ fi
+}
+
+if [ -n "${output#-}" -a -s "${output}" ]; then
+ if ! ${force}; then
+ if [ -n "${input}" ]; then
+ perform_diff <${output}
+ exit 0
+ fi
+ echo "${RED}[ ERROR ]${NORMAL} will not overwrite existing content" >&2
+ exit 1
+ fi
+fi
+
+if [ -z "${filter}" ]; then
+ if inFastboot; then
+ echo "${RED}[ ERROR ]${NORMAL} in fastboot mode" >&2
+ exit 1
+ fi
+ if inRecovery; then
+ echo "${RED}[ ERROR ]${NORMAL} in recovery mode" >&2
+ exit 1
+ fi
+ if ! inAdb; then
+ any_wait 2m
+ if ! inAdb; then
+ if [ -n "${ANDROID_SERIAL}" ]; then
+ echo "${RED}[ ERROR ]${NORMAL} not in adb mode" >&2
+ exit 1
+ fi
+ COUNT=`adb devices </dev/null |
+ grep -v -e 'List of devices attached' -e '^$' |
+ wc -l`
+ echo "${RED}[ ERROR ]${NORMAL} ${COUNT} devices attached" >&2
+ exit 1
+ fi
+ fi
+ counter=0
+ while ${display}; do
+ if inFastboot; then
+ fastboot reboot
+ elif inAdb; then
+ if [ "1" = "`get_property sys.boot_completed`" ]; then
+ break
+ fi
+ fi
+ counter=$((${counter} + 1))
+ if [ ${counter} -gt 120 ]; then
+ break
+ fi
+ sleep 1
+ done
+fi
+
+if [ -n "${filter}" ]; then
+ cat ${filter}
+else
+ adb_su find /dev /sys </dev/null 2>/dev/null |
+ if [ -n "${output}" -a X"${output}" != X"-" ]; then
+ # Generate ${output}.probed:
+ #
+ # Report all the instantiated devices and which driver is responsible.
+ # If drivers do not have any instantiated devices, report them at end.
+ # Drivers are of a form driver:<subsystem>:<name>, if <subsystem> is
+ # empty, it is short hand for platform.
+ #
+ DRIVERS=
+ FOUND=
+ (
+ tee /proc/self/fd/99 |
+ sed -n \
+ -e 's@/sys/devices/platform/.*/driver$@&@p' \
+ -e 's@/sys/bus/\([^/]*\)/drivers/\([^/]*\)$@driver:\1:\2@p' |
+ sort -u
+ echo DONE
+ ) |
+ while read driver; do
+ [ -n "${driver}" ] || continue
+ case ${driver} in
+ DONE)
+ [ -n "${DRIVERS}" ] || break
+ if [ -z "${FOUND}" ]; then
+ echo "${DRIVERS}"
+ else
+ echo "${DRIVERS}" |
+ grep -ve "${FOUND}\)\$" ||
+ true
+ fi |
+ sed 's/driver:platform:/driver::/'
+ break
+ ;;
+ driver:*)
+ [ -z "${DRIVERS}" ] || DRIVERS="${DRIVERS}
+"
+ DRIVERS="${DRIVERS}${driver}"
+ ;;
+ *)
+ INSTANCE="${driver#/sys/devices/platform/}"
+ INSTANCE="${INSTANCE%/driver}"
+ DRIVER="`adb_su ls -l ${driver} </dev/null 2>/dev/null |
+ sed -n 's@.* -> .*/bus/\([^/]*\)/drivers/\(.*\)@driver:\1:\2@p'`"
+ if [ -z "${DRIVER}" ]; then
+ echo "${INSTANCE}"
+ else
+ if [ -z "${FOUND}" ]; then
+ FOUND="^\(${DRIVER}"
+ else
+ FOUND="${FOUND}\|${DRIVER}"
+ fi
+ DRIVER="${DRIVER#driver:}"
+ echo "${INSTANCE} -> driver:${DRIVER#platform}"
+ fi
+ ;;
+ esac
+ done >"${output}.probed"
+ [ -s "${output}.probed" ] || rm -f "${output}.probed"
+ # Generate ${output}.dmesg
+ adb_su dmesg </dev/null 2>/dev/null >"${output}.dmesg"
+ [ -s "${output}.dmesg" ] || rm -f "${output}.dmesg"
+ # Generate ${output}.config if kernel provides it.
+ adb_su cat /proc/config.gz </dev/null 2>/dev/null |
+ gunzip >"${output}.config"
+ [ -s "${output}.config" ] || rm -f "${output}.config"
+ # Generate ${output}.getprop
+ adb $QD shell su root getprop </dev/null 2>/dev/null |
+ sort -u >"${output}.getprop"
+ [ -s "${output}.getprop" ] || rm -f "${output}.getprop"
+ else
+ cat - >&99
+ fi 99>&1
+fi |
+ grep -v '^\(/dev/ashmem\|/dev/block/mapper/by-uuid/\|/dev/fscklogs/log\)' |
+ grep -v '^\(/dev/socket/location/\(socket_hal\|cld80211\)\|/sys/class/hwmon/\)' |
+ grep -v '^/dev/socket/netmgr/netmgr_connect_socket$' |
+ grep -v '^/dev/socket/qdma/qdma-\(file\|campmgr\)-s$' |
+ grep -v '^/dev/socket/qmux_radio/' |
+ grep -v '^/dev/socket/vendor_wpa_wlan' |
+ grep -v '^/dev/socket/wifihal/wifihal_ctrlsock' |
+ grep -v '^/sys/dev/char/[0-9]*:[0-9]*$' |
+ grep -v '^/sys/devices/virtual/thermal/tz-by-name/wsatz[.][0-9]*$' |
+ grep -v '^/sys/kernel/debug/tracing/instances/wifi' |
+ grep -v '^/sys/kernel/debug/\(wlan\|WMI\|p2p\|msm-bus-dbg/client-data/npu_bwmon_cdsp\)' |
+ grep -v '^/sys/class/net/\(wlan\|p2p\)' |
+ grep -v '^/sys/class/ieee80211/phy' |
+ grep -v '^/sys/devices/platform/soc/[0-9a-f]*.qcom,icnss/\(net\|firmware\|ieee80211\)' |
+ grep -v '^/sys/devices/platform/soc/[0-9a-f]*.*@[0-9][0-9]*-cam_\(vana\|vdig\|vio\|clk\)$' |
+ grep -v '^/sys/kernel/wlan/' |
+ grep -v '^/sys/kernel/slab/\(f2fs_fsync_inode_entry\|zs\|:[0-9a-f]\{,7\}\)' |
+ grep -v '^/sys/devices/system/cpu/cpufreq/policy[0-9]*/schedutil' |
+ grep -v '/__trace_printk_fmt$' |
+ sed "s@\(/regulator[.]\)[0-9][0-9]*\$@\1${NUM}@
+ s@\(/regulator[.]\)[0-9][0-9]*/@\1${NUM}/@g
+ s@\(/vppservice_\)[0-9][0-9]*\$@\1${NUM}@
+ s@\(/msi_irqs/\)[0-9][0-9]*\$@\1${NUM}@
+ s@\(/sys/class/rfkill/rfkill\)[0-9][0-9]*@\1${NUM}@
+ s@\(/sys/class\|/sys/devices/platform/soc/[0-9a-f]*[.]qcom,gpi-dma\)\(/dma/dma\)[0-9]*\(chan[0-9]*\(\|/.*\)\)\$@\1\2${NUM}\3@
+ s@\(/i2c-\)\([0-9]\)\(/[^/]*/i2c-\)\2\(\|/.*\)\$@\1${NUM}\3${NUM}\4@
+ s@\(/i2c-\)[0-9]\(\|/[^/]*\)\$@\1${NUM}\2@
+ s@-\([0-9]\)/\1\(-[0-9][0-9][0-9][0-9]/\)@-${NUM}/${NUM}\2@g
+ s@/[0-9]\(-[0-9][0-9][0-9][0-9]\(\|-vdd\|-vdd/.*\|-avdd\|-avdd/.*\|-vio\|-vio/.*\|/.*\)\)\$@${NUM}\1@
+ s@\(/sys/devices/platform/soc/[0-9a-z]*[.]qcom,[^/]*/subsys\)[0-9][0-9]*@\1${NUM}@
+ s@\(rpmsg_chrdev[.]0[.]0/rpmsg/rpmsg_ctrl\)[0-9][0-9]*@\1${NUM}@
+ s@\(/sys/devices/virtual/kgsl/kgsl/pagetables/\)[0-9][0-9]*@\1${NUM}@
+ s@\(/sys/devices/virtual/kgsl/kgsl/proc/\)[0-9][0-9]*@\1${NUM}@
+ s@\(/sys/devices/virtual/thermal/thermal_zone\)[0-9][0-9]*@\1${NUM}@
+ s@\(/sys/devices/virtual/net/\)\(r_\|\)\(rmnet_data\)[0-9][0-9]*\(/queues/tx-\)[0-9][0-9]*@\1\3${NUM}\4${NUM}@
+ s@\(/sys/devices/platform/soc/soc:qcom,msm-audio-apr/soc:qcom,msm-audio-apr:qcom,q6core-audio/soc:qcom,msm-audio-apr:qcom,q6core-audio:lpi_pinctrl[@][0-9a-f]*/gpiochip\)[0-9][0-9]*@\1${NUM}@
+ s@\(/sys/kernel/debug/adsprpc/\(adsp\|cdsp\|ssc\)rpcd_\)[0-9][0-9]*\$@\1${NUM}@
+ s@\(/sys/kernel/debug/binder/proc/\)[0-9][0-9]*\$@\1${NUM}@
+ s@\(/sys/kernel/debug/kgsl/proc/\)[0-9][0-9]*@\1${NUM}@
+ s@\(/sys/kernel/debug/kgsl/kgsl-[0-9a-f][0-9a-f]*/ctx/\)[0-9][0-9]*@\1${NUM}@
+ s@\(/sys/kernel/debug/msm_cvp/core0/inst_\)[0-9a-f][0-9a-f]*@\1${NUM}@
+ s@\(/sys/kernel/iommu_groups/\)[0-9][0-9]*@\1${NUM}@
+ s@\(/devices/soc:qcom,msm_fastrpc:qcom,msm_fastrpc_compute_cb\)[0-9][0-9]*@\1${NUM}@
+ s@/mmc[0-9][0-9]*\($\|/\|:\)@/mmc${NUM}\1@
+ s@\(/sys/kernel/irq/\)[0-9][0-9]*@\1${NUM}@" |
+ if [ -n "${output}" -a X"${output}" != X"-" ]; then
+ sort -u |
+ if [ -n "${input}" ]; then
+ tee "${output}" | perform_diff
+ else
+ cat - >"${output}"
+ fi
+ else
+ TMP=`mktemp -d`
+ if [ X"${output}" = X"-" ]; then
+ echo "------------------------> cut dump < ------------------------"
+ sort -u |
+ tee /proc/self/fd/99 |
+ sed -n 's@/sys/devices/platform/\(.*\)/driver$@\1@p' >${TMP}/probed
+ else
+ sort -u >&99
+ fi 99>&1
+ if [ -s "${TMP}/probed" ]; then
+ echo "-----------------------> cut probed <------------------------"
+ cat ${TMP}/probed
+ fi
+ rm -rf ${TMP}
+ fi
+if [ -z "${filter}" -a X"${output}" = X"-" ]; then
+ echo "------------------------> cut dmesg <------------------------"
+ adb_su dmesg </dev/null 2>/dev/null
+ echo "-----------------------> cut .config <-----------------------"
+ adb_su cat /proc/config.gz </dev/null 2>/dev/null | gunzip
+fi
diff --git a/gki/find_circular b/gki/find_circular
new file mode 100755
index 00000000..e0b76bc2
--- /dev/null
+++ b/gki/find_circular
@@ -0,0 +1,170 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# (c) 2019, Google
+progname="${0##*/}"
+
+USAGE="USAGE: ${progname} [dir]
+
+Call this when depmod breaks down, or when one needs a list of the symbols
+implicated in the circular dependency.
+
+Search current or dir directory for all kernel modules. Itemize what they
+export, and what they import. Discover links and report who fulfills them.
+Report any first order circular relationships and the symbols that got us
+into the situation.
+
+Standard output is of the form:
+
+module1.ko(symbols) -> module2.ko(symbols) -> module1.ko
+
+Leaves an annotated modules.dep file in the specified directory.
+
+TBA: higher order circular dependencies"
+
+if [ X"--help" = X"${1}" -o X"{-h}" = X"${1}" ]; then
+ echo "${USAGE}" >&2
+ exit
+fi
+DIR=.
+if [ 1 = ${#} ]; then
+ DIR=${1}
+ shift
+fi
+if [ 0 != ${#} ]; then
+ echo "Unexpected Argument: ${*}" >&2
+ echo >&2
+ echo "${USAGE}" >&2
+ exit 1
+fi
+
+# A _real_ embedded tab character
+TAB="`echo | tr '\n' '\t'`"
+
+#
+# Start Work
+#
+
+# Construct our version (symbols annoted as comments) of the modules.dep file.
+
+TMP=`mktemp -d`
+
+# Acquire a list of files that are modules
+find ${DIR%/} -name '*.ko' >${TMP}/modules
+
+# Fill symbols with file type symbol
+# type is > for requires symbol
+# type is < for supplies symbol
+# type is pre for requires module (in symbol field)
+# type is post for supplies module (in file field)
+
+# Mine for symbols
+xargs nm -o <${TMP}/modules |
+ sed "s@^${DIR%/}/@@" |
+ sed -n \
+ -e 's/^\([^:]*\):.* U \(.*\)/\1 > \2/p' \
+ -e 's/^\([^:]*\):.* [TD] \(.*\)/\1 < \2/p' >${TMP}/symbols
+if [ ! -s ${TMP}/symbols ]; then
+ rm -rf ${TMP}
+ echo ERROR: failed to find any .ko module files in the specified directory ${DIR%/}
+ exit 1
+fi
+
+# Mine for softdep pre
+ while read file; do
+ strings ${file} |
+ sed -n 's/^softdep=pre: \(.*\)/\1/p' |
+ tr ' ' '\n' |
+ sed "s@.*@${file#${DIR%/}/} pre &@"
+ done < ${TMP}/modules |
+ sort -u >>${TMP}/symbols
+
+# Mine for softdep post
+ while read file; do
+ strings ${file} |
+ sed -n 's/^softdep=post: \(.*\)/\1/p' |
+ tr ' ' '\n' |
+ sed "s@.*@$& post {file#${DIR%/}/}@"
+ done < ${TMP}/modules |
+ sort -u >>${TMP}/symbols
+
+# Translate symbols to annotated modules.dep
+(
+ sed -n 's/ > / /p' ${TMP}/symbols |
+ while read file symbol ; do
+ sed -n "s@^\(.*\) < ${symbol}\$@${file}: \1 # ${symbol}@p" ${TMP}/symbols
+ done
+ sed -n 's/ pre / /p' ${TMP}/symbols |
+ while read file softdep ; do
+ grep "/${softdep}[.]ko\$" ${TMP}/modules |
+ sed "s@^${DIR%/}/@@" |
+ while read source; do
+ echo "${file}: ${source} # pre:${softdep}"
+ done
+ done
+ sed -n 's/ post / /p' ${TMP}/symbols |
+ while read softdep source ; do
+ grep "/${softdep}[.]ko\$" ${TMP}/modules |
+ sed "s@^${DIR%/}/@@" |
+ while read file; do
+ echo "${file}: ${source} # post:${softdep}"
+ done
+ done
+) |
+ sort -u >${DIR%/}/modules.dep
+
+# Cleanup (already!)
+rm -rf ${TMP}
+
+# Evaluate first order dependencies from our annotated ${DIR}/modules.dep file.
+
+# squash adjacent lines with match for first symbols, merge second
+merge_second_symbols() {
+ sed ': loop
+ N
+ s/^\(.*(.*) -> .*(\)\(.*\)\().*\)\n\1\(.*\)\3/\1\2,\4\3/
+ t loop
+ h
+ s/\n.*//p
+ g
+ s/^[^\n]*\n//
+ t loop'
+}
+
+# squash adjacent lines with match for second symbols, merge first
+merge_first_symbols() {
+ sed ': loop
+ N
+ s/^\(.*(\)\(.*\)\() -> .*(.*).*\)\n\1\(.*\)\3/\1\2,\4\3/
+ t loop
+ h
+ s/\n.*//p
+ g
+ s/^[^\n]*\n//
+ t loop'
+}
+
+# squash adjacent lines with identical, but shifted one, circular dependencies
+merge_duplicates() {
+ sed ': loop
+ N
+ s/^\(.*\)\((.*)\) -> \(.*\)\((.*)\) -> \1\n\3\4 -> \1\2 -> \3$/\1\2 -> \3\4 -> \1/
+ t end
+ s/\n.*//p
+ g
+ s/^[^\n]*\n//
+ t loop
+ : end'
+}
+
+# Report the first order circular dependencies
+sed 's/://' ${DIR%/}/modules.dep |
+ while read file source comment symbol; do
+ sed -n "s@^${source}: ${file} # \(.*\)@${file}(${symbol}) -> ${source}(\1) -> ${file}@p" ${DIR%/}/modules.dep
+ done |
+ merge_second_symbols |
+ merge_first_symbols |
+ merge_duplicates |
+ sort -u
+
+# TBA: second order dependencies
diff --git a/gki/instrument_module_init b/gki/instrument_module_init
new file mode 100755
index 00000000..4f3c886d
--- /dev/null
+++ b/gki/instrument_module_init
@@ -0,0 +1,307 @@
+#! /bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# (c) 2019, Google
+progname="${0##*/}"
+
+# Add instrumentation to module_init and probe functions.
+
+USAGE="USAGE: ${progname} [dir|file]
+
+Add debug instrumentation to module_init and probe functions."
+
+if [ X"--help" = X"${1}" -o X"{-h}" = X"${1}" ]; then
+ echo "${USAGE}" >&2
+ exit
+fi
+DIR=.
+if [ 1 = ${#} ]; then
+ DIR=${1}
+ shift
+fi
+if [ 0 != ${#} ]; then
+ echo "Unexpected Argument: ${*}" >&2
+ echo >&2
+ echo "${USAGE}" >&2
+ exit 1
+fi
+
+# A _real_ embedded tab character
+TAB="`echo | tr '\n' '\t'`"
+# A _real_ embedded escape character
+ESCAPE="`echo | tr '\n' '\033'`"
+# Colours
+RED="${ESCAPE}[38;5;196m"
+ORANGE="${ESCAPE}[38;5;255:165:0m"
+BLUE="${ESCAPE}[35m"
+NORMAL="${ESCAPE}[0m"
+
+TMP=`mktemp -d`
+
+# ${file} ${call} and ${symbol} input
+SYMBOLS=" "
+add_debug_printk()
+{
+ message="printk(KERN_WARNING \"${file##*/}:"
+ if [ -z "${call#select}" ]; then
+ # We need uniqueness for discovery, so instead of truth of __func__ to
+ # cover any of our mistakes(!), we select the expectation.
+ message+="${symbol}: ENTER\\\\n\");"
+ else
+ message+="%s:${call}: ENTER\\\\n\", __func__);"
+ fi
+ if grep "${TAB}${message%%\\*}" ${file} >/dev/null; then
+ if [ "${SYMBOLS}" == "${SYMBOLS#* ${symbol}:${call#select}}" ]; then
+ echo INFO: already ${file} instrumented ${call#select} ${symbol} >&2
+ SYMBOLS="${SYMBOLS}${symbol}:${call} "
+ fi
+ return
+ fi
+ if [ "device_initcall" = "${call}" -o "module_init" = "${call}" -o "module_exit" = "${call}" ] &&
+ grep "${TAB}printk(KERN_WARNING \"${file##*/}:%s:\(builtin\|module\)_[a-z]*_driver: ENTER" ${file} >/dev/null; then
+ if [ "${SYMBOLS}" == "${SYMBOLS#* ${symbol}:${call#select}}" ]; then
+ echo INFO: maybe already ${file} instrumented ${call#select} ${symbol} >&2
+ fi
+ return
+ fi
+ sed "/^\(static \)\{0,1\}.* ${symbol}(/ {
+ N
+ s/^\(static \)\{0,1\}\(.* ${symbol}(\)\(void\)\{0,1\}) {[ ${TAB}]*}\(\n\)/\1\2\3)\4{\4${TAB}${message}\4}\4/
+ t exit
+ N
+ /\/[*][^*]*\$/ {
+ : comment_loop
+ N
+ /\/[*].*[*]\// b comment_done
+ b comment_loop
+ : comment_done
+ /\/[*].*[*]\/\$/ N
+ }
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ 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}&/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ 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}&/
+ t exit
+ s/\(static void .*\)\(\n${TAB}\)\([a-z].*\)\2}\$/\1\2${message}\2\3\2}/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ t exit
+ N
+ /printk(KERN_WARNING \"${file##*/}:/ b exit
+ s/\(.*\)\(\n${TAB}\)\(.*\n\)\2/&${message}\2/
+ : exit
+ }
+ 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);/
+ 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);/
+ " ${file} > ${TMP}/${file##*/} &&
+ ! cmp -s ${file} ${TMP}/${file##*/} &&
+ cp ${TMP}/${file##*/} ${file} &&
+ (
+ echo INFO: modified ${file} to instrument ${call#select} ${symbol} >&2
+ echo ${symbol}
+ ) ||
+ (
+ files=`grep -lr "^\(static \)\{0,1\}[^ ${TAB}][ %{TAB}_a-zA-Z0-9]* ${symbol}(" ${DIR} |
+ sed -e '/[.]h$/d' -e 's@^[.]/@@'`
+ if [ X"${file}" != X"${files}" ]; then
+ echo "${ORANGE}WARNING${NORMAL}: ${symbol} is in ${files}" >&2
+ if [ 1 -eq `echo ${files} | wc -w` ]; then
+ file=${files}
+ add_debug_printk
+ exit
+ fi
+ fi
+ if [ "${SYMBOLS}" == "${SYMBOLS#* ${symbol}:${call#select}}" ]; then
+ echo "${RED}ERROR${NORMAL}: failed to modify ${file} to instrument" ${call#select} ${symbol} >&2
+ fi
+ false
+ )
+ ret=${?}
+ rm -f ${TMP}/${file##*/}
+ if [ 0 -eq ${ret} ]; then
+ SYMBOLS="${SYMBOLS}${symbol}:${call} "
+ fi
+ return ${ret}
+}
+
+# module_init, module_exit, late_initcall ...
+(
+ grep -Hr '^\(builtin_[a-z]*_driver\|module_[a-z]*_driver\|module_\(init\|exit\)\|[a-z]*_initcall\)(' ${DIR} |
+ sed -n 's@^[.]/@@
+ s/^\([^:]*\):\(builtin_[a-z]*_driver\|module_[a-z]*_driver\|module_init\|module_exit\|[a-z]*_initcall\)(\([^)]*\));$/\1 \2 \3/p' |
+ sort -u
+ find ${DIR} -name '*.c' |
+ while read file; do
+ sed -n "/.* [a-z_0-9]*(void)\$/ {
+ : loop
+ N
+ /^[^\n]* [a-z_0-9]*(void)\n.*\n}\$/ {
+ /.*platform_\(driver\|device\)_\(un\)\{0,1\}register([&][^)]*).*/ {
+ s@^[^\n]* \([a-z_0-9]*\)(void)\n.*@${file} select \1@p
+ b exit
+ }
+ /.*[ ${TAB}]_[a-z]_\(un\)\{0,1\}register_driver([&][^, ${TAB})]*).*/ {
+ s@^[^\n]* \([a-z_0-9]*\)(void)\n.*@${file} select \1@p
+ b exit
+ }
+ /.*i2c_\(add\|del\)_driver([&][^)]*).*/ {
+ s@^[^\n]* \([a-z_0-9]*\)(void)\n.*@${file} select \1@p
+ }
+ b exit
+ }
+ b loop
+ }
+ : exit" ${file}
+ done |
+ sort -u
+) |
+ while read file call symbol; do
+ if ! add_debug_printk && [ "${SYMBOLS}" == "${SYMBOLS#* ${symbol}:${call#select}}" ]; then
+ echo FAILED
+ fi
+
+ if [ "${call}" != "${call#builtin_*_driver}" -o "${call}" != "${call#module_*_driver}" ]; then
+ symbol=${symbol}_init
+ fi
+ call=probe
+ sed -n "/\(static \)\{0,1\}.* ${symbol}(/,/^}/ {
+ s/.*platform_\(driver\|device\)_register([&]\([^)]*\)).*/struct platform_\1 \2/p
+ s/.*[ ${TAB}]\(_[a-z]\)_register_driver([&]\([^, ${TAB})]*\)).*/struct \1_driver \2/p
+ s/.*i2c_add_driver([&]\([^)]*\)).*/struct i2c_driver \1/p
+ }
+ s/\(builtin\|module\)_\([a-z]*_driver\)(\([^)]*\));/struct \2 \3/p" ${file} |
+ sort -u |
+ while read struct; do
+ sed -n "/\(static \)\{0,1\}${struct} = {/,/^};/ {
+ s/^[ ${TAB}]*[.]probe[ ${TAB}]*=[ ${TAB}]*\([^ ${TAB}]*\),\$/\1/p
+ }" ${file} |
+ sort -u |
+ while read symbol; do
+ if ! add_debug_printk && [ "${SYMBOLS}" == "${SYMBOLS#* ${symbol}:${call} }" ]; then
+ echo FAILED
+ fi
+ done
+ done
+ done |
+ sort -u |
+ tee ${TMP}/list |
+ grep '^FAILED' >/dev/null
+ret=${?}
+SYMBOLS=`grep -v '^FAILED$' ${TMP}/list`
+
+rm -rf ${TMP}
+
+if [ 0 -ne ${ret} ]; then
+ echo "DONE" >&2
+
+ AUTHOR_NAME="`git config user.name`"
+ AUTHOR_EMAIL="`git config user.email`"
+ if [ -z "${AUTHOR_EMAIL}" ]; then
+ AUTHOR_EMAIL="`${USER}@google.com`"
+ fi
+ if [ -z "${AUTHOR_NAME}" ]; then
+ convert_ldap_to_name() {
+ echo "${1##*/}" |
+ sed "s@[-_]@ @g
+ s@ *@ @g" |
+ sed 's@\(^\| \)a@\1A@g
+ s@\(^\| \)b@\1B@g
+ s@\(^\| \)c@\1C@g
+ s@\(^\| \)d@\1D@g
+ s@\(^\| \)e@\1E@g
+ s@\(^\| \)f@\1F@g
+ s@\(^\| \)g@\1G@g
+ s@\(^\| \)h@\1H@g
+ s@\(^\| \)i@\1I@g
+ s@\(^\| \)j@\1J@g
+ s@\(^\| \)k@\1K@g
+ s@\(^\| \)l@\1L@g
+ s@\(^\| \)m@\1M@g
+ s@\(^\| \)n@\1N@g
+ s@\(^\| \)o@\1O@g
+ s@\(^\| \)p@\1P@g
+ s@\(^\| \)q@\1Q@g
+ s@\(^\| \)r@\1R@g
+ s@\(^\| \)s@\1S@g
+ s@\(^\| \)t@\1T@g
+ s@\(^\| \)u@\1U@g
+ s@\(^\| \|Mc\)v@\1V@g
+ s@\(^\| \)w@\1W@g
+ s@\(^\| \)x@\1X@g
+ s@\(^\| \)y@\1Y@g
+ s@\(^\| \)z@\1Z@g'
+ }
+ AUTHOR_NAME="`convert_ldap_to_name ${USER}`"
+ fi
+
+ git commit -a -m "GKI: DEBUG: add instrumentation to init and probe functions
+
+Automatically generated by ${0}
+
+The following symbols are instrumented:
+`echo \"${SYMBOLS}\" |
+ sed 's/^/ - /'`
+
+Signed-off-by: ${AUTHOR_NAME} <${AUTHOR_EMAIL}>
+Test: compile" ||
+ echo "${RED}ERROR${NORMAL}: failed to commit changes to git" >&2
+ exit
+fi
+echo "${RED}FAILED${NORMAL}: could not complete task" >&2
+exit 1