From 04a4af896d64511a3819c618df6b0158a8913bab Mon Sep 17 00:00:00 2001 From: Eugene Syromiatnikov Date: Tue, 23 May 2023 16:17:39 +0200 Subject: [PATCH] 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 --- find-provides.ksyms | 47 +++++++++++++++++++++------------------------ find-requires.ksyms | 47 +++++++++++++++++++++------------------------ 2 files changed, 44 insertions(+), 50 deletions(-) diff --git a/find-provides.ksyms b/find-provides.ksyms index 1259dcb..6b676e5 100755 --- a/find-provides.ksyms +++ b/find-provides.ksyms @@ -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" diff --git a/find-requires.ksyms b/find-requires.ksyms index d236cff..eac4010 100644 --- a/find-requires.ksyms +++ b/find-requires.ksyms @@ -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"