diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/abilist.awk | 70 | ||||
-rw-r--r-- | scripts/extract-abilist.awk | 44 | ||||
-rw-r--r-- | scripts/merge-abilist.awk | 129 |
3 files changed, 233 insertions, 10 deletions
diff --git a/scripts/abilist.awk b/scripts/abilist.awk index 9781834..346527e 100644 --- a/scripts/abilist.awk +++ b/scripts/abilist.awk @@ -1,8 +1,6 @@ # This awk script processes the output of objdump --dynamic-syms # into a simple format that should not change when the ABI is not changing. -BEGIN { outpipe = "sort" } - # Normalize columns. /^[0-9a-fA-F]+ / { sub(/ /, " - ") } @@ -13,11 +11,11 @@ $4 == "*UND*" { next } $2 == "l" { next } $2 == "g" || $2 == "w" && NF == 7 { - weak = ($2 == "w") ? "weak" : "strong"; + weak = $2; type = $3; size = $5; sub(/^0*/, "", size); - size = "0x" size; + size = " 0x" size; version = $6; symbol = $7; gsub(/[()]/, "", version); @@ -25,24 +23,36 @@ $2 == "g" || $2 == "w" && NF == 7 { if (version == "GLIBC_PRIVATE") next; if (type == "D" && $4 == ".tbss") { - print symbol, version, weak, "TLS", size | outpipe; + type = "T"; } else if (type == "D" && $4 == ".opd") { - print symbol, version, weak, "FDESC" | outpipe; + type = "O"; + size = ""; } else if (type == "DO" && $4 == "*ABS*") { - print symbol, version, weak, "ABS" | outpipe; + type = "A"; + size = ""; } else if (type == "DO") { - print symbol, version, weak, "DATA", size | outpipe; + type = "D"; } else if (type == "DF") { - print symbol, version, weak, "FUNC" | outpipe; + type = "F"; + size = ""; } else { - print symbol, version, weak, "UNEXPECTED", type, $4, $5; + print symbol, version, weak, "?", type, $4, $5; + next; } + desc = " " symbol " " (weak == "w" ? tolower(type) : type) size; + + if (version in versions) { + versions[version] = versions[version] "\n" desc; + } + else { + versions[version] = desc; + } next; } @@ -52,3 +62,43 @@ NF == 0 || /DYNAMIC SYMBOL TABLE/ || /file format/ { next } { print "Don't grok this line:", $0 } + +END { + nverlist = 0; + for (version in versions) { + if (nverslist == 0) { + verslist = version; + nverslist = 1; + continue; + } + split(verslist, s, "\n"); + if (version < s[1]) { + verslist = version; + for (i = 1; i <= nverslist; ++i) { + verslist = verslist "\n" s[i]; + } + } + else { + verslist = s[1]; + for (i = 2; i <= nverslist; ++i) { + if (version < s[i]) break; + verslist = verslist "\n" s[i]; + } + verslist = verslist "\n" version; + for (; i <= nverslist; ++i) { + verslist = verslist "\n" s[i]; + } + } + ++nverslist; + } + + split(verslist, order, "\n"); + for (i = 1; i <= nverslist; ++i) { + version = order[i]; + + print version; + outpipe = "sort"; + print versions[version] | outpipe; + close(outpipe); + } +} diff --git a/scripts/extract-abilist.awk b/scripts/extract-abilist.awk new file mode 100644 index 0000000..c5b76e1 --- /dev/null +++ b/scripts/extract-abilist.awk @@ -0,0 +1,44 @@ +# awk script to extract a config-specific .symlist file from a merged file. +# This must be passed run with awk -v config=TUPLE to specify the configuration +# tuple we will match. The merged file contains stanzas in the form: +# GLIBC_x.y regexp... +# function F +# variable D 0x4 +# Each regexp is matched against TUPLE, and only matching stanzas go +# into the output, with the regexp list removed. The result matches the +# original .symlist file from abilist.awk that was fed into merge-abilist.awk. + +BEGIN { + outpipe = ""; +} + +/^ / { if (!ignore) print | outpipe; next; } + +{ + for (i = 2; i <= NF; ++i) { + regex = "^" $i "$"; + if (match(config, regex) != 0) { + if ($1 != version) { + if (outpipe != "") { + close(outpipe); + } + version = $1; + print version; + outpipe = "sort"; + } + ignore = 0; + next; + } + } + ignore = 1; + next; +} + +END { + if (outpipe == "") { + print "No stanza matched", config > "/dev/stderr"; + exit 2; + } + else + close(outpipe); +} diff --git a/scripts/merge-abilist.awk b/scripts/merge-abilist.awk new file mode 100644 index 0000000..016debc --- /dev/null +++ b/scripts/merge-abilist.awk @@ -0,0 +1,129 @@ +# awk script to merge a config-specific .symlist file with others. +# The input files should be an existing .abilist file, and a .symlist file. +# This must be passed run with awk -v config=REGEXP to specify a regexp +# matching configuration tuples for which the .symlist input defines an ABI. +# The result merges all duplicate occurrences of any symbol in a version set +# into a stanza listing the regexps matching configurations that contain it. + +/^[^ ]/ { + if (NF < 2 && config == "") { + print "BAD LINE:", $0 > "/dev/stderr"; + exit 2; + } + + if (NF < 2) { + current = $1 ":" config; + } + else { + current = $1 ":" $2; + for (i = 3; i <= NF; ++i) { + current = current "," $1 ":" $i; + } + } + + next; +} + +{ + if ($0 in seen) { + seen[$0] = seen[$0] "\n" current; + } + else { + seen[$0] = current; + } + + next; +} + +END { + for (line in seen) { + split(seen[line], setlist, "\n"); + for (i in setlist) { + split(setlist[i], configs, ","); + for (j in configs) { + split(configs[j], temp, ":"); + version = temp[1]; + conf = temp[2]; + + if ((version,conf) in have) continue; + have[version,conf] = 1; + + if (version in confs) { + split(confs[version], c, " "); + if (conf < c[1]) { + confs[version] = conf; + for (k = 1; k <= nconfs[version]; ++k) { + confs[version] = confs[version] " " c[k]; + } + } + else { + confs[version] = c[1]; + for (k = 2; k <= nconfs[version]; ++k) { + if (conf < c[k]) break; + confs[version] = confs[version] " " c[k]; + } + confs[version] = confs[version] " " conf; + for (; k <= nconfs[version]; ++k) { + confs[version] = confs[version] " " c[k]; + } + } + ++nconfs[version]; + } + else { + confs[version] = conf; + nconfs[version] = 1; + } + } + } + for (idx in have) delete have[idx]; + + for (version in confs) { + idx = version " " confs[version]; + if (idx in final) { + final[idx] = final[idx] "\n" line; + } + else { + final[idx] = line; + } + delete confs[version]; + delete nconfs[version]; + } + } + + nstanzas = 0; + for (stanza in final) { + if (nstanzas == 0) { + stanzas = stanza; + nstanzas = 1; + continue; + } + split(stanzas, s, "\n"); + if (stanza < s[1]) { + stanzas = stanza; + for (i = 1; i <= nstanzas; ++i) { + stanzas = stanzas "\n" s[i]; + } + } + else { + stanzas = s[1]; + for (i = 2; i <= nstanzas; ++i) { + if (stanza < s[i]) break; + stanzas = stanzas "\n" s[i]; + } + stanzas = stanzas "\n" stanza; + for (; i <= nstanzas; ++i) { + stanzas = stanzas "\n" s[i]; + } + } + ++nstanzas; + } + + split(stanzas, order, "\n"); + for (i = 1; i <= nstanzas; ++i) { + stanza = order[i]; + print stanza; + outpipe = "sort"; + print final[stanza] | outpipe; + close(outpipe); + } +} |