find-provides.ksyms, find-requires.ksyms: avoid iterating over sections

Since the section retrieval code is implemented inside the awk script
now, the next step is to eliminate external iteration over the section
list and just retrieve the required sections inside awk on demand.  This
allows calling (and processing the output of) objdump -t just once,
which saves around 8-12% of time on kernels that store modversions
as non-absolute symbols:

    $ for i in ./lib/modules/*; do \
        echo "====== $i ====="; \
        diff -u <(find $i | ./find-provides.ksyms.old) <(find $i | ./find-provides.ksyms.new); \
        echo -n "old: "; find $i | time ./find-provides.ksyms.old > /dev/null; \
        echo -n "new: "; find $i | time ./find-provides.ksyms.new > /dev/null; \
    done
    ====== ./lib/modules/4.18.0-372.57.1.el8_6.s390x =====
    old: ../find-provides.ksyms.old > /dev/null  4.41s user 3.46s system 136% cpu 5.756 total
    new: ../find-provides.ksyms.new > /dev/null  3.90s user 2.94s system 129% cpu 5.279 total
    ====== ./lib/modules/4.18.0-372.57.1.el8_6.x86_64 =====
    old: ../find-provides.ksyms.old > /dev/null  6.04s user 3.88s system 124% cpu 7.993 total
    new: ../find-provides.ksyms.new > /dev/null  6.08s user 3.91s system 124% cpu 8.012 total
    ====== ./lib/modules/5.14.0-284.15.1.el9_2.s390x =====
    old: ../find-provides.ksyms.old > /dev/null  5.09s user 3.51s system 133% cpu 6.452 total
    new: ../find-provides.ksyms.new > /dev/null  4.65s user 2.89s system 126% cpu 5.949 total
    ====== ./lib/modules/5.14.0-284.15.1.el9_2.x86_64 =====
    old: ../find-provides.ksyms.old > /dev/null  6.52s user 4.14s system 123% cpu 8.638 total
    new: ../find-provides.ksyms.new > /dev/null  6.64s user 4.12s system 123% cpu 8.690 total
    ====== ./lib/modules/6.4.0-0.rc1.20230511git80e62bc8487b.19.eln126.s390x =====
    old: ../find-provides.ksyms.old > /dev/null  4.45s user 3.29s system 136% cpu 5.661 total
    new: ../find-provides.ksyms.new > /dev/null  3.84s user 2.54s system 127% cpu 4.980 total
    ====== ./lib/modules/6.4.0-0.rc1.20230511git80e62bc8487b.19.eln126.x86_64 =====
    old: ../find-provides.ksyms.old > /dev/null  7.34s user 4.33s system 129% cpu 9.019 total
    new: ../find-provides.ksyms.new > /dev/null  6.67s user 3.51s system 122% cpu 8.278 total

* find-provides.ksyms: Remove "objdump -t" section loop, do not supply
sectname to the awk script, treat sectdata as an array keyed on section
name, convert section retrieval to a function with a section name
as an argument, call it if a section name is not present in sectdata.
* find-requires.ksyms (all_provides): Likewise.

Resolves: #2178935
Signed-off-by: Eugene Syromiatnikov <esyr@redhat.com>
This commit is contained in:
Eugene Syromiatnikov 2023-05-23 16:17:39 +02:00
parent cd6eedad11
commit 04a4af896d
2 changed files with 44 additions and 50 deletions

View File

@ -60,33 +60,30 @@ for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do
END { exit exit_code }'
[ 23 = "$?" ] && {
kmod_elf_hdr="$(readelf -h "$module")"
[ "x$kmod_elf_hdr" = "x${kmod_elf_hdr%Data:*little endian*}" ]
revbytes="$?"
objdump -t "$module" \
| sed -n 's/^[0-9a-f][0-9a-f]* [gl]...... \(.*\) [0-9a-f][0-9a-f]* __crc_.*$/\1/p' \
| sort -u \
| while read -r sectname; do
[ -n "$sectname" ] || continue
kmod_elf_hdr="$(readelf -h "$module")"
[ "x$kmod_elf_hdr" = "x${kmod_elf_hdr%Data:*little endian*}" ]
revbytes="$?"
objdump -t "$module" \
| awk \
-v 'dep_pfx='"$dep_pfx" \
-v 'module='"$module" \
-v 'revbytes='"$revbytes" \
-v 'sectname='"$sectname" \
--non-decimal-data \
'BEGIN {
sectdata = "";
while (("readelf -R \"" sectname "\" \"" module "\"" | getline t) > 0) {
if (match(t, /^ 0x[0-9a-f]{8}/))
sectdata = sectdata substr(t, 14, 8) substr(t, 23, 8) substr(t, 32, 8) substr(t, 41, 8);
}
if (revbytes) { sectdata = gensub(/(..)(..)(..)(..)/, "\\4\\3\\2\\1", "g", sectdata); }
| awk \
-v 'dep_pfx='"$dep_pfx" \
-v 'module='"$module" \
-v 'revbytes='"$revbytes" \
--non-decimal-data \
'function readsect(name, a, t) {
a = "";
while (("readelf -R \"" name "\" \"" module "\"" | getline t) > 0) {
if (match(t, /^ 0x[0-9a-f]{8}/))
a = a substr(t, 14, 8) substr(t, 23, 8) substr(t, 32, 8) substr(t, 41, 8);
}
match($0, /^([0-9a-f]+) [gl]...... (.*) [0-9a-f]+ __crc_(.*)$/, a) && a[2] == sectname { printf("%s(%s) = 0x%08s\n", dep_pfx, a[3], substr(sectdata, (strtonum("0x" a[1]) * 2) + 1, 8)) }'
done
if (revbytes) { a = gensub(/(..)(..)(..)(..)/, "\\4\\3\\2\\1", "g", a); }
sectdata[name] = a;
}
match($0, /^([0-9a-f]+) [gl]...... (.*) [0-9a-f]+ __crc_(.*)$/, a) {
if (!(a[2] in sectdata)) { readsect(a[2]) }
printf("%s(%s) = 0x%08s\n", dep_pfx, a[3], substr(sectdata[a[2]], (strtonum("0x" a[1]) * 2) + 1, 8))
}'
}
[ -z "$tmpfile" ] || rm -f -- "$tmpfile"

View File

@ -62,33 +62,30 @@ all_provides() {
END { exit exit_code }'
[ 23 = "$?" ] && {
kmod_elf_hdr="$(readelf -h "$module")"
[ "x$kmod_elf_hdr" = "x${kmod_elf_hdr%Data:*little endian*}" ]
revbytes="$?"
objdump -t "$module" \
| sed -n 's/^[0-9a-f][0-9a-f]* [gl]...... \(.*\) [0-9a-f][0-9a-f]* __crc_.*$/\1/p' \
| sort -u \
| while read -r sectname; do
[ -n "$sectname" ] || continue
kmod_elf_hdr="$(readelf -h "$module")"
[ "x$kmod_elf_hdr" = "x${kmod_elf_hdr%Data:*little endian*}" ]
revbytes="$?"
objdump -t "$module" \
| awk \
-v 'dep_pfx='"$dep_pfx" \
-v 'module='"$module" \
-v 'revbytes='"$revbytes" \
-v 'sectname='"$sectname" \
--non-decimal-data \
'BEGIN {
sectdata = "";
while (("readelf -R \"" sectname "\" \"" module "\"" | getline t) > 0) {
if (match(t, /^ 0x[0-9a-f]{8}/))
sectdata = sectdata substr(t, 14, 8) substr(t, 23, 8) substr(t, 32, 8) substr(t, 41, 8);
}
if (revbytes) { sectdata = gensub(/(..)(..)(..)(..)/, "\\4\\3\\2\\1", "g", sectdata); }
| awk \
-v 'dep_pfx='"$dep_pfx" \
-v 'module='"$module" \
-v 'revbytes='"$revbytes" \
--non-decimal-data \
'function readsect(name, a, t) {
a = "";
while (("readelf -R \"" name "\" \"" module "\"" | getline t) > 0) {
if (match(t, /^ 0x[0-9a-f]{8}/))
a = a substr(t, 14, 8) substr(t, 23, 8) substr(t, 32, 8) substr(t, 41, 8);
}
match($0, /^([0-9a-f]+) [gl]...... (.*) [0-9a-f]+ __crc_(.*)$/, a) && a[2] == sectname { printf("%s(%s) = 0x%08s\n", dep_pfx, a[3], substr(sectdata, (strtonum("0x" a[1]) * 2) + 1, 8)) }'
done
if (revbytes) { a = gensub(/(..)(..)(..)(..)/, "\\4\\3\\2\\1", "g", a); }
sectdata[name] = a;
}
match($0, /^([0-9a-f]+) [gl]...... (.*) [0-9a-f]+ __crc_(.*)$/, a) {
if (!(a[2] in sectdata)) { readsect(a[2]) }
printf("%s(%s) = 0x%08s\n", dep_pfx, a[3], substr(sectdata[a[2]], (strtonum("0x" a[1]) * 2) + 1, 8))
}'
}
[ -z "$tmpfile" ] || rm -f -- "$tmpfile"