1*288bf522SAndroid Build Coastguard Worker#! /bin/sh 2*288bf522SAndroid Build Coastguard Workerprogname="${0##*/}" 3*288bf522SAndroid Build Coastguard Workerprogname="${progname%.sh}" 4*288bf522SAndroid Build Coastguard Worker 5*288bf522SAndroid Build Coastguard Workerusage() { 6*288bf522SAndroid Build Coastguard Worker echo "Host side filter pipeline tool to convert kernel /proc/lockdep_chains via" 7*288bf522SAndroid Build Coastguard Worker echo "graphviz into dependency chart for visualization. Watch out for any up-arrows" 8*288bf522SAndroid Build Coastguard Worker echo "as they signify a circular dependency." 9*288bf522SAndroid Build Coastguard Worker echo 10*288bf522SAndroid Build Coastguard Worker echo "Usage: ${progname} [flags...] [regex...] < input-file > output-file" 11*288bf522SAndroid Build Coastguard Worker echo 12*288bf522SAndroid Build Coastguard Worker echo "flags:" 13*288bf522SAndroid Build Coastguard Worker echo " --format={png|ps|svg|fig|imap|cmapx} | -T<format>" 14*288bf522SAndroid Build Coastguard Worker echo " Output format, default png" 15*288bf522SAndroid Build Coastguard Worker echo " --debug | -d" 16*288bf522SAndroid Build Coastguard Worker echo " Leave intermediate files /tmp/${progname}.*" 17*288bf522SAndroid Build Coastguard Worker echo " --verbose | -v" 18*288bf522SAndroid Build Coastguard Worker echo " Do not strip address from lockname" 19*288bf522SAndroid Build Coastguard Worker echo " --focus | -f" 20*288bf522SAndroid Build Coastguard Worker echo " Show only primary references for regex matches" 21*288bf522SAndroid Build Coastguard Worker echo " --cluster" 22*288bf522SAndroid Build Coastguard Worker echo " Cluster the primary references for regex matches" 23*288bf522SAndroid Build Coastguard Worker echo " --serial=<serial> | -s <serial>" 24*288bf522SAndroid Build Coastguard Worker echo " Input from 'adb -s <serial> shell su 0 cat /proc/lockdep_chains'" 25*288bf522SAndroid Build Coastguard Worker echo " --input=<filename> | -i <filename>" 26*288bf522SAndroid Build Coastguard Worker echo " Input lockdeps from filename, otherwise from standard in" 27*288bf522SAndroid Build Coastguard Worker echo " --output=<filename> | -o <filename>" 28*288bf522SAndroid Build Coastguard Worker echo " Output formatted graph to filename, otherwise to standard out" 29*288bf522SAndroid Build Coastguard Worker echo 30*288bf522SAndroid Build Coastguard Worker echo "Chart is best viewed in portrait. ps or pdf formats tend to pixelate. png tends" 31*288bf522SAndroid Build Coastguard Worker echo "to hit a bug in cairo rendering at scale. Not having a set of regex matches for" 32*288bf522SAndroid Build Coastguard Worker echo "locknames will probably give you what you deserve ..." 33*288bf522SAndroid Build Coastguard Worker echo 34*288bf522SAndroid Build Coastguard Worker echo "Kernel Prerequisite to get /proc/lockdep_chains:" 35*288bf522SAndroid Build Coastguard Worker echo " CONFIG_PROVE_LOCKING=y" 36*288bf522SAndroid Build Coastguard Worker echo " CONFIG_LOCK_STAT=y" 37*288bf522SAndroid Build Coastguard Worker echo " CONFIG_DEBUG_LOCKDEP=y" 38*288bf522SAndroid Build Coastguard Worker} 39*288bf522SAndroid Build Coastguard Worker 40*288bf522SAndroid Build Coastguard Workerrm -f /tmp/${progname}.* 41*288bf522SAndroid Build Coastguard Worker 42*288bf522SAndroid Build Coastguard Worker# Indent rules and strip out address (may be overridden below) 43*288bf522SAndroid Build Coastguard Workerbeautify() { 44*288bf522SAndroid Build Coastguard Worker sed 's/^./ &/ 45*288bf522SAndroid Build Coastguard Worker s/"[[][0-9a-f]*[]] /"/g' 46*288bf522SAndroid Build Coastguard Worker} 47*288bf522SAndroid Build Coastguard Worker 48*288bf522SAndroid Build Coastguard Workerinput="cat -" 49*288bf522SAndroid Build Coastguard Workeroutput="cat -" 50*288bf522SAndroid Build Coastguard Worker 51*288bf522SAndroid Build Coastguard Workerdot_format="-Tpng" 52*288bf522SAndroid Build Coastguard Workerfilter= 53*288bf522SAndroid Build Coastguard Workerdebug= 54*288bf522SAndroid Build Coastguard Workerfocus= 55*288bf522SAndroid Build Coastguard Workercluster= 56*288bf522SAndroid Build Coastguard Worker 57*288bf522SAndroid Build Coastguard Workerwhile [ ${#} -gt 0 ]; do 58*288bf522SAndroid Build Coastguard Worker case ${1} in 59*288bf522SAndroid Build Coastguard Worker 60*288bf522SAndroid Build Coastguard Worker -T | --format) 61*288bf522SAndroid Build Coastguard Worker dot_format="-T${2}" 62*288bf522SAndroid Build Coastguard Worker shift 63*288bf522SAndroid Build Coastguard Worker ;; 64*288bf522SAndroid Build Coastguard Worker 65*288bf522SAndroid Build Coastguard Worker -T*) 66*288bf522SAndroid Build Coastguard Worker dot_format="${1}" 67*288bf522SAndroid Build Coastguard Worker ;; 68*288bf522SAndroid Build Coastguard Worker 69*288bf522SAndroid Build Coastguard Worker --format=*) 70*288bf522SAndroid Build Coastguard Worker dot_format="-T${1#--format=}" 71*288bf522SAndroid Build Coastguard Worker ;; 72*288bf522SAndroid Build Coastguard Worker 73*288bf522SAndroid Build Coastguard Worker --debug | -d) 74*288bf522SAndroid Build Coastguard Worker debug=1 75*288bf522SAndroid Build Coastguard Worker ;; 76*288bf522SAndroid Build Coastguard Worker 77*288bf522SAndroid Build Coastguard Worker --verbose | -v) 78*288bf522SAndroid Build Coastguard Worker # indent, but do _not_ strip out addresses 79*288bf522SAndroid Build Coastguard Worker beautify() { 80*288bf522SAndroid Build Coastguard Worker sed 's/^./ &/' 81*288bf522SAndroid Build Coastguard Worker } 82*288bf522SAndroid Build Coastguard Worker ;; 83*288bf522SAndroid Build Coastguard Worker 84*288bf522SAndroid Build Coastguard Worker --focus | -f | --primary) # reserving --primary 85*288bf522SAndroid Build Coastguard Worker focus=1 86*288bf522SAndroid Build Coastguard Worker ;; 87*288bf522SAndroid Build Coastguard Worker 88*288bf522SAndroid Build Coastguard Worker --secondary) # reserving --secondary 89*288bf522SAndroid Build Coastguard Worker focus= 90*288bf522SAndroid Build Coastguard Worker ;; 91*288bf522SAndroid Build Coastguard Worker 92*288bf522SAndroid Build Coastguard Worker --cluster) # reserve -c for dot (configure plugins) 93*288bf522SAndroid Build Coastguard Worker cluster=1 94*288bf522SAndroid Build Coastguard Worker ;; 95*288bf522SAndroid Build Coastguard Worker 96*288bf522SAndroid Build Coastguard Worker --serial | -s) 97*288bf522SAndroid Build Coastguard Worker if [ "${input}" != "cat -" ]; then 98*288bf522SAndroid Build Coastguard Worker usage >&2 99*288bf522SAndroid Build Coastguard Worker echo "ERROR: --input or --serial can only be specified once" >&2 100*288bf522SAndroid Build Coastguard Worker exit 1 101*288bf522SAndroid Build Coastguard Worker fi 102*288bf522SAndroid Build Coastguard Worker input="adb -s ${2} shell su 0 cat /proc/lockdep_chains" 103*288bf522SAndroid Build Coastguard Worker shift 104*288bf522SAndroid Build Coastguard Worker ;; 105*288bf522SAndroid Build Coastguard Worker 106*288bf522SAndroid Build Coastguard Worker --serial=*) 107*288bf522SAndroid Build Coastguard Worker input="adb -s ${1#--serial=} shell su 0 cat /proc/lockdep_chains" 108*288bf522SAndroid Build Coastguard Worker ;; 109*288bf522SAndroid Build Coastguard Worker 110*288bf522SAndroid Build Coastguard Worker --input | -i) 111*288bf522SAndroid Build Coastguard Worker if [ "${input}" != "cat -" ]; then 112*288bf522SAndroid Build Coastguard Worker usage >&2 113*288bf522SAndroid Build Coastguard Worker echo "ERROR: --input or --serial can only be specified once" >&2 114*288bf522SAndroid Build Coastguard Worker exit 1 115*288bf522SAndroid Build Coastguard Worker fi 116*288bf522SAndroid Build Coastguard Worker input="cat ${2}" 117*288bf522SAndroid Build Coastguard Worker shift 118*288bf522SAndroid Build Coastguard Worker ;; 119*288bf522SAndroid Build Coastguard Worker 120*288bf522SAndroid Build Coastguard Worker --input=*) 121*288bf522SAndroid Build Coastguard Worker if [ "${input}" != "cat -" ]; then 122*288bf522SAndroid Build Coastguard Worker usage >&2 123*288bf522SAndroid Build Coastguard Worker echo "ERROR: --input or --serial can only be specified once" >&2 124*288bf522SAndroid Build Coastguard Worker exit 1 125*288bf522SAndroid Build Coastguard Worker fi 126*288bf522SAndroid Build Coastguard Worker input="cat ${1#--input=}" 127*288bf522SAndroid Build Coastguard Worker ;; 128*288bf522SAndroid Build Coastguard Worker 129*288bf522SAndroid Build Coastguard Worker --output | -o) 130*288bf522SAndroid Build Coastguard Worker if [ "${output}" != "cat -" ]; then 131*288bf522SAndroid Build Coastguard Worker usage >&2 132*288bf522SAndroid Build Coastguard Worker echo "ERROR: --output can only be specified once" >&2 133*288bf522SAndroid Build Coastguard Worker exit 1 134*288bf522SAndroid Build Coastguard Worker fi 135*288bf522SAndroid Build Coastguard Worker output="cat - > ${2}" # run through eval 136*288bf522SAndroid Build Coastguard Worker shift 137*288bf522SAndroid Build Coastguard Worker ;; 138*288bf522SAndroid Build Coastguard Worker 139*288bf522SAndroid Build Coastguard Worker --output=*) 140*288bf522SAndroid Build Coastguard Worker if [ "${output}" != "cat -" ]; then 141*288bf522SAndroid Build Coastguard Worker usage >&2 142*288bf522SAndroid Build Coastguard Worker echo "ERROR: --output can only be specified once" >&2 143*288bf522SAndroid Build Coastguard Worker exit 1 144*288bf522SAndroid Build Coastguard Worker fi 145*288bf522SAndroid Build Coastguard Worker output="cat - > ${1#--output=}" # run through eval 146*288bf522SAndroid Build Coastguard Worker ;; 147*288bf522SAndroid Build Coastguard Worker 148*288bf522SAndroid Build Coastguard Worker --help | -h | -\?) 149*288bf522SAndroid Build Coastguard Worker usage 150*288bf522SAndroid Build Coastguard Worker exit 151*288bf522SAndroid Build Coastguard Worker ;; 152*288bf522SAndroid Build Coastguard Worker 153*288bf522SAndroid Build Coastguard Worker *) 154*288bf522SAndroid Build Coastguard Worker # Everything else is a filter, which will also hide bad option flags, 155*288bf522SAndroid Build Coastguard Worker # which is an as-designed price we pay to allow "->rwlock" for instance. 156*288bf522SAndroid Build Coastguard Worker if [ X"${1}" = X"${1#* }" ]; then 157*288bf522SAndroid Build Coastguard Worker if [ -z "${filter}" ]; then 158*288bf522SAndroid Build Coastguard Worker filter="${1}" 159*288bf522SAndroid Build Coastguard Worker else 160*288bf522SAndroid Build Coastguard Worker filter="${filter}|${1}" 161*288bf522SAndroid Build Coastguard Worker fi 162*288bf522SAndroid Build Coastguard Worker else 163*288bf522SAndroid Build Coastguard Worker if [ -z "${filter}" ]; then 164*288bf522SAndroid Build Coastguard Worker filter=" ${1}" 165*288bf522SAndroid Build Coastguard Worker else 166*288bf522SAndroid Build Coastguard Worker filter="${filter}| ${1}" 167*288bf522SAndroid Build Coastguard Worker fi 168*288bf522SAndroid Build Coastguard Worker fi 169*288bf522SAndroid Build Coastguard Worker ;; 170*288bf522SAndroid Build Coastguard Worker 171*288bf522SAndroid Build Coastguard Worker esac 172*288bf522SAndroid Build Coastguard Worker shift 173*288bf522SAndroid Build Coastguard Workerdone 174*288bf522SAndroid Build Coastguard Worker 175*288bf522SAndroid Build Coastguard Workerif [ -z "${filter}" ]; then 176*288bf522SAndroid Build Coastguard Worker echo "WARNING: no regex specified will give you what you deserve!" >&2 177*288bf522SAndroid Build Coastguard Workerfi 178*288bf522SAndroid Build Coastguard Workerif [ -n "${focus}" -a -z "${filter}" ]; then 179*288bf522SAndroid Build Coastguard Worker echo "WARNING: --focus without regex, ignored" >&2 180*288bf522SAndroid Build Coastguard Workerfi 181*288bf522SAndroid Build Coastguard Workerif [ -n "${cluster}" -a -z "${filter}" ]; then 182*288bf522SAndroid Build Coastguard Worker echo "WARNING: --cluster without regex, ignored" >&2 183*288bf522SAndroid Build Coastguard Workerfi 184*288bf522SAndroid Build Coastguard Workerif [ -n "${cluster}" -a -n "${focus}" -a -n "${filter}" ]; then 185*288bf522SAndroid Build Coastguard Worker echo "WARNING: orthogonal options --cluster & --focus, ignoring --cluster" >&2 186*288bf522SAndroid Build Coastguard Worker cluster= 187*288bf522SAndroid Build Coastguard Workerfi 188*288bf522SAndroid Build Coastguard Worker 189*288bf522SAndroid Build Coastguard Worker# convert to dot digraph series 190*288bf522SAndroid Build Coastguard Worker${input} | 191*288bf522SAndroid Build Coastguard Worker sed '/^all lock chains:$/d 192*288bf522SAndroid Build Coastguard Worker / [&]__lockdep_no_validate__$/d 193*288bf522SAndroid Build Coastguard Worker /irq_context: 0/d 194*288bf522SAndroid Build Coastguard Worker s/irq_context: [1-9]/irq_context/ 195*288bf522SAndroid Build Coastguard Worker s/..*/"&" ->/ 196*288bf522SAndroid Build Coastguard Worker s/^$/;/' | 197*288bf522SAndroid Build Coastguard Worker sed ': loop 198*288bf522SAndroid Build Coastguard Worker N 199*288bf522SAndroid Build Coastguard Worker s/ ->\n;$/ ;/ 200*288bf522SAndroid Build Coastguard Worker t 201*288bf522SAndroid Build Coastguard Worker s/ ->\n/ -> / 202*288bf522SAndroid Build Coastguard Worker b loop' > /tmp/${progname}.formed 203*288bf522SAndroid Build Coastguard Worker 204*288bf522SAndroid Build Coastguard Workerif [ ! -s /tmp/${progname}.formed ]; then 205*288bf522SAndroid Build Coastguard Worker echo "ERROR: no input" >&2 206*288bf522SAndroid Build Coastguard Worker if [ -z "${debug}" ]; then 207*288bf522SAndroid Build Coastguard Worker rm -f /tmp/${progname}.* 208*288bf522SAndroid Build Coastguard Worker fi 209*288bf522SAndroid Build Coastguard Worker exit 2 210*288bf522SAndroid Build Coastguard Workerfi 211*288bf522SAndroid Build Coastguard Worker 212*288bf522SAndroid Build Coastguard Workerif [ -n "${filter}" ]; then 213*288bf522SAndroid Build Coastguard Worker grep "${filter}" /tmp/${progname}.formed | 214*288bf522SAndroid Build Coastguard Worker sed 's/ ;// 215*288bf522SAndroid Build Coastguard Worker s/ -> /|/g' | 216*288bf522SAndroid Build Coastguard Worker tr '|' '\n' | 217*288bf522SAndroid Build Coastguard Worker sort -u > /tmp/${progname}.symbols 218*288bf522SAndroid Build Coastguard Workerfi 219*288bf522SAndroid Build Coastguard Worker 220*288bf522SAndroid Build Coastguard Worker( 221*288bf522SAndroid Build Coastguard Worker echo 'digraph G {' 222*288bf522SAndroid Build Coastguard Worker ( 223*288bf522SAndroid Build Coastguard Worker echo 'remincross="true";' 224*288bf522SAndroid Build Coastguard Worker echo 'concentrate="true";' 225*288bf522SAndroid Build Coastguard Worker echo 226*288bf522SAndroid Build Coastguard Worker 227*288bf522SAndroid Build Coastguard Worker if [ -s /tmp/${progname}.symbols ]; then 228*288bf522SAndroid Build Coastguard Worker if [ -n "${cluster}" ]; then 229*288bf522SAndroid Build Coastguard Worker echo 'subgraph cluster_symbols {' 230*288bf522SAndroid Build Coastguard Worker ( 231*288bf522SAndroid Build Coastguard Worker grep "${filter}" /tmp/${progname}.symbols | 232*288bf522SAndroid Build Coastguard Worker sed 's/.*/& [shape=box] ;/' 233*288bf522SAndroid Build Coastguard Worker grep -v "${filter}" /tmp/${progname}.symbols | 234*288bf522SAndroid Build Coastguard Worker sed 's/.*/& [shape=diamond] ;/' 235*288bf522SAndroid Build Coastguard Worker ) | beautify 236*288bf522SAndroid Build Coastguard Worker echo '}' 237*288bf522SAndroid Build Coastguard Worker else 238*288bf522SAndroid Build Coastguard Worker grep "${filter}" /tmp/${progname}.symbols | 239*288bf522SAndroid Build Coastguard Worker sed 's/.*/& [shape=box] ;/' 240*288bf522SAndroid Build Coastguard Worker grep -v "${filter}" /tmp/${progname}.symbols | 241*288bf522SAndroid Build Coastguard Worker sed 's/.*/& [shape=diamond] ;/' 242*288bf522SAndroid Build Coastguard Worker fi 243*288bf522SAndroid Build Coastguard Worker 244*288bf522SAndroid Build Coastguard Worker echo 245*288bf522SAndroid Build Coastguard Worker fi 246*288bf522SAndroid Build Coastguard Worker ) | beautify 247*288bf522SAndroid Build Coastguard Worker 248*288bf522SAndroid Build Coastguard Worker if [ -s /tmp/${progname}.symbols ]; then 249*288bf522SAndroid Build Coastguard Worker if [ -z "${focus}" ]; then 250*288bf522SAndroid Build Coastguard Worker # Secondary relationships 251*288bf522SAndroid Build Coastguard Worker fgrep -f /tmp/${progname}.symbols /tmp/${progname}.formed 252*288bf522SAndroid Build Coastguard Worker else 253*288bf522SAndroid Build Coastguard Worker # Focus only on primary relationships 254*288bf522SAndroid Build Coastguard Worker grep "${filter}" /tmp/${progname}.formed 255*288bf522SAndroid Build Coastguard Worker fi 256*288bf522SAndroid Build Coastguard Worker else 257*288bf522SAndroid Build Coastguard Worker cat /tmp/${progname}.formed 258*288bf522SAndroid Build Coastguard Worker fi | 259*288bf522SAndroid Build Coastguard Worker # optimize int A -> B ; single references 260*288bf522SAndroid Build Coastguard Worker sed 's/\("[^"]*"\) -> \("[^"]*"\) ->/\1 -> \2 ;|\2 ->/g' | 261*288bf522SAndroid Build Coastguard Worker sed 's/\("[^"]*"\) -> \("[^"]*"\) ->/\1 -> \2 ;|\2 ->/g' | 262*288bf522SAndroid Build Coastguard Worker tr '|' '\n' | 263*288bf522SAndroid Build Coastguard Worker beautify | 264*288bf522SAndroid Build Coastguard Worker grep ' -> ' | 265*288bf522SAndroid Build Coastguard Worker sort -u | 266*288bf522SAndroid Build Coastguard Worker if [ -s /tmp/${progname}.symbols ]; then 267*288bf522SAndroid Build Coastguard Worker beautify < /tmp/${progname}.symbols | 268*288bf522SAndroid Build Coastguard Worker sed 's/^ */ /' > /tmp/${progname}.short 269*288bf522SAndroid Build Coastguard Worker tee /tmp/${progname}.split | 270*288bf522SAndroid Build Coastguard Worker fgrep -f /tmp/${progname}.short | 271*288bf522SAndroid Build Coastguard Worker sed 's/ ;$/ [color=red] ;/' 272*288bf522SAndroid Build Coastguard Worker fgrep -v -f /tmp/${progname}.short /tmp/${progname}.split 273*288bf522SAndroid Build Coastguard Worker rm -f /tmp/${progname}.short /tmp/${progname}.split 274*288bf522SAndroid Build Coastguard Worker else 275*288bf522SAndroid Build Coastguard Worker cat - 276*288bf522SAndroid Build Coastguard Worker fi 277*288bf522SAndroid Build Coastguard Worker 278*288bf522SAndroid Build Coastguard Worker echo '}' 279*288bf522SAndroid Build Coastguard Worker) | 280*288bf522SAndroid Build Coastguard Worker tee /tmp/${progname}.input | 281*288bf522SAndroid Build Coastguard Worker if dot ${dot_format} && [ -z "${debug}" ]; then 282*288bf522SAndroid Build Coastguard Worker rm -f /tmp/${progname}.* 283*288bf522SAndroid Build Coastguard Worker fi | 284*288bf522SAndroid Build Coastguard Worker eval ${output} 285