#!/bin/sh -ef export LC_ALL=C cd "${workdir:?}" [ -n "$*" ] || set -- -ap rpmelfsym "$@" >sym awk -F'\t' '$3~/[DT]/' sym >def sort -t$'\t' -k4 -o def def # avoid most frequent symbols nelf=`sort -u -k2,2 def |wc -l` cut -f4 def |uniq -cd |sort -n >freq awk -v n=$nelf '$1defsym 3<<'__EOF__' __cxa_ __cxxabiv1 __gnu_cxx __gxx_personality ^__dynamic_cast$ ^_Znwj$ ^_ZdlPv$ ^_Znaj$ ^_ZdaPv$ ^_ZNSt[0-9] ^_ZNKSt[0-9] ^_ZSt[0-9] ^_Unwind_ ^__register_frame ^yy[a-z_] __EOF__ sort -o defsym -u defsym join -t$'\t' -14 -21 -o '1.1 1.2 1.3 1.4' def defsym >xdef # product ::= pkg1 elf1 pkg2 elf2 symtype symname join -t$'\t' -j 4 -o '1.1 1.2 1.3 2.1 2.2 2.3 0' xdef xdef | awk -F'\t' 'function prio(f) { if (f~"^/lib/lib[^/]+[.]so[^/]*$") return 1 if (f~"^/usr/lib/lib[^/]+[.]so[^/]*$") return 2 if (f~"^/usr/X11R./lib/lib[^/]+[.]so[^/]*$") return 3 if (f~"lib/lib[^/]+[.]so[^/]*$") return 4 if (f~"/lib[^/]+[.]so[^/]*$") return 5 if (f~"[^/][.]so[^/]*$") return 6 return 9 } ($2<$5 && $3==$6) { OFS="\t" pd = prio($2)-prio($5) if (pd<0 || pd==0 && length($2)<=length($5)) print $1,$2,$4,$5,$6,$7 else print $4,$5,$1,$2,$6,$7 }' >product # suspect ::= pkg1 elf1 pkg2 elf2 log2(nsym) # I need logarithmic scale here to facilitate diffing # 3-5 symbols (approx. 4) log2 = 2 # 6-11 symbols (approx. 8) log2 = 3 # 12-22 symbols (approx. 16) log2 = 4 # 23-45 symbols (approx. 32) log2 = 5 # 46-90 symbols (approx. 64) log2 = 6 # 91-181 symbols (approx. 128) log2 = 7 # 182-362 symbols (approx. 256) log2 = 8 cut -f-4 product |sort |uniq -cd |sed 's/^ *\([0-9]\+\) \+\(.\+\)$/\2\t\1/' | awk -F'\t' 'BEGIN{OFS=FS}($NF=int(log($NF)/log(2)+0.5))>1' >suspect sort -o suspect -u suspect cat suspect cd - >/dev/null