From 6c3b3ba7f5e85f1ecef1129e1fabbcca47b501ed Mon Sep 17 00:00:00 2001
From: MSVSphere Packaging Team <packager@msvsphere-os.ru>
Date: Wed, 8 Nov 2023 15:19:17 +0300
Subject: [PATCH] import kernel-srpm-macros-1.0-13.el9

---
 SOURCES/find-provides.ksyms   | 80 ++++++++++++++++++-----------
 SOURCES/find-requires.ksyms   | 94 ++++++++++++++++++++++-------------
 SOURCES/kabi.attr             |  2 +-
 SOURCES/kabi.sh               | 10 +++-
 SPECS/kernel-srpm-macros.spec | 18 ++++++-
 5 files changed, 135 insertions(+), 69 deletions(-)
 mode change 100755 => 100644 SOURCES/find-requires.ksyms

diff --git a/SOURCES/find-provides.ksyms b/SOURCES/find-provides.ksyms
index aa656e1..6b676e5 100755
--- a/SOURCES/find-provides.ksyms
+++ b/SOURCES/find-provides.ksyms
@@ -3,6 +3,10 @@
 IFS=$'\n'
 export LC_ALL=C
 
+# Prevent elfutils from trying to download debuginfos
+unset DEBUGINFOD_URLS
+
+
 for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do
     dep_pfx="ksym"
     # For built-in kmods, "kernel()" syntax is used instead of "ksym()"
@@ -34,36 +38,54 @@ for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do
         module="$tmpfile"
     fi
 
-    if nm "$module" | grep -qE '^([0-9a-f]+) A __crc_(.+)' 2> /dev/null; then
-        nm "$module" \
-        | awk \
-           -v 'dep_pfx='"$dep_pfx" \
-           --non-decimal-data \
-          'match($0, /^([0-9a-f]+) A __crc_(.+)/, a) { printf("%s(%s) = 0x%08x\n", dep_pfx, a[2], strtonum("0x" a[1])) }' \
-        | sort -u
-    else
-        objdump -t "$module" \
-        | sed -n 's/^[0-9a-f][0-9a-f]* g...... \(.*\)	[0-9a-f][0-9a-f]* __crc_.*$/\1/p' \
-        | sort -u \
-        | while read sectname; do
-            [ -n "$sectname" ] || continue
+    # awk script return code:
+    #   0 - absolute __crc_* symbols have been found, output has been
+    #       generated;
+    #   23 - a non-absolute __crc_* symbold has been found;
+    #   42 - no __crc_* symbols have been found.
+    nm "$module" \
+    | awk \
+       -v 'dep_pfx='"$dep_pfx" \
+       --non-decimal-data \
+       'BEGIN { exit_code = 42 }
+       match($0, /^([0-9a-f]+) (.) __crc_(.+)/, a) {
+           if (a[2] == "A") {
+               printf("%s(%s) = 0x%08x\n", dep_pfx, a[3], strtonum("0x" a[1]));
+               exit_code = 0;
+           } else {
+               exit_code = 23;
+               exit;
+           }
+       }
+       END { exit exit_code }'
 
-            ELFSECTDATA=$(readelf -R "$sectname" "$module" | awk '/0x/{printf $2$3$4$5}')
-            if [[ -n $(readelf -h $module | grep "little endian") ]]; then
-                SECTDATA=$(echo $ELFSECTDATA | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/g')
-            else
-                SECTDATA=$ELFSECTDATA
-            fi
+    [ 23 = "$?" ] && {
+        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 'sectdata='"$SECTDATA" \
-              --non-decimal-data \
-              'match($0, /^([0-9a-f]+) g...... .*	[0-9a-f]+ __crc_(.*)$/, a) { printf("%s(%s) = 0x%08s\n", dep_pfx, a[2], substr(sectdata, (strtonum("0x" a[1]) * 2) + 1, 8)) }'
-        done \
-        | sort -u
-    fi
+        objdump -t "$module" \
+        | 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);
+              }
+              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"
-done
+done \
+| sort -k1,1 -u
diff --git a/SOURCES/find-requires.ksyms b/SOURCES/find-requires.ksyms
old mode 100755
new mode 100644
index e2cd33b..eac4010
--- a/SOURCES/find-requires.ksyms
+++ b/SOURCES/find-requires.ksyms
@@ -6,6 +6,11 @@
 # provided by an external module and "ksym" replaces th regular "kernel" dep.
 
 IFS=$'\n'
+export LC_ALL=C
+
+# Prevent elfutils from trying to download debuginfos
+unset DEBUGINFOD_URLS
+
 
 # Extract all of the symbols provided by this module.
 all_provides() {
@@ -35,38 +40,57 @@ all_provides() {
             module="$tmpfile"
         fi
 
-        if nm "$module" | grep -qE '^([0-9a-f]+) A __crc_(.+)' 2> /dev/null; then
-            nm "$module" \
-            | awk \
-               -v 'dep_pfx='"$dep_pfx" \
-               --non-decimal-data \
-              'match($0, /^([0-9a-f]+) A __crc_(.+)/, a) { printf("%s(%s) = 0x%08x\n", dep_pfx, a[2], strtonum("0x" a[1])) }'
-        else
+        # awk script return code:
+        #   0 - absolute __crc_* symbols have been found, output has been
+        #       generated;
+        #   23 - a non-absolute __crc_* symbold has been found;
+        #   42 - no __crc_* symbols have been found.
+        nm "$module" \
+        | awk \
+           -v 'dep_pfx='"$dep_pfx" \
+           --non-decimal-data \
+           'BEGIN { exit_code = 42 }
+           match($0, /^([0-9a-f]+) (.) __crc_(.+)/, a) {
+               if (a[2] == "A") {
+                   printf("%s(%s) = 0x%08x\n", dep_pfx, a[3], strtonum("0x" a[1]));
+                   exit_code = 0;
+               } else {
+                   exit_code = 23;
+                   exit;
+               }
+           }
+           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]* g...... \(.*\)	[0-9a-f][0-9a-f]* __crc_.*$/\1/p' \
-            | sort -u \
-            | while read sectname; do
-                [ -n "$sectname" ] || continue
-
-                ELFSECTDATA=$(readelf -R .rodata "$module" | awk '/0x/{printf $2$3$4$5}')
-                if [[ -n $(readelf -h "$module" | grep "little endian") ]]; then
-                    SECTDATA=$(echo $ELFSECTDATA | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/g')
-                else
-                    SECTDATA=$ELFSECTDATA
-                fi
-
-                objdump -t "$module" \
-                | awk \
-                  -v 'dep_pfx='"$dep_pfx" \
-                  -v 'sectdata='"$SECTDATA" \
-                  --non-decimal-data \
-                  'match($0, /^([0-9a-f]+) g...... .*	[0-9a-f]+ __crc_(.*)$/, a) { printf("%s(%s) = 0x%08s\n", dep_pfx, a[2], substr(sectdata, (strtonum("0x" a[1]) * 2) + 1, 8)) }'
-            done
-        fi
+            | 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);
+                  }
+                  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"
     done \
-    | LC_ALL=C sort -k1,1 -u
+    | sort -k1,1 -u
 }
 
 # Extract all of the requirements of this module.
@@ -79,15 +103,15 @@ all_requires() {
             {printf("%s:0x%08x\n", $2, $1)}' \
         | sed -r -e 's:$:\t'"$1"':'
     done \
-    | LC_ALL=C sort -k1,1 -u
+    | sort -k1,1 -u
 }
 
 # Filter out requirements fulfilled by the module itself.
 mod_requires() {
-    LC_ALL=C join -t $'\t' -j 1 -v 1 \
+    join -t $'\t' -j 1 -v 1 \
         <(all_requires "$@") \
         <(all_provides "$@") \
-    | LC_ALL=C sort -k1,1 -u
+    | sort -k1,1 -u
 }
 
 if ! [ -e /sbin/modinfo -a -e /sbin/modprobe ]; then
@@ -150,21 +174,21 @@ if [ ${#modules[@]} -gt 0 ]; then
         { print $2 ":" $1 }
     ' \
     | sed -r -e 's:$:\t'"$kernel"':' \
-    | LC_ALL=C sort -k1,1 -u > $symvers
+    | sort -k1,1 -u > $symvers
 
     # Symbols matching with the kernel get a "kernel" dependency
     mod_req=$(mktemp -t mod_req.XXXXX)
     mod_requires "${modules[@]}" > "$mod_req"
-    LC_ALL=C join -t $'\t' -j 1 $symvers "$mod_req" | LC_ALL=C sort -u \
+    join -t $'\t' -j 1 $symvers "$mod_req" | sort -u \
     | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print "kernel(" $1 ") = " $2 }'
 
     # Symbols from elsewhere get a "ksym" dependency
-    LC_ALL=C join -t $'\t' -j 1 -v 2 $symvers "$mod_req" | LC_ALL=C sort -u \
+    join -t $'\t' -j 1 -v 2 $symvers "$mod_req" | sort -u \
     | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print "ksym(" $1 ") = " $2 }'
 
     # Check kABI if the kabi-stablelists package is installed
     # Do this last so we can try to output this error at the end
-    kabi_check_symbols=($(LC_ALL=C join -t $'\t' -j 1 $symvers "$mod_req" | LC_ALL=C sort -u \
+    kabi_check_symbols=($(join -t $'\t' -j 1 $symvers "$mod_req" | sort -u \
     | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print $1 }'))
     check_kabi "${kabi_check_symbols[@]}"
 fi
diff --git a/SOURCES/kabi.attr b/SOURCES/kabi.attr
index 2d81387..5500b17 100644
--- a/SOURCES/kabi.attr
+++ b/SOURCES/kabi.attr
@@ -1,2 +1,2 @@
 %__kabi_provides	%{_rpmconfigdir}/kabi.sh
-%__kabi_path            ^(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.gz$
+%__kabi_path            ^(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.(gz|xz)$
diff --git a/SOURCES/kabi.sh b/SOURCES/kabi.sh
index 3fb749b..dd49b8b 100644
--- a/SOURCES/kabi.sh
+++ b/SOURCES/kabi.sh
@@ -7,10 +7,16 @@
 
 IFS=$'\n'
 
-for symvers in $(grep -E '(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.gz') "$@";
+for symvers in $(grep -E '(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.(gz|xz)') "$@";
 do
+	cat_prog="cat"
+	case "$symvers" in
+	*.gz) cat_prog="zcat" ;;
+	*.xz) cat_prog="xzcat" ;;
+	esac
+
 	# We generate dependencies only for symbols exported by vmlinux itself
 	# and not for kmods here as they are spread across subpackages,
 	# so Provides: generation for kmods is handled by find-provides.ksyms.
-	zcat $symvers | awk '/[^	]*	[^	]*	vmlinux	.*/ { print "kernel(" $2 ") = " $1 }'
+	"$cat_prog" "$symvers" | awk '/[^	]*	[^	]*	vmlinux	.*/ { print "kernel(" $2 ") = " $1 }'
 done
diff --git a/SPECS/kernel-srpm-macros.spec b/SPECS/kernel-srpm-macros.spec
index 991e317..acaf875 100644
--- a/SPECS/kernel-srpm-macros.spec
+++ b/SPECS/kernel-srpm-macros.spec
@@ -1,6 +1,6 @@
 Name:           kernel-srpm-macros
 Version:        1.0
-Release:        12%{?dist}
+Release:        13%{?dist}
 Summary:        RPM macros that list arches the full kernel is built on
 # This package only exist in Fedora repositories
 # The license is the standard (MIT) specified in
@@ -134,7 +134,21 @@ install -p -m 644 -t "%{buildroot}%{_fileattrsdir}" modalias.attr
 %{rrcdir}/find-provides.d/modalias.prov
 
 %changelog
-* Wed Mar 15 2023 MSVSphere Packaging Team <packager@msvsphere.ru> - 1.0-11
+* Mon Jun 12 2023 Eugene Syromiatnikov <esyr@redhat.com> - 1.0-13
+- Handle symvers.xz in kabi.attr (#2209253).
+- Fix indirect __crc_* sumbols parsing in find-provides.ksyms
+  and find-requires.ksyms to avoid matching multiple sections
+  producing bogus duplicate provides for kmods that have both __kcrctab
+  and __kcrctab_gpl sections (#2115811, #2178935).
+- Call "readelf -R" on a correct section in find-requires.ksyms.
+- Rewrite section data extraction in find-provides.ksyms and find-requires.ksyms
+  to avoid garbage at the end of extracted sections, causing unnecessary awk
+  complaints (#2115811).
+- Perform section parsing inside the awk script in find-provides.ksyms
+  and find-requires.ksyms to avoid hitting command line argument limit
+  when handling large .rodata sections (#2178935).
+
+* Wed Mar 15 2023 MSVSphere Packaging Team <packager@msvsphere.ru> - 1.0-12
 - Rebuilt for MSVSphere 9.1.
 
 * Tue Jan 31 2023 Eugene Syromiatnikov <esyr@redhat.com> - 1.0-12